[ Index ]
 

Code source de GeekLog 1.4.1

Accédez au Source d'autres logiciels libres

title

Body

[fermer]

/system/ -> lib-plugins.php (source)

   1  <?php
   2  
   3  /* Reminder: always indent with 4 spaces (no tabs). */
   4  // +---------------------------------------------------------------------------+
   5  // | Geeklog 1.4                                                               |
   6  // +---------------------------------------------------------------------------+
   7  // | lib-plugins.php                                                           |
   8  // |                                                                           |
   9  // | This file implements plugin support in Geeklog.                           |
  10  // +---------------------------------------------------------------------------+
  11  // | Copyright (C) 2000-2006 by the following authors:                         |
  12  // |                                                                           |
  13  // | Authors: Tony Bibbs       - tony AT tonybibbs DOT com                     |
  14  // |          Blaine Lang      - blaine AT portalparts DOT com                 |
  15  // |          Dirk Haun        - dirk AT haun-online DOT de                    |
  16  // +---------------------------------------------------------------------------+
  17  // |                                                                           |
  18  // | This program is free software; you can redistribute it and/or             |
  19  // | modify it under the terms of the GNU General Public License               |
  20  // | as published by the Free Software Foundation; either version 2            |
  21  // | of the License, or (at your option) any later version.                    |
  22  // |                                                                           |
  23  // | This program is distributed in the hope that it will be useful,           |
  24  // | but WITHOUT ANY WARRANTY; without even the implied warranty of            |
  25  // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             |
  26  // | GNU General Public License for more details.                              |
  27  // |                                                                           |
  28  // | You should have received a copy of the GNU General Public License         |
  29  // | along with this program; if not, write to the Free Software Foundation,   |
  30  // | Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.           |
  31  // |                                                                           |
  32  // +---------------------------------------------------------------------------+
  33  //
  34  // $Id: lib-plugins.php,v 1.113 2006/12/09 19:18:08 dhaun Exp $
  35  
  36  /**
  37  * This is the plugin library for Geeklog.  This is the API that plugins can
  38  * implement to get tight integration with Geeklog.
  39  * See each function for more details.
  40  *
  41  */
  42  
  43  if (strpos ($_SERVER['PHP_SELF'], 'lib-plugins.php') !== false) {
  44      die ('This file can not be used on its own!');
  45  }
  46  
  47  require_once($_CONF['path_system'] . 'classes/plugin.class.php');
  48  
  49  // buffer for function names for the center block API
  50  $PLG_bufferCenterAPI = array ();
  51  $PLG_buffered = false;
  52  
  53  // buffer enabled plugins
  54  $result = DB_query("SELECT pi_name FROM {$_TABLES['plugins']} WHERE pi_enabled = 1");
  55  $_PLUGINS = array();
  56  while ($A = DB_fetchArray($result)) {
  57      $_PLUGINS[] = $A['pi_name'];
  58  }
  59  
  60  /**
  61  * Calls a function for all enabled plugins
  62  *
  63  * @param     string     $function_name      holds name of function to call
  64  *
  65  */
  66  function PLG_callFunctionForAllPlugins($function_name)
  67  {
  68      global $_PLUGINS;
  69  
  70      foreach ($_PLUGINS as $pi_name) {
  71          $function = $function_name . $pi_name;
  72          if (function_exists($function)) {
  73              $function();
  74          }
  75      }
  76  }
  77  
  78  /**
  79  * Calls a function for a single plugin
  80  *
  81  * This is a generic function used by some of the other API functions to
  82  * call a function for a specific plugin and, optionally pass parameters.
  83  * This function can handle up to 5 arguments and if more exist it will
  84  * try to pass the entire args array to the function.
  85  *
  86  * @param        string      $function       holds name of function to call
  87  * @param        array       $args           arguments to send to function
  88  * @return       mixed       returns result of function call, otherwise false
  89  *
  90  */
  91  function PLG_callFunctionForOnePlugin($function, $args='')
  92  {
  93      if (function_exists($function)) {
  94          if (empty ($args)) {
  95              $args = array ();
  96          }
  97  
  98          // great, function exists, run it
  99          switch (count($args)) {
 100          case 0:
 101              return $function();
 102              break;
 103          case 1:
 104              return $function($args[1]);
 105              break;
 106          case 2:
 107              return $function($args[1], $args[2]);
 108              break;
 109          case 3:
 110              return $function($args[1], $args[2], $args[3]);
 111              break;
 112          case 4:
 113              return $function($args[1], $args[2], $args[3], $args[4]);
 114              break;
 115          case 5:
 116              return $function($args[1], $args[2], $args[3], $args[4], $args[5]);
 117              break;
 118          case 6:
 119              return $function($args[1], $args[2], $args[3], $args[4], $args[5], $args[6]);
 120              break;
 121          case 7:
 122              return $function($args[1], $args[2], $args[3], $args[4], $args[5], $args[6], $args[7]);
 123              break;
 124          default:
 125              return $function($args);
 126              break;
 127          }
 128      } else {
 129          return false;
 130      }
 131  }
 132  
 133  /**
 134  * Tells a plugin to install itself. NOTE: not currently used anymore
 135  *
 136  * @param        string      $type       Plugin name
 137  * @return       boolean     Returns true on success otherwise false
 138  *
 139  */
 140  function PLG_install($type)
 141  {
 142      return PLG_callFunctionForOnePlugin('plugin_install_' . $type);
 143  }
 144  
 145  /**
 146  * Upgrades a plugin. Tells a plugin to upgrade itself.
 147  *
 148  * @param        string      $type       Plugin name
 149  * @return       boolean     Returns true on success otherwise false
 150  *
 151  */
 152  function PLG_upgrade($type)
 153  {
 154      return PLG_callFunctionForOnePlugin('plugin_upgrade_' . $type);
 155  }
 156  
 157  /**
 158  * Calls the plugin function to return the current version of code.
 159  * Used to indicate to admin if an update or upgrade is requied.
 160  *
 161  * @param        string      $type       Plugin name
 162  * @return       boolean     Returns true on success otherwise false
 163  *
 164  */
 165  function PLG_chkVersion($type)
 166  {
 167      return PLG_callFunctionForOnePlugin('plugin_chkVersion_' . $type);
 168  }
 169  
 170  /**
 171  * Tells a plugin to uninstall itself.
 172  *
 173  * @param        string      $type       Plugin to uninstall
 174  * @return       boolean     Returns true on success otherwise false
 175  *
 176  */
 177  function PLG_uninstall ($type)
 178  {
 179      global $_PLUGINS, $_TABLES;
 180  
 181      if (empty ($type)) {
 182          return false;
 183      }
 184  
 185      $retval = PLG_callFunctionForOnePlugin ('plugin_uninstall_' . $type);
 186  
 187      if ($retval === true) {
 188          $plg = array_search ($type, $_PLUGINS);
 189          if ($plg !== false) {
 190              unset ($_PLUGINS[$plg]);
 191          }
 192  
 193          return true;
 194      /**
 195      } else if ($PLG_$type['auto_uninstall'] == true)
 196  
 197          // removing tables
 198          $i = count($PLG_$type['tables']);
 199          for ($i=0; $i < count; $i++) {
 200              COM_errorLog ('Dropping table' . $_PLG_$type['tables'][$i], 1);
 201              DB_query ("DROP TABLE {$_TABLES[$_PLG_$type['tables'][$i]]}");
 202              COM_errorLog ('...success', 1);
 203          }
 204  
 205          // removing groups
 206          $i = count($PLG_$type['groups']);
 207          for ($i=0; $i < count; $i++) {
 208              $grp_id = DB_getItem ($_TABLES['groups'], 'grp_id',
 209                                    "grp_name = '{$_PLG_$type['groups'][$i]}'");
 210              if (!empty ($grp_id)) {
 211                  COM_errorLog ('Attempting to remove the {$_PLG_$type['groups'][$i]} group', 1);
 212                  DB_query ("DELETE FROM {$_TABLES['groups']} WHERE grp_id = $grp_id");
 213                  COM_errorLog ('...success', 1);
 214                  COM_errorLog ('Attempting to {$_PLG_$type['groups'][$i]} group from all groups.', 1);
 215                  DB_query("DELETE FROM {$_TABLES['group_assignments']} WHERE ug_main_grp_id = $grp_id");
 216                  COM_errorLog ('...success', 1);
 217              }
 218          }
 219  
 220          // removing features
 221          $i = count($PLG_$type['features']);
 222          for ($i=0; $i < count; $i++) {
 223              $access_id = DB_getItem ($_TABLES['features'], 'ft_id',
 224                                      "ft_name = '{$_PLG_$type['features'][$i]}'");
 225              if (!empty ($acess_id)) {
 226                  COM_errorLog ('Attempting to remove {$_PLG_$type['features'][$i]} rights from all groups' ,1);
 227                  DB_query ("DELETE FROM {$_TABLES['access']} WHERE acc_ft_id = $edit_id");
 228                  COM_errorLog ('...success', 1);
 229                  COM_errorLog ('Attempting to remove the {$_PLG_$type['features'][$i]} feature', 1);
 230                  DB_query ("DELETE FROM {$_TABLES['features']} WHERE ft_id = $edit_id");
 231                  COM_errorLog ('...success', 1);
 232              }
 233          }
 234  
 235          #uninstall feeds
 236          $sql = "SELECT filename FROM {$_TABLES['syndication']} WHERE type = '$type';";
 237          $result = DB_query( $sql );
 238          $nrows = DB_numRows( $result );
 239          if ( $nrows > 0 ) {
 240              COM_errorLog ('removing feed files', 1);
 241              COM_errorLog ($nrows. ' files stored in table.', 1);
 242              for ( $i = 0; $i < $nrows; $i++ ) {
 243                  $fcount = $i + 1;
 244                  $A = DB_fetchArray( $result );
 245                  $fullpath = SYND_getFeedPath( $A[0] );
 246                  if ( file_exists( $fullpath ) ) {
 247                      unlink ($fullpath);
 248                      COM_errorLog ("removed file $fcount of $nrows: $fullpath", 1);
 249                  } else {
 250                      COM_errorLog ("cannot remove file $fcount of $nrows, it does not exist! ($fullpath)", 1);
 251                  }
 252              }
 253              COM_errorLog ('...success', 1);
 254              // Remove Links Feeds from syndiaction table
 255              COM_errorLog ('removing links feeds from table', 1);
 256              DB_query ("DELETE FROM {$_TABLES['syndication']} WHERE `type` = '$type'");
 257              COM_errorLog ('...success', 1);
 258          }
 259  
 260          // uninstall php-blocks
 261          $i = count($PLG_$type['php_blocks']);
 262          for ($i=0; $i < count; $i++) {
 263              DB_delete ($_TABLES['blocks'], array ('type',     'phpblockfn'),
 264                                             array ('phpblock', 'phpblock_{$_PLG_$type['php_blocks'][$i]}'));
 265          }
 266  
 267          // uninstall the plugin
 268          COM_errorLog ('Attempting to unregister the $type plugin from Geeklog', 1);
 269          DB_query ("DELETE FROM {$_TABLES['plugins']} WHERE pi_name = '$type'");
 270          COM_errorLog ('...success',1);
 271  
 272          COM_errorLog ('Finished uninstalling the $type plugin.', 1);
 273      **/
 274      }
 275  
 276      return false;
 277  }
 278  
 279  /**
 280  * Inform plugin that it is either being enabled or disabled.
 281  *
 282  * @param    string      $type       Plugin name
 283  * @param    boolean     $enable     true if enabling, false if disabling
 284  * @return   boolean     Returns true on success otherwise false
 285  *
 286  */
 287  function PLG_enableStateChange ($type, $enable)
 288  {
 289     global $_CONF, $_TABLES, $_DB_table_prefix;
 290  
 291      $args[1] = $enable;
 292  
 293      // IF we are enabling the plugin
 294      // THEN we must include its functions.inc so we have access to the function
 295      if ($enable) {
 296          require_once ($_CONF['path'] . 'plugins/' . $type . '/functions.inc');
 297      }
 298  
 299      return PLG_callFunctionForOnePlugin ('plugin_enablestatechange_' . $type,
 300                                           $args);
 301  }
 302  
 303  /**
 304  * Checks to see if user is a plugin moderator
 305  *
 306  * Geeklog is asking if the user is a moderator for any installed plugins.
 307  *
 308  * @return   boolean     True if current user is moderator of plugin otherwise false
 309  *
 310  */
 311  function PLG_isModerator()
 312  {
 313      return PLG_callFunctionForAllPlugins('plugin_ismoderator_');
 314  }
 315  
 316  /**
 317  * Gives plugins a chance to print their menu items in header
 318  *
 319  * Note that this is fairly unflexible.  This simply loops through the plugins
 320  * in the database in the order they were installed and get their menu items.
 321  * If you want more flexibility in your menu then you should hard code the menu
 322  * items in header.thtml for the theme(s) you are using.
 323  *
 324  * @return   array   Returns menu options for plugin
 325  *
 326  */
 327  function PLG_getMenuItems()
 328  {
 329      global $_PLUGINS;
 330  
 331      $menu = array();
 332      foreach ($_PLUGINS as $pi_name) {
 333          $function = 'plugin_getmenuitems_' . $pi_name;
 334          if (function_exists($function)) {
 335              $menuitems = $function();
 336              if (is_array ($menuitems)) {
 337                  $menu = array_merge ($menu, $menuitems);
 338              }
 339          }
 340      }
 341  
 342      return $menu;
 343  }
 344  
 345  /**
 346   * Get view URL and name of unique identifier
 347   *
 348   * @author Vincent Furia <vinny01 AT users DOT sourceforge DOT net>
 349   * @param   string  $type   Plugin to delete comment
 350   * @return  array   string of URL of view page, name of unique identifier
 351   */
 352  function PLG_getCommentUrlId($type)
 353  {
 354      global $_CONF;
 355  
 356      $ret = PLG_callFunctionForOnePlugin('plugin_getcommenturlid_' . $type);
 357      if (empty($ret[0])) {
 358          $ret[0] = $_CONF['site_url'] . "/$type/index.php";
 359      }
 360      if (empty($ret[1])) {
 361          $ret[1] = 'id';
 362      }
 363  
 364      return $ret;
 365  }
 366  
 367  /**
 368   * Plugin should delete a comment
 369   *
 370   * @author Vincent Furia <vinny01 AT users DOT sourceforge DOT net>
 371   * @param   string  $type   Plugin to delete comment
 372   * @param   int     $cid    Comment to be deleted
 373   * @param   string  $id     Item id to which $cid belongs
 374   * @return  mixed   false for failure, HTML string (redirect?) for success
 375   */
 376  function PLG_commentDelete($type, $cid, $id)
 377  {
 378      $args[1] = $cid;
 379      $args[2] = $id;
 380  
 381      return PLG_callFunctionForOnePlugin('plugin_deletecomment_' . $type, $args);
 382  }
 383  
 384  /**
 385   * Plugin should save a comment
 386   *
 387   * @author Vincent Furia <vinny01 AT users DOT sourceforge DOT net>
 388   * @param   string  $type   Plugin to delete comment
 389   * @param   string  $title  comment title
 390   * @param   string  $comment comment text
 391   * @param   string  $id     Item id to which $cid belongs
 392   * @param   int     $pid    comment parent
 393   * @param   string  $postmode 'html' or 'text'
 394   * @return  mixed   false for failure, HTML string (redirect?) for success
 395   */
 396  function PLG_commentSave($type, $title, $comment, $id, $pid, $postmode)
 397  {
 398      $args[1] = $title;
 399      $args[2] = $comment;
 400      $args[3] = $id;
 401      $args[4] = $pid;
 402      $args[5] = $postmode;
 403  
 404      return PLG_callFunctionForOnePlugin('plugin_savecomment_' . $type, $args);
 405  }
 406  
 407  /**
 408   * Plugin should display [a] comment[s]
 409   *
 410   * @author Vincent Furia <vinny01 AT users DOT sourceforge DOT net>
 411   * @param   string  $type   Plugin to display comment
 412   * @param   string  $id     Unique idenifier for item comment belongs to
 413   * @param   int     $cid    Comment id to display (possibly including sub-comments)
 414   * @param   string  $title  Page/comment title
 415   * @param   string  $order  'ASC' or 'DSC' or blank
 416   * @param   string  $format 'threaded', 'nested', or 'flat'
 417   * @param   int     $page   Page number of comments to display
 418   * @param   boolean $view   True to view comment (by cid), false to display (by $pid)
 419   * @return  mixed   results of calling the plugin_displaycomment_ function
 420   */
 421  function PLG_displayComment($type, $id, $cid, $title, $order, $format, $page, $view)
 422  {
 423      $args[1] = $id;
 424      $args[2] = $cid;
 425      $args[3] = $title;
 426      $args[4] = $order;
 427      $args[5] = $format;
 428      $args[6] = $page;
 429      $args[7] = $view;
 430  
 431      return PLG_callFunctionForOnePlugin('plugin_displaycomment_' . $type, $args);
 432  }
 433  
 434  /**
 435  * Allows plugins a chance to handle a comment before GL does.
 436  
 437  * This is a first-come-first-serve affair so if a plugin returns an error, other
 438  * plugins wishing to handle comment preprocessing won't get called
 439  *
 440  * @author Tony Bibbs <tony@geeklog.net>
 441  * @access public
 442  * @param integer $uid User ID
 443  * @param string $title Comment title
 444  * @param string $sid Story ID (not always a story, remember!)
 445  * @param integer $pid Parent comment ID
 446  * @param string $type Type of comment
 447  * @param string $postmode HTML or text
 448  * @return an error otherwise false if no errors were encountered
 449  *
 450  */
 451  function PLG_commentPreSave($uid, &$title, &$comment, $sid, $pid, $type, &$postmode)
 452  {
 453      global $_PLUGINS;
 454  
 455      foreach ($_PLUGINS as $pi_name) {
 456          $function = 'plugin_commentPreSave_' . $pi_name;
 457          if (function_exists($function)) {
 458              $someError = $function($uid, $title, $comment, $sid, $pid, $type, $postmode);
 459              if ($someError) {
 460                  // Plugin doesn't want to save the comment
 461                  return $someError;
 462              }
 463          }
 464      }
 465  
 466      return false;
 467  }
 468  
 469  /**
 470  * Allows plugins a chance to handle an item before GL does. Modeled
 471  * after the PLG_commentPreSave() function.
 472  *
 473  * This is a first-come-first-serve affair so if a plugin returns an error, other
 474  * plugins wishing to handle comment preprocessing won't get called
 475  *
 476  * @author Mark Evans <mevans@ecsnet.com>
 477  * @access public
 478  * @param string $type Type of item, i.e.; registration, contact ...
 479  * @param string $content item specific content
 480  * @return string empty is no error, error message if error was encountered
 481  *
 482  */
 483  function PLG_itemPreSave($type, $content)
 484  {
 485      global $_PLUGINS;
 486  
 487      foreach ($_PLUGINS as $pi_name) {
 488          $function = 'plugin_itemPreSave_' . $pi_name;
 489          if (function_exists ($function)) {
 490              $msgError = $function ($type, $content);
 491              if (!empty ($msgError)) {
 492                  // Plugin doesn't want to save the item
 493                  return $msgError;
 494              }
 495          }
 496      }
 497  
 498      return '';
 499  }
 500  
 501  /**
 502  * The way this function works is very specific to how Geeklog shows its
 503  * statistics.  On stats.php, there is the top box which gives overall
 504  * statistics for Geeklog and then there are blocks below it that give
 505  * more specific statistics for various components of Geeklog.
 506  *
 507  * This plugin API function suffers from a variety of bugs and bad design
 508  * decisions for which we have to provide backward compatibility, so please
 509  * bear with us ...
 510  *
 511  * The only parameter to this function, $showsitestats, was documented as being
 512  * 1 for the site stats and 0 for the plugin-specific stats. However, the latter
 513  * was always called with a value of 2, so plugins only did a check for 1 and
 514  * "else", which makes extensions somewhat tricky.
 515  * Furthermore, due to the original templates for the site stats, it has
 516  * become standard practice to hard-code a <table> in the plugins as the return
 517  * value for $showsitestats == 1. This table, however, didn't align properly
 518  * with the built-in site stats entries.
 519  *
 520  * Because of all this, the new mode, 3, works differently:
 521  * - for $showsitestats == 3, we call a new plugin API function,
 522  *   plugin_statssummary_<plugin-name>, which is supposed to return the plugin's
 523  *   entry for the site stats in an array which stats.php will then properly
 524  *   format, alongside the entries for the built-in items.
 525  * - for $showsitestats == 1, we only call those plugins that do NOT have a
 526  *   plugin_statssummary_<plugin-name> function, thus providing backward
 527  *   compatibility
 528  * - for $showsitestats == 2, nothing has changed
 529  *
 530  * @param    int     $showsitestats      value indicating type of stats to return
 531  * @return   mixed                       array (for mode 3) or string
 532  *
 533  */
 534  function PLG_getPluginStats ($showsitestats)
 535  {
 536      global $_PLUGINS;
 537  
 538      if ($showsitestats == 3) {
 539          $retval = array ();
 540      } else {
 541          $retval = '';
 542      }
 543  
 544      foreach ($_PLUGINS as $pi_name) {
 545          if ($showsitestats == 3) {
 546              $function = 'plugin_statssummary_' . $pi_name;
 547              if (function_exists ($function)) {
 548                  $summary = $function ();
 549                  if (is_array ($summary)) {
 550                      $retval[$pi_name] = $summary;
 551                  }
 552              }
 553          } else if ($showsitestats == 1) {
 554              $function1 = 'plugin_showstats_' . $pi_name;
 555              $function2 = 'plugin_statssummary_' . $pi_name;
 556              if (!function_exists ($function2)) {
 557                  if (function_exists ($function1)) {
 558                      $retval .= $function1 ($showsitestats);
 559                  }
 560              }
 561          } else if ($showsitestats == 2) {
 562              $function = 'plugin_showstats_' . $pi_name;
 563              if (function_exists ($function)) {
 564                  $retval .= $function ($showsitestats);
 565              }
 566          }
 567      }
 568  
 569      return $retval;
 570  }
 571  
 572  /**
 573  * This function gives each plugin the opportunity to put a value(s) in
 574  * the 'Type' drop down box on the search.php page so that their plugin
 575  * can be incorporated into searches.
 576  *
 577  * @return   array   String array of search types for plugin(s)
 578  *
 579  */
 580  function PLG_getSearchTypes()
 581  {
 582      global $_PLUGINS;
 583  
 584      $types = array();
 585      $cur_types = array();
 586  
 587      foreach ($_PLUGINS as $pi_name) {
 588          $function = 'plugin_searchtypes_' . $pi_name;
 589          if (function_exists ($function)) {
 590              $cur_types = $function ();
 591              if (is_array ($cur_types) && (count ($cur_types) > 0)) {
 592                  $types = array_merge ($types, $cur_types);
 593              }
 594          } // no else because this is not a required API function
 595      }
 596      asort($types);
 597      return $types;
 598  }
 599  
 600  /**
 601  * Determines if a specific plugin supports Geeklog's
 602  * expanded search results feature
 603  *
 604  * @author Tony Bibbs <tony AT geeklog DOT net>
 605  * @access public
 606  * @param string $type Plugin name
 607  * @return boolean True if it is supported, otherwise false
 608  *
 609  * NOTE: This function is not currently used
 610  *
 611  */
 612  function PLG_supportsExpandedSearch($type)
 613  {
 614      $retval = '';
 615      $function = 'plugin_supportsexpandedsearch_' . $type;
 616      if (function_exists($function)) {
 617          $retval = $function();
 618      }
 619      if (empty($retval) OR !is_bool($retval)) {
 620          $retval = false;
 621      }
 622  
 623      return $retval;
 624  }
 625  
 626  /**
 627  * This function gives each plugin the opportunity to do their search
 628  * and return their results.  Results comeback in an array of HTML
 629  * formatted table rows that can be quickly printed by search.php
 630  *
 631  * @param    string  $query      What the user searched for
 632  * @param    date    $datestart  beginning of date range to search for
 633  * @param    date    $dateend    ending date range to search for
 634  * @param    string  $topic      the topic the user searched within
 635  * @param    string  $type       Type of items they are searching, or 'all'
 636  * @param    int     $author     UID...only return results for this person
 637  * @param    string  $keyType    search key type: 'all', 'phrase', 'any'
 638  * @param    int     $page       page number of current search
 639  * @param    int     $perpage    number of results per page
 640  * @return   array               Returns search results
 641  *
 642  */
 643  function PLG_doSearch($query, $datestart, $dateend, $topic, $type, $author, $keyType = 'all', $page = 1, $perpage = 10)
 644  {
 645      global $_PLUGINS;
 646  
 647      $search_results = array();
 648  
 649      $nrows_plugins = 0;
 650      $total_plugins = 0;
 651      foreach ($_PLUGINS as $pi_name) {
 652          $function = 'plugin_dopluginsearch_' . $pi_name;
 653          if (function_exists($function)) {
 654              $plugin_result = $function($query, $datestart, $dateend, $topic, $type, $author, $keyType, $page, $perpage);
 655              $nrows_plugins = $nrows_plugins + $plugin_result->num_searchresults;
 656              $total_plugins = $total_plugins + $plugin_result->num_itemssearched;
 657              $search_results[] = $plugin_result;
 658          } // no else because implementation of this API function not required
 659      }
 660  
 661      return array($nrows_plugins, $total_plugins, $search_results);
 662  }
 663  
 664  /**
 665  * Asks each plugin to report any submissions they may have in their
 666  * submission queue
 667  *
 668  * @return   int     Number of submissions in queue for plugins
 669  *
 670  */
 671  function PLG_getSubmissionCount()
 672  {
 673      global $_PLUGINS;
 674  
 675      $num = 0;
 676      foreach ($_PLUGINS as $pi_name) {
 677          $function = 'plugin_submissioncount_' . $pi_name;
 678          if (function_exists($function)) {
 679              $num = $num + $function();
 680          }
 681      }
 682  
 683      return $num;
 684  }
 685  
 686  /**
 687  * This function will get & check user or admin options from plugins and check
 688  * required ones for availability. This function is called by several other
 689  * functions and is not to be called from the plugin directly. The function which
 690  * call this here follow below.
 691  *
 692  * NOTE for plugin developers:
 693  * The plugin is responsible for its own security.
 694  * This supports a plugin having either a single menuitem or multiple menuitems.
 695  * The plugin has to provide an array for the menuitem of the format:
 696  * array (menuitem_title, item_url, submission_count)
 697  * or an array of arrays in case there are several entries:
 698  * array (
 699  *   array (menuitem1_title, item1_url, submission1_count),
 700  *   array (menuitem2_title, item2_url, submission2_count),
 701  *   array (menuitem3_title, item3_url, submission3_count))
 702  * Plugin function can return a single record array or multiple records
 703  *
 704  *
 705  * @param    array $var_names    An array of the variables that are retrieved.
 706  *                               This has to match the named array that is used
 707  *                               in the function returning the values
 708  * @param    array $required_names An array of true/false-values, describing
 709  *                                 which of the above listed values is required
 710  *                                 to give a valid set of data.
 711  * @param    string $function_name A string that gives the name of the function
 712  *                                 at the plugin that will return the values.
 713  * @return   array Returns options to add to the given menu that is calling this
 714  *
 715  */
 716  function PLGINT_getOptionsforMenus($var_names, $required_names, $function_name)
 717  {
 718      global $_PLUGINS;
 719  
 720      $plgresults = array ();
 721  
 722      $counter = 0;
 723      foreach ($_PLUGINS as $pi_name) {
 724          $function = $function_name . $pi_name;
 725          if (function_exists ($function)) {
 726              $plg_array = $function();
 727              if (($plg_array !== false) && (count ($plg_array) > 0)) {
 728                  // Check if plugin is returning a single record array or multiple records
 729                  $entries = count ($plg_array[0]);
 730                  if ($entries == 0) {
 731                      $sets_array = array ();
 732                  } else if ($entries == 1) {
 733                      // Single record - so we need to prepare the sets_array;
 734                      $sets_array[0] = $plg_array;
 735                  } else {
 736                      // Multiple menuitem records - in required format
 737                      $sets_array = $plg_array;
 738                  }
 739                  foreach ($sets_array as $val) {
 740                      $plugin = new Plugin();
 741                      $good_array = true;
 742                      for ($n = 0; $n < count($var_names); $n++) {
 743                          if (isset ($val[$n])) {
 744                              $plugin->$var_names[$n] = $val[$n];
 745                          } else {
 746                              $plugin->$var_names[$n] = '';
 747                          }
 748                          if (empty ($plugin->$var_names[$n]) && $required_names[$n]) {
 749                              $good_array = false;
 750                          }
 751                      }
 752                      $counter++;
 753                      if ($good_array) {
 754                          $plgresults[$counter] = $plugin;
 755                      }
 756                  }
 757              }
 758          }
 759      }
 760  
 761      return $plgresults;
 762  }
 763  
 764  /**
 765  * This function shows the option for all plugins at the top of the
 766  * command and control center.
 767  *
 768  * This supports that a plugin can have several lines in the CC menu.
 769  * The plugin has to provide simply a set arrays with 3 variables in order to
 770  * get n lines in the menu such as
 771  * array(
 772  *   array("first line", "url1", "1"),
 773  *   array("second line", "url2", "44"),
 774  *            etc, etc)
 775  * If there is only one item, a single array is enough:
 776  * array("first line", "url1", "1")
 777  *
 778  * @return   array   Returns Command and Control options for moderation.php
 779  *
 780  */
 781  function PLG_getCCOptions()
 782  {
 783      $var_names = array('adminlabel', 'adminurl', 'plugin_image');
 784      $required_names = array(true, true, true);
 785      $function_name = 'plugin_cclabel_';
 786      $plgresults = PLGINT_getOptionsforMenus($var_names, $required_names, $function_name);
 787  
 788      return $plgresults;
 789  }
 790  
 791  /**
 792  * This function will show any plugin adminstrative options in the
 793  * admin functions block on every page (assuming the user is an admin
 794  * and is logged in).
 795  *
 796  * NOTE: the plugin is responsible for its own security.
 797  * This supports that a plugin can have several lines in the Admin menu.
 798  * The plugin has to provide simply a set arrays with 3 variables in order to
 799  * get n lines in the menu such as
 800  * array(
 801  *   array("first line", "url1", "1"),
 802  *   array("second line", "url2", "44"),,
 803  *            etc, etc)
 804  * If there is only one item, a single array is enough:
 805  * array("first line", "url1", "1")
 806  *
 807  * @return   array   Returns options to put in admin menu
 808  *
 809  */
 810  function PLG_getAdminOptions()
 811  {
 812      $var_names = array('adminlabel', 'adminurl', 'numsubmissions');
 813      $required_names = array(true, true, false);
 814      $function_name = 'plugin_getadminoption_';
 815      $plgresults = PLGINT_getOptionsforMenus($var_names, $required_names, $function_name);
 816  
 817      return $plgresults;
 818  }
 819  
 820  /**
 821  * This function will show any plugin user options in the
 822  * user block on every page
 823  *
 824  * This supports that a plugin can have several lines in the User menu.
 825  * The plugin has to provide simply a set of arrays with 3 variables in order to
 826  * get n lines in the menu such as
 827  * array(
 828  *   array("first line", "url1", "1"),
 829  *   array("second line", "url2", "44"),
 830  *            etc, etc)
 831  * If there is only one item, a single array is enough:
 832  * array("first line", "url1", "1")
 833  *
 834  * NOTE: the plugin is responsible for its own security.
 835  *
 836  * @return   array   Returns options to add to user menu
 837  *
 838  */
 839  function PLG_getUserOptions()
 840  {
 841      // I know this uses the adminlabel, adminurl but who cares?
 842      $var_names = array('adminlabel', 'adminurl', 'numsubmissions');
 843      $required_names = array(true, true, false);
 844      $function_name = 'plugin_getuseroption_';
 845      $plgresults = PLGINT_getOptionsforMenus($var_names, $required_names, $function_name);
 846  
 847      return $plgresults;
 848  }
 849  
 850  /**
 851  * This function is responsible for calling
 852  * plugin_moderationapproves_<pluginname> which approves an item from the
 853  * submission queue for a plugin.
 854  *
 855  * @param        string      $type       Plugin name to do submission approval for
 856  * @param        string      $id         used to identify the record to approve
 857  * @return       boolean     Returns true on success otherwise false
 858  *
 859  */
 860  function PLG_approveSubmission($type, $id)
 861  {
 862      $args[1] = $id;
 863  
 864      return PLG_callFunctionForOnePlugin('plugin_moderationapprove_' . $type, $args);
 865  }
 866  
 867  /**
 868  * This function is responsible for calling
 869  * plugin_moderationdelete_<pluginname> which deletes an item from the
 870  * submission queue for a plugin.
 871  *
 872  * @param        string      $type       Plugin to do submission deletion for
 873  * @param        string      $id         used to identify the record for which to delete
 874  * @return       boolean     Returns true on success otherwise false
 875  *
 876  */
 877  function PLG_deleteSubmission($type, $id)
 878  {
 879      $args[1] = $id;
 880  
 881      return PLG_callFunctionForOnePlugin('plugin_moderationdelete_' . $type, $args);
 882  }
 883  
 884  /**
 885  * This function calls the plugin_savesubmission_<pluginname> to save
 886  * a user submission
 887  *
 888  * @param        string      $type       Plugin to save submission for
 889  * @param        array       $A          holds plugin specific data to save
 890  * @return       boolean     Returns true on success otherwise false
 891  *
 892  */
 893  function PLG_saveSubmission($type, $A)
 894  {
 895      $args[1] = $A;
 896  
 897      return PLG_callFunctionForOnePlugin('plugin_savesubmission_' . $type, $args);
 898  }
 899  
 900  /**
 901  * This function starts the chain of calls needed to show any submissions
 902  * needing moderation for the plugins.
 903  *
 904  * @return   string      returns list of items needing moderation for plugins
 905  *
 906  */
 907  function PLG_showModerationList()
 908  {
 909      global $_PLUGINS;
 910  
 911      $retval = '';
 912  
 913      foreach ($_PLUGINS as $pi_name) {
 914          $retval .= itemlist($pi_name);
 915      }
 916  
 917      return $retval;
 918  }
 919  
 920  /**
 921  * This function is responsible for setting the plugin-specific values
 922  * needed by moderation.php to approve stuff.
 923  *
 924  * @param        string      $type       Plugin to call function for
 925  * @return       string
 926  *
 927  */
 928  function PLG_getModerationValues($type)
 929  {
 930      return PLG_callFunctionForOnePlugin('plugin_moderationvalues_' . $type);
 931  }
 932  
 933  /**
 934  * This function is resonsible for calling plugin_submit_<pluginname> so
 935  * that the submission form for the plugin is displayed.
 936  *
 937  * @param        string      $type       Plugin to show submission form for
 938  * @return       string      HTML for submit form for plugin
 939  *
 940  */
 941  function PLG_showSubmitForm($type)
 942  {
 943      return PLG_callFunctionForOnePlugin('plugin_submit_' . $type);
 944  }
 945  
 946  /**
 947  * This function will show the centerblock for any plugin
 948  * It will be display before any news and after any defined staticpage content.
 949  * The plugin is responsible to format the output correctly.
 950  *
 951  * @param   where   int      1 = top, 2 = after feat. story, 3 = bottom of page
 952  * @param   page    int      page number (1, ...)
 953  * @param   topic   string   topic ID or empty string == front page
 954  * @return  Formatted center block content
 955  *
 956  */
 957  function PLG_showCenterblock($where = 1, $page = 1, $topic = '')
 958  {
 959      global $PLG_bufferCenterAPI, $PLG_buffered, $_PLUGINS;
 960  
 961      $retval = '';
 962  
 963      // buffer function names since we're coming back for them two more times
 964      if (!$PLG_buffered) {
 965          $PLG_bufferCenterAPI = array ();
 966          foreach ($_PLUGINS as $pi_name) {
 967              $function = 'plugin_centerblock_' . $pi_name;
 968              if (function_exists ($function)) {
 969                  $PLG_bufferCenterAPI[$pi_name] = $function;
 970              }
 971          }
 972          $PLG_buffered = true;
 973      }
 974  
 975      foreach ($PLG_bufferCenterAPI as $function) {
 976          $retval .= $function ($where, $page, $topic);
 977  
 978          if (($where == 0) && !empty ($retval)) {
 979              break;
 980          }
 981      }
 982  
 983      return $retval;
 984  }
 985  
 986  /**
 987  * This function will inform all plugins when a new user account is created.
 988  *
 989  * @param     int     $uid     user id of the new user account
 990  *
 991  */
 992  function PLG_createUser ($uid)
 993  {
 994      global $_PLUGINS;
 995  
 996      foreach ($_PLUGINS as $pi_name) {
 997          $function = 'plugin_user_create_' . $pi_name;
 998          if (function_exists ($function)) {
 999              $function ($uid);
1000          }
1001      }
1002  }
1003  
1004  /**
1005  * This function will inform all plugins when a user account is deleted.
1006  *
1007  * @param     int     $uid     user id of the deleted user account
1008  *
1009  */
1010  function PLG_deleteUser ($uid)
1011  {
1012      global $_PLUGINS;
1013  
1014      foreach ($_PLUGINS as $pi_name) {
1015          $function = 'plugin_user_delete_' . $pi_name;
1016          if (function_exists ($function)) {
1017              $function ($uid);
1018          }
1019      }
1020  }
1021  
1022  /**
1023  * This function will inform all plugins when a user logs in
1024  *
1025  * Note: This function is NOT called when users are re-authenticated by their
1026  * long-term cookie. The global variable $_USER['auto_login'] will be set to
1027  * 'true' in that case, however.
1028  *
1029  * @param     int     $uid     user id
1030  *
1031  */
1032  function PLG_loginUser ($uid)
1033  {
1034      global $_PLUGINS;
1035  
1036      foreach ($_PLUGINS as $pi_name) {
1037          $function = 'plugin_user_login_' . $pi_name;
1038          if (function_exists ($function)) {
1039              $function ($uid);
1040          }
1041      }
1042  }
1043  
1044  /**
1045  * This function will inform all plugins when a user logs out.
1046  * Plugins should not rely on this ever being called, as the user may simply
1047  * close the browser instead of logging out.
1048  *
1049  * @param     int     $uid     user id
1050  *
1051  */
1052  function PLG_logoutUser ($uid)
1053  {
1054      global $_PLUGINS;
1055  
1056      foreach ($_PLUGINS as $pi_name) {
1057          $function = 'plugin_user_logout_' . $pi_name;
1058          if (function_exists ($function)) {
1059              $function ($uid);
1060          }
1061      }
1062  }
1063  
1064  /**
1065  * This functions is called to inform plugins when a user's information
1066  * (profile or preferences) has changed.
1067  *
1068  * @param    int     $uid    User ID
1069  *
1070  */
1071  function PLG_userInfoChanged ($uid)
1072  {
1073      global $_PLUGINS;
1074  
1075      foreach ($_PLUGINS as $pi_name) {
1076          $function = 'plugin_user_changed_' . $pi_name;
1077          if (function_exists ($function)) {
1078              $function ($uid);
1079          }
1080      }
1081  }
1082  
1083  /**
1084  * This functions is called to inform plugins when a group's information has
1085  * changed or a new group has been created.
1086  *
1087  * @param    int     $grp_id     Group ID
1088  * @param    string  $mode       type of change: 'new', 'edit', or 'delete'
1089  *
1090  */
1091  function PLG_groupChanged ($grp_id, $mode)
1092  {
1093      global $_PLUGINS;
1094  
1095      foreach ($_PLUGINS as $pi_name) {
1096          $function = 'plugin_group_changed_' . $pi_name;
1097          if (function_exists ($function)) {
1098              $function ($grp_id, $mode);
1099          }
1100      }
1101  }
1102  
1103  /**
1104  * Geeklog is about to display the edit form for the user's profile. Plugins
1105  * now get a chance to add their own variables and input fields to the form.
1106  *
1107  * @param   int   $uid        user id of the user profile to be edited
1108  * @param   ref   $template   reference of the Template for the profile edit form
1109  *
1110  */
1111  function PLG_profileVariablesEdit ($uid, &$template)
1112  {
1113      global $_PLUGINS;
1114  
1115      foreach ($_PLUGINS as $pi_name) {
1116          $function = 'plugin_profilevariablesedit_' . $pi_name;
1117          if (function_exists($function)) {
1118              $function ($uid, $template);
1119          }
1120      }
1121  }
1122  
1123  /**
1124  * Geeklog is about to display the edit form for the user's profile. Plugins
1125  * now get a chance to add their own blocks below the standard form.
1126  *
1127  * @param    int      $uid   user id of the user profile to be edited
1128  * @return   string          HTML for additional block(s)
1129  *
1130  */
1131  function PLG_profileBlocksEdit ($uid)
1132  {
1133      global $_PLUGINS;
1134  
1135      $retval = '';
1136  
1137      foreach ($_PLUGINS as $pi_name) {
1138          $function = 'plugin_profileblocksedit_' . $pi_name;
1139          if (function_exists($function)) {
1140              $retval .= $function ($uid);
1141          }
1142      }
1143  
1144      return $retval;
1145  }
1146  
1147  /**
1148  * Geeklog is about to display the user's profile. Plugins now get a chance to
1149  * add their own variables to the profile.
1150  *
1151  * @param   int   $uid        user id of the user profile to be edited
1152  * @param   ref   $template   reference of the Template for the profile edit form
1153  *
1154  */
1155  function PLG_profileVariablesDisplay ($uid, &$template)
1156  {
1157      global $_PLUGINS;
1158  
1159      foreach ($_PLUGINS as $pi_name) {
1160          $function = 'plugin_profilevariablesdisplay_' . $pi_name;
1161          if (function_exists($function)) {
1162              $function ($uid, $template);
1163          }
1164      }
1165  }
1166  
1167  /**
1168  * Geeklog is about to display the user's profile. Plugins now get a chance to
1169  * add their own blocks below the standard profile form.
1170  *
1171  * @param    int      $uid        user id of the user profile to be edited
1172  * @return   string               HTML for additional block(s)
1173  *
1174  */
1175  function PLG_profileBlocksDisplay ($uid)
1176  {
1177      global $_PLUGINS;
1178  
1179      $retval = '';
1180  
1181      foreach ($_PLUGINS as $pi_name) {
1182          $function = 'plugin_profileblocksdisplay_' . $pi_name;
1183          if (function_exists($function)) {
1184              $retval .= $function ($uid);
1185          }
1186      }
1187  
1188      return $retval;
1189  }
1190  
1191  /**
1192  * The user wants to save changes to his/her profile. Any plugin that added its
1193  * own variables or blocks to the profile input form will now have to extract
1194  * its data and save it.
1195  * Plugins will have to refer to the global $_POST array to get the
1196  * actual data.
1197  *
1198  * @param   string   $plugin   name of a specific plugin or empty (all plugins)
1199  *
1200  */
1201  function PLG_profileExtrasSave ($plugin = '')
1202  {
1203      if (empty ($plugin)) {
1204          PLG_callFunctionForAllPlugins ('plugin_profileextrassave_');
1205      } else {
1206          PLG_callFunctionForOnePlugin ('plugin_profileextrassave_' . $plugin);
1207      }
1208  }
1209  
1210  /**
1211  * This function can be called to check if an plugin wants to set a template
1212  * variable
1213  * Example in COM_siteHeader, the API call is now added
1214  * A plugin can now check for templatename == 'header' and then set additional
1215  * template variables
1216  *
1217  * @param   string   $templatename     Name of calling template - used as test in plugin function
1218  * @param   ref      $template         reference for the Template
1219  *
1220  */
1221  function PLG_templateSetVars ($templatename, &$template)
1222  {
1223      global $_PLUGINS;
1224  
1225      if (function_exists ('CUSTOM_templateSetVars')) {
1226          CUSTOM_templatesetvars($templatename, $template);
1227      }
1228  
1229      foreach ($_PLUGINS as $pi_name) {
1230          $function = 'plugin_templatesetvars_' . $pi_name;
1231          if (function_exists($function)) {
1232              $function ($templatename, $template);
1233          }
1234      }
1235  }
1236  
1237  /**
1238  * This function is called from COM_siteHeader and will return additional header
1239  * information. This can be used for JavaScript functions required for the plugin
1240  * or extra Metatags
1241  *
1242  * @return   string      returns a concatenated string of all plugins extra header code
1243  */
1244  function PLG_getHeaderCode()
1245  {
1246      global $_PLUGINS;
1247  
1248      $headercode = '';
1249  
1250      foreach ($_PLUGINS as $pi_name) {
1251          $function = 'plugin_getheadercode_' . $pi_name;
1252          if (function_exists($function)) {
1253              $headercode .= $function();
1254          }
1255      }
1256  
1257      return $headercode;
1258  }
1259  
1260  /**
1261  * Get a list of all currently supported autolink tags.
1262  *
1263  * Returns an associative array where $A['tag-name'] = 'plugin-name'
1264  *
1265  * @return   array   All currently supported autolink tags
1266  *
1267  */
1268  function PLG_collectTags ()
1269  {
1270      global $_CONF, $_PLUGINS;
1271  
1272      if (isset ($_CONF['disable_autolinks']) && ($_CONF['disable_autolinks'] == 1)) {
1273          // autolinks are disabled - return an empty array
1274          return array ();
1275      }
1276  
1277      // Determine which Core Modules and Plugins support AutoLinks
1278      //                        'tag'   => 'module'
1279      $autolinkModules = array ('story' => 'geeklog');
1280  
1281      foreach ($_PLUGINS as $pi_name) {
1282          $function = 'plugin_autotags_' . $pi_name;
1283          if (function_exists ($function)) {
1284              $autotag = $function ('tagname');
1285              if (is_array ($autotag)) {
1286                  foreach ($autotag as $tag) {
1287                      $autolinkModules[$tag] = $pi_name;
1288                  }
1289              } else {
1290                  $autolinkModules[$autotag] = $pi_name;
1291              }
1292          }
1293      }
1294  
1295      return $autolinkModules;
1296  }
1297  
1298  /**
1299  * This function will allow plugins to support the use of custom autolinks
1300  * in other site content. Plugins can now use this API when saving content
1301  * and have the content checked for any autolinks before saving.
1302  * The autolink would be like:  [story:20040101093000103 here]
1303  *
1304  * @param   string   $content   Content that should be parsed for autolinks
1305  * @param   string   $plugin    Optional if you only want to parse using a specific plugin
1306  *
1307  */
1308  function PLG_replaceTags ($content, $plugin = '')
1309  {
1310      global $_CONF, $_TABLES, $LANG32;
1311  
1312      if (isset ($_CONF['disable_autolinks']) && ($_CONF['disable_autolinks'] == 1)) {
1313          // autolinks are disabled - return $content unchanged
1314          return $content;
1315      }
1316  
1317      $autolinkModules = PLG_collectTags ();
1318  
1319      // For each supported module, scan the content looking for any AutoLink tags
1320      $tags = array ();
1321      foreach ($autolinkModules as $moduletag => $module) {
1322          $autotag_prefix = '['. $moduletag . ':';
1323          $offset = 0;
1324          $prev_offset = 0;
1325          $contentlen = MBYTE_strlen ($content);
1326          while ($offset < $contentlen) {
1327              $start_pos = MBYTE_strpos (MBYTE_strtolower ($content), $autotag_prefix,
1328                                   $offset);
1329              if ($start_pos === false) {
1330                  break;
1331              } else {
1332                  $end_pos = MBYTE_strpos (MBYTE_strtolower ($content), ']', $start_pos);
1333                  $next_tag = MBYTE_strpos (MBYTE_strtolower ($content), '[', $start_pos + 1);
1334                  if (($end_pos > $start_pos) AND
1335                          (($next_tag === false) OR ($end_pos < $next_tag))) {
1336                      $taglength = $end_pos - $start_pos + 1;
1337                      $tag = MBYTE_substr ($content, $start_pos, $taglength);
1338                      $parms = explode (' ', $tag);
1339  
1340                      // Extra test to see if autotag was entered with a space
1341                      // after the module name
1342                      if (MBYTE_substr ($parms[0], -1) == ':') {
1343                          $startpos = MBYTE_strlen ($parms[0]) + MBYTE_strlen ($parms[1]) + 2;
1344                          $label = str_replace (']', '', MBYTE_substr ($tag, $startpos));
1345                          $tagid = $parms[1];
1346                      } else {
1347                          $label = str_replace (']', '',
1348                                   MBYTE_substr ($tag, MBYTE_strlen ($parms[0]) + 1));
1349                          $parms = explode (':', $parms[0]);
1350                          if (count ($parms) > 2) {
1351                              // whoops, there was a ':' in the tag id ...
1352                              array_shift ($parms);
1353                              $tagid = implode (':', $parms);
1354                          } else {
1355                              $tagid = $parms[1];
1356                          }
1357                      }
1358  
1359                      $newtag = array (
1360                          'module'    => $module,
1361                          'tag'       => $moduletag,
1362                          'tagstr'    => $tag,
1363                          'startpos'  => $start_pos,
1364                          'length'    => $taglength,
1365                          'parm1'     => str_replace (']', '', $tagid),
1366                          'parm2'     => $label
1367                      );
1368                      $tags[] = $newtag;
1369                  } else {
1370                      // Error: tags do not match - return with no changes
1371                      return $content . $LANG32[32];
1372                  }
1373                  $prev_offset = $offset;
1374                  $offset = $end_pos;
1375              }
1376          }
1377      }
1378  
1379      // If we have found 1 or more AutoLink tag
1380      if (count ($tags) > 0) {       // Found the [tag] - Now process them all
1381          foreach ($tags as $autotag) {
1382              $function = 'plugin_autotags_' . $autotag['module'];
1383              if (($autotag['module'] == 'geeklog') AND
1384                      (empty ($plugin) OR ($plugin == 'geeklog'))) {
1385                  $url = '';
1386                  $linktext = $autotag['parm2'];
1387                  if ($autotag['tag'] == 'story') {
1388                      $autotag['parm1'] = COM_applyFilter ($autotag['parm1']);
1389                      $url = COM_buildUrl ($_CONF['site_url']
1390                           . '/article.php?story=' . $autotag['parm1']);
1391                      if (empty ($linktext)) {
1392                          $linktext = stripslashes (DB_getItem ($_TABLES['stories'], 'title', "sid = '{$autotag['parm1']}'"));
1393                      }
1394                  }
1395  
1396                  if (!empty ($url)) {
1397                      $filelink = '<a href="' . $url . '">' . $linktext . '</a>';
1398                      $content = str_replace ($autotag['tagstr'], $filelink,
1399                                              $content);
1400                  }
1401              } else if (function_exists ($function) AND
1402                      (empty ($plugin) OR ($plugin == $autotag['module']))) {
1403                  $content = $function ('parse', $content, $autotag);
1404              }
1405          }
1406      }
1407  
1408      return $content;
1409  }
1410  
1411  
1412  /**
1413  * Prepare a list of all plugins that support feeds. To do this, we re-use
1414  * plugin_getfeednames_<plugin name> and only keep the names of those plugins
1415  * which support that function
1416  *
1417  * @return   array   array of plugin names (can be empty)
1418  *
1419  */
1420  function PLG_supportingFeeds ()
1421  {
1422      global $_PLUGINS;
1423  
1424      $plugins = array ();
1425  
1426      foreach ($_PLUGINS as $pi_name) {
1427          $function = 'plugin_getfeednames_' . $pi_name;
1428          if (function_exists ($function)) {
1429              $feeds = $function ();
1430              if (is_array ($feeds) && (sizeof ($feeds) > 0)) {
1431                  $plugins[] = $pi_name;
1432              }
1433          }
1434      }
1435  
1436      return $plugins;
1437  }
1438  
1439  /**
1440  * Ask the plugin for a list of feeds it supports. The plugin is expected to
1441  * return an array of id/name pairs where 'id' is the plugin's internal id
1442  * for the feed and 'name' is what will be presented to the user.
1443  *
1444  * @param    string   plugin   plugin name
1445  * @return   array             array of id/name pairs
1446  *
1447  */
1448  function PLG_getFeedNames ($plugin)
1449  {
1450      global $_PLUGINS;
1451  
1452      $feeds = array ();
1453  
1454      if (in_array ($plugin, $_PLUGINS)) {
1455          $function = 'plugin_getfeednames_' . $plugin;
1456          if (function_exists ($function)) {
1457              $feeds = $function ();
1458          }
1459      }
1460  
1461      return $feeds;
1462  }
1463  
1464  /**
1465  * Get the content of a feed from the plugin.
1466  * The plugin is expected to return an array holding the content of the feed
1467  * and to fill in 'link' (some link that represents the same content on the
1468  * site as that in the feed) and 'update_data' (to be stored for later up-to-date
1469  * checks.
1470  *
1471  * @param    string   plugin        plugin name
1472  * @param    int      feed          feed id
1473  * @param    string   link          link to content on the site
1474  * @param    string   update_data   information for later up-to-date checks
1475  * @param    string   feedType      The type of feed (RSS/Atom etc)
1476  * @param    string   feedVersion   The version info of the feed.
1477  * @return   array                  content of feed
1478  *
1479  */
1480  function PLG_getFeedContent ($plugin, $feed, &$link, &$update_data, $feedType, $feedVersion)
1481  {
1482      global $_PLUGINS;
1483  
1484      $content = array ();
1485  
1486      if (in_array ($plugin, $_PLUGINS)) {
1487          $function = 'plugin_getfeedcontent_' . $plugin;
1488          if (function_exists ($function)) {
1489              $content = $function ($feed, $link, $update_data, $feedType, $feedVersion);
1490          }
1491      }
1492  
1493      return $content;
1494  }
1495  
1496  /**
1497    * Get extension tags for a feed. For example, some plugins may extened the
1498    * available elements for an RSS 2.0 feed for articles. For some reason. This
1499    * function allows that.
1500    *
1501    * @param  string  contentType     Type of feed content, article or a plugin specific type
1502    * @param  string  contentID       Unique identifier of content item to extend
1503    * @param  string  feedType        Type of feed format (RSS/Atom/etc)
1504    * @param  string  feedVersion     Type of feed version (RSS 1.0 etc)
1505    * @param  string  topic           The topic for the feed.
1506    * @param  string  fid             The ID of the feed being fethed.
1507    */
1508  function PLG_getFeedElementExtensions($contentType, $contentID, $feedType, $feedVersion, $topic, $fid)
1509  {
1510      global $_PLUGINS;
1511  
1512      $extensions = array();
1513      foreach( $_PLUGINS as $plugin )
1514      {
1515          $function = 'plugin_feedElementExtensions_'.$plugin;
1516          if (function_exists($function))
1517          {
1518              $extensions = array_merge($extensions, $function($contentType, $contentID, $feedType, $feedVersion, $topic, $fid));
1519          }
1520      }
1521      return $extensions;
1522  }
1523  
1524  /**
1525    * Get namespaces extensions for a feed. If a plugin has added extended tags
1526    * to a feed, then it may also need to insert some extensions to the name
1527    * spaces.
1528    * @param string contentType   Type of feed content, article or a plugin specific type
1529    * @param  string  feedType        Type of feed format (RSS/Atom/etc)
1530    * @param  string  feedVersion     Type of feed version (RSS 1.0 etc)
1531    * @param  string  topic           The topic for the feed.
1532    * @param  string  fid             The ID of the feed being fethed.
1533    */
1534  function PLG_getFeedNSExtensions($contentType, $feedType, $feedVersion, $topic, $fid)
1535  {
1536      global $_PLUGINS;
1537  
1538      $namespaces = array();
1539      foreach( $_PLUGINS as $plugin )
1540      {
1541          $function = 'plugin_feedNSExtensions_'.$plugin;
1542          if (function_exists($function))
1543          {
1544              $namespaces = array_merge($namespaces, $function($contentType, $feedType, $feedVersion, $topic, $fid));
1545          }
1546      }
1547  
1548      return $namespaces;
1549  }
1550  
1551  /**
1552    * Get meta tag extensions for a feed. Add extended tags to the meta
1553    * area of a feed.
1554    * @param  string contentType      Type of feed content, article or a plugin specific type
1555    * @param  string  feedType        Type of feed format (RSS/Atom/etc)
1556    * @param  string  feedVersion     Type of feed version (RSS 1.0 etc)
1557    * @param  string  topic           The topic for the feed.
1558    * @param  string  fid             The ID of the feed being fethed.
1559    */
1560  function PLG_getFeedExtensionTags($contentType, $feedType, $feedVersion, $topic, $fid)
1561  {
1562      global $_PLUGINS;
1563  
1564      $tags = array();
1565      foreach( $_PLUGINS as $plugin )
1566      {
1567          $function = 'plugin_feedExtensionTags_'.$plugin;
1568          if (function_exists($function))
1569          {
1570              $tags = array_merge($tags, $function($contentType, $feedType, $feedVersion, $topic, $fid));
1571          }
1572      }
1573  
1574      return $tags;
1575  }
1576  
1577  /**
1578  * The plugin is expected to check if the feed content needs to be updated.
1579  * This is called from COM_rdfUpToDateCheck() every time Geeklog's index.php
1580  * is displayed - it should try to be as efficient as possible ...
1581  *
1582  * @param    string  plugin          plugin name
1583  * @param    int     feed            feed id
1584  * @param    string  topic           "topic" of the feed - plugin specific
1585  * @param    string  limit           number of entries or number of hours
1586  * @param    string  updated_type    (optional) type of feed to update
1587  * @param    string  updated_topic   (optional) topic to update
1588  * @param    string  updated_id      (optional) entry id to update
1589  * @return   bool                    false = feed has to be updated, true = ok
1590  *
1591  * @note The presence of non-empty $updated_XXX parameters indicates that an
1592  *       existing entry has been changed. The plugin may therefore apply a
1593  *       different method to check if its feed has to be updated.
1594  *
1595  */
1596  function PLG_feedUpdateCheck ($plugin, $feed, $topic, $update_data, $limit, $updated_type = '', $updated_topic = '', $updated_id = '')
1597  {
1598      global $_PLUGINS;
1599  
1600      $is_current = true;
1601  
1602      if (in_array ($plugin, $_PLUGINS)) {
1603          $function = 'plugin_feedupdatecheck_' . $plugin;
1604          if (function_exists ($function)) {
1605              $is_current = $function ($feed, $topic, $update_data, $limit,
1606                              $updated_type, $updated_topic, $updated_id);
1607          }
1608      }
1609  
1610      return $is_current;
1611  }
1612  
1613  /**
1614  * Ask plugins if they want to add something to Geeklog's What's New block.
1615  *
1616  * @return   array   array($headlines[], $bylines[], $content[$entries[]])
1617  *
1618  */
1619  function PLG_getWhatsNew ()
1620  {
1621      global $_PLUGINS;
1622  
1623      $newheadlines = array ();
1624      $newbylines   = array ();
1625      $newcontent   = array ();
1626  
1627      foreach ($_PLUGINS as $pi_name) {
1628          $fn_head = 'plugin_whatsnewsupported_' . $pi_name;
1629          if (function_exists ($fn_head)) {
1630              $supported = $fn_head ();
1631              if (is_array ($supported)) {
1632                  list ($headline, $byline) = $supported;
1633  
1634                  $fn_new = 'plugin_getwhatsnew_' . $pi_name;
1635                  if (function_exists ($fn_new)) {
1636                      $whatsnew = $fn_new ();
1637                      $newcontent[] = $whatsnew;
1638                      $newheadlines[] = $headline;
1639                      $newbylines[] = $byline;
1640                  }
1641              }
1642          }
1643      }
1644  
1645      return array ($newheadlines, $newbylines, $newcontent);
1646  }
1647  
1648  /**
1649  * Allows plugins and Core GL Components to filter out spam.
1650  *
1651  * The Spam-X Plugin is now part of the Geeklog Distribution
1652  * This plugin API will call the main function in the Spam-X plugin
1653  * but can also be used to call other plugins or custom functions
1654  * if available for filtering spam or content.
1655  *
1656  * @param    string  $content    Text to be filtered or checked for spam
1657  * @param    integer $action     what to do if spam found
1658  * @return   integer             > 0: spam detected, == 0: no spam detected
1659  *
1660  * The caller should check for return values > 0 in which case spam has been
1661  * detected and the poster should be told, either via
1662  *
1663  *   echo COM_refresh ($_CONF['site_url'] . '/index.php?msg=' . $result
1664  *                     . '&amp;plugin=spamx');
1665  *
1666  * or by
1667  *
1668  *   COM_displayMessageAndAbort ($result, 'spamx', 403, 'Forbidden');
1669  *
1670  * Where the former will only display a "spam detected" message while the latter
1671  * will also send an HTTP status code 403 with the message.
1672  *
1673  */
1674  function PLG_checkforSpam ($content, $action = -1)
1675  {
1676      global $_PLUGINS;
1677  
1678      foreach ($_PLUGINS as $pi_name) {
1679          $function = 'plugin_checkforSpam_' . $pi_name;
1680          if (function_exists ($function)) {
1681              $result = $function ($content, $action);
1682              if ($result > 0) { // Plugin found a match for spam
1683  
1684                  $result = PLG_spamAction ($content, $action);
1685  
1686                  return $result;
1687              }
1688          }
1689      }
1690  
1691      return 0;
1692  }
1693  
1694  /**
1695  * Act on spam
1696  *
1697  * This is normally called from PLG_checkforSpam (see above) automatically when
1698  * spam has been detected. There may however be situations where spam has been
1699  * detected by some other means, in which case you may want to trigger the
1700  * spam action explicitly.
1701  *
1702  * @param    string  $content    Text to be filtered or checked for spam
1703  * @param    integer $action     what to do if spam found
1704  * @return   integer             > 0: spam detected, == 0: no spam detected
1705  *
1706  */
1707  function PLG_spamAction ($content, $action = -1)
1708  {
1709      global $_PLUGINS;
1710  
1711      $result = 0;
1712  
1713      foreach ($_PLUGINS as $pi_name) {
1714          $function = 'plugin_spamaction_' . $pi_name;
1715          if (function_exists ($function)) {
1716              $res = $function ($content, $action);
1717              $result = max ($result, $res);
1718          }
1719      }
1720  
1721      return $result;
1722  }
1723  
1724  /**
1725  * Ask plugin for information about one of its items
1726  *
1727  * @param    string  $type       plugin type
1728  * @param    string  $id         ID of an item under the plugin's control
1729  * @param    string  $what       comma-separated list of item properties
1730  * @return   mixed               string or array of strings with the information
1731  *
1732  * Item properties that can be requested:
1733  * 'url'         - URL of the item
1734  * 'title'       - title of the item
1735  * 'excerpt'     - short description of the item
1736  * 'description' - full description of the item
1737  *
1738  * 'excerpt' and 'description' may return the same value. Properties should be
1739  * returned in the order they are listed in $what. Properties that are not
1740  * available should return an empty string.
1741  * Return false for errors (e.g. access denied, item does not exist, etc.).
1742  *
1743  */
1744  function PLG_getItemInfo ($type, $id, $what)
1745  {
1746      $args[1] = $id;
1747      $args[2] = $what;
1748  
1749      $function = 'plugin_getiteminfo_' . $type;
1750  
1751      return PLG_callFunctionForOnePlugin ($function, $args);
1752  }
1753  
1754  /**
1755  * Geeklog is about to perform an operation on a trackback or pingback comment
1756  * to one of the items under the plugin's control and asks for the plugin's
1757  * permission to continue.
1758  *
1759  * Geeklog handles receiving and deleting trackback comments and pingbacks
1760  * for the plugin but since it doesn't know about the plugin's access control,
1761  * it has to ask the plugin to approve / reject such an operation.
1762  *
1763  * @param    string  $type       plugin type
1764  * @param    string  $id         an ID or URL, depending on the operation
1765  * @param    string  $operation  operation to perform
1766  *
1767  * $operation can be one of the following:
1768  * 'acceptByID'  - accept a trackback comment on item with ID $id
1769  *                 returns: true for accept, false for reject
1770  * 'acceptByURI' - accept a pingback comment on item at URL $id
1771  *                 returns: the item's ID for accept, false for reject
1772  * 'delete'      - is the current user allowed to delete item with ID $id?
1773  *                 returns: true for accept, false for reject
1774  *
1775  */
1776  function PLG_handlePingComment ($type, $id, $operation)
1777  {
1778      $args[1] = $id;
1779      $args[2] = $operation;
1780  
1781      $function = 'plugin_handlepingoperation_' . $type;
1782  
1783      return PLG_callFunctionForOnePlugin ($function, $args);
1784  }
1785  
1786  
1787  /**
1788  * Check if plugins have a scheduled task they want to run
1789  * The interval between runs is determined by $_CONF['cron_schedule_interval']
1790  */
1791  function PLG_runScheduledTask ()
1792  {
1793      global $_PLUGINS;
1794  
1795      if (function_exists ('CUSTOM_runScheduledTask')) {
1796          CUSTOM_runScheduledTask();
1797      }
1798      foreach ($_PLUGINS as $pi_name) {
1799          $function = 'plugin_runScheduledTask_' . $pi_name;
1800          if (function_exists ($function)) {
1801              $function ();
1802          }
1803      }
1804  }
1805  
1806  /**
1807  * "Generic" plugin API: Save item
1808  *
1809  * To be called (eventually) whenever Geeklog saves an item into the database.
1810  * Plugins can hook into this and modify the item (which is already in the
1811  * database but not visible on the site yet).
1812  *
1813  * Plugins can signal an error by returning an error message (otherwise, they
1814  * should return 'false' to signal "no errors"). In case of an error, all the
1815  * plugins called up to that point will be invoked through an "abort" call to
1816  * undo their changes.
1817  *
1818  * @param    string  $id     unique ID of the item
1819  * @param    string  $type   type of the item, e.g. 'article'
1820  * @returns  mixed           Boolean false for "no error", or an error msg text
1821  *
1822  */
1823  function PLG_itemSaved ($id, $type)
1824  {
1825      global $_PLUGINS;
1826  
1827      $error = false;
1828  
1829      $plugins = count ($_PLUGINS);
1830      for ($save = 0; $save < $plugins; $save++) {
1831          $function = 'plugin_itemsaved_' . $_PLUGINS[$save];
1832          if (function_exists ($function)) {
1833              $error = $function ($id, $type);
1834              if ($error !== false) {
1835                  // plugin reported a problem - abort
1836  
1837                  for ($abort = 0; $abort < $save; $abort++) {
1838                      $function = 'plugin_abortsave_' . $_PLUGINS[$abort];
1839                      if (function_exists ($function)) {
1840                          $function ($id, $type);
1841                      }
1842                  }
1843                  break; // out of for($save) loop
1844              }
1845          }
1846      }
1847  
1848      return $error;
1849  }
1850  
1851  /**
1852  * Gets Geeklog blocks from plugins
1853  *
1854  * Returns data for blocks on a given side and, potentially, for
1855  * a given topic.
1856  *
1857  * @param        string      $side       Side to get blocks for (right or left for now)
1858  * @param        string      $topic      Only get blocks for this topic
1859  * @return   array of block data
1860  *
1861  */
1862  function PLG_getBlocks( $side, $topic='')
1863  {
1864      global $_PLUGINS;
1865  
1866      $ret = array();
1867      foreach ($_PLUGINS as $pi_name)
1868      {
1869          $function = 'plugin_getBlocks_' . $pi_name;
1870          if (function_exists($function))
1871          {
1872              $items = $function($side, $topic='');
1873              if (is_array ($items))
1874              {
1875                  $ret = array_merge ($ret, $items);
1876              }
1877          }
1878      }
1879  
1880      // future code to do a lib-custom function
1881      /*
1882      if (function_exists('CUSTOM_getBlocks')) {
1883         $cust_items .= CUSTOM_getBlocks($side, $topic='');
1884         if (is_array ($cust_items)) {
1885            $ret = array_merge ($ret, $cust_items)
1886         }
1887      }
1888      */
1889  
1890      return $ret;
1891  }
1892  
1893  /**
1894  * Get the URL of a plugin's icon
1895  *
1896  * @param    string  $type   plugin name
1897  * @return   string          URL of the icon
1898  *
1899  */
1900  function PLG_getIcon ($type)
1901  {
1902      global $_CONF;
1903  
1904      $retval = '';
1905  
1906      // try the "geticon" function first
1907      $function = 'plugin_geticon_' . $type;
1908      if (function_exists ($function)) {
1909          $retval = $function ();
1910      }
1911  
1912      // if that didn't work, try the "cclabel" function
1913      if (empty ($retval)) {
1914          $function = 'plugin_cclabel_' . $type;
1915          if (function_exists ($function)) {
1916              $cclabel = $function ();
1917              if (is_array ($cclabel)) {
1918                  if (!empty ($cclabel[2])) {
1919                      $retval = $cclabel[2];
1920                  }
1921              }
1922          }
1923      }
1924  
1925      // lastly, search for the icon (assuming it's a GIF)
1926      if (empty ($retval)) {
1927          $icon = $_CONF['site_url'] . '/' . $type . '/images/' . $type . '.gif';
1928          $fh = @fopen ($icon, 'r');
1929          if ($fh === false) {
1930              $icon = $_CONF['site_admin_url'] . '/plugins/' . $type . '/images/'
1931                    . $type . '.gif';
1932              $fh = @fopen ($icon, 'r');
1933              if ($fh === false) {
1934                  // give up and us a generic icon
1935                  $retval = $_CONF['site_url'] . '/images/icons/plugins.gif';
1936              } else {
1937                  $retval = $icon;
1938                  fclose ($fh);
1939              }
1940          } else {
1941              $retval = $icon;
1942              fclose ($fh);
1943          }
1944      }
1945  
1946      return $retval;
1947  }
1948  
1949  ?>


Généré le : Wed Nov 21 12:27:40 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics