b2evolution PHP Cross Reference Blogging Systems

Source: /inc/plugins/_plugin.class.php - 3335 lines - 104342 bytes - Summary - Text - Print

Description: This file implements the abstract {@link Plugin} class. This file is part of the evoCore framework - {@link http://evocore.net/} See also {@link http://sourceforge.net/projects/evocms/}.

   1  <?php
   2  /**
   3   * This file implements the abstract {@link Plugin} class.
   4   *
   5   * This file is part of the evoCore framework - {@link http://evocore.net/}
   6   * See also {@link http://sourceforge.net/projects/evocms/}.
   7   *
   8   * @copyright (c)2003-2014 by Francois Planque - {@link http://fplanque.com/}
   9   * Parts of this file are copyright (c)2004-2006 by Daniel HAHLER - {@link http://thequod.de/contact}.
  10   *
  11   * {@internal License choice
  12   * - If you have received this file as part of a package, please find the license.txt file in
  13   *   the same folder or the closest folder above for complete license terms.
  14   * - If you have received this file individually (e-g: from http://evocms.cvs.sourceforge.net/)
  15   *   then you must choose one of the following licenses before using the file:
  16   *   - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php
  17   *   - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php
  18   * }}
  19   *
  20   * {@internal Open Source relicensing agreement:
  21   * Daniel HAHLER grants Francois PLANQUE the right to license
  22   * Daniel HAHLER's contributions to this file and the b2evolution project
  23   * under any OSI approved OSS license (http://www.opensource.org/licenses/).
  24   * }}
  25   *
  26   * @package plugins
  27   *
  28   * @todo Add links to pages on b2evolution.net/man, once they are "clean"/tiny
  29   *
  30   * {@internal Below is a list of authors who have contributed to design/coding of this file: }}
  31   * @author fplanque: Francois PLANQUE - {@link http://fplanque.net/}
  32   * @author blueyed: Daniel HAHLER
  33   *
  34   * @version $Id: _plugin.class.php 6136 2014-03-08 07:59:48Z manuel $
  35   */
  36  if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );
  37  
  38  
  39  /**
  40   * Plugin Class
  41   *
  42   * Real plugins should be derived from this class.
  43   *
  44   * @abstract
  45   * @package plugins
  46   */
  47  class Plugin
  48  {
  49      /**#@+
  50       * Variables below MUST be overriden by plugin implementations,
  51       * either in the subclass declaration or in the subclass constructor.
  52       */
  53  
  54      /**
  55       * Default plugin name as it will appear in lists.
  56       *
  57       * To make it available for translation set it in the constructor by
  58       * using the {@link Plugin::T_()} function.
  59       *
  60       * This should be no longer than 50 characters.
  61       *
  62       * @var string
  63       */
  64      var $name = '';
  65  
  66      /**
  67       * Globally unique code for this plugin functionality. 32 chars. MUST BE SET.
  68       *
  69       * A common code MIGHT be shared between different plugins providing the same functionnality.
  70       * This allows to replace a given renderer with another one and keep the associations with posts.
  71       * Example: replacing a GIF smiley renderer with an SWF smiley renderer...
  72       *
  73       * @var string
  74       */
  75      var $code = '';
  76  
  77      /**
  78       * Default priority.
  79       *
  80       * Priority determines in which order the plugins get called.
  81       * Range: 1 to 100 (the lower the number, the earlier it gets called)
  82       *
  83       * @var int
  84       */
  85      var $priority = 50;
  86  
  87      /**
  88       * Plugin version number (max 42 chars, so obscure CVS Revision keywords get handled).
  89       *
  90       * This must be compatible to PHP's {@link version_compare()},
  91       * e.g. '1', '2', '1.1', '2.1b' and '10-1-1a' are fine.
  92       *
  93       * This can be used by other plugins when requiring your plugin
  94       * through {@link Plugin::GetDependencies()}.
  95       *
  96       * By increasing it you can request a call of {@link GetDbLayout()} upon instantiating.
  97       * If there are DB layout changes to be made, the plugin gets changed to status "needs_config".
  98       *
  99       * @var string
 100       */
 101      var $version = '0';
 102  
 103      /**
 104       * Plugin author.
 105       *
 106       * This is for user info only.
 107       *
 108       * @var string
 109       */
 110      var $author = 'Unknown author';
 111  
 112      /**
 113       * URL for more info about the plugin, author and new versions.
 114       *
 115       * This is for user info only.
 116       *
 117       * If empty, it defaults to 'http://b2evolution.net/man/[plugin_classname]',
 118       * where '[plugin_classname]' is the plugin's PHP class name (with first char uppercased).
 119       *
 120       * @var string
 121       */
 122      var $help_url = '';
 123  
 124      /**
 125       * Plugin short description.
 126       *
 127       * This should be no longer than a line and is limited to 255 chars.
 128       *
 129       * @var string
 130       */
 131      var $short_desc;
 132  
 133      /**#@-*/
 134  
 135  
 136      /**#@+
 137       * Variables below MAY be overriden.
 138       */
 139  
 140      /**
 141       * Plugin long description.
 142       *
 143       * This should be no longer than a line.
 144       *
 145       * @var string
 146       */
 147      var $long_desc;
 148  
 149  
 150      /**
 151       * Number of allowed installs.
 152       *
 153       * When installing the plugin it gets checked if the plugin is already installed this
 154       * many times. If so, the installation gets aborted.
 155       */
 156      var $number_of_installs;
 157  
 158  
 159      /**
 160       * Main group of the plugin.
 161       *
 162       * @var string
 163       */
 164      var $group;
 165  
 166  
 167      /**
 168       * Sub-Group of the plugin.
 169       *
 170       * @var string
 171       */
 172      var $sub_group;
 173  
 174  
 175      /**
 176       * Name of the ping service (if this is a ping plugin, see {@link Plugin::ItemSendPing()})
 177       * @var string
 178       */
 179      var $ping_service_name;
 180  
 181      /**
 182       * Note about the ping service, used in the list of ping services in the blog settings
 183       * (if this is a ping plugin, see {@link Plugin::ItemSendPing()})
 184       * @var string
 185       */
 186      var $ping_service_note;
 187  
 188      /**#@-*/
 189  
 190  
 191      /**#@+
 192       * Variables below MUST NOT be overriden or changed by you!
 193       * @access private
 194       */
 195  
 196      /**
 197       * Name of the current class. (AUTOMATIC)
 198       *
 199       * Will be set automatically (from filename) when registering the plugin.
 200       *
 201       * @var string
 202       */
 203      var $classname;
 204  
 205      /**
 206       * Internal (DB) ID. (AUTOMATIC)
 207       *
 208       * ID < 1 means 'NOT installed'
 209       *
 210       * @var int
 211       */
 212      var $ID = 0;
 213  
 214  
 215      /**
 216       * If the plugin provides settings, this will become the object to access them.
 217       *
 218       * This gets instantianted on Plugin registration for PHP4 and through
 219       * overloading in PHP5+, which means on first access.
 220       *
 221       * @see GetDefaultSettings()
 222       * @var PluginSettings
 223       */
 224      var $Settings;
 225  
 226  
 227      /**
 228       * If the plugin provides user settings, this will become the object to access them.
 229       *
 230       * This gets instantianted on Plugin registration for PHP4 and through
 231       * overloading in PHP5+, which means on first access.
 232       *
 233       * NOTE: its methods use {@link $current_User::$ID} by default, but you may call it
 234       *       if there's no {@link $current_User} instantiated (yet).
 235       *
 236       * @see GetDefaultUserSettings()
 237       * @var PluginUserSettings
 238       */
 239      var $UserSettings;
 240  
 241  
 242      /**
 243       * The status of the plugin.
 244       *
 245       * Use {@link set_status()} to change it, if you need to.
 246       * Either 'enabled', 'disabled', 'needs_config' or 'broken'.
 247       *
 248       * @var string
 249       */
 250      var $status;
 251  
 252      /**
 253       * The translations keyed by locale. They get loaded through include() of _global.php.
 254       * @see Plugin::T_()
 255       * @var array
 256       */
 257      var $_trans = array();
 258  
 259      /**
 260       * Has the global /locales/_global.php file (where translation for
 261       * all languages can be put into) been loaded?
 262       *
 263       * @var boolean
 264       */
 265      var $_trans_loaded_global = false;
 266  
 267      /**
 268       * Plugin URL
 269       * This gets lazy-filled with both 'abs' and 'rel' URLs by {@link get_plugin_url()}.
 270       *
 271       * @var array
 272       */
 273      private $_plugin_url = array();
 274  
 275      /**#@-*/
 276  
 277  
 278      /**
 279       * Constructor.
 280       *
 281       * You should not use a constructor with your plugin, but the
 282       * {@link Plugin::PluginInit()} method instead!
 283       */
 284  	function Plugin()
 285      {
 286      }
 287  
 288  
 289      /**
 290       * Init the Plugin after it has been registered/instantiated.
 291       *
 292       * Should set name and description in a localizable fashion.
 293       *
 294       * This gets called on every instantiated plugin, also if it's just for
 295       * discovering the list of available plugins in the backoffice.
 296       *
 297       * Use this to validate Settings/requirements and/or cache them into class properties.
 298       *
 299       * @param array Associative array of parameters.
 300       *              'is_installed': true, if the plugin is installed; false if not (probably it got discovered then)
 301       *              'db_row': an array with the columns of the plugin DB entry (in T_plugins).
 302       *                        This is empty, if the plugin is not installed!
 303       *                        E.g., 'plug_version' might be interesting to compare again "$this->version".
 304       * @return boolean If this method returns false, the Plugin gets unregistered (for the current request only).
 305       */
 306  	function PluginInit( & $params )
 307      {
 308          // NOTE: the code below is just to handle stuff that has been deprecated since
 309          //       b2evolution 1.9. You don't have to include this, if you override this method.
 310  
 311          if( is_null($this->short_desc) )
 312          { // may have been set in plugin's constructor (which is deprecated since 1.9)
 313              $this->short_desc = T_('No desc available');
 314          }
 315          if( is_null($this->long_desc) )
 316          { // may have been set in plugin's constructor (which is deprecated since 1.9)
 317              $this->long_desc = T_('No description available');
 318          }
 319  
 320          if( method_exists( $this, 'AppendPluginRegister' ) && $params['is_installed'] )
 321          { // Wrapper for deprecated AppendPluginRegister method (deprecated since 1.9)
 322              $this->debug_log('Plugin has deprecated AppendPluginRegister method. Use PluginInit instead.', array('deprecated'));
 323  
 324              return $this->AppendPluginRegister($params);
 325          }
 326  
 327          return true;
 328      }
 329  
 330  
 331      // Plugin information (settings, DB layout, ..): {{{
 332  
 333      /**
 334       * Define default settings here.
 335       * Those can then be edited in the backoffice.
 336       *
 337       * You can access them in the plugin through the member object
 338       * {@link Plugin::$Settings}, e.g.:
 339       * <code>$this->Settings->get( 'my_param' );</code>
 340       *
 341       * fp> this is unclear: You probably don't need to set or change values (other than the
 342       * defaultvalues), but if you know what you're doing, see
 343       * {@link PluginSettings}, where {@link Plugin::$Settings} gets derived from.
 344       *
 345       * NOTE: this method gets called by b2evo when instantiating the plugin
 346       *       settings and when the settings get displayed for editing in the backoffice.
 347       *       In the second case, $params['for_editing'] will be true.
 348       *
 349       * @todo 3.0 fp> 1) This is not an event: RENAME to lowercase (in b2evo 3.0)
 350       *           dh> Not only events are CamelCase, but "interactions" with the Plugins(_admin) class, too!
 351       *               Maybe it should get prefixed with "Plugin"?!
 352       *               The intention is: all interfacing methods are camel-cased. That makes a lot of sense,
 353       *               given the provided helpers (get_plugin_url etc).
 354       *               This applies to the other todos below, too.
 355       * @todo 3.0 fp> 2) This defines more than Default values ::  confusing name
 356       * @todo name tentative get_general_param_definitions()
 357       *
 358       * @param array Associative array of parameters (since 1.9).
 359       *    'for_editing': true, if the settings get queried for editing;
 360       *                   false, if they get queried for instantiating {@link Plugin::$Settings}.
 361       * @return array
 362       * The array to be returned should define the names of the settings as keys (max length is 30 chars)
 363       * and assign an array with the following keys to them (only 'label' is required):
 364       *
 365       * 'label': Name/Title of the param, gets displayed as label for the input field, or
 366       *              as "legend" tag with types "array" and "fieldset".
 367       * 'defaultvalue': Default value for the setting, defaults to '' (empty string)
 368       * 'type', which can be:
 369       *     'text' (default): a simple string
 370       *     'password': like text, but hidden during input
 371       *     'html_input' : like text, but allows html
 372       *     'checkbox': either 0 or 1
 373       *     'integer': a number (no float, can have leading "+" or "-") (like 'text' for input, but gets validated when submitting)
 374       *     'float': a floating number (can have leading "+" or "-", e.g. "+1", "-0.05") (like 'text' for input, but gets validated when submitting)
 375       *     'textarea': several lines of input. The following can be set for this type:
 376       *         'rows': number of rows
 377       *         'cols': number of columns
 378       *     'html_textarea': like textarea, but allows html
 379       *     'select': a drop down field; you must set 'options' for it:
 380       *         'options': an array of options ('value' => 'description'), see {@link Form::select_input_array()}.
 381       *     'select_blog': a drop down field, providing all existing blogs (Blog ID is the value or "" if "allow_none" is true) (WARNING: does not scale - not recommended)
 382       *     'select_group': a drop down field, providing all existing groups (Group ID is the value or "" if "allow_none" is true)
 383       *     'select_user': a drop down field, providing all existing groups (User ID is the value or "" if "allow_none" is true) (WARNING: does not scale - not recommended)
 384       *     'array': a subset of settings. The value gets automagically (un)serialized through get() and set().
 385       *         The following keys apply to this type:
 386       *        'entries': an array with meta information about sub-settings
 387       *             (which can be everything from the top-level, except: "valid_pattern", "valid_range").
 388       *             Note: currently there's no type forcing or checking
 389       *                 for sub-entries involved (e.g., if you have an entry of type "integer", you could get
 390       *                 a non-numeric string there).
 391       *         fp> TODO: !!!! very unsafe
 392       *        'key': defines the key to use for each entry. This may be a text input for example
 393       *              (with label, note etc). (optional, default is numeric keys, which are not editable)
 394       *       'max_count': maximum count of sets (optional, default is no restriction)
 395       *       'min_count': minimum count of sets (optional, default is no restriction)
 396       * 'note' (gets displayed as a note to the param field),
 397       * 'size': Size of the HTML input field (applies to types 'text', 'password' and 'integer'; defaults to 15)
 398       * 'maxlength': maxlength attribute for the input field (See 'size' above; defaults to no limit)
 399       * 'disabled': if true, it adds a 'disabled="disabled"' html attribute to the element and the value cannot be changed
 400       * 'no_edit': if true, the setting is not editable. This is useful for internal settings.
 401       * 'allow_none': set this to true to have "None" in the options list for types 'select_group' and 'select_user'.
 402       * 'valid_pattern': A regular expression pattern that the value must match.
 403       *                      This is either just a regexp pattern as string or an array
 404       *                      with the keys 'pattern' and 'error' to define a custom error message.
 405       * 'valid_range': An array with keys 'min', 'max' and (optionally) 'error' to define
 406       *                    a custom error message. At least "min" or "max" must be given.
 407       * 'help': can be:
 408       *          '#anchor': anchor that gets appended to {@link $help_url}
 409       *          true: the settings name/key gets transformed to an html ID and gets used as anchor to {@link $help_url}.
 410       *          'http://example.com/uri': a full URL (starting with http:// or https://)
 411       * 'layout': Use this to visually group your settings.
 412       *               Either 'begin_fieldset', 'end_fieldset' or 'separator'. You can use 'label' for 'begin_fieldset'.
 413       * 'multiple': This allows to select multiple values in a SELECT (including select_*) (boolean)
 414       * 'id', 'onchange', 'onclick', 'onfocus', 'onkeyup', 'onkeydown', 'onreset', 'onselect', 'cols', 'rows', 'maxlength':
 415       *       get passed through as attributes to the form/input element.
 416       *
 417       * e.g.:
 418       * <code>
 419       * return array(
 420       *   'my_param' => array(
 421       *     'label' => $this->T_('My Param'),
 422       *     'defaultvalue' => '10',
 423       *     'note' => $this->T_('Quite cool, eh?'),
 424       *     'valid_pattern' => array( 'pattern' => '[1-9]\d+', $this->T_('The value must be >= 10.') ),
 425       *   ),
 426       *   'another_param' => array( // this one has no 'note'
 427       *     'label' => $this->T_('My checkbox'),
 428       *     'defaultvalue' => '1',
 429       *     'type' => 'checkbox',
 430       *   ),
 431       *   array( 'layout' => 'separator' ),
 432       *   'my_select' => array(
 433       *     'label' => $this->T_('Selector'),
 434       *     'defaultvalue' => 'one',
 435       *     'type' => 'select',
 436       *     'options' => array( 'sun' => $this->T_('Sunday'), 'mon' => $this->T_('Monday') ),
 437       *   ) );
 438       * </code>
 439       *
 440       */
 441  	function GetDefaultSettings( & $params )
 442      {
 443          return array();
 444      }
 445  
 446  
 447      /**
 448       * Define here default user settings that are then available in the backoffice.
 449       *
 450       * You can access them in the plugin through the member object
 451       * {@link $UserSettings}, e.g.:
 452       * <code>$this->UserSettings->get( 'my_param' );</code>
 453       *
 454       * This method behaves exactly like {@link Plugin::GetDefaultSettings()},
 455       * except that it defines user specific settings instead of global settings.
 456       *
 457       * @todo 3.0 fp> 1) This is not an event: RENAME to lowercase (in b2evo 3.0)
 458       * @todo 3.0 fp> 2) This defines more than Default values ::  confusing name
 459       * @todo name tentative get_user_param_definitions()
 460       *
 461       * @see Plugin::GetDefaultSettings()
 462       * @param array Associative array of parameters.
 463       *    'for_editing': true, if the settings get queried for editing;
 464       *                   false, if they get queried for instantiating {@link Plugin::$UserSettings}.
 465       * @return array See {@link Plugin::GetDefaultSettings()}.
 466       */
 467  	function GetDefaultUserSettings( & $params )
 468      {
 469          return array();
 470      }
 471  
 472  
 473      /**
 474       * Define here default collection/blog settings that are to be made available in the backoffice.
 475       *
 476       * @see Plugin::GetDefaultSettings()
 477       * @param array Associative array of parameters.
 478       *    'for_editing': true, if the settings get queried for editing;
 479       *                   false, if they get queried for instantiating {@link Plugin::$UserSettings}.
 480       * @return array See {@link Plugin::GetDefaultSettings()}.
 481       */
 482  	function get_coll_setting_definitions( & $params )
 483      {
 484          if( $this->group != 'rendering' )
 485          {
 486              return array();
 487          }
 488  
 489          $render_note = get_manual_link('Plugin/apply_rendering');
 490          if( empty( $this->code ) )
 491          {
 492              $render_note .= ' '.T_('Note: The plugin code is empty, so this plugin will not work as an "opt-out", "opt-in" or "lazy" renderer.');
 493          }
 494          $admin_Plugins = & get_Plugins_admin();
 495          $rendering_options = $admin_Plugins->get_apply_rendering_values( true );
 496          $default_post_rendering = ( isset( $params['default_post_rendering'] ) && in_array( $params['default_post_rendering'], $rendering_options ) ) ? $params['default_post_rendering'] : 'opt-out';
 497          $default_comment_rendering = ( isset( $params['default_comment_rendering'] ) && in_array( $params['default_comment_rendering'], $rendering_options ) ) ? $params['default_comment_rendering'] : 'never';
 498          $r = array(
 499              'coll_apply_rendering' => array(
 500                      'label' => T_('Apply rendering to posts'),
 501                      'type' => 'select',
 502                      'options' => $rendering_options,
 503                      'defaultvalue' => $default_post_rendering,
 504                      'note' => $render_note,
 505                  ),
 506              'coll_apply_comment_rendering' => array(
 507                      'label' => T_('Apply rendering to comments'),
 508                      'type' => 'select',
 509                      'options' => $rendering_options,
 510                      'defaultvalue' => $default_comment_rendering,
 511                      'note' => $render_note,
 512                  ),
 513              );
 514  
 515          return $r;
 516      }
 517  
 518  
 519    /**
 520     * Get definitions for widget specific editable params
 521     *
 522       * @see Plugin::GetDefaultSettings()
 523       * @param array Local params like 'for_editing' => true
 524       */
 525  	function get_widget_param_definitions( $params )
 526      {
 527          return array();
 528      }
 529  
 530  
 531      /**
 532       * Get the list of dependencies that the plugin has.
 533       *
 534       * This gets checked on install or uninstall of a plugin.
 535       *
 536       * There are two <b>classes</b> of dependencies:
 537       *  - 'recommends': This is just a recommendation. If it cannot get fulfilled
 538       *                  there will just be a note added on install.
 539       *  - 'requires': A plugin cannot be installed if the dependencies cannot get
 540       *                fulfilled. Also, a plugin cannot get uninstalled, if another
 541       *                plugin depends on it.
 542       *
 543       * Each <b>class</b> of dependency can have the following types:
 544       *  - 'events_by_one': A list of eventlists that have to be provided by a single plugin,
 545       *                     e.g., <code>array( array('CaptchaPayload', 'CaptchaValidated') )</code>
 546       *                     to look for a plugin that provides both events.
 547       *  - 'plugins':
 548       *    A list of plugins, either just the plugin's classname or an array with
 549       *    classname and minimum version of the plugin (see {@link Plugin::$version}).
 550       *    E.g.: <code>array( 'test_plugin', '1' )</code> to require at least version "1"
 551       *          of the test plugin.
 552       *  - 'app_min': Minimum application (b2evo) version, e.g. "1.9".
 553       *               This way you can make sure that the hooks you need are implemented
 554       *               in the core.
 555       *               (Available since b2evo 1.8.3. To make it work before 1.8.2 use
 556       *               "api_min" and check for array(1, 2) (API version of 1.9)).
 557       *  - 'api_min': You can require a specific minimum version of the Plugins API here.
 558       *               If it's just a number, only the major version is checked against.
 559       *               To check also for the minor version, you have to give an array:
 560       *               array( major, minor ).
 561       *               Obsolete since 1.9! Used API versions: 1.1 (b2evo 1.8.1) and 1.2 (b2evo 1.9).
 562       *
 563       * @see test_plugin::GetDependencies()
 564       * @return array
 565       */
 566  	function GetDependencies()
 567      {
 568          return array(); // no dependencies by default, of course
 569      }
 570  
 571  
 572      /**
 573       * This method should return your DB schema, consisting of a list of CREATE TABLE
 574       * queries.
 575       *
 576       * The DB gets changed accordingly on installing or enabling your Plugin.
 577       *
 578       * If you want to change your DB layout in a new version of your Plugin, simply
 579       * adjust the queries here and increase {@link Plugin::$version}, because this will
 580       * request to check the current DB layout against the one you require.
 581       *
 582       * For restrictions see {@link db_delta()}.
 583       */
 584  	function GetDbLayout()
 585      {
 586          return array();
 587      }
 588  
 589  
 590      /**
 591       * This method gets asked when plugins get installed and allows you to return a list
 592       * of extra events, which your plugin triggers itself (e.g. through
 593       * {@link $Plugins->trigger_event()}).
 594       *
 595       * NOTE: PLEASE use a distinct prefix for the event name, e.g. "$this->classname".
 596       *
 597       * NOTE: The length of event names is limited to 40 chars.
 598       *
 599       * NOTE: Please comment the params and the return value here with the list
 600       *       that you return. Only informal as comment, but makes it easier for
 601       *       others.
 602       *
 603       * @see test_plugin::GetExtraEvents()
 604       * @return NULL|array "event_name" => "description"
 605       */
 606  	function GetExtraEvents()
 607      {
 608      }
 609  
 610  
 611      /**
 612       * Override this method to define methods/functions that you want to make accessible
 613       * through /htsrv/call_plugin.php, which allows you to call those methods by HTTP request.
 614       *
 615       * This is useful for things like AJAX or displaying an IFRAME element, where the content
 616       * should get provided by the plugin itself.
 617       *
 618       * E.g., the image captcha plugin uses this method to serve a generated image.
 619       *
 620       * NOTE: the Plugin's method must be prefixed with "htsrv_", but in this list (and the URL) it
 621       *       is not. E.g., to have a method "disp_image" that should be callable through this method
 622       *       return <code>array('disp_image')</code> here and implement it as
 623       *       <code>function htsrv_disp_image( $params )</code> in your plugin.
 624       *       This is used to distinguish those methods from others, but keep URLs nice.
 625       *
 626       * @see get_htsrv_url()
 627       * @return array
 628       */
 629  	function GetHtsrvMethods()
 630      {
 631          return array();
 632      }
 633  
 634  
 635      /**
 636       * This method gets asked for a list of cronjobs that the plugin
 637       * provides.
 638       * If a user installs a cron job out of this list, the
 639       * {@link Plugin::ExecCronJob()} of the plugin gets called.
 640       *
 641       * @return array Array of arrays with keys "name", "ctrl" and "params".
 642       *               "name" gets used for display. "ctrl" (string) and
 643       *               "params" (array) get passed to the
 644       *               {@link Plugin::ExecCronJob()} method when the cronjob
 645       *               gets executed.
 646       */
 647  	function GetCronJobs( & $params )
 648      {
 649          return array();
 650      }
 651  
 652  
 653      /**
 654       * Execute/handle a cron job, which has been scheduled by the admin out
 655       * of the list that the Plugin provides (see {@link GetCronJobs()}).
 656       *
 657       * @param array Associative array of parameters
 658       *   - 'ctrl': The "ctrl" name as defined in {@link GetCronJobs()}
 659       *   - 'params': The "params" value as defined in {@link GetCronJobs()},
 660       *               plus "ctsk_ID" which holds the cron task ID.
 661       * @return array with keys "code" (integer, 1 is ok), "message" (gets logged)
 662       */
 663  	function ExecCronJob( & $params )
 664      {
 665      }
 666  
 667      // }}}
 668  
 669  
 670      /*
 671       * Event handlers. These are meant to be implemented by your plugin. {{{
 672       */
 673  
 674      // Admin/backoffice events (without events specific to Items or Comments): {{{
 675  
 676  
 677      /**
 678       * Event handler: Gets invoked in /toolbar.inc.php after the menu structure is built.
 679       */
 680  	function AdminAfterEvobarInit()
 681      {
 682      }
 683  
 684  
 685      /**
 686       * Event handler: Gets invoked in /admin.php for every backoffice page after
 687       *                the menu structure is built. You could use the {@link $AdminUI} object
 688       *                to modify it.
 689       *
 690       * This is the hook to register menu entries. See {@link register_menu_entry()}.
 691       */
 692  	function AdminAfterMenuInit()
 693      {
 694          // Example:
 695          $this->register_menu_entry( $this->T_('My Tab') );
 696      }
 697  
 698  
 699      /**
 700       * Event handler: Called when ending the admin html head section.
 701       *
 702       * @param array Associative array of parameters
 703       * @return boolean did we do something?
 704       */
 705  	function AdminEndHtmlHead( & $params )
 706      {
 707          return false;        // Do nothing by default.
 708      }
 709  
 710  
 711      /**
 712       * Event handler: Called right after displaying the admin page footer.
 713       *
 714       * @param array Associative array of parameters
 715       * @return boolean did we do something?
 716       */
 717  	function AdminAfterPageFooter( & $params )
 718      {
 719          return false;        // Do nothing by default.
 720      }
 721  
 722  
 723      /**
 724       * Event handler: Called when displaying editor buttons (in back-office).
 725       *
 726       * This method, if implemented, should output the buttons
 727       * (probably as html INPUT elements) and return true, if
 728       * button(s) have been displayed.
 729       *
 730       * You should provide an unique html ID with your button.
 731       *
 732       * @param array Associative array of parameters.
 733       *   - 'target_type': either 'Comment' or 'Item'.
 734       *   - 'edit_layout': "simple", "expert", etc. (users, hackers, plugins, etc. may create their own layouts in addition to these)
 735       *                    NOTE: Please respect the "simple" mode, which should display only the most simple things!
 736       * @return boolean did we display a button?
 737       */
 738  	function AdminDisplayEditorButton( $params )
 739      {
 740          if( $params['edit_layout'] == 'simple' )
 741          { // Do nothing in simple mode
 742              return false;
 743          }
 744  
 745          return false;        // Do nothing by default.
 746      }
 747  
 748  
 749      /**
 750       * Event handler: Called when displaying editor buttons (in front-office).
 751       *
 752       * This method, if implemented, should output the buttons
 753       * (probably as html INPUT elements) and return true, if
 754       * button(s) have been displayed.
 755       *
 756       * You should provide an unique html ID with your button.
 757       *
 758       * @param array Associative array of parameters.
 759       *   - 'target_type': either 'Comment' or 'Item'.
 760       *   - 'edit_layout': "simple", "expert", etc. (users, hackers, plugins, etc. may create their own layouts in addition to these)
 761       *                    NOTE: Please respect the "simple" mode, which should display only the most simple things!
 762       * @return boolean did we display a button?
 763       */
 764  	function DisplayEditorButton( $params )
 765      {
 766          return false;        // Do nothing by default.
 767      }
 768  
 769  
 770      /**
 771       * Event handler: Called when displaying editor toolbars.
 772       *
 773       * @param array Associative array of parameters
 774       *   - 'target_type': either 'Comment' or 'Item'.
 775       *   - 'edit_layout': "simple", "expert", etc. (users, hackers, plugins, etc. may create their own layouts in addition to these)
 776       *                    NOTE: Please respect the "simple" mode, which should display only the most simple things!
 777       * @return boolean did we display a toolbar?
 778       */
 779  	function AdminDisplayToolbar( & $params )
 780      {
 781          return false;        // Do nothing by default.
 782      }
 783  
 784  
 785      /**
 786       * Event handler: Called when handling actions for the "Tools" menu.
 787       *
 788       * Use {@link msg()} to add messages for the user.
 789       */
 790  	function AdminToolAction()
 791      {
 792      }
 793  
 794  
 795      /**
 796       * Event handler: Called when displaying the block in the "Tools" menu.
 797       *
 798       * @return boolean did we display something?
 799       */
 800  	function AdminToolPayload()
 801      {
 802          return false;        // Do nothing by default.
 803      }
 804  
 805  
 806      /**
 807       * Event handler: Method that gets invoked when our tab is selected.
 808       *
 809       * You should catch (your own) params (using {@link param()}) here and do actions
 810       * (but no output!).
 811       *
 812       * Use {@link msg()} to add messages for the user.
 813       */
 814  	function AdminTabAction()
 815      {
 816      }
 817  
 818  
 819      /**
 820       * Event handler: Gets invoked when our tab is selected and should get displayed.
 821       *
 822       * Do your output here.
 823       *
 824       * @return boolean did we display something?
 825       */
 826  	function AdminTabPayload()
 827      {
 828          return false;        // Do nothing by default.
 829      }
 830  
 831  
 832      /**
 833       * Event handler: Gets invoked before the main payload in the backoffice.
 834       */
 835  	function AdminBeginPayload()
 836      {
 837      }
 838  
 839      // }}}
 840  
 841  
 842      // Skin/Blog events: {{{
 843  
 844      /**
 845       * Event handler: Called before a blog gets displayed (in _blog_main.inc.php).
 846       */
 847  	function BeforeBlogDisplay( & $params )
 848      {
 849      }
 850  
 851  
 852      /**
 853       * Event handler: Called when a MainList object gets created.
 854       *
 855       * Note: you must create your own MainList object here, set filters and query the database, see init_MainList() for detailes.
 856       *
 857       * @param array Associative array of parameters
 858       *   - 'MainList': The "MainList" object (by reference).
 859       *   - 'limit': The number of posts to display
 860       *
 861       * @return boolean True if you've created your own MainList object and queried the database, false otherwise.
 862       */
 863  	function InitMainList( & $params )
 864      {
 865          // Do nothing by default:
 866          return false;
 867      }
 868  
 869  
 870      /**
 871       * Event handler: Called at the beginning of the skin's HTML HEAD section.
 872       *
 873       * Use this to add any HTML HEAD lines (like CSS styles or links to resource
 874       * files (CSS, JavaScript, ..)).
 875       */
 876  	function SkinBeginHtmlHead( & $params )
 877      {
 878      }
 879  
 880  
 881      /**
 882       * Event handler: Called at the end of the skin's HTML BODY section.
 883       *
 884       * Use this to add any HTML snippet at the end of the generated page.
 885       */
 886  	function SkinEndHtmlBody( & $params )
 887      {
 888      }
 889  
 890      /**
 891       * Called when a plugin gets called by its {@link $code}.
 892       *
 893       * If you provide this event, b2evolution will assume your plugin
 894       * provides a widget and list it in the "Available widgets" list.
 895       *
 896       * @see $code
 897       * @see Plugins::call_by_code()
 898       * @param array The array passed to {@link Plugins::call_by_code()}.
 899       */
 900  	function SkinTag( & $params )
 901      {
 902      }
 903  
 904      /**
 905       * Event handler: Gets asked about a list of skin names that the plugin handles.
 906       *
 907       * If one of the skins returned gets called through the "skin=X" URL param, the
 908       * {@link Plugin::DisplaySkin()} method of your plugin gets called.
 909       *
 910       * @return array
 911       */
 912  	function GetProvidedSkins()
 913      {
 914          return array();
 915      }
 916  
 917  
 918      /**
 919       * Event handler: Display a skin. Use {@link Plugin::GetProvidedSkins()} to return
 920       * a list of names that you register.
 921       *
 922       * @param array Associative array of parameters
 923       *   - 'skin': name of skin to be displayed (from the list of {@link Plugin::GetProvidedSkins()}).
 924       *             If your Plugin only registers one skin, you can ignore it.
 925       */
 926  	function DisplaySkin( & $params )
 927      {
 928      }
 929  
 930      // }}}
 931  
 932  
 933      // (Un)Install / (De)Activate events: {{{
 934  
 935      /**
 936       * Event handler: Called before the plugin is going to be installed.
 937       *
 938       * This is the hook to create any DB tables or the like.
 939       *
 940       * If you just want to add a note, use {@link Plugin::msg()} (and return true).
 941       *
 942       * @return true|string True, if the plugin can be enabled/activated,
 943       *                     a string with an error/note otherwise.
 944       */
 945  	function BeforeInstall()
 946      {
 947          return true;  // default is to allow Installation
 948      }
 949  
 950  
 951      /**
 952       * Event handler: Called after the plugin has been installed.
 953       */
 954  	function AfterInstall()
 955      {
 956      }
 957  
 958  
 959      /**
 960       * Event handler: Called before the plugin is going to be un-installed.
 961       *
 962       * This is the hook to remove any files or the like - tables with canonical names
 963       * (see {@link Plugin::get_sql_table()}, are handled internally.
 964       *
 965       * See {@link BeforeUninstallPayload()} for the corresponding payload handler, which you
 966       * can request to invoke by returning NULL here.
 967       *
 968       * Note: this method gets called again, if the uninstallation has to be confirmed,
 969       *       either because you've requested a call to {@link BeforeUninstallPayload()}
 970       *       or there are tables to be dropped (what the admin user has to confirm).
 971       *
 972       * @param array Associative array of parameters.
 973       *              'unattended': true if Uninstall is unattended (e.g., the /install action "deletedb" uses it).
 974       *                            This should cleanup everything without confirmation!
 975       * @return boolean|NULL
 976       *         true when it's ok to uninstall,
 977       *         false on failure (the plugin won't get uninstalled then).
 978       *               You should add the reason for it through {@link Plugin::msg()}.
 979       *         NULL requests to execute the {@link BeforeUninstallPayload()} method.
 980       */
 981  	function BeforeUninstall( & $params )
 982      {
 983          return true;
 984      }
 985  
 986  
 987      /**
 988       * Event handler: Gets invoked to display the payload before uninstalling the plugin.
 989       *
 990       * You have to request a call to this during the plugin uninstall procedure by
 991       * returning NULL in {@link BeforeUninstall()}.
 992       *
 993       * @param array Associative array of parameters.
 994       *              'Form': The {@link Form} that asks the user for confirmation (by reference).
 995       *                      If your plugin uses canonical table names (see {@link Plugin::get_sql_table()}),
 996       *                      there will be already a list of those tables included in it.
 997       *                      Do not end the form, just add own inputs or hidden keys to it.
 998       */
 999  	function BeforeUninstallPayload( & $params )
1000      {
1001      }
1002  
1003  
1004      /**
1005       * Event handler: Called when the admin tries to enable the plugin, changes
1006       * its configuration/settings and after installation.
1007       *
1008       * Use this, if your plugin needs configuration before it can be used.
1009       *
1010       * @return true|string True, if the plugin can be enabled/activated,
1011       *                     a string with an error/note otherwise.
1012       */
1013  	function BeforeEnable()
1014      {
1015          return true;  // default is to allow Activation
1016      }
1017  
1018  
1019      /**
1020       * Event handler: Your plugin gets notified here, just before it gets
1021       * disabled.
1022       *
1023       * You cannot prevent this, but only clean up stuff, if you have to.
1024       */
1025  	function BeforeDisable()
1026      {
1027      }
1028  
1029  
1030      /*
1031       * NOTE: function AppendPluginRegister( & $params ) is deprecated since 1.9.
1032       * Use Plugin::PluginInit() instead.
1033       */
1034  
1035  
1036      /**
1037       * Event handler: Called when we detect a version change (in {@link Plugins::register()}).
1038       *
1039       * Use this for your upgrade needs.
1040       *
1041       * @param array Associative array of parameters.
1042       *              'old_version': The old version of your plugin as stored in DB.
1043       *              'db_row': an array with the columns of the plugin DB entry (in T_plugins).
1044       *                        The key 'plug_version' is the same as the 'old_version' key.
1045       * @return boolean If this method returns false, the Plugin's status gets changed to "needs_config" and
1046       *                 it gets unregistered for the current request.
1047       */
1048  	function PluginVersionChanged( & $params )
1049      {
1050          return true;
1051      }
1052  
1053      // }}}
1054  
1055  
1056      // Blog events: {{{
1057  
1058      /**
1059       * Event handler: called at the end of {@link Blog::dbinsert() inserting
1060       * a blog into the database}, which means it has been created.
1061       *
1062       * @param array Associative array of parameters
1063       *   - 'Blog': the related Blog (by reference)
1064       */
1065  	function AfterCollectionInsert( & $params )
1066      {
1067      }
1068  
1069  
1070      /**
1071       * Event handler: called at the end of {@link Blog::dbupdate() updating
1072       * a blog in the database}.
1073       *
1074       * @param array Associative array of parameters
1075       *   - 'Blog': the related Blog (by reference)
1076       */
1077  	function AfterCollectionUpdate( & $params )
1078      {
1079      }
1080  
1081  
1082      /**
1083       * Event handler: called at the end of {@link Blog::dbdelete() deleting
1084       * a blog from the database}.
1085       *
1086       * @param array Associative array of parameters
1087       *   - 'Blog': the related Blog (by reference)
1088       */
1089  	function AfterCollectionDelete( & $params )
1090      {
1091      }
1092  
1093  
1094      /**
1095       * Event handler: Defines blog kinds, their names and description.
1096       * Define blog settings in {@link Plugin::InitCollectionKinds()} method of your plugin.
1097       *
1098       * Note: You can change default blog kinds $params['default_kinds'] (which get passed by reference).
1099       *
1100       * @param array Associative array of parameters
1101       *   - 'kinds': dafault blog kinds (by reference)
1102       * @retun: array
1103       */
1104  	function GetCollectionKinds( & $params )
1105      {
1106          return array();
1107      }
1108  
1109  
1110      /**
1111       * Event handler: Defines blog settings by its kind. Use {@link get_collection_kinds()} to return
1112       * an array of available blog kinds and their names.
1113       * Define new blog kinds in {@link Plugin::GetCollectionKinds()} method of your plugin.
1114       *
1115       * Note: You have to change $params['Blog'] (which gets passed by reference).
1116       *
1117       * @param array Associative array of parameters
1118       *   - 'Blog': created Blog (by reference)
1119       *   - 'kind': the kind of created blog (by reference)
1120       */
1121  	function InitCollectionKinds( & $params )
1122      {
1123      }
1124  
1125      // }}}
1126  
1127  
1128      // Item events: {{{
1129  
1130      /**
1131       * Event handler: Called when rendering item/post contents as HTML. (CACHED)
1132       *
1133       * The rendered content will be *cached* and the cached content will be reused on subsequent displays.
1134       * Use {@link DisplayItemAsHtml()} instead if you want to do rendering at display time.
1135       *
1136        * Note: You have to change $params['data'] (which gets passed by reference).
1137       *
1138       * @param array Associative array of parameters
1139       *   - 'data': the data (by reference). You probably want to modify this.
1140       *   - 'format': see {@link format_to_output()}. Only 'htmlbody' and 'entityencoded' will arrive here.
1141       *   - 'Item': the {@link Item} object which gets rendered.
1142       *   - 'view_type': What part of a post are we displaying: 'teaser', 'extension' or 'full'
1143       * @return boolean Have we changed something?
1144       */
1145  	function RenderItemAsHtml( & $params )
1146      {
1147          /*
1148          $content = & $params['data'];
1149          $content = 'PREFIX__'.$content.'__SUFFIX'; // just an example
1150          return true;
1151          */
1152      }
1153  
1154  
1155      /**
1156       * Event handler: Called when rendering item/post contents as XML.
1157       *
1158       * Should this plugin apply to XML?
1159       * It should actually only apply when:
1160       * - it generates some content that is visible without HTML tags
1161       * - it removes some dirty markup when generating the tags (which will get stripped afterwards)
1162       * Note: htmlentityencoded is not considered as XML here.
1163       *
1164       * Note: You have to change $params['data'] (which gets passed by reference).
1165       *
1166       * @param array Associative array of parameters
1167       *   - 'data': the data (by reference). You probably want to modify this.
1168       *   - 'format': see {@link format_to_output()}. Only 'xml' will arrive here.
1169       *   - 'Item': the {@link Item} object which gets rendered.
1170       *   - 'view_type': What part of a post are we displaying: 'teaser', 'extension' or 'full'
1171       * @return boolean Have we changed something?
1172       */
1173  	function RenderItemAsXml( & $params )
1174      {
1175          return false;        // Do nothing by default.
1176      }
1177  
1178  
1179      /**
1180       * Event handler: Called when rendering item/post contents other than XML or HTML.
1181       *
1182       * Note: return value is ignored. You have to change $params['data'].
1183       *
1184       * @param array Associative array of parameters
1185       *   - 'data': the data (by reference). You probably want to modify this.
1186       *   - 'format': see {@link format_to_output()}. Only 'text' will arrive here.
1187       *   - 'Item': the {@link Item} object which gets rendered.
1188       *   - 'view_type': What part of a post are we displaying: 'teaser', 'extension' or 'full'
1189       * @return boolean Have we changed something?
1190       */
1191  	function RenderItemAsText()
1192      {
1193          return false;        // Do nothing by default.
1194      }
1195  
1196  
1197      /**
1198       * Event handler: Called when displaying an item/post's content as HTML.
1199       *
1200       * This is different from {@link RenderItemAsHtml()}, because it gets called
1201       * on every display (while rendering gets cached).
1202       *
1203       * @param array Associative array of parameters
1204       *   - 'data': the data (by reference). You probably want to modify this.
1205       *   - 'format': see {@link format_to_output()}.
1206       *   - 'Item': The {@link Item} that gets displayed (by reference).
1207       *   - 'preview': Is this only a preview?
1208       *   - 'dispmore': Does this include the "more" text (if available), which means "full post"?
1209       *   - 'view_type': What part of a post are we displaying: 'teaser', 'extension' or 'full'
1210       * @return boolean Have we changed something?
1211       */
1212  	function DisplayItemAsHtml( & $params )
1213      {
1214          return false;        // Do nothing by default.
1215      }
1216  
1217  
1218      /**
1219       * Event handler: Called when displaying an item/post's content as XML.
1220       *
1221       * This is different from {@link RenderItemAsXml()}, because it gets called
1222       * on every display (while rendering gets cached).
1223       *
1224       * @param array Associative array of parameters
1225       *   - 'data': the data (by reference). You probably want to modify this.
1226       *   - 'format': see {@link format_to_output()}.
1227       *   - 'Item': The {@link Item} that gets displayed (by reference).
1228       *   - 'preview': Is this only a preview?
1229       *   - 'dispmore': Does this include the "more" text (if available), which means "full post"?
1230       *   - 'view_type': What part of a post are we displaying: 'teaser', 'extension' or 'full'
1231       * @return boolean Have we changed something?
1232       */
1233  	function DisplayItemAsXml( & $params )
1234      {
1235          return false;        // Do nothing by default.
1236      }
1237  
1238  
1239      /**
1240       * Event handler: Called when displaying an item/post's content as text.
1241       *
1242       * This is different from {@link RenderItemAsText()}, because it gets called
1243       * on every display (while rendering gets cached).
1244       *
1245       * @param array Associative array of parameters
1246       *   - 'data': the data (by reference). You probably want to modify this.
1247       *   - 'format': see {@link format_to_output()}. Only 'text' will arrive here.
1248       *   - 'Item': The {@link Item} that gets displayed (by reference).
1249       *   - 'preview': Is this only a preview?
1250       *   - 'dispmore': Does this include the "more" text (if available), which means "full post"?
1251       *   - 'view_type': What part of a post are we displaying: 'teaser', 'extension' or 'full'
1252       * @return boolean Have we changed something?
1253       */
1254  	function DisplayItemAsText( & $params )
1255      {
1256          return false;        // Do nothing by default.
1257      }
1258  
1259  
1260      /**
1261       * Event handler: called at the beginning of {@link Item::dbupdate() updating
1262       * an item/post in the database}.
1263       *
1264       * Use this to manipulate the {@link Item}, e.g. adding a renderer code
1265       * through {@link Item::add_renderer()}.
1266       *
1267       * @param array Associative array of parameters
1268       *   - 'Item': the related Item (by reference)
1269       */
1270  	function PrependItemUpdateTransact( & $params )
1271      {
1272      }
1273  
1274  
1275      /**
1276       * Event handler: called at the end of {@link Item::dbupdate() updating
1277       * an item/post in the database}.
1278       *
1279       * @param array Associative array of parameters
1280       *   - 'Item': the related Item (by reference)
1281       *   - 'dbchanges': array with DB changes; a copy of {@link Item::dbchanges()},
1282       *                  before they got applied (since 1.9)
1283       */
1284  	function AfterItemUpdate( & $params )
1285      {
1286      }
1287  
1288  
1289      /**
1290       * Event handler: called at the beginning of {@link Item::dbinsert() inserting
1291       * an item/post in the database}.
1292       *
1293       * Use this to manipulate the {@link Item}, e.g. adding a renderer code
1294       * through {@link Item::add_renderer()}.
1295       *
1296       * @param array Associative array of parameters
1297       *   - 'Item': the related Item (by reference)
1298       */
1299  	function PrependItemInsertTransact( & $params )
1300      {
1301      }
1302  
1303  
1304      /**
1305       * Event handler: called at the end of {@link Item::dbinsert() inserting
1306       * a item/post into the database}, which means it has been created.
1307       *
1308       * @param array Associative array of parameters
1309       *   - 'Item': the related Item (by reference)
1310       *   - 'dbchanges': array with DB changes; a copy of {@link Item::dbchanges()},
1311       *                  before they got applied (since 1.9)
1312       */
1313  	function AfterItemInsert( & $params )
1314      {
1315      }
1316  
1317  
1318      /**
1319       * Event handler: called at the end of {@link Item::dbdelete() deleting
1320       * an item/post from the database}.
1321       *
1322       * @param array Associative array of parameters
1323       *   - 'Item': the related Item (by reference)
1324       */
1325  	function AfterItemDelete( & $params )
1326      {
1327      }
1328  
1329  
1330      /**
1331       * Event handler: called when instantiating an Item for preview.
1332       *
1333       * @param array Associative array of parameters
1334       *   - 'Item': the related Item (by reference)
1335       */
1336  	function AppendItemPreviewTransact( & $params )
1337      {
1338      }
1339  
1340  
1341      /**
1342       * Event handler: Called when the view counter of an item got increased.
1343       *
1344       * @param array Associative array of parameters
1345       *   - 'Item': the Item object (by reference)
1346       */
1347  	function ItemViewsIncreased( & $params )
1348      {
1349      }
1350  
1351  
1352      /**
1353       * Event handler: Called at the end of the "Edit item" form.
1354       *
1355       * @param array Associative array of parameters
1356       *   - 'Form': the {@link Form} object (by reference)
1357       *   - 'Item': the Item which gets edited (by reference)
1358       *   - 'edit_layout': "simple", "expert", etc. (users, hackers, plugins, etc. may create their own layouts in addition to these)
1359       *                    NOTE: Please respect the "simple" mode, which should display only the most simple things!
1360       * @return boolean did we display something?
1361       */
1362  	function AdminDisplayItemFormFieldset( & $params )
1363      {
1364          return false;        // Do nothing by default.
1365      }
1366  
1367  
1368      /**
1369       * Event handler: Called at the end of the "Edit item" form in front-office.
1370       *
1371       * @param array Associative array of parameters
1372       *   - 'Form': the {@link Form} object (by reference)
1373       *   - 'Item': the Item which gets edited (by reference)
1374       *   - 'edit_layout': "simple", "expert", etc. (users, hackers, plugins, etc. may create their own layouts in addition to these)
1375       *                    NOTE: Please respect the "simple" mode, which should display only the most simple things!
1376       * @return boolean did we display something?
1377       */
1378  	function DisplayItemFormFieldset( & $params )
1379      {
1380          return false;        // Do nothing by default.
1381      }
1382  
1383  
1384      /**
1385       * Event handler: Called before an item gets deleted (in the backoffice).
1386       *
1387       * You could {@link Plugin::msg() add a message} of
1388       * category "error" here, to prevent the comment from being deleted.
1389       *
1390       * @since 2.0
1391       * @param array Associative array of parameters
1392       *              'Item': the Item which gets created (by reference)
1393       */
1394  	function AdminBeforeItemEditDelete( & $params )
1395      {
1396      }
1397  
1398  
1399      /**
1400       * Event handler: Called before a new item gets created (in the backoffice).
1401       *
1402       * You could {@link Plugin::msg() add a message} of
1403       * category "error" here, to prevent the comment from being inserted.
1404       *
1405       * @param array Associative array of parameters
1406       *              'Item': the Item which gets created (by reference)
1407       */
1408  	function AdminBeforeItemEditCreate( & $params )
1409      {
1410      }
1411  
1412  
1413      /**
1414       * Event handler: Called before an existing item gets updated (in the backoffice).
1415       *
1416       * You could {@link Plugin::msg() add a message} of
1417       * category "error" here, to prevent the comment from being inserted.
1418       *
1419       * @param array Associative array of parameters
1420       *              'Item': the Item which gets updated (by reference)
1421       */
1422  	function AdminBeforeItemEditUpdate( & $params )
1423      {
1424      }
1425  
1426  
1427      /**
1428       * Event handler: the plugin gets asked if an item can receive feedback/comments.
1429       *
1430       * @param array Associative array of parameters
1431       *              'Item': the Item
1432       * @return boolean|string
1433       *   true, if the Item can receive feedback
1434       *   false/string, if the Item cannot receive feedback. If you return a string
1435       *                 this gets displayed as an error/explanation.
1436       *   NULL, if you do not want to say "yes" or "no".
1437       */
1438  	function ItemCanComment( & $params )
1439      {
1440      }
1441  
1442  
1443      /**
1444       * Event handler: send a ping about a new item.
1445       *
1446       * @param array Associative array of parameters
1447       *        'Item': the Item (by reference)
1448       *        'xmlrpcresp': Set this to the {@link xmlrpcresp} object, if the plugin
1449       *                      uses XMLRPC.
1450       *        'display': Should results get displayed? (normally you should not need
1451       *                   to care about this, especially if you can set 'xmlrpcresp')
1452       * @return boolean Was the ping successful?
1453       */
1454  	function ItemSendPing( & $params )
1455      {
1456      }
1457  
1458  
1459      /**
1460       * Event handler: called to display the URL that accepts trackbacks for
1461       *                an item.
1462       *
1463       * @param array Associative array of parameters
1464       *   - 'Item': the {@link Item} object (by reference)
1465       *   - 'template': the template to display the URL (%url%)
1466       */
1467  	function DisplayTrackbackAddr( & $params )
1468      {
1469      }
1470  
1471  
1472      /**
1473       * Event handler: Does your Plugin want to apply as a renderer for the item?
1474       *
1475       * NOTE: this is especially useful for lazy Plugins, which would look
1476       *       at the content and decide, if they apply.
1477       *
1478       * @param array Associative array of parameters
1479       *   - 'Item': the {@link Item} object (by reference)
1480       * @return boolean|NULL If true, the Plugin gets added as a renderer, false
1481       *         removes it as a renderer (if existing) and NULL does not change the
1482       *         renderer setting regarding your Plugin.
1483       */
1484  	function ItemApplyAsRenderer( & $params )
1485      {
1486      }
1487  
1488      // }}}
1489  
1490  
1491      // Feedback (Comment/Trackback) events: {{{
1492  
1493      /**
1494       * Event handler: Called when displaying editor toolbars.
1495       *
1496       * @param array Associative array of parameters
1497       * @return boolean did we display a toolbar?
1498       */
1499  	function DisplayCommentToolbar( & $params )
1500      {
1501          return false;        // Do nothing by default.
1502      }
1503  
1504  
1505      /**
1506       * Event handler: Called at the end of the "Edit comment" form.
1507       *
1508       * @param array Associative array of parameters
1509       *   - 'Form': the {@link Form} object (by reference)
1510       *   - 'Comment': the Comment which gets edited (by reference)
1511       *   - 'edit_layout': only NULL currently, as there's only one layout
1512       * @return boolean did we display something?
1513       */
1514  	function AdminDisplayCommentFormFieldset( & $params )
1515      {
1516          return false;        // Do nothing by default.
1517      }
1518  
1519  
1520      /**
1521       * Event handler: Called at the end of the frontend comment form.
1522       *
1523       * You might want to use this to inject antispam payload to use in
1524       * in {@link GetSpamKarmaForComment()} or modify the Comment according
1525       * to it in {@link BeforeCommentFormInsert()}.
1526       *
1527       * @see Plugin::BeforeCommentFormInsert(), Plugin::AfterCommentFormInsert()
1528       * @param array Associative array of parameters
1529       *   - 'Form': the comment form generating object
1530       *   - 'Item': the Item for which the comment is meant
1531       */
1532  	function DisplayCommentFormFieldset( & $params )
1533      {
1534      }
1535  
1536  
1537      /**
1538       * Event handler: Called in the submit button section of the
1539       * frontend comment form.
1540       *
1541       * @param array Associative array of parameters
1542       *   - 'Form': the comment form generating object
1543       *   - 'Item': the Item for which the comment is meant
1544       */
1545  	function DisplayCommentFormButton( & $params )
1546      {
1547      }
1548  
1549  
1550      /**
1551       * Event handler: Called before at the beginning, if a comment form gets sent (and received).
1552       *
1553       * Use this to filter input, e.g. the OpenID uses this to provide alternate authentication.
1554       *
1555       * If you need to delegate to another service (what OpenID does), you need to remember all
1556       * these params (use array_keys($params)) and restore them when coming back.
1557       * Only comment_post_ID is required at the beginning of comment_post.php (where this hook)
1558       * is located (and has to be passed via GET/POST) - all other params can get stored in a
1559       * local session and restored when coming back (this is recommended.)
1560       *
1561       * @since 1.10.0
1562       * @see Plugin::DisplayCommentFormFieldset()
1563       * @param array Associative array of parameters
1564       *   - 'comment_post_ID': ID of the item the comment is for
1565       *   - 'comment': the comment text (by reference)
1566       *   - 'original_comment': the original, unfiltered comment text - you should not modify it here,
1567       *      this is meant e.g. for the OpenID plugin to re-inject it after redirection (by reference)
1568       *   - 'action': "save" or "preview" (by reference)
1569       *   - 'User': {@link User}, if logged in or null (by reference)
1570       *   - 'anon_name': Name of the anonymous commenter (by reference)
1571       *   - 'anon_email': E-Mail of the anonymous commenter (by reference)
1572       *   - 'anon_url': URL of the anonymous commenter (by reference)
1573       *   - 'anon_allow_msgform': "Allow msgform" preference of the anonymous commenter (by reference)
1574       *   - 'anon_cookies': "Remember me" preference of the anonymous commenter (by reference)
1575       *   - 'redirect_to': URL where to redirect to in the end of comment posting (by reference)
1576       *   - 'crumb_comment': Crumb expected for the comment (see {@link Session::assert_received_crumb()})
1577       *     (by reference).
1578       */
1579  	function CommentFormSent( & $params )
1580      {
1581      }
1582  
1583  
1584      /**
1585       * Event handler: Called before a comment gets inserted through the public comment
1586       *                form.
1587       *
1588       * Use this, to validate a comment: you could {@link Plugin::msg() add a message} of
1589       * category "error" here, to prevent the comment from being inserted.
1590       *
1591       * @see Plugin::DisplayCommentFormFieldset()
1592       * @param array Associative array of parameters
1593       *   - 'Comment': the Comment (by reference)
1594       *   - 'original_comment': this is the unstripped and unformated posted comment
1595       *   - 'action': "save" or "preview" (by reference) (since 1.10)
1596       *   - 'is_preview': is this a request for previewing the comment? (boolean)
1597       */
1598  	function BeforeCommentFormInsert( & $params )
1599      {
1600      }
1601  
1602  
1603      /**
1604       * Event handler: Called when a comment form has been processed and the comment
1605       *                got inserted into DB.
1606       *
1607       * @param array Associative array of parameters
1608       *   - 'Comment': the Comment (by reference)
1609       *   - 'original_comment': this is the unstripped and unformated posted comment
1610       */
1611  	function AfterCommentFormInsert( & $params )
1612      {
1613      }
1614  
1615  
1616      /**
1617       * Event handler: Called to ask the plugin for the spam karma of a comment/trackback.
1618       *
1619       * This gets called just before the comment gets stored.
1620       *
1621       * @param array Associative array of parameters
1622       *   - 'Comment': the {@link Comment} object (by reference)
1623       *   - The following values are interesting if you want to provide skipping of a test:
1624       *     - 'cur_karma': current karma value (cur_karma_abs/cur_karma_divider or NULL)
1625       *     - 'cur_karma_abs': current karma absolute value or NULL (if no Plugin returned karma before)
1626       *     - 'cur_karma_divider': current divider (sum of weights)
1627       *     - 'cur_count_plugins': number of Plugins that have already been asked
1628       * @return integer|NULL Spam probability (-100 - 100).
1629       *                -100 means "absolutely no spam", 100 means "absolutely spam".
1630       *                Only if you return a numeric value, it gets considered (e.g., "", NULL or false get ignored).
1631       */
1632  	function GetSpamKarmaForComment( & $params )
1633      {
1634          return;
1635      }
1636  
1637  
1638      /**
1639       * Event handler: called at the end of {@link Comment::dbupdate() updating
1640       * a comment in the database}.
1641       *
1642       * @param array Associative array of parameters
1643       *   - 'Comment': the related Comment (by reference)
1644       *   - 'dbchanges': array with DB changes; a copy of {@link Comment::dbchanges()},
1645       *                  before they got applied (since 1.9)
1646       */
1647  	function AfterCommentUpdate( & $params )
1648      {
1649      }
1650  
1651  
1652      /**
1653       * Event handler: called at the end of {@link Comment::dbinsert() inserting
1654       * a comment into the database}, which means it has been created.
1655       *
1656       * @param array Associative array of parameters
1657       *   - 'Comment': the related Comment (by reference)
1658       *   - 'dbchanges': array with DB changes; a copy of {@link Comment::dbchanges()},
1659       *                  before they got applied (since 1.9)
1660       */
1661  	function AfterCommentInsert( & $params )
1662      {
1663      }
1664  
1665  
1666      /**
1667       * Event handler: called at the end of {@link Comment::dbdelete() deleting
1668       * a comment from the database}.
1669       *
1670       * @param array Associative array of parameters
1671       *   - 'Comment': the related Comment (by reference)
1672       */
1673  	function AfterCommentDelete( & $params )
1674      {
1675      }
1676  
1677  
1678      /**
1679       * Event handler: called before a trackback gets recorded.
1680       *
1681       * Use this, to validate a trackback: you could {@link Plugin::msg() add a message} of
1682       * category "error" here, to prevent the trackback from being accepted.
1683       *
1684       * @param array Associative array of parameters
1685       *   - 'Comment': the trackback (which is a {@link Comment} object with "trackback" type) (by reference)
1686       *        The trackback-params get mapped like this:
1687       *        - "blog_name" => "author"
1688       *        - "url" => "author_url"
1689       *        - "title"/"excerpt" => "comment"
1690       *
1691       */
1692  	function BeforeTrackbackInsert( & $params )
1693      {
1694      }
1695  
1696      /**
1697       * Event handler: Gets called after a trackback has been recorded.
1698       *
1699       * @param array Associative array of parameters
1700       *   - 'Comment': the trackback (which is a {@link Comment} object with "trackback" type) (by reference)
1701       *        The trackback-params get mapped like this:
1702       *        - "blog_name" => "author"
1703       *        - "url" => "author_url"
1704       *        - "title"/"excerpt" => "comment"
1705       */
1706  	function AfterTrackbackInsert( & $params )
1707      {
1708      }
1709  
1710      /**
1711       * Event handler: called to filter the comment's author name (blog name for trackbacks)
1712       *
1713       * @param array Associative array of parameters
1714       *   - 'data': the name of the author/blog (by reference)
1715       *   - 'makelink': true, if the "data" contains a link
1716       *   - 'Comment': the {@link Comment} object
1717       */
1718  	function FilterCommentAuthor( & $params )
1719      {
1720      }
1721  
1722  
1723      /**
1724       * Event handler: called to filter the comment's author URL.
1725       * This may be either the URL only or a full link (A tag).
1726       *
1727       * @param array Associative array of parameters
1728       *   - 'data': the URL of the author/blog (by reference)
1729       *   - 'makelink': true, if the "data" contains a link (HTML A tag)
1730       *   - 'Comment': the {@link Comment} object
1731       */
1732  	function FilterCommentAuthorUrl( & $params )
1733      {
1734      }
1735  
1736  
1737      /**
1738       * Event handler: called to filter the comment's content
1739       *
1740       * @param array Associative array of parameters
1741       *   - 'data': the name of the author/blog (by reference)
1742       *   - 'Comment': the {@link Comment} object
1743       */
1744  	function FilterCommentContent( & $params )
1745      {
1746          if( $this->group == 'rendering' )
1747          { // All plugin from 'rendering' group has a 'coll_apply_comment_rendering' setting
1748              $Comment = & $params['Comment'];
1749              $comment_Item = & $Comment->get_Item();
1750              $comment_Blog = & $comment_Item->get_Blog();
1751              if( in_array( $this->code, $Comment->get_renderers_validated() ) )
1752              { // Always allow rendering for comment
1753                  $render_params = array_merge(  array( 'data' => & $Comment->content ), $params );
1754                  $this->RenderItemAsHtml( $render_params );
1755              }
1756          }
1757      }
1758  
1759      // }}}
1760  
1761  
1762      // Message form events: {{{
1763  
1764      /**
1765       * Event handler: Called at the end of the frontend message form, which
1766       * allows to send an email to a user/commentator.
1767       *
1768       * You might want to use this to inject antispam payload to use in
1769       * in {@link MessageFormSent()}.
1770       *
1771       * @param array Associative array of parameters
1772       *   - 'Form': the comment form generating object
1773       *   - 'recipient_ID': ID of the user (if any)
1774       *   - 'item_ID': ID of the item where the user clicked the msgform icon (if any)
1775       *   - 'comment_ID': ID of the comment where the user clicked the msgform icon (if any)
1776       */
1777  	function DisplayMessageFormFieldset( & $params )
1778      {
1779      }
1780  
1781  
1782      /**
1783       * Event handler: Called in the submit button section of the
1784       * frontend message form.
1785       *
1786       * @param array Associative array of parameters
1787       *   - 'Form': the comment form generating object
1788       *   - 'recipient_ID': ID of the user (if any)
1789       *   - 'item_ID': ID of the item where the user clicked the msgform icon (if any)
1790       *   - 'comment_ID': ID of the comment where the user clicked the msgform icon (if any)
1791       */
1792  	function DisplayMessageFormButton( & $params )
1793      {
1794      }
1795  
1796  
1797      /**
1798       * Event handler: Called when a message form has been submitted.
1799       *
1800       * Add messages of category "error" to prevent the message from being sent.
1801       *
1802       * You can also alter the "message" or "message_footer" that gets sent here.
1803       *
1804       * @param array Associative array of parameters
1805       *   - 'recipient_ID': ID of the user (if any)
1806       *   - 'item_ID': ID of the item where the user clicked the msgform icon (if any)
1807       *   - 'comment_ID': ID of the comment where the user clicked the msgform icon (if any)
1808       *   - 'sender_name': The name of the sender (by reference) (since 1.10.0)
1809       *   - 'sender_email': The email address of the sender (by reference) (since 1.10.0)
1810       *   - 'subject': The subject of the message to be sent (by reference) (since 1.10.0)
1811       *   - 'message': The message to be sent (by reference)
1812       *   - 'Blog': The blog, depending on the context (may be null) (by reference) (since 1.10.0)
1813       */
1814  	function MessageFormSent( & $params )
1815      {
1816      }
1817  
1818  
1819      /**
1820       * Event handler: Called after a message has been sent through the public email form.
1821       *
1822       * This is meant to cleanup generated data.
1823       *
1824       * @param array Associative array of parameters
1825       *   - 'success_message' (bool): true if the message has been sent, false otherwise
1826       */
1827  	function MessageFormSentCleanup( & $params )
1828      {
1829      }
1830  
1831      // }}}
1832  
1833  
1834      // Caching events: {{{
1835  
1836      /**
1837       * Event handler: called to cache object data.
1838       *
1839       * @param array Associative array of parameters
1840       *   - 'action': 'delete', 'set', 'get'
1841       *   - 'key': The key to refer to 'data'
1842       *   - 'data': The actual data. This must be set by the plugin.
1843       * @return boolean True if action was successful, false otherwise.
1844       */
1845  	function CacheObjects( & $params )
1846      {
1847      }
1848  
1849  
1850      /**
1851       * Event handler: called to cache page content (get cached content or request caching).
1852       *
1853       * This method must build a unique key for the requested page (including cookie/session info) and
1854       * start an output buffer, to get the content to cache.
1855       *
1856       * Note, that there are special occassions when this event does not get called, because we want
1857       * really fresh content always:
1858       *  - we're generating static pages
1859       *  - there gets a "dynamic object", such as "Messages" or "core.preview_Comment" transported in the session
1860       *
1861       * @see Plugin::CacheIsCollectingContent()
1862       * @param array Associative array of parameters
1863       *   - 'data': this must get set to the page content on cache hit
1864       * @return boolean True if we handled the request (either returned caching data or started buffering),
1865       *                 false if we do not want to cache this page.
1866       */
1867  	function CachePageContent( & $params )
1868      {
1869      }
1870  
1871  
1872      /**
1873       * Event handler: gets asked for if we are generating cached content.
1874       *
1875       * This is useful to not generate a list of online users or the like.
1876       *
1877       * @see Plugin::CachePageContent()
1878       * @return boolean
1879       */
1880  	function CacheIsCollectingContent()
1881      {
1882      }
1883  
1884  
1885      /**
1886       * This gets called before an image thumbnail gets created.
1887       *
1888       * This is useful to post-process the thumbnail image (add a watermark or change colors).
1889       *
1890       * @param array Associative array of parameters
1891       *   - 'File': the related File (by reference)
1892       *   - 'imh': image resource (by reference)
1893       *   - 'size': size name (by reference)
1894       *   - 'mimetype': mimetype of thumbnail (by reference)
1895       *   - 'quality': JPEG image quality [0-100] (by reference)
1896       *   - 'root_type': file root type 'user', 'group', 'collection' etc. (by reference)
1897       *   - 'root_type_ID': ID of user, group or collection (by reference)
1898       */
1899  	function BeforeThumbCreate( & $params )
1900      {
1901      }
1902  
1903      // }}}
1904  
1905  
1906      // PluginSettings {{{
1907      /**
1908       * Event handler: Called before displaying or setting a plugin's setting in the backoffice.
1909       *
1910       * @see GetDefaultSettings()
1911       * @param array Associative array of parameters
1912       *   - 'name': name of the setting
1913       *   - 'value': value of the setting (by reference)
1914       *   - 'meta': meta data of the setting (as given in {@link GetDefaultSettings()})
1915       *   - 'action': 'display' or 'set'
1916       * @return string|NULL Return a string with an error to prevent the setting from being set
1917       *                     and/or a message added to the settings field.
1918       */
1919  	function PluginSettingsValidateSet( & $params )
1920      {
1921      }
1922  
1923  
1924      /**
1925       * Event handler: Called as action just before updating the {@link Plugin::$Settings plugin's settings}.
1926       *
1927       * The "regular" settings from {@link GetDefaultSettings()} have been set into
1928       * {@link Plugin::$Settings}, but get saved into DB after this method has been called.
1929       *
1930       * Use this to catch custom input fields from {@link PluginSettingsEditDisplayAfter()} or
1931       * add notes/errors through {@link Plugin::msg()}.
1932       *
1933       * If you want to modify plugin events (see {@link Plugin::enable_event()} and
1934       * {@link Plugin::disable_event()}), you should use {@link Plugin::BeforeEnable()}, because Plugin
1935       * events get saved (according to the edit settings screen) after this event.
1936       *
1937       * @return false|NULL Return false to prevent the settings from being updated to DB.
1938       */
1939  	function PluginSettingsUpdateAction()
1940      {
1941      }
1942  
1943  
1944      /**
1945       * Event handler: Called as action before displaying the "Edit plugin" form,
1946       * which includes the display of the {@link Plugin::$Settings plugin's settings}.
1947       *
1948       * You may want to use this to check existing settings or display notes about
1949       * something.
1950       */
1951  	function PluginSettingsEditAction()
1952      {
1953      }
1954  
1955  
1956      /**
1957       * Event handler: Called after the form to edit the {@link Plugin::$Settings} has been
1958       * displayed.
1959       *
1960       * Use this to add custom input fields (and catch them in {@link PluginSettingsUpdateAction()})
1961       * or display custom output (e.g. a test link).
1962       *
1963       * @param array Associative array of parameters
1964       *   - 'Form': the {@link Form}, where an fieldset has been opened already (by reference)
1965       */
1966  	function PluginSettingsEditDisplayAfter( & $params )
1967      {
1968      }
1969  
1970      // }}}
1971  
1972  
1973      // PluginUserSettings {{{
1974      /**
1975       * Event handler: Called before displaying or setting a plugin's user setting in the backoffice.
1976       *
1977       * @see GetDefaultUserSettings()
1978       * @param array Associative array of parameters
1979       *   - 'name': name of the setting
1980       *   - 'value': value of the setting (by reference)
1981       *   - 'meta': meta data of the setting (as given in {@link GetDefaultUserSettings()})
1982       *   - 'User': the {@link User} for which the setting is
1983       *   - 'action': 'display' or 'set'
1984       * @return string|NULL Return a string with an error to prevent the setting from being set
1985       *                     and/or a message added to the settings field.
1986       */
1987  	function PluginUserSettingsValidateSet( & $params )
1988      {
1989      }
1990  
1991  
1992      /**
1993       * Event handler: Called as action just before updating the {@link Plugin::$UserSettings plugin's user settings}.
1994       *
1995       * The "regular" settings from {@link GetDefaultUserSettings()} have been set into
1996       * {@link Plugin::$UserSettings}, but get saved into DB after this method has been called.
1997       *
1998       * Use this to catch custom input fields from {@link PluginUserSettingsEditDisplayAfter()} or
1999       * add notes/errors through {@link Plugin::msg()}.
2000       *
2001       * @param array Associative array of parameters
2002       *   - 'User': the {@link User} for which the settings get updated
2003       *   - 'action': "save", "reset"
2004       *
2005       * @return false|NULL Return false to prevent the settings from being updated to DB.
2006       */
2007  	function PluginUserSettingsUpdateAction( & $params )
2008      {
2009      }
2010  
2011  
2012      /**
2013       * Event handler: Called as action before displaying the "Edit user" form,
2014       * which includes the display of the {@link Plugin::$UserSettings plugin's user settings}.
2015       *
2016       * You may want to use this to check existing settings or display notes about
2017       * something.
2018       *
2019       * @param array Associative array of parameters
2020       *   - 'User': the {@link User} for which the settings are being displayed/edited
2021       */
2022  	function PluginUserSettingsEditAction( & $params )
2023      {
2024      }
2025  
2026  
2027      /**
2028       * Event handler: Called after the form to edit the {@link Plugin::$UserSettings} has been
2029       * displayed.
2030       *
2031       * Use this to add custom input fields (and catch them in {@link PluginUserSettingsUpdateAction()})
2032       * or display custom output (e.g. a test link).
2033       *
2034       * @param array Associative array of parameters
2035       *   - 'Form': the {@link Form}, where an fieldset has been opened already (by reference)
2036       *   - 'User': the {@link User} whose settings get displayed for editing (since 1.10.0)
2037       */
2038  	function PluginUserSettingsEditDisplayAfter( & $params )
2039      {
2040      }
2041  
2042      // }}}
2043  
2044      // PluginCollSettings {{{
2045      /**
2046       * Event handler: Called as action just before updating plugin's collection/blog settings.
2047       *
2048       * Use this to add notes/errors through {@link Plugin::msg()} or to process saved settings.
2049       */
2050  	function PluginCollSettingsUpdateAction()
2051      {
2052      }
2053  
2054      // }}}
2055  
2056  
2057      // User related events, including registration and login (procedure): {{{
2058  
2059      /**
2060       * Event handler: Called at the end of the login procedure, if the
2061       *                user is anonymous ({@link $current_User current User} NOT set).
2062       *
2063       * Use this for example to read some cookie and define further handling of
2064       * this visitor or force them to login, by {@link Plugin::msg() adding a message}
2065       * of class "login_error", which will trigger the login screen.
2066       * asimo> There is no message with "login_error" class anymore,
2067       * there is a $login_error global variable
2068       */
2069  	function AfterLoginAnonymousUser( & $params )
2070      {
2071      }
2072  
2073  
2074      /**
2075       * Event handler: Called at the end of the login procedure, if the
2076       *                {@link $current_User current User} is set and the
2077       *                user is therefor registered.
2078       *
2079       * Use this for example to re-act on specific {@link Plugin::$UserSettings user settings},
2080       * e.g., call {@link Plugin::forget_events()} to de-activate the plugin for
2081       * the current request.
2082       *
2083       * You can also {@link Plugin::msg() add a message} of class "login_error"
2084       * to prevent the user from accessing the site and triggering
2085       * the login screen.
2086       * asimo> There is no message with "login_error" class anymore,
2087       * there is a $login_error global variable
2088       */
2089  	function AfterLoginRegisteredUser( & $params )
2090      {
2091      }
2092  
2093  
2094      /**
2095       * Event handler: Called when a new user has registered, at the end of the
2096       *                DB transaction that created this user.
2097       *
2098       * If you want to modify the about-to-be-created user (if the transaction gets
2099       * committed), you'll have to call {@link User::dbupdate()} on it, because he
2100       * got already inserted (but the transaction is not yet committed).
2101       *
2102       * Note: if you want to re-act on a new user,
2103       * use {@link Plugin::AfterUserRegistration()} instead!
2104       *
2105       * @param array Associative array of parameters
2106       *   - 'User': the {@link User user object} (as reference).
2107       * @return boolean false if the whole transaction should get rolled back (the user does not get created).
2108       */
2109  	function AppendUserRegistrTransact( & $params )
2110      {
2111          return true;
2112      }
2113  
2114  
2115      /**
2116       * Event handler: Called when a new user has registered and got created.
2117       *
2118       * Note: if you want to modify a new user,
2119       * use {@link Plugin::AppendUserRegistrTransact()} instead!
2120       *
2121       * @param array Associative array of parameters
2122       *   - 'User': the {@link User user object} (as reference).
2123       */
2124  	function AfterUserRegistration( & $params )
2125      {
2126      }
2127  
2128  
2129      /**
2130       * Event handler: Called at the begining of the "Register as new user" form.
2131       *
2132       * You might want to use this to inject antispam payload to use
2133       * in {@link Plugin::RegisterFormSent()}.
2134       *
2135       * @param array Associative array of parameters
2136       *   - 'Form': the comment form generating object (by reference)
2137       *   - 'inskin': boolean true if the form is displayed in skin
2138       */
2139  	function DisplayRegisterFormBefore( & $params )
2140      {
2141      }
2142  
2143  
2144      /**
2145       * Event handler: Called at the end of the "Register as new user" form.
2146       *
2147       * You might want to use this to inject antispam payload to use
2148       * in {@link Plugin::RegisterFormSent()}.
2149       *
2150       * @param array Associative array of parameters
2151       *   - 'Form': the comment form generating object (by reference)
2152       *   - 'inskin': boolean true if the form is displayed in skin
2153       */
2154  	function DisplayRegisterFormFieldset( & $params )
2155      {
2156      }
2157  
2158  
2159      /**
2160       * Event handler: Called when a "Register as new user" form has been submitted.
2161       *
2162       * You can cancel the registration process by {@link Plugin::msg() adding a message}
2163       * of type "error".
2164       *
2165       * @param array Associative array of parameters
2166       *   - 'login': Login name (by reference) (since 1.10.0)
2167       *   - 'email': E-Mail value (by reference) (since 1.10.0)
2168       *   - 'locale': Locale value (by reference) (since 1.10.0)
2169       *   - 'pass1': Password (by reference) (since 1.10.0)
2170       *   - 'pass2': Confirmed password (by reference) (since 1.10.0)
2171       */
2172  	function RegisterFormSent( & $params )
2173      {
2174      }
2175  
2176  
2177      /**
2178       * Event handler: Called at the end of the "Login" form.
2179       *
2180       * You might want to use this to inject payload to use
2181       * in {@link LoginAttempt()}.
2182       *
2183       * @param array Associative array of parameters
2184       *   - 'Form': the comment form generating object (by reference)
2185       */
2186  	function DisplayLoginFormFieldset( & $params )
2187      {
2188      }
2189  
2190  
2191      /**
2192       * Event handler: called when a user attemps to login.
2193       *
2194       * You can prevent the user from logging in by {@link Plugin::msg() adding a message}
2195       * of type "login_error".
2196       *
2197       * Otherwise, this hook is meant to authenticate a user against some
2198       * external database (e.g. LDAP) and generate a new user.
2199       *
2200       * To check, if a user already exists in b2evo with that login/password, you might
2201       * want to use <code>user_pass_ok( $login, $pass_md5, true )</code>.
2202       *
2203       * NOTE: if 'pass_hashed' is not empty, you won't receive the password in clear-type. It
2204       *       has been hashed using client-side Javascript.
2205       *       SHA1( MD5($params['pass']).$params['pass_salt'] ) should result in $params['pass_hashed']!
2206       *       If you need the raw password, see {@link LoginAttemptNeedsRawPassword()}.
2207       *
2208       * @see Plugin::AlternateAuthentication()
2209       * @see Plugin::Logout()
2210       * @param array Associative array of parameters
2211       *   - 'login': user's login (by reference since 1.10.0)
2212       *   - 'pass': user's password (by reference since 1.10.0)
2213       *   - 'pass_md5': user's md5 password (by reference since 1.10.0)
2214       *   - 'pass_salt': the salt used in "pass_hashed" (by reference)
2215       *   - 'pass_hashed': if non-empty this is the users passwords hashed. See note above. (by reference)
2216       *   - 'pass_ok': is the password ok for 'login'? (by reference) (since 1.10.0)
2217       */
2218  	function LoginAttempt( & $params )
2219      {
2220      }
2221  
2222  
2223      /**
2224       * Event handler: your Plugin should return true here, if it needs a raw (un-hashed)
2225       * password for the {@link Plugin::LoginAttempt()} event. If any Plugin returns true
2226       * for this event, client-side hashing of the password is not used.
2227       * NOTE: this causes passwords to travel un-encrypted, unless SSL/HTTPS get used.
2228       *
2229       * @return boolean True, if you need the raw password.
2230       */
2231  	function LoginAttemptNeedsRawPassword()
2232      {
2233          return false;
2234      }
2235  
2236  
2237      /**
2238       * Event handler: called when a user logs out.
2239       *
2240       * This is meant to cleanup data, e.g. if you use the
2241       * {@link Plugin::AlternateAuthentication()} hook.
2242       *
2243       * @see Plugin::AlternateAuthentication()
2244       * @see Plugin::Logout()
2245       * @param array Associative array of parameters
2246       *   - 'User': the user object
2247       */
2248  	function Logout( $params )
2249      {
2250      }
2251  
2252  
2253      /**
2254       * Event handler: Called at the end of the "Validate user account" form, which gets
2255       *                invoked if newusers_mustvalidate is enabled and the user has not
2256       *                been validated yet.
2257       *
2258       * The corresponding action event is {@link Plugin::ValidateAccountFormSent()}.
2259       *
2260       * @param array Associative array of parameters
2261       *   - 'Form': the comment form generating object (by reference)
2262       */
2263  	function DisplayValidateAccountFormFieldset( & $params )
2264      {
2265      }
2266  
2267  
2268      /**
2269       * Event handler: Called when a "Validate user account" form has been submitted.
2270       *
2271       * You can cancel the registration process by {@link Plugin::msg() adding a message}
2272       * of type "error".
2273       */
2274  	function ValidateAccountFormSent( & $params )
2275      {
2276      }
2277  
2278  
2279      /**
2280       * Event handler: Called at the end of the "User profile" form.
2281       *
2282       * The corresponding action event is {@link Plugin::ProfileFormSent()}.
2283       *
2284       * @param array Associative array of parameters
2285       *   - 'Form': the user profile form generating object (by reference)
2286       *   - 'User': the edited user object (by reference)
2287       *   - 'edit_layout':
2288       *            "public" - public frontend user profile form (info only),
2289       *            "private" - private frontend user profile form (editable),
2290       *   - 'is_admin_page': (boolean) indicates whether we are in frontend or backoffice
2291       */
2292  	function DisplayProfileFormFieldset( & $params )
2293      {
2294          if( $params['edit_layout'] == 'public' )
2295          { // Do nothing in public mode
2296              return false;
2297          }
2298  
2299          return false;        // Do nothing by default.
2300      }
2301  
2302  
2303      /**
2304       * Event handler: Called before at the beginning, if a profile form gets sent (and received).
2305       *
2306       * Use this to filter input
2307       *
2308       * @see Plugin::DisplayProfileFormFieldset()
2309       * @param array Associative array of parameters
2310       *   - 'User': edited {@link User} object (by reference)
2311       *   - 'newuser_firstname': firstname (by reference)
2312       *   - 'newuser_lastname': lastname (by reference)
2313       *   - 'newuser_nickname': nickname (by reference)
2314       *   - 'newuser_locale': locale (by reference)
2315       *   - 'newuser_url': URL (by reference)
2316       *   - 'newuser_email': email (by reference)
2317       *   - 'newuser_allow_msgform': "message form" status (by reference)
2318       *   - 'newuser_notify': "notifications" status (by reference)
2319       *   - 'newuser_showonline': "show online" status (by reference)
2320       *   - 'newuser_gender': gender (by reference)
2321       *   - 'pass1': pass1 (by reference)
2322       *   - 'pass2': pass2 (by reference)
2323       */
2324  	function ProfileFormSent( & $params )
2325      {
2326      }
2327  
2328  
2329      /**
2330       * Event handler: called at the end of the login process, if the user did not try to
2331       *                login (by sending "login" and "pwd"), the session has no user attached
2332       *                or only "login" is given.
2333       *
2334       * This hook is meant to automagically login/authenticate an user by his/her IP address,
2335       * special cookie, etc..
2336       *
2337       * If you can authenticate the user, you'll have to attach him to the {@link $Session},
2338       * either through {@link Session::set_user_ID()} or {@link Session::set_User()}.
2339       *
2340       * @see Plugin::LoginAttempt()
2341       * @see Plugin::Logout()
2342       * @return boolean True, if the user has been authentificated (set in $Session)
2343       */
2344  	function AlternateAuthentication( & $params )
2345      {
2346      }
2347  
2348  
2349      /**
2350       * Event handler: called at the end of {@link User::dbupdate() updating
2351       * an user account in the database}, which means that it has been changed.
2352       *
2353       * @since 1.8.1
2354       * @param array Associative array of parameters
2355       *   - 'User': the related User (by reference)
2356       */
2357  	function AfterUserUpdate( & $params )
2358      {
2359      }
2360  
2361  
2362      /**
2363       * Event handler: called at the end of {@link User::dbinsert() inserting
2364       * an user account into the database}, which means it has been created.
2365       *
2366       * @since 1.8.1
2367       * @param array Associative array of parameters
2368       *   - 'User': the related User (by reference)
2369       */
2370  	function AfterUserInsert( & $params )
2371      {
2372      }
2373  
2374  
2375      /**
2376       * Event handler: called at the end of {@link User::dbdelete() deleting
2377       * an user from the database}.
2378       *
2379       * @since 1.8.1
2380       * @param array Associative array of parameters
2381       *   - 'User': the related User (by reference)
2382       */
2383  	function AfterUserDelete( & $params )
2384      {
2385      }
2386  
2387      // }}}
2388  
2389  
2390      // General events: {{{
2391  
2392      /**
2393       * Event handler: general event to inject payload for a captcha test.
2394       *
2395       * This does not get called by b2evolution itself, but provides an interface
2396       * to other plugins. E.g., the {@link dnsbl_antispam_plugin DNS blacklist plugin}
2397       * uses this event optionally to whitelist a user.
2398       *
2399       * @param array Associative array of parameters
2400       *   - 'Form': the {@link form} where payload should get added (by reference, OPTIONALLY!)
2401       *     If it's not given as param, you have to create an own form, if you need one.
2402       *   - 'form_use_fieldset': if a "Form" param is given and we use it, should we add
2403       *                          an own fieldset? (boolean, default "true", OPTIONALLY!)
2404       *   - 'key': A key that is associated to the caller of the event (string, OPTIONALLY!)
2405       * @return boolean True, if you have provided payload for a captcha test
2406       */
2407  	function CaptchaPayload( & $params )
2408      {
2409      }
2410  
2411  
2412      /**
2413       * Event handler: general event to validate a captcha which payload was added
2414       * through {@link CaptchaPayload()}.
2415       *
2416       * This does not get called by b2evolution itself, but provides an interface
2417       * to other plugins. E.g., the {@link dnsbl_antispam_plugin DNS blacklist plugin}
2418       * uses this event optionally to whitelist a user.
2419       *
2420       * NOTE: if the action is verified/completed in total, you HAVE to call
2421       *       {@link CaptchaValidatedCleanup()}, so that the plugin can cleanup its data
2422       *       and is not vulnerable against multiple usage of the same captcha!
2423       *
2424       * @param array Associative array of parameters
2425       *   - 'validate_error': you can optionally set this, if you want to give a reason
2426       *     of the failure. This is optionally and meant to be used by other plugins
2427       *     that trigger this event.
2428       * @return boolean true if the catcha could be validated
2429       */
2430  	function CaptchaValidated( & $params )
2431      {
2432      }
2433  
2434  
2435      /**
2436       * Event handler: general event to be called after an action has been taken, which
2437       * involved {@link CaptchaPayload()} and {@link CaptchaValidated()}.
2438       *
2439       * This is meant to cleanup generated data for the Captcha test.
2440       *
2441       * This does not get called by b2evolution itself, but provides an interface
2442       * to other plugins. E.g., the {@link dnsbl_antispam_plugin DNS blacklist plugin}
2443       * uses this event optionally to whitelist a user.
2444       */
2445  	function CaptchaValidatedCleanup( & $params )
2446      {
2447      }
2448  
2449  
2450      /**
2451       * Event handler: called at the end of {@link DataObject::dbinsert() inserting an object in the database}.
2452       *
2453       * @param array Associative array of parameters
2454       *   - 'Object': the related Object (by reference)
2455       *   - 'type': class name of deleted Object (Chapter, File, Blog, Link, Comment, Slug etc.) (by reference)
2456       */
2457  	function AfterObjectInsert( & $params )
2458      {
2459      }
2460  
2461  
2462      /**
2463       * Event handler: called at the end of {@link DataObject::dbupdate() updating an object in the database}.
2464       *
2465       * @param array Associative array of parameters
2466       *   - 'Object': the related Object (by reference)
2467       *   - 'type': class name of deleted Object (Chapter, File, Blog, Link, Comment, Slug etc.) (by reference)
2468       */
2469  	function AfterObjectUpdate( & $params )
2470      {
2471      }
2472  
2473  
2474      /**
2475       * Event handler: called at the end of {@link DataObject::dbdelete() deleting an object from the database}.
2476       *
2477       * @param array Associative array of parameters
2478       *   - 'Object': the related Object (by reference)
2479       *   - 'type': class name of deleted Object (Chapter, File, Blog, Link, Comment, Slug etc.) (by reference)
2480       */
2481  	function AfterObjectDelete( & $params )
2482      {
2483      }
2484      // }}}
2485  
2486  
2487      /**
2488       * Event handler: Called when an IP address gets displayed, typically in a protected
2489       * area or for a privileged user, e.g. in the backoffice statistics menu.
2490       *
2491       * @param array Associative array of parameters
2492       *   - 'data': the data (by reference). You probably want to modify this.
2493       *   - 'format': see {@link format_to_output()}.
2494       * @return boolean Have we changed something?
2495       */
2496  	function FilterIpAddress( & $params )
2497      {
2498          return false;        // Do nothing by default.
2499      }
2500  
2501  
2502      /**
2503       * Event handler: Called after initializing plugins, DB, Settings, Hit, .. but
2504       * quite early.
2505       *
2506       * This is meant to be a good point for Antispam plugins to cancel the request.
2507       *
2508       * @see dnsbl_antispam_plugin
2509       */
2510  	function SessionLoaded()
2511      {
2512      }
2513  
2514  
2515      /**
2516       * Event handler: Called right after initializing plugins. This is the earliest event you can use.
2517       *
2518       * This is meant to be a good point for doing early processing and cancelling the request.
2519       * Note that at this point DB charset is not set, Session and Hit aren't initialized
2520       */
2521  	function AfterPluginsInit()
2522      {
2523      }
2524  
2525  
2526      /**
2527       * Event handler: Called at the end of _main.inc.php. This is the the latest event called before blog initialization.
2528       *
2529       * This is meant to be a good point for doing processing that don't require a blog to be initialized.
2530       */
2531  	function AfterMainInit()
2532      {
2533      }
2534  
2535  
2536      /**
2537       * Event handler: Called before pruning sessions. The plugin can prevent deletion
2538       * of particular sessions, by returning their IDs.
2539       *
2540       * Note: There can be hundreds of thousands of sessions about to be deleted.
2541       * Any plugin making use of this may have serious performance/memory issues.
2542       *
2543       * fp> TODO: maybe we should pass the prune cut off date instead.
2544       * What's a use case for this?
2545       *
2546       * @param array Associative array of parameters
2547       *   - 'IDs': list of session IDs that are about to get deleted (WARNING: potentially huge)
2548       * @return array List of IDs that should not get deleted
2549       */
2550  	function BeforeSessionsDelete( & $params )
2551      {
2552          return array();
2553      }
2554  
2555  
2556      /**
2557       * Event handler: Called when a hit gets logged, but before it gets recorded.
2558       *
2559       * @param array Associative array of parameters
2560       *   - 'Hit': The "Hit" object (by reference).
2561       *
2562       * @return boolean True if you've handled the recording of the hit, false otherwise.
2563       */
2564  	function AppendHitLog( & $params )
2565      {
2566          // Do nothing by default:
2567          return false;
2568      }
2569  
2570  
2571      /**
2572       * Event handler: Called before an uploaded file gets saved on server.
2573       *
2574       * @param array Associative array of parameters
2575       *   - 'File': The "File" object (by reference).
2576       *   - 'name': file name (by reference).
2577       *   - 'type': file mimetype (by reference).
2578       *   - 'tmp_name': file location (by reference).
2579       *   - 'size': file size in bytes  (by reference).
2580       *
2581       * @return boolean 'false' to abort file upload, otherwise return 'true'
2582       */
2583  	function AfterFileUpload( & $params )
2584      {
2585          return array(); // Do nothing by default:
2586      }
2587  
2588  
2589      /*
2590       * Event handlers }}}
2591       */
2592  
2593  
2594      /*
2595       * Helper methods. You should not change/derive those in your plugin, but use them only. {{{
2596       */
2597  
2598      /**
2599       * Get a string, unqiue for the plugin, usable in HTML form elements.
2600       *
2601       * @param string Optional text to append (gets prefixed with "_").
2602       * @return string
2603       */
2604  	function get_class_id( $append = '' )
2605      {
2606          return $this->classname.'_id'.$this->ID.( $append ? '_'.$append : '' );
2607      }
2608  
2609  
2610      /**
2611       * Translate a given string, in the Plugin's context.
2612       *
2613       * This means, that the translation is obtained from the Plugin's "locales" folder.
2614       * @link http://b2evolution.net/man/localization
2615       *
2616       * It uses the global/regular {@link T_()} function as a fallback.
2617       *
2618       * @param string The string (english), that should be translated
2619       * @param string Requested locale ({@link $current_locale} gets used by default)
2620       * @return string The translated string.
2621       * @uses T_()
2622       */
2623      function T_( $string, $req_locale = '' )
2624      {
2625          global $plugins_path;
2626  
2627          $globalfile_path = $plugins_path.$this->classname.'/locales/_global.php';
2628          $trans = & $this->_trans;
2629  
2630          // Load the global messages file, if existing:
2631          if( ! $this->_trans_loaded_global )
2632          {
2633              $this->_trans_loaded_global = true;
2634  
2635              // fp> TODO: there should not be any filestats for plugins that don't implement localization.
2636              if( file_exists( $globalfile_path ) && is_readable( $globalfile_path ) )
2637              {
2638                  include_once $globalfile_path;
2639              }
2640              else
2641              {
2642                  // This is pollution of the debug log.
2643                  // $this->debug_log( 'T_: Plugin global messages file does not exist or is not readable: '.$globalfile_path, 'locale' );
2644              }
2645          }
2646  
2647          if ( ( $return = T_( $string, $req_locale, array(
2648                                  'ext_transarray' => & $this->_trans,
2649                                  'alt_basedir'    => $plugins_path.$this->classname,
2650                              ) ) ) == $string )
2651          {    // Fallback to global translation file:
2652              return T_( $string, $req_locale );
2653          }
2654          return $return;
2655      }
2656  
2657  
2658      /**
2659       * Translate and escape single quotes.
2660       *
2661       * This is to be used mainly for Javascript strings.
2662       *
2663       * @uses Plugin::T_()
2664       * @since 2.5.0
2665       * @param string String to translate
2666       * @param string Locale to use
2667       * @return string The translated and escaped string.
2668       */
2669  	function TS_( $string, $req_locale = '' )
2670      {
2671          return str_replace( "'", "\\'", $this->T_( $string, $req_locale ) );
2672      }
2673  
2674  
2675      /**
2676       * Get the absolute URL to the plugin's directory (where the plugins classfile is).
2677       * Trailing slash included.
2678       *
2679       * @param string Get absolute URL? (or make it relative to $ReqHost)
2680       * @return string
2681       */
2682  	function get_plugin_url( $abs = false )
2683      {
2684          global $ReqHost, $plugins_url, $plugins_path;
2685  
2686          $key = $abs ? 'abs' : 'rel';
2687  
2688          if( empty($this->_plugin_url) )
2689          {
2690              // Get sub-path below $plugins_path, if any
2691              $sub_path = preg_replace( ':^'.preg_quote($plugins_path, ':').':', '', dirname($this->classfile_path).'/' );
2692  
2693              $r = $plugins_url.$sub_path;
2694  
2695              // Use the same protocol as with current host (so includes from within https do not fail when on http)
2696              $r = url_same_protocol($r);
2697  
2698              $this->_plugin_url = array(
2699                      'abs' => $r, // absolute
2700                      'rel' => url_rel_to_same_host($r, $ReqHost), // relative to current host
2701                  );
2702          }
2703          return $this->_plugin_url[$key];
2704      }
2705  
2706  
2707      /**
2708       * Log a debug message.
2709       *
2710       * This gets added to {@link $Debuglog the global Debuglog} with
2711       * the category '[plugin_classname]_[plugin_ID]'.
2712       *
2713       * NOTE: if debugging is not enabled (see {@link $debug}), {@link $Debuglog}
2714       * is of class {@link Log_noop}, which means it does not accept nor display
2715       * messages.
2716       *
2717       * @param string Message to log.
2718       * @param array Optional list of additional categories.
2719       */
2720  	function debug_log( $msg, $add_cats = array() )
2721      {
2722          global $Debuglog;
2723  
2724          if( ! is_array($add_cats) )
2725          {
2726              $add_cats = array($add_cats);
2727          }
2728  
2729          if( ! isset($this->ID, $this->classname) )
2730          { // plugin not yet instantiated. This happens, if the (deprecated) constructor of a plugin gets used.
2731              $add_cats[] = get_class($this).'_?';
2732          }
2733          else
2734          {
2735              $add_cats[] = $this->classname.'_'.$this->ID;
2736          }
2737          $Debuglog->add( $msg, $add_cats );
2738      }
2739  
2740  
2741      /**
2742       * Get the URL to call a plugin method through http. This links to the /htsrv/call_plugin.php
2743       * file.
2744       *
2745       * It uses either {@link $htsrv_url} or {@link $htsrv_url_sensitive} (if {@link $ReqHost} is on https).
2746       *
2747       * NOTE: AJAX callbacks are required to be on the same domain/protocol, so if you're using absolute
2748       *       blog URLs on different domains you must set {@link $htsrv_url} dynamically, to use the same domain!
2749       *
2750       * @todo dh> we might want to provide whitelisting of methods through {@link $Session} here and check for it in the htsrv handler.
2751       *
2752       * @param string Method to call. This must be listed in {@link GetHtsrvMethods()}.
2753       * @param array Array of optional parameters passed to the method.
2754       * @param string Glue for additional GET params used internally.
2755       * @param string Get absolute URL? (or cut off $ReqHost at the beginning)
2756       * @return string The URL
2757       */
2758  	function get_htsrv_url( $method, $params = array(), $glue = '&amp;', $abs = false )
2759      {
2760          global $htsrv_url, $htsrv_url_sensitive;
2761          global $ReqHost, $Blog;
2762  
2763          $base = substr($ReqHost, 0, 6) == 'https:' ? $htsrv_url_sensitive : $htsrv_url;
2764  
2765          if( ! $abs && strpos( $base, $ReqHost ) === 0 )
2766          { // cut off $ReqHost if the resulting URL starts with it:
2767              $base = substr($base, strlen($ReqHost));
2768          }
2769  
2770          $r = $base.'call_plugin.php?plugin_ID='.$this->ID.$glue.'method='.$method;
2771          if( !empty( $params ) )
2772          {
2773              $r .= $glue.'params='.rawurlencode(serialize( $params ));
2774          }
2775  
2776          return $r;
2777      }
2778  
2779  
2780      /**
2781       * A simple wrapper around the {@link $Messages} object with a default
2782       * catgory of 'note'.
2783       *
2784       * @param string Message
2785       * @param string|array category ('note', 'error', 'success'; default: 'note')
2786       */
2787  	function msg( $msg, $category = 'note' )
2788      {
2789          global $Messages;
2790          $Messages->add( $msg, $category );
2791      }
2792  
2793  
2794      /**
2795       * Register a tab (sub-menu) for the backoffice Tools menus.
2796       *
2797       * @param string Text for the tab.
2798       * @param string|array Path to add the menu entry into.
2799       *        See {@link AdminUI::add_menu_entries()}. Default: 'options' -> 'misc' for the Tools menu.
2800       * @param array Optional params. See {@link AdminUI::add_menu_entries()}.
2801       */
2802  	function register_menu_entry( $text, $path = array( 'options', 'misc' ), $menu_entry_props = array() )
2803      {
2804          global $AdminUI;
2805  
2806          $menu_entry_props['text'] = $text;
2807          $menu_entry_props['href'] = $this->get_tools_tab_url();
2808  
2809          $AdminUI->add_menu_entries( $path, array( 'plug_ID_'.$this->ID => $menu_entry_props ) );
2810      }
2811  
2812  
2813      /**
2814       * Get URL for the tools tab for this plugin.
2815       *
2816       * The tools tab must be provided with AdminTabPayload()
2817       */
2818  	function get_tools_tab_url()
2819      {
2820          global $admin_url;
2821          return $admin_url.'?ctrl=tools&amp;tab=plug_ID_'.$this->ID;
2822      }
2823  
2824  
2825      /**
2826       * Check if the requested list of events is provided by any or one plugin.
2827       *
2828       * @param array|string A single event or a list thereof
2829       * @param boolean Make sure there's at least one plugin that provides them all?
2830       *                This is useful for event pairs like "CaptchaPayload" and "CaptchaValidated", which
2831       *                should be served by the same plugin.
2832       * @return boolean
2833       */
2834  	function are_events_available( $events, $by_one_plugin = false )
2835      {
2836          global $Plugins;
2837  
2838          return $Plugins->are_events_available( $events, $by_one_plugin );
2839      }
2840  
2841  
2842      /**
2843       * Set the status of the plugin.
2844       *
2845       * @param string 'enabled', 'disabled' or 'needs_config'
2846       * @return boolean
2847       */
2848  	function set_status( $status )
2849      {
2850          global $Plugins;
2851  
2852          if( ! in_array( $status, array( 'enabled', 'disabled', 'needs_config' ) ) )
2853          {
2854              return false;
2855          }
2856  
2857          return $Plugins->set_Plugin_status( $this, $status );
2858      }
2859  
2860  
2861      /**
2862       * Get canonical name for database tables a plugin uses, by adding an unique
2863       * prefix for your plugin instance.
2864       *
2865       * You should use this when refering to your SQL table names.
2866       *
2867       * E.g., for the "test_plugin" with ID 7 and the default {@link $tableprefix} of "evo_" it
2868       * would generate: "evo_plugin_test_7_log" for a requested name "log".
2869       *
2870       * @param string Your name, which gets returned with the unique prefix.
2871       * @return string
2872       */
2873  	function get_sql_table( $name )
2874      {
2875          global $tableprefix;
2876  
2877          // NOTE: table name length seems limited to 64 chars (MySQL 5) - classname is limited to 40 (in T_plugins)
2878          return $tableprefix.'plugin_'.preg_replace( '#_plugin$#', '', $this->classname ).'_'.$this->ID.'_'.$name;
2879      }
2880  
2881  
2882      /**
2883       * Stop propagation of the event to next plugins (with lower priority)
2884       * in events that get triggered for a batch of Plugins.
2885       *
2886       * @see Plugins::trigger_event()
2887       * @see Plugins::stop_propagation()
2888       */
2889  	function stop_propagation()
2890      {
2891          global $Plugins;
2892          $Plugins->stop_propagation();
2893      }
2894  
2895  
2896      /**
2897       * Set a data value for the session.
2898       *
2899       * NOTE: the session data is limited to about 64kb, so do not use it for huge data!
2900       *       Please consider using an own database table (see {@link Plugin::GetDbLayout()}).
2901       *
2902       * @param string Name of the data's key (gets prefixed with 'plugIDX_' internally).
2903       * @param mixed The value
2904       * @param integer Time in seconds for data to expire (0 to disable).
2905       * @param boolean Should the data get saved immediately? (otherwise it gets saved on script shutdown)
2906       */
2907  	function session_set( $name, $value, $timeout, $save_immediately = false )
2908      {
2909          global $Session;
2910  
2911          $r = $Session->set( 'plugID'.$this->ID.'_'.$name, $value, $timeout );
2912          if( $save_immediately )
2913          {
2914              $Session->dbsave();
2915          }
2916          return $r;
2917      }
2918  
2919  
2920      /**
2921       * Get a data value for the session, using a unique prefix to the Plugin.
2922       * This checks for the data to be expired and unsets it then.
2923       *
2924       * @param string Name of the data's key (gets prefixed with 'plugIDX_' internally).
2925       * @param mixed Default value to use if key is not set or has expired. (since 1.10.0)
2926       * @return mixed The value, if set; otherwise $default
2927       */
2928  	function session_get( $name, $default = NULL )
2929      {
2930          global $Session;
2931  
2932          return $Session->get( 'plugID'.$this->ID.'_'.$name, $default );
2933      }
2934  
2935  
2936      /**
2937       * Delete a value from the session data, using a unique prefix to the Plugin.
2938       *
2939       * @param string Name of the data's key (gets prefixed with 'plugIDX_' internally).
2940       */
2941  	function session_delete( $name )
2942      {
2943          global $Session;
2944  
2945          return $Session->delete( 'plugID'.$this->ID.'_'.$name );
2946      }
2947  
2948  
2949      /**
2950       * Call this to unregister all your events for the current request.
2951       */
2952  	function forget_events()
2953      {
2954          global $Plugins;
2955          $Plugins->forget_events( $this->ID );
2956      }
2957  
2958  
2959      /**
2960       * Disable an event.
2961       *
2962       * This removes it from the events table.
2963       *
2964       * @return boolean True, if status has changed; false if it was disabled already
2965       */
2966  	function disable_event( $event )
2967      {
2968          $Plugins_admin = & get_Plugins_admin();
2969          return $Plugins_admin->set_event_status( $this->ID, $event, 0 );
2970      }
2971  
2972  
2973      /**
2974       * Enable an event.
2975       *
2976       * This adds it to the events table.
2977       *
2978       * @return boolean True, if status has changed; false if it was enabled already
2979       */
2980  	function enable_event( $event )
2981      {
2982          $Plugins_admin = & get_Plugins_admin();
2983          return $Plugins_admin->set_event_status( $this->ID, $event, 1 );
2984      }
2985  
2986      /*
2987       * Helper methods }}}
2988       */
2989  
2990  
2991      /*
2992       * Interface methods. You should not override those! {{{
2993       *
2994       * These are used to access certain plugin internals.
2995       */
2996  
2997      /**
2998       * Get a link to a help page (with icon).
2999       *
3000       * @param string Target; one of the following:
3001       *         - anchor to {@link $help_url} ("#anchor")
3002       *         - absolute link to some URL, e.g. "http://example.com/example.php"
3003       *         - '$help_url' or empty for {@link $help_url}, then also the "www" icon gets used
3004       * @return string The html A tag, linking to the help (or empty in case of $readme, if there is none).
3005       */
3006  	function get_help_link( $target = '' )
3007      {
3008          static $target_counter = 0;
3009          $title = '';
3010          $icon = 'help';
3011          $word = '';
3012          $link_attribs = array( 'target' => '_blank', 'id'=>'anchor_help_plugin_'.$this->ID.'_'.$target_counter++ );
3013  
3014          if( $target == '$help_url' || empty($target) )
3015          {
3016              $url = $this->get_help_url();
3017              $title = T_('Homepage of the plugin');
3018              $icon = 'help';
3019              $link_attribs['class'] = 'action_icon help_plugin_icon';
3020              $link_attribs['rel'] = format_to_output( $this->long_desc, 'htmlspecialchars' );
3021          }
3022          elseif( $target == '$readme' )
3023          { // README
3024              // fplanque> note: we do NOT want the plugin to waste time searching for files on disk -- this has been replaced with bubbletips.
3025              return '';
3026          }
3027          elseif( substr($target, 0, 1) == '#' )
3028          { // anchor
3029              $url = $this->get_help_url().$target;
3030          }
3031          elseif( preg_match( '~^https?://~', $target ) )
3032          { // absolute URL (strict match to allow other formats later if needed)
3033              $url = $target;
3034          }
3035          else
3036          {
3037              debug_die( 'Invalid get_help_link() target: '.$target );
3038          }
3039  
3040          return action_icon( $title, $icon, $url, $word, 4, 1, $link_attribs );
3041      }
3042  
3043  
3044      /**
3045       * Get the plugin's external help/website URL.
3046       *
3047       * If {@link Plugin::$help_url} is empty, it defaults to the manual wiki.
3048       *
3049       * @return string
3050       */
3051  	function get_help_url()
3052      {
3053          if( empty( $this->help_url ) )
3054          {
3055              return 'http://b2evolution.net/man/'.strtolower( str_replace( '_', '-', $this->classname ) );
3056          }
3057          else
3058          {
3059              return $this->help_url;
3060          }
3061      }
3062  
3063  
3064      /**
3065       * @deprecated Backwards compatibility wrapper (for 1.8)
3066       */
3067  	function get_README_link()
3068      {
3069          // fplanque> note: we do NOT want the plugin to waste time searching for files on disk -- this has been replaced with bubbletips.
3070          return '';
3071      }
3072  
3073  
3074      /**
3075       * Get the help file for a Plugin ID. README.LOCALE.html will take
3076       * precedence above the general (english) README.html.
3077       *
3078       * @todo Handle encoding of files (to $io_charset)
3079       *
3080       * @return false|string
3081       */
3082  	function get_help_file()
3083      {
3084          global $default_locale, $plugins_path, $current_User;
3085  
3086          if( empty( $current_User ) || !$current_User->check_perm( 'options', 'view', false ) )
3087          { // README gets displayed through plugins controller, which requires these perms
3088              // TODO: Catch "disp_help" and "disp_help_plain" messages in plugins.php before general perms check!?
3089              return false;
3090          }
3091  
3092          // Get the language. We use $default_locale because it does not have to be activated ($current_locale)
3093          $lang = substr( $default_locale, 0, 2 );
3094  
3095          $help_dir = dirname($this->classfile_path).'/';
3096          if( $help_dir == $plugins_path )
3097          {
3098              $help_dir .= $this->classname.'/';
3099          }
3100  
3101          // Try help for the user's locale:
3102          $help_file = $help_dir.'README.'.$lang.'.html';
3103  
3104          if( ! file_exists($help_file) )
3105          { // Fallback: README.html
3106              $help_file = $help_dir.'README.html';
3107  
3108              if( ! file_exists($help_file) )
3109              {
3110                  return false;
3111              }
3112          }
3113  
3114          return $help_file;
3115      }
3116  
3117  
3118      /**
3119       * Get a link to edit the Plugin's settings (if the user has permission).
3120       *
3121       * @return false|string
3122       */
3123  	function get_edit_settings_link()
3124      {
3125          if( $url = $this->get_edit_settings_url() )
3126          {
3127              return action_icon( T_('Edit plugin settings!'), 'edit', $url );
3128          }
3129          return false;
3130      }
3131  
3132  
3133      /**
3134       * Get an URL to edit the Plugin's settings (if the user has permission).
3135       *
3136       * @return false|string
3137       */
3138  	function get_edit_settings_url()
3139      {
3140          global $current_User, $admin_url;
3141  
3142          if( ! $current_User->check_perm( 'options', 'edit', false ) )
3143          {
3144              return false;
3145          }
3146  
3147          return $admin_url.'?ctrl=plugins&amp;action=edit_settings&amp;plugin_ID='.$this->ID;
3148      }
3149  
3150  
3151      /**
3152       * Get Widget setting
3153       * @param string Name of setting
3154       * @param array Array of params (like widget params)
3155       * @return mixed|null
3156       */
3157  	function get_widget_setting( $name = NULL, $params = NULL )
3158      {
3159          if ( empty( $name ) || ! isset ( $params[$name] ) )
3160          {
3161              return NULL;
3162          }
3163          else
3164          {
3165              return $params[$name];
3166          }
3167      }
3168  
3169  
3170      /**
3171       * PHP5 overloading of get method to lazy-load (User)Settings, when they get
3172       * accessed.
3173       *
3174       * With PHP4, settings get instantiated in Plugins::init_settings right away.
3175       *
3176       * @return Reference to the object or null
3177       */
3178      function & __get( $nm )
3179      {
3180          global $inc_path;
3181          global $Plugins;
3182  
3183          switch( $nm )
3184          {
3185              case 'Settings':
3186                  if( $this->ID < 0 )
3187                  {
3188                      debug_die('Tried to access "Settings" on a non-installed plugin. ('.$this->classname.'/'.$this->ID.')');
3189                  }
3190                  $Plugins->instantiate_Settings( $this, 'Settings' );
3191                  if( isset($this->Settings) )
3192                  {
3193                      return $this->Settings;
3194                  }
3195                  break;
3196  
3197              case 'UserSettings':
3198                  if( $this->ID < 0 )
3199                  {
3200                      debug_die('Tried to access "UserSettings" on a non-installed plugin. ('.$this->classname.'/'.$this->ID.')');
3201                  }
3202                  $Plugins->instantiate_Settings( $this, 'UserSettings' );
3203                  if( isset($this->UserSettings) )
3204                  {
3205                      return $this->UserSettings;
3206                  }
3207                  break;
3208          }
3209          $r = null;
3210          return $r;
3211      }
3212  
3213      /*
3214       * Interface methods }}}
3215       */
3216  
3217      /**
3218        * Get a skin specific param value from current Blog
3219        *
3220        * @param string
3221        * @param Blog collection
3222       */
3223  	function get_coll_setting( $parname, & $Blog )
3224      {
3225          if( empty($Blog) )
3226          {    // Blog is not defined
3227              return NULL;
3228          }
3229  
3230          // Name of the setting in the blog settings:
3231          $blog_setting_name = 'plugin'.$this->ID.'_'.$parname;
3232  
3233          $value = $Blog->get_setting( $blog_setting_name );
3234  
3235          if( ! is_null( $value ) )
3236          {    // We have a value for this param:
3237              return $value;
3238          }
3239  
3240          // Try default values:
3241          $params = $this->get_coll_setting_definitions( $tmp_params = array( 'for_editing' => true, 'blog_type' => $Blog->get( 'type' ) ) );
3242          if( isset( $params[$parname]['defaultvalue'] ) )
3243          {    // We have a default value:
3244              return $params[$parname]['defaultvalue'] ;
3245          }
3246  
3247          return NULL;
3248      }
3249  
3250  
3251      /**
3252       * Set a skin specific param value for current Blog
3253       *
3254       * @param string parameter name
3255       * @param mixed parameter value
3256       */
3257  	function set_coll_setting( $parname, $parvalue, $blog = NULL )
3258      {
3259          /**
3260           * @var Blog
3261           */
3262  
3263          if( empty( $blog ) )
3264          {
3265              global $Blog;
3266          }
3267          else
3268          {
3269              $BlogCache = & get_BlogCache();
3270              $Blog = & $BlogCache->get_by_ID( $blog, false, false );
3271          }
3272  
3273          // Name of the setting in the blog settings:
3274          $blog_setting_name = 'plugin'.$this->ID.'_'.$parname;
3275          $Blog->set_setting( $blog_setting_name, $parvalue );
3276      }
3277  
3278  
3279      /**
3280       * Delete param setting from current Blog
3281       *
3282       * @param string parameter name
3283       * @param string blog id
3284       */
3285  	function delete_coll_setting( $parname, $blog = NULL )
3286      {
3287          /**
3288           * @var Blog
3289           */
3290  
3291          if( empty( $blog ) )
3292          {
3293              global $Blog;
3294          }
3295          else
3296          {
3297              $BlogCache = & get_BlogCache();
3298              $Blog = & $BlogCache->get_by_ID( $blog, false, false );
3299          }
3300  
3301          // Name of the setting in the blog settings:
3302          $blog_setting_name = 'plugin'.$this->ID.'_'.$parname;
3303          $Blog->delete_setting( $blog_setting_name );
3304      }
3305  
3306  
3307      /**
3308       * This method should return a string that used as suffix
3309       *   for the field 'From Country' on the user profile page in the BackOffice
3310       *
3311       * @param array Associative array of parameters
3312       *   - 'User': the related User (by reference)
3313       * @return string Field suffix
3314       */
3315  	function GetUserFromCountrySuffix( & $params )
3316      {
3317          return '';
3318      }
3319  
3320  
3321      /**
3322       * This method initializes an array that used as additional columns
3323       *   for the results table in the BackOffice
3324       *
3325       * @param array Associative array of parameters
3326       *   'table'   - Special name that used to know what plugin must use current table
3327       *   'column'  - DB field which contains IP address
3328       *   'Results' - Object
3329       */
3330  	function GetAdditionalColumnsTable( & $params  )
3331      {
3332      }
3333  }
3334  
3335  ?>

title

Description

title

Description

title

Description

title

title

Body