[ Index ]
 

Code source de Phorum 5.1.25

Accédez au Source d'autres logiciels libres

Classes | Fonctions | Variables | Constantes | Tables

title

Body

[fermer]

/docs/ -> creating_mods.txt (source)

   1  Creating Modules for Phorum5
   2  ============================
   3  
   4  This document describes the Phorum5 module system. It is targeted at
   5  developers who want to do customization and extend the functionality
   6  of Phorum5. Modules are the preferred way to archieve this in
   7  Phorum5.
   8  
   9  For much of this document, we will be talking about an example module
  10  "foo". Of course you will not name your module "foo", but something much
  11  more appropriate. If you're not familiar with the terms "foo" and "bar",
  12  you can visit http://en.wikipedia.org/wiki/Metasyntactic_variable
  13  
  14  Be sure to read at least the **CAUTIONS AND SECURITY ISSUES** section,
  15  before making your own modules.
  16  
  17  
  18  Table of contents:
  19  
  20  1. Introduction
  21     1.1 Modules
  22     1.2 Hacks
  23     1.3 Hooks
  24  2. Creating your own modules
  25     2.1 What modules are built of
  26         2.1.1 Hook functions
  27         2.1.2 Module information
  28         2.1.3 Other "stuff"
  29     2.2 Module structure
  30         2.2.1 Single file modules
  31         2.2.2 Multiple file modules
  32     2.3 Supporting multiple languages
  33     2.4 Storing message data
  34         2.4.1 From hooks that are run before saving a message to the database
  35         2.4.2 From other hooks
  36     2.5 Storing user data
  37     2.6 Creating custom URLs
  38     2.7 Implementing settings for your module
  39     2.8 Changing the template
  40     2.9 Example modules
  41  3. **CAUTIONS AND SECURITY ISSUES**
  42     3.1 Make modules, not hacks
  43     3.2 Reload your module if you change the module information
  44     3.3 How to access the $PHORUM array from your hook functions
  45     3.4 How to access additional files in your multi file module
  46     3.5 Secure your PHP files agains hackers
  47     3.6 Secure your pages from XSS
  48     3.7 Prevent namespace collisions
  49         3.7.1 (Hook) functions
  50         3.7.2 Data stored in $PHORUM
  51         3.7.3 Language strings stored in $PHORUM
  52         3.7.4 Data stored in messages, users and settings
  53  4. Overview of available Phorum hooks
  54     4.1 Code hooks
  55     4.2 Template hooks
  56  5. Support
  57  
  58  
  59  1. Introduction
  60  -------------------------------------------------------------------------------
  61  
  62  
  63   1.1 Modules
  64   -----------
  65  
  66     Modules are self contained pieces of software, that can be added to
  67     Phorum to change or extend its functionality. Modules can do this
  68     without having to change anything in the standard Phorum distribution
  69     files or database structure. So installing a module means: drop in
  70     the code, go to the admin "Modules" page, enable the module and it
  71     works.
  72  
  73  
  74   1.2 Hacks
  75   ---------
  76  
  77     The moment it is neccessary to make changes to the standard Phorum
  78     distribution files or database structure to implement some kind of
  79     functionality, we're talking about a hack (even if the changes
  80     that have to be made are accompanied by a drop in module).
  81  
  82     Although there is nothing wrong with writing hacks, the Phorum team
  83     wants to urge you to try if you can write a module before resorting
  84     to a hack. Modules are the preferred way of modifying Phorum
  85     functionality, because that will make both upgrading your distribution
  86     and having your modification adopted by others easier.
  87  
  88  
  89   1.3 Hooks
  90   ---------
  91  
  92     Phorum uses hooks to run its modules. Hooks are points in the
  93     application where Phorum stops and runs its data through the modules
  94     that are configured to handle the hook. The modules can act upon and
  95     change this data.
  96  
  97     The following image visualizes what happens when Phorum reaches
  98     a hook point in the application, for which two modules ("foo" and
  99     "bar") have been configured.
 100  
 101  
 102       Phorum
 103     Application
 104         (1)                                (1) Phorum is running.
 105          |                                 (2) Phorum reaches the
 106          |                                     hook named "some_hook".
 107          v           Phorum                (3) Phorum sends data to
 108      some_hook >----- data ------+             the module system.
 109         (2)            (3)       |         (4) The module "foo" is run.
 110                                  v         (5) The module "bar" is run.
 111                         (4) module "foo"   (6) The Phorum data (which
 112                                  |             might be modified by the
 113                                  v             modules) is sent back
 114                         (5) module "bar"       to Phorum.
 115                                  |         (7) Phorum continues running
 116       Phorum        Modified     |             with the modified data.
 117     Application <---- data ------+
 118         (7)            (6)
 119          |
 120          |
 121          v
 122  
 123  
 124  2. Creating your own modules
 125  -------------------------------------------------------------------------------
 126  
 127  
 128   2.1 What modules are built of
 129   -----------------------------
 130  
 131  
 132    2.1.1 Hook functions
 133    --------------------
 134  
 135     A module contains one or more PHP functions that act as hook
 136     functions. Hook functions will receive some data in a variable
 137     from Phorum and have to return the (possibly modified) data, which
 138     will then go either back to Phorum or to the input of another module
 139     which also handles the same hook (see 1.3). So the most basic (and
 140     useless :-) hook function you could write would look somewhat like this
 141     (see 3.7 for an explanation of the naming of the function):
 142  
 143        function phorum_mod_foo_some_hook ($data) {
 144            return $data;
 145        }
 146  
 147     The exact nature of the data that is sent to the hook functions
 148     depends solely on the hook that is run. In chapter 4 of this document
 149     you will find a description of all supported hooks, including a
 150     specification of the type of data that is sent.
 151  
 152  
 153    2.1.2 Module information
 154    ------------------------
 155  
 156     For each hook that you want to handle in your module, you will have
 157     to point the module system to the function in your module that will
 158     handle the hook. Together with some other information, used for
 159     describing the module, this is stored in the module information.
 160     The module information acts as the glue between Phorum and your
 161     module.
 162  
 163     Module information is formatted using lines of plain text. Each line
 164     contains a bit of information about the module. The general format
 165     of the lines in the module information is:
 166  
 167        <type>: <data>
 168  
 169     Here is a list of the types that can be used:
 170  
 171     +--------+-----------------------------------------------------------+
 172     | <type> | <data>                                                    |
 173     +--------+-----------------------------------------------------------+
 174     | title  | This is the title for the module that is displayed in the |
 175     |        | "Modules" page of the admin interface.                    |
 176     +--------+-----------------------------------------------------------+
 177     | desc   | This is the description that is displayed along with the  |
 178     |        | title in the admin interface, to give a little more       |
 179     |        | information about the module. Using HTML in the <data>    |
 180     |        | part is allowed.                                          |
 181     +--------+-----------------------------------------------------------+
 182     | hook   | This describes which hook functions are called for which  |
 183     |        | Phorum hooks. The data consists of two fields, separated  |
 184     |        | by a pipe "|" symbol. The first field contains the name   |
 185     |        | of the hook that this module is hooking into. The second  |
 186     |        | field contains the name of the hook function that will be |
 187     |        | called for the hook.                                      |
 188     +--------+-----------------------------------------------------------+
 189  
 190     It is allowed to use multiple hook lines in your module information,
 191     so your module can hook into multiple hooks. When doing this, it
 192     is also allowed to use the same hook function for handling different
 193     hooks in your module (asuming the hooks are compatible).
 194  
 195     Here's an example of what the module information for our example
 196     module "foo" might look like:
 197  
 198        title: Foo example module
 199        desc: This is the Foo module for Phorum. Nothing exciting...
 200        hook: some_hook|phorum_mod_foo_some_hook
 201        hook: some_other_hook|phorum_mod_foo_some_other_hook
 202        hook: yet_another_hook|phorum_mod_foo_some_other_hook
 203  
 204     So what this module info for example does, is telling Phorum that
 205     when it gets to "some_other_hook", it will have to call the function
 206     phorum_mod_foo_some_other_hook() in your module. It also tells
 207     that for "yet_another_hook" the same function has to be called.
 208  
 209  
 210    2.1.3 Other "stuff"
 211    -------------------
 212  
 213     Hook functions and the module information are all the parts needed
 214     for creating a working module. However, your module might need
 215     extra stuff like template, language and image files. You can
 216     store these files along with your module when using the multiple
 217     file module structure (see 2.2.2 below).
 218  
 219     If you do not need to store any other stuff with your module, you
 220     can also choose to use the single file (see 2.2.1 below) module
 221     structure.
 222  
 223  
 224   2.2 Module structure
 225   --------------------
 226  
 227  
 228    2.2.1 Single file modules
 229    -------------------------
 230  
 231     Single file modules are useful in case case no additional files have
 232     to be distributed with your module. Because the module consist of
 233     only one single file, it is very easy to distribute. Beware that the
 234     moment you want to support for example a settings screen, multiple
 235     languages or custom images, you will have to switch to the multiple
 236     file module structure.
 237  
 238     Single file modules consist of one single PHP file, which contains
 239     both the module information and the hook functions. For storing the
 240     module informaton, a special PHP comment is used. This comment must
 241     look like the following:
 242  
 243        /* phorum module info
 244        <module information lines go here>
 245        */
 246  
 247     Using the example module info from 2.1.2, the complete single
 248     file module would look like this (see 3.5 why we use the
 249     check on PHORUM at the start of this file):
 250  
 251        <?php
 252  
 253        if(!defined("PHORUM")) return;
 254  
 255        /* phorum module info
 256        title: Foo example module
 257        desc: This is the Foo module for Phorum. Nothing exciting...
 258        hook: some_hook|phorum_mod_foo_some_hook
 259        hook: some_other_hook|phorum_mod_foo_some_other_hook
 260        hook: yet_another_hook|phorum_mod_foo_some_other_hook
 261        */
 262  
 263        function phorum_mod_foo_some_hook ($data) {
 264            // Do stuff for "some_hook".
 265            return $data;
 266        }
 267  
 268        function phorum_mod_foo_some_other_hook ($data) {
 269            // Do stuff for "some_other_hook" and "yet_another_hook".
 270            return $data;
 271        }
 272  
 273        ?>
 274  
 275     Installation of a single file module is done by putting the PHP
 276     file (e.g. foo.php) directly in the directory {phorum dir}/mods/
 277     and activating the module from the "Modules" screen in your
 278     admin interface.
 279  
 280  
 281    2.2.2 Multiple file modules
 282    ---------------------------
 283  
 284     Multiple file modules are useful in case you need additional files
 285     to be stored with your module, for example a settings screen,
 286     language files or custom images.
 287  
 288     Multiple file modules are stored in their own subdirectory below
 289     the directory {phorum dir}/mods/. So if you have a module named
 290     "foo", you will have to create a directory {phorum dir}/mods/foo/ for
 291     storing all module files.
 292  
 293     Inside this subdirectory, you will have to create a least two files.
 294     The first is a file called "info.txt". This file contains the
 295     module information for your module (see 2.1.2). The second file
 296     is the PHP file which contains the hook functions for your module.
 297     The basename of this file should be the same as the name of the
 298     module subdirectory. So for our example module "foo", you will have
 299     to create a file named "foo.php".
 300  
 301     Using the example module info from 2.1.2, the complete multiple
 302     file module would look like this (see 3.5 why we use the
 303     check on PHORUM at the start of the PHP file):
 304  
 305     info.txt:
 306  
 307        title: Foo example module
 308        desc: This is the Foo module for Phorum. Nothing exciting...
 309        hook: some_hook|phorum_mod_foo_some_hook
 310        hook: some_other_hook|phorum_mod_foo_some_other_hook
 311        hook: yet_another_hook|phorum_mod_foo_some_other_hook
 312  
 313     foo.php:
 314  
 315        <?php
 316  
 317        if(!defined("PHORUM")) return;
 318  
 319        function phorum_mod_foo_some_hook ($data) {
 320            // Do stuff for "some_hook".
 321            return $data;
 322        }
 323  
 324        function phorum_mod_foo_some_other_hook ($data) {
 325            // Do stuff for "some_other_hook" and "yet_another_hook".
 326            return $data;
 327        }
 328  
 329        ?>
 330  
 331     So far, the module has exactly same functionality as the single
 332     file module from 2.2.1. From here on, the functionality can be
 333     extended. Some of the possibilities are:
 334  
 335     - Using custom files for your module (images, classes, libs, etc.);
 336     - Letting your module support multiple languages;
 337     - Creating a settings screen for your module;
 338  
 339  
 340   2.3 Supporting multiple languages
 341   ---------------------------------
 342  
 343     (this feature is only available for the multiple file module structure)
 344  
 345     If your module includes text that will be displayed to end users,
 346     you should strongly consider making it support multiple languages.
 347     This will allow Phorum installations using another language to display
 348     output of your module in the same language, instead of the language
 349     you have written the module in.
 350  
 351     For supporting multiple languages, the first thing to do is add the
 352     following to your module information file (info.txt):
 353  
 354        hook: lang|
 355  
 356     There is no hook function configured here, because the "lang" hook
 357     is only used as a marker for Phorum. This only tells Phorum that your
 358     module supports multiple languages.
 359  
 360     Next, you must provide at least one language file with your module.
 361     Language files are stored in a subdirectory name "lang" inside your
 362     module directory. So in our sample module, the full directory would be
 363     {phorum dir}/foo/lang/. The language files must be named identical
 364     to the main language files that Phorum uses. So, to include both
 365     English and French, your module would have the following file
 366     structure below the Phorum's mods directory:
 367  
 368        foo/info.txt
 369        foo/foo.php
 370        foo/lang/english.php
 371        foo/lang/french.php
 372  
 373     The structure of your language files will be almost identical to that
 374     of the main Phorum language files. However, for your own language files
 375     it is advisable to add an extra level in the language variables, to
 376     avoid conflicts with other modules or Phorum itself. Here is an
 377     example of how you would do that:
 378  
 379        <?php
 380        $PHORUM["DATA"]["LANG"]["mod_foo"]["Hello"] = "Hello!";
 381        ?>
 382  
 383     Here, the extra inserted level is ["mod_foo"]. You can add as many
 384     lines as you need for your module. To access the above language string,
 385     from your module code you would use:
 386  
 387        $PHORUM["DATA"]["LANG"]["mod_foo"]["Hello"]
 388  
 389     From a template file, you would use:
 390  
 391        {LANG->mod_foo->Hello}
 392  
 393     In case a Phorum installation is using a language that your module
 394     does not support, Phorum will automatically attempt to fallback to
 395     English. So it is highly recommend that you include an english.php
 396     language file in all your modules. If both the current language and
 397     english.php are not found, Phorum will be unable to load a language
 398     for your module and will display empty space instead of language
 399     strings.
 400  
 401     Try to reuse strings that are already in the main Phorum language
 402     files itself. Only create custom strings when there is no alternative
 403     available. Having more text to translate is more work for everybody,
 404     especially the Phorum translators.
 405  
 406  
 407   2.4 Storing message data
 408   ------------------------
 409  
 410     If your module needs to store data along with a Phorum message,
 411     you can make use of the meta information array that is attached
 412     to each message ($message["meta"]). This array is a regular PHP
 413     array, which is stored in the database as serialized data
 414     (see http://www.php.net/serialize). Because Phorum and other modules
 415     make use of this meta data as well, you should not squash it,
 416     neither access the meta data in the database directly. Instead
 417     use the methods described in this section.
 418  
 419     Remark: because the meta data is stored as serialized data in the
 420     database, it is not possible to include data you store in there
 421     in SQL queries.
 422  
 423     When storing information in the meta data from a hook function, you
 424     can encounter two different situations, which both need a different
 425     way of handling.
 426  
 427  
 428    2.4.1 From hooks that are run before saving a message to the database
 429    ---------------------------------------------------------------------
 430  
 431     There are some hooks that send a full message structure to the
 432     hook functions, so these can change the message data before storing
 433     the message in the database. Examples are the hooks "pre_post"
 434     and "pre_edit". In this case you can simply update the meta
 435     information directly. Here's an example of how this would look
 436     in your hook function:
 437  
 438        function phorum_mod_foo_pre_post ($message) {
 439            $message["meta"]["mod_foo"]["foodata"] = "Some data";
 440            $message["meta"]["mod_foo"]["bardata"] = "Some more data";
 441            return $message;
 442        }
 443  
 444     Phorum will take care of storing the updated meta data in the database.
 445  
 446  
 447    2.4.2 From other hooks
 448    ----------------------
 449  
 450     For other hooks, the proper way to store information in the meta
 451     data is to retrieve the current meta data using phorum_db_get_message(),
 452     copy the meta data to a new message structure, make changes as needed
 453     and use phorum_db_update_message() to update the message in the
 454     database. Here is an example of how this could look in your hook
 455     function:
 456  
 457        function phorum_mod_foo_some_hook ($data) {
 458  
 459            // Somehow you get the id for the message. Here we asume
 460            // that it is stored in the $data parameter.
 461            $message_id = $data["message_id"];
 462  
 463            // Retrieve the current message data.
 464            $message = phorum_db_get_message ($message_id);
 465  
 466            // Create updated meta data.
 467            $new_message = array("meta" => $message["meta"]);
 468            $new_message["meta"]["mod_foo"]["foodata"] = "Some data";
 469            $new_message["meta"]["mod_foo"]["bardata"] = "Some more data";
 470  
 471            // Store the updated data in the database.
 472            phorum_db_update_message($message_id, $new_message);
 473  
 474            return $data;
 475        }
 476  
 477     Changing meta data for a message this way will ensure that the
 478     existing meta data is kept intact.
 479  
 480  
 481   2.5 Storing user data
 482   ---------------------
 483  
 484     If your module needs to store data along with a Phorum user,
 485     you can make use of custom profile fields. In the admin interface,
 486     under "Custom Profiles", you can add your own profile fields
 487     (see also docs/creating_custom_userfields.txt).
 488  
 489     The custom profile fields will be accessible from within the user
 490     data. E.g. if you have created a custom profile field named "foobar",
 491     the value of that field will be stored in $user["foobar"].
 492  
 493     When using a custom profile field for storing module information,
 494     you can use a separate field for each piece of data you want to
 495     store. But instead, you can also create a single field for storing
 496     a complete array of information. Phorum will automatically take care
 497     of storing this information (serialized) in the database. You only
 498     should make sure that the custom profile field is large enough to
 499     store all the data. When your module needs to store multiple fields,
 500     this is the preferred way.
 501  
 502     For storing data in the custom profile field, you can make use of the
 503     phorum_user_save() function. This function needs the user_id of the
 504     user and all fields that need to be updated. Below are two pieces of
 505     code which show how our example module might store data for a user
 506     (asuming $user_id is the id of the user that must be changed).
 507  
 508     When using multiple fields "mod_foo_foodata" and "mod_foo_bardata":
 509  
 510        $userdata = array(
 511            "user_id"         => $user_id,
 512            "mod_foo_foodata" => "Some user data",
 513            "mod_foo_bardata" => "Some more user data"
 514        );
 515        phorum_user_save($userdata);
 516  
 517     When using a single custom field "mod_foo" for this module:
 518  
 519        $user = phorum_user_get($user_id);
 520        $userdata = array(
 521            "user_id" => $user_id,
 522            "mod_foo" => array (
 523                "foodata" => "Some user data",
 524                "bardata" => "Some more user data"
 525            )
 526        );
 527        phorum_user_save($user);
 528  
 529  
 530   2.6 Creating custom URLs
 531   -------------------------
 532  
 533     Phorum uses the function phorum_get_url() to consistenly build URLs
 534     that point to parts of Phorum. It is recommended that you use this
 535     function as well when creating links yourself, so special features
 536     and future changes will automatically be incorporated in the links
 537     you use.
 538  
 539     Here's an example of building an URL, which will open the profile
 540     for the user with user_id = 17:
 541  
 542        $url = phorum_get_url(PHORUM_PROFILE_URL, 17);
 543  
 544     The argument list that this function takes, depends on the first
 545     argument which tells Phorum what kind of URL has to be built.
 546     So when building other URLs, other arguments will probably
 547     be used.
 548  
 549     If you need to build a custom URL to link to your own module, you
 550     can use phorum_get_url() as well. The way to go is simple. You
 551     need to use PHORUM_CUSTOM_URL as the first argument and add all
 552     URL building parameters to it.
 553  
 554     The first parameter needs to be the filename of the file to link
 555     to, without the (.php) extension. The second parameter needs to
 556     be 0 or 1. If it is 1, the current forum_id is added to the URL.
 557     All other parameters are added comma separated to the URL.
 558  
 559     Here's an example of building a custom URL which links to the
 560     file "myfile.php". The URL has to have the forum_id in it and
 561     needs to contain the additional parameter "foo=bar":
 562  
 563        $url = phorum_get_url(PHORUM_CUSTOM_URL, "myfile", 1, "foo=bar");
 564  
 565  
 566   2.7 Implementing settings for your module
 567   -----------------------------------------
 568  
 569     (this feature is only available for the multiple file module structure)
 570  
 571     Some modules that you write might need to store settings for later
 572     use. For those, you can create a settings page which will be used
 573     from within the admin interface.
 574  
 575     The settings page must be put in your modules's directory by the
 576     name of "settings.php". So for our example module "foo" the file
 577     would go in {phorum dir}/mods/foo/settings.php. In the admin
 578     interface under the option "Modules", a link to the settings.php
 579     page will automatically be added if the settings.php file is
 580     available for your module.
 581  
 582     Although you can do anything you want from your settings.php script,
 583     it is recommended that you use the tools that are handed to you
 584     by Phorum for building pages and storing settings.
 585  
 586     One of those tools is a PHP object "PhorumInputForm" which
 587     can be used to create standard input forms and table displays in
 588     the admin interface. The best example here is to look at one of the
 589     modules that come with Phorum like "bbcode" or "replace".
 590  
 591     Another tool is the function phorum_db_update_settings() which can
 592     be used for storing settings in the database. To store settings using
 593     this function you do something like the following:
 594  
 595        $foo_settings["foodata"] = "Some setting data";
 596        $foo_settings["bardata"] = "Some more setting data";
 597        phorum_db_update_settings(array("mod_foo" => $foo_settings));
 598  
 599     $foo_settings can be anything you like: an array, object, string, etc.
 600     The first request after you have stored your settings, the setting
 601     data for this example will be available in $PHORUM["mod_foo"].
 602  
 603     To ensure that your settings file is only loaded from the admin
 604     interface, place this line at the top of your settings.php file
 605     (see also 3.5):
 606  
 607        if(!defined("PHORUM_ADMIN")) return;
 608  
 609  
 610   2.8 Changing the templates using template hooks
 611   -----------------------------------------------
 612  
 613  
 614    2.8.1 When to use a template hook
 615    ---------------------------------
 616  
 617     Changing the templates should be avoided as much as possible when
 618     writing a module. This will basically turn your mod into a hack,
 619     because files have to be edited for it. Inexperienced users might
 620     find it hard to install your module if they have to modify files
 621     to get it to work.
 622  
 623     If you cannot avoid changing the template, then consider to use
 624     template hooks for this. You can use these if your template change
 625     involves adding extra code to a template. The advantage is that
 626     there's only little code that has to be added to the templates,
 627     which makes things less confusing to users that want to install the
 628     module.
 629  
 630  
 631    2.8.2 How to use a template hook
 632    --------------------------------
 633  
 634     To create a template hook, you do the following:
 635  
 636     * Add "{HOOK tpl_some_hook}" to the template at an appropriate spot;
 637  
 638     * Put "hook: tpl_some_hook|phorum_mod_foo_tpl_some_hook" in your
 639       module info;
 640  
 641     * Create the hook function phorum_mod_foo_tpl_some_hook() that
 642       prints out the code that has to be placed at the position of
 643       the "{HOOK tpl_some_hook}" code the the template.
 644  
 645     If you want to pass on the data from template variables to
 646     the hook function, you can simply add the variables to the hook
 647     definition in the template. Example:
 648  
 649        {HOOK tpl_some_hook DATA1 DATA2}
 650  
 651     The hook function will get the contents of these variables passed in
 652     a single array. This can for example be useful if your template hook
 653     needs access to loop data. Example:
 654  
 655        {LOOP MESSAGES}
 656           ...
 657           {HOOK tpl_some_hook MESSAGES}
 658           ...
 659        {/LOOP MESSAGES}
 660  
 661  
 662    2.8.3 Preventing collisions in hook names
 663    -----------------------------------------
 664  
 665     You can use any name for "tpl_some_hook", but beware that your
 666     name does not collide with an already existing hook name.
 667  
 668     The easiest way to do this is use the techniques from section 3.7.
 669     As a rule of thumb, you can use the following format:
 670  
 671        tpl_mod_<modulename>_<identifier>
 672  
 673     Example: If a buttonbar is added in one of the templates for a module
 674     named "foo", the name for the hook could be "tpl_mod_foo_buttonbar".
 675  
 676  
 677   2.9 Example modules
 678   -------------------
 679  
 680     The best way of learning how to write modules is probably looking
 681     at existing module code. In your Phorum distribution's docs directory,
 682     you will find the directory example_mods. This directory contains a
 683     couple of example modules, demonstrating the features described in this
 684     document. The modules have no real functional purpose, but they might
 685     be easier to read than the real Phorum modules.
 686  
 687  
 688  3. **CAUTIONS AND SECURITY ISSUES**
 689  -------------------------------------------------------------------------------
 690  
 691  
 692   3.1 Make modules, not hacks
 693   ---------------------------
 694  
 695     Making modules that require database changes are discouraged and may
 696     not be accepted as an approved module. We want modules to be as
 697     transparent as possible for upgrades. Please attempt to store your
 698     data in the proper place. See chapter 2 for more information on that.
 699  
 700  
 701   3.2 Reload your module if you change the module information
 702   -----------------------------------------------------------
 703  
 704     If you are changing the module info for a module that is already
 705     activated in your Phorum installation, you must deactivate and
 706     reactivate it to have Phorum reload the changed information. For
 707     performance reasons the module information is only read when the
 708     module is activated.
 709  
 710     If you have added a new hook function to your module and it seems
 711     not to be run, it probably is because you did not do this.
 712  
 713  
 714   3.3 How to access the $PHORUM array from your hook functions
 715   ------------------------------------------------------------
 716  
 717     The $PHORUM array is in the global scope. From inside a function,
 718     you can not directly access this array. So you will have to import
 719     the $PHORUM array into your function scope. The Phorum team
 720     recommends the following method for doing this (check out the
 721     faq.txt to see why we do not use the "global" keyword):
 722  
 723        function phorum_mod_foo_some_hook ($data) {
 724            $PHORUM = $GLOBALS["PHORUM"];
 725  
 726            // Do stuff for "some_hook".
 727  
 728            return $data;
 729        }
 730  
 731  
 732   3.4 How to access additional files in your multi file module
 733   ------------------------------------------------------------
 734  
 735     All standard Phorum pages are run from the Phorum installation
 736     directory. The hook functions that you write also work from
 737     the same directory. So if you want to access files in your module
 738     directory, you will have to specify the relative path to those
 739     files. This path looks like:
 740  
 741        ./mods/<module>/<filename>
 742  
 743     So let's say that our module "foo" has a subdirectory "images"
 744     which contains "bar.gif", then we could display that image
 745     using the HTML code:
 746  
 747        <img src="./mods/foo/images/bar.gif" />
 748  
 749     Another example: let's say that there is a function library
 750     named "my_module_functions.php" in the module, which must be
 751     included from then module code, then this is done using:
 752  
 753        include("./mods/foo/my_module_functions.php");
 754  
 755  
 756   3.5 Secure your PHP files agains hackers
 757   ----------------------------------------
 758  
 759     To prevent hackers from loading your PHP module files directly, you
 760     should add the following to the start of your PHP files:
 761  
 762        if(!defined("PHORUM")) return;
 763  
 764     This will make sure that the file will only work when loaded from
 765     the Phorum application. If you are writing pages that are loaded
 766     from the admin interface (like a settings screen for your module),
 767     then use the following line instead:
 768  
 769        if(!defined("PHORUM_ADMIN")) return;
 770  
 771     This will make sure that the file will only work when loaded from
 772     the Phorum admin interface.
 773  
 774  
 775   3.6 Secure your pages from XSS
 776   ------------------------------
 777  
 778     XSS stands for cross site scripting. This means that hackers
 779     can feed HTML data to your application, which is displayed on
 780     screen without stripping or escaping the HTML data. This way
 781     it can be possible for hackers to feed malicous javascript
 782     code into the browser of users on the forum, causing a security
 783     risk. If you want to learn more about XSS, please visit
 784     http://en.wikipedia.org/wiki/XSS
 785  
 786     To prevent XSS security holes, you must take care that all
 787     user input is properly sanitized before displaying it on screen.
 788     Sanitizing can be done by either stripping all HTML from
 789     the data (e.g. using http://www.php.net/strip_tags) or by escaping
 790     all html characters (using http://www.php.net/htmlspecialchars).
 791  
 792     Example:
 793  
 794     If your module needs to display the username for a user on
 795     screen, it must not simply do:
 796  
 797         print $user["username"];
 798  
 799     Instead you must use:
 800  
 801         print htmlspecialchars($user["username"]);
 802  
 803     It's not only for security that you have to sanitize data before
 804     displaying it. You must use htmlspecialchars() to prevent some other
 805     possible problems as well. Imagine you have a user with the username
 806     "<b>ob". Without htmlspecialchars() the username would be interpreted
 807     as HTML code, possibly making the full page bold from the username on.
 808  
 809  
 810   3.7 Prevent namespace collisions
 811   --------------------------------
 812  
 813     When creating modules, you must always be aware that you are
 814     working in the same namespace as other modules and Phorum itself.
 815     This means that there is a risk of duplicate use of function
 816     and variable names. By following a couple of simple rules, you
 817     can greatly reduce this risk.
 818  
 819  
 820    3.7.1 (Hook) functions
 821    ----------------------
 822  
 823     Always construct names for your module functions like this:
 824  
 825        phorum_mod_<module name>_<identifier>
 826  
 827     So if you are writing functions for a module named "foo", all
 828     function names will look like:
 829  
 830        phorum_mod_foo_<identifier>
 831  
 832     You can use whatever you like for the <identifier> part. When writing
 833     a hook function, it is recommended to use the name of the hook for
 834     which you are writing the function (this will make clear what the
 835     function does, without having to check the module info). So in case
 836     you are writing a hook function for the hook "some_hook", the full
 837     function name would be:
 838  
 839        phorum_mod_foo_some_hook
 840  
 841     If your hook function handles multiple hooks at once, then
 842     simply use one of the hook's names as the <identifier> or make up
 843     something yourself.
 844  
 845  
 846    3.7.2 Data stored in $PHORUM
 847    ----------------------------
 848  
 849     When storing data in $PHORUM, always prepend the array key name
 850     with mod_<module name>. If your module is named "foo", do not use:
 851  
 852        $PHORUM["mydata"]
 853  
 854     but instead:
 855  
 856        $PHORUM["mod_foo_mydata"]
 857  
 858  
 859    3.7.3 Language strings stored in $PHORUM
 860    ----------------------------------------
 861  
 862     When storing your custom language strings, do not put them directly
 863     in $PHORUM["DATA"]["LANG"] like Phorum does, because that might
 864     result in conflicting language strings. Instead add an extra data level,
 865     which makes sure that your module keeps all language strings to itself.
 866  
 867     If your module is named "foo", you should store language strings in:
 868  
 869        $PHORUM["DATA"]["LANG"]["mod_foo"]
 870  
 871     See also section 2.3.
 872  
 873  
 874    3.7.4 Data stored in messages, users and settings
 875    -------------------------------------------------
 876  
 877     When using the Phorum provided ways of storing data in messages,
 878     users and settings, always prepend the data key with
 879     mod_<module name>. SO if your module is named "foo", do not use
 880     things like:
 881  
 882        $new_message["meta"]["foodata"] = "Some data";
 883        $user["foodata"] = "Some data";
 884        phorum_db_update_settings(array("settings" => $foo_settings));
 885  
 886     but instead:
 887  
 888        $new_message["meta"]["mod_foo_foodata"] = "Some data";
 889        $user["mod_foo_foodata"] = "Some data";
 890        phorum_db_update_settings(array("mod_foo" => $foo_settings));
 891  
 892     See also sections 2.4 (message data), 2.5 (user data) and 2.7 (settings).
 893  
 894  
 895  4. Overview of available Phorum hooks
 896  -------------------------------------------------------------------------------
 897  
 898     In this chapter you will find an overview of all available Phorum
 899     hooks and a description of what they do.
 900  
 901     Remarks:
 902  
 903     * Input is what your module function should expect as parameters.
 904  
 905     * Return is what your module function should return. Most hooks
 906       expect the same data structure as was sent. For those items,
 907       the Return is listed simply as "Same as Input".
 908  
 909     * Normally, hook functions are allowed to modify the data that was
 910       sent as input. If this is not allowed, the input data will be
 911       flagged as read-only.
 912  
 913     * In most cases the hook description will provide only one or more
 914       of the possible uses for the hook. The full leverage of each hook
 915       is only limited by the imagination of the module writer (it's
 916       as much a cliche as it is true).
 917  
 918     * It may be that you need to hook into a spot where there is
 919       currently no hook available. If that is the case, let the dev
 920       team know by posting a message in the development forum
 921       on phorum.org, explaining where and why you need an extra hook.
 922       Hooks will be added as neccessary, especially while Phorum 5
 923       is young.
 924  
 925  
 926   4.1 Code hooks
 927   --------------
 928  
 929     Code hooks are hooks that are called from within the Phorum core
 930     code. These hooks are typically used for modifying Phorum's internal
 931     datastructures.
 932  
 933  
 934     ----------------------------------------------------------------------------
 935     admin_general
 936  
 937     Where  : admin interface
 938     When   : Right before the PhorumInputForm object is shown.
 939     Input  : The PhorumInputForm object.
 940     Return : Same as Input
 941  
 942     This hook can be used for adding items to the form on the
 943     "General Settings" page of the admin interface.
 944  
 945     ----------------------------------------------------------------------------
 946     admin_file_purge
 947  
 948     Where  : admin interface, option "Purge Stale Files"
 949     When   : Right before stale files are deleted from the database.
 950     Input  : An array, containing a description of all stale files.
 951     Return : Same as Input
 952  
 953     The primary use of this hook would be to cleanup stale files, created
 954     by an alternate storage system for attachments (see after_attach and
 955     after_detach as well). The array that is passed on to the hook function
 956     contains arrays, which contain the following fields:
 957  
 958     file_id      : Internal id to reference the file.
 959     filename     : Name of the file.
 960     filesize     : Filesize in KB.
 961     add_datetime : Epoch timestamp for the time the file was created.
 962     reason       : A description why this file is considered to be stale.
 963  
 964     ----------------------------------------------------------------------------
 965     after_attach
 966  
 967     Where  : include/posting/action_attachments.php
 968     When   : Just after a file attachment is saved in the database
 969     Input  : Two part array where the first element is the message array and
 970              the second element is a file array that contains the name, size,
 971              and file_id of the newly saved file.
 972     Return : Same as Input
 973  
 974     The primary use of this hook would be for creating an alternate storage
 975     system for attachments. You would need to use the before_attach hook to
 976     remove the file data and in this hook it could be saved properly. You will
 977     need to use the file hook to retreive the file data later.
 978  
 979     ----------------------------------------------------------------------------
 980     after_detach
 981  
 982     Where  : include/posting/action_attachments.php
 983     When   : Just after a file attachment is deleted from the database
 984     Input  : Two part array where the first element is the message array and
 985              the second element is a file array that contains the name, size,
 986              and file_id of the deleted file.
 987     Return : Same as Input
 988  
 989     The primary use of this hook would be for creating an alternate storage
 990     system for attachments. Using this hook, you can delete the file from
 991     your alternate storage.
 992  
 993     ----------------------------------------------------------------------------
 994     after_header
 995  
 996     Where  : Every page, except for the admin interface pages
 997     When   : Right after the header is displayed.
 998     Input  : none
 999     Return : none
1000  
1001     This hook can be used for creating content at the end of the header,
1002     just before the main content is displayed.
1003  
1004     ----------------------------------------------------------------------------
1005     after_login
1006  
1007     Where  : login.php
1008     When   : After a successful login, just before redirecting the
1009              user to a Phorum page.
1010     Input  : The redirection URL.
1011     Return : Same as Input
1012  
1013     This hook can be used for performing tasks after a successful user
1014     login and for changing the page to which the user will be redirected
1015     (by returning a different redirection URL). If you need to access the
1016     user data, then you can do this through the global $PHORUM variable.
1017     The user data will be in $PHORUM["user"].
1018  
1019     ----------------------------------------------------------------------------
1020     after_logout
1021  
1022     Where  : login.php
1023     When   : After a logout, just before redirecting the user to
1024              a Phorum page.
1025     Input  : The redirection URL.
1026     Return : Same as Input
1027  
1028     This hook can be used for performing tasks after a successful user
1029     logout and for changing the page to which the user will be redirected
1030     (by returning a different redirection URL). The user data will still
1031     be availbale in $PHORUM["user"] at this point.
1032  
1033     ----------------------------------------------------------------------------
1034     after_message_save
1035  
1036     Where  : action_post.php
1037     When   : After storing a new message and all database updates are done.
1038     Input  : Array containing message data.
1039     Return : Same as Input
1040  
1041     This hook can be used for performing actions based on what the message
1042     contained or altering it before it is emailed to the subscribed users.
1043     It is also useful for adding or removing subscriptions.
1044  
1045     ----------------------------------------------------------------------------
1046     after_register
1047  
1048     Where  : register.php
1049     When   : Right after a successful registration of a new user is done
1050              and all confirmation mails are sent.
1051     Input  : Array containing the user data of the user (read-only).
1052     Return : Same as Input
1053  
1054     This hook can be used for performing tasks (like logging and
1055     notification) after a successful user registration.
1056  
1057     ----------------------------------------------------------------------------
1058     before_attach
1059  
1060     Where  : include/posting/action_attachments.php
1061     When   : Just before a file attachment is saved in the database
1062     Input  : Two part array where the first element is the message array and
1063              the second element is a file array that contains the name, size
1064              and data.
1065     Return : Same as Input
1066  
1067     The primary use of this hook would be for creating an alternate storage
1068     system for attachments. You would need to use the after_attach hook to
1069     complete the process as you do not yet have the file_id for the file. You
1070     will need to use the file hook to retreive the file data later.
1071  
1072     ----------------------------------------------------------------------------
1073     before_editor
1074  
1075     Where  : posting.php
1076     When   : Just before the message editor is displayed.
1077     Input  : Array containing data for the message that will be shown
1078              in the editor screen.
1079     Return : Same as Input
1080  
1081     This hook can be used for changing message data, just before the editor
1082     is displayed. This is done after escaping message data for XSS prevention
1083     is done. So in the hook, the module writer will have to be aware that
1084     data is escaped and that he has to escape data himself if needed.
1085  
1086     This hook is called every time the editor is displayed. If modifying
1087     the message data does not have to be done on every request (for example
1088     only on the first request when replying to a message), the module will
1089     have to check the state the editor is in. Here's some hints on what
1090     you could do to accomplish this:
1091  
1092     * Check the editor mode: this can be done by looking at the "mode" field
1093       in the message data. This field can be one of "post", "reply" and "edit".
1094  
1095     * Check if it's the first request: this can be done by looking at the
1096       $_POST array. If no field "message_id" can be found in there, the
1097       editor is handing the first request.
1098  
1099     Using this, an example hook function that appends the string "FOO!"
1100     to the subject when replying to a message (how useful ;-) could look
1101     like this:
1102  
1103        function phorum_mod_foo_before_editor ($data)
1104        {
1105           if ($data["mode"] == "reply" && ! isset($_POST["message_id])) {
1106               $data["reply"] = $data["reply"] . " FOO!";
1107           }
1108  
1109           return $data;
1110        }
1111  
1112     Beware: this hook function only changes message data before it is
1113     displayed in the editor. From the editor, the user can still change
1114     the data. Therefore, this hook cannot be used to control the data which
1115     will be stored in the database. If you need that functionality, then
1116     use the hooks pre_edit and/or pre_post instead.
1117  
1118     ----------------------------------------------------------------------------
1119     before_footer
1120  
1121     Where  : Every page, except for the admin interface pages
1122     When   : Right before the footer is displayed.
1123     Input  : none
1124     Return : none
1125  
1126     This hook can be used for creating content at the end of the main
1127     content, just before the footer. It can also be used for
1128     performing tasks that have to be executed at the end of each page.
1129  
1130     ----------------------------------------------------------------------------
1131     before_register
1132  
1133     Where  : register.php
1134     When   : Right before a new user is stored in the database.
1135     Input  : Array containing the user data of the user.
1136     Return : Same as Input
1137  
1138     This hook can be used for performing tasks before user registration.
1139     This hook is useful if you want to add some data to or change some
1140     data in the user data and to check if the user data is correct.
1141  
1142     When checking the registration data, the hook can set the "error" field
1143     in the returned user data array. When this field is set after running
1144     the hook, the registration processed will be halted and the error
1145     will be displayed. If you created a custom form field "foo" and you
1146     require that field to be filled in, you could create a hook function
1147     which looks like this:
1148  
1149        function phorum_mod_foo_before_register ($data)
1150        {
1151           $myfield = trim($data['your_custom_field']);
1152           if (empty($myfield)) {
1153               $data['error'] = 'You need to fill in my custom field';
1154           }
1155  
1156           return $data;
1157        }
1158  
1159     The error must be safely HTML escaped, so if you use untrusted data in
1160     your error, then make sure that it is escaped using htmlspecialchars()
1161     to prevent XSS (see also paragraph 3.6: Secure your pages from XSS).
1162  
1163     ----------------------------------------------------------------------------
1164     buddy_add
1165  
1166     Where  : pm.php
1167     When   : Right after a buddy has been added successfully.
1168     Input  : The user id of the buddy that has been added.
1169     Return : Same as Input
1170  
1171     This hook can be used for performing actions after a buddy has been
1172     added for a user (e.g. sending the new buddy a PM about this event,
1173     update popularity counters, do logging, synchronizing with other
1174     databases, etc.).
1175  
1176     ----------------------------------------------------------------------------
1177     buddy_delete
1178  
1179     Where  : pm.php
1180     When   : Right after a buddy has been deleted successfully.
1181     Input  : The user id of the buddy that has been deleted.
1182     Return : Same as Input
1183  
1184     This hook can be used for performing actions after a buddy has
1185     been deleted for a user.
1186  
1187     ----------------------------------------------------------------------------
1188     cc_save_user
1189  
1190     Where  : control.php
1191     When   : Right before data for a user is saved in the control panel.
1192     Input  : Array containing the user data to save.
1193     Return : Same as Input
1194  
1195     This hook works the same way as the before_register hook, so you can
1196     also use it for changing and checking the user data that will be
1197     saved in the database. There's one difference. If you want to
1198     check a custom field, you'll also need to check the panel which
1199     you are on, because this hook is called from multiple panels.
1200     The panel that you are on, will be stored in the 'panel' field
1201     of the user data.
1202  
1203     If you have added a custom field to the template for the option
1204     "Edit My Profile" in the control panel, your hook function will
1205     look like this:
1206  
1207        function phorum_mod_foo_cc_save_user ($data)
1208        {
1209           // Only check data for the panel "user".
1210           if ($data['panel'] != "user") return $data;
1211  
1212           $myfield = trim($data['your_custom_field']);
1213           if (empty($myfield)) {
1214               $data['error'] = 'You need to fill in my custom field';
1215           }
1216  
1217           return $data;
1218        }
1219  
1220     ----------------------------------------------------------------------------
1221     check_post
1222  
1223     Where  : post.php
1224     When   : Right after performing preliminary posting checks, unless
1225              these checks have returned something bad.
1226     Input  : Array containing:
1227              0 => the $_POST array with form data
1228              1 => $error, to return errors in
1229     Return : Same as Input
1230  
1231     This hook can be used for modifying data in the $_POST array and for
1232     running additional checks on the data. If an error is put in $error,
1233     Phorum will stop posting the message and show the error to the user
1234     in the post-form.
1235  
1236     Beware that $error can already contain an error on input, in case
1237     multiple modules are run for this hook. Therefore you might want to
1238     return immediately in your hook function in case $error is already
1239     set.
1240  
1241     Below is an example of how a function for this hook could look.
1242     This example will disallow the use of the word "bar" in the
1243     message body.
1244  
1245        function phorum_mod_foo_check_post ($args) {
1246            list ($message, $error) = $args;
1247            if (!empty($error)) return $args;
1248  
1249            if (stristr($message["body"], "bar") !== false) {
1250                return array($message, "The body may not contain 'bar'");
1251            }
1252  
1253            return $args;
1254        }
1255  
1256     ----------------------------------------------------------------------------
1257     close_thread
1258  
1259     Where  : moderation.php
1260     When   : Right after a thread has been closed by a moderator.
1261     Input  : The id of the thread that has been closed (read-only).
1262     Return : Same as Input
1263  
1264     This hook can be used for performing actions like sending notifications
1265     or making log entries after closing threads.
1266  
1267     ----------------------------------------------------------------------------
1268     common
1269  
1270     Where  : common.php, so in practice every page
1271     When   : Right before the end of the common.php include script.
1272     Input  : none
1273     Return : none
1274  
1275     This hook can be used for applying custom settings or altering
1276     Phorum settings based on external parameters.
1277  
1278     ----------------------------------------------------------------------------
1279     common_no_forum
1280  
1281     Where  : common.php, so in practice every page
1282     When   : Right after no forum settings were found, before doing the redirect
1283     Input  : none
1284     Return : none
1285  
1286     This hook can be used for returning some other message (i.e. a 404-page)
1287     to the visitor if the requested forum was not found.
1288  
1289     ----------------------------------------------------------------------------
1290     common_post_user
1291  
1292     Where  : common.php, so in practice every page
1293     When   : Right after loading the user from the database, but just
1294              before making descisions on language and template.
1295     Input  : none
1296     Return : none
1297  
1298     This hook can be used for applying custom settings or altering
1299     Phorum settings based on external parameters.
1300  
1301     ----------------------------------------------------------------------------
1302     common_pre
1303  
1304     Where  : common.php, so in practice every page
1305     When   : Right after loading the settings from the database, but just
1306              before making descisions on language, template and user.
1307     Input  : none
1308     Return : none
1309  
1310     This hook can be used for applying custom settings or altering
1311     Phorum settings based on external parameters.
1312  
1313     ----------------------------------------------------------------------------
1314     delete
1315  
1316     Where  : moderation.php
1317     When   : Right after deleting a message from the database.
1318     Input  : Array of ids for messages that have been deleted (read-only).
1319     Return : none
1320  
1321     This hook can be used for cleaning up anything you may have created
1322     with the post_post hook or any other hook that stored data tied to
1323     messages.
1324  
1325     ----------------------------------------------------------------------------
1326     external
1327  
1328     The external hook functions are never called from any of the standard
1329     Phorum pages. These functions are called by invoking script.php on the
1330     command line with the --module parameter. This can be used to pipe
1331     output from some arbitrary command to a specific module, which can do
1332     something with that input. If your module does not need any command
1333     line input and is meant to be run on a regular basis, you should
1334     consider using the scheduled hook.
1335  
1336     Mind that for using an external hook, the module in which it is
1337     handled must be enabled in your admin interface. So if an external
1338     hook is not running, the containing module might be disabled.
1339  
1340     To run the external hook from the command line, you have to be in
1341     the phorum installation directory. So running the external hook of
1342     a module named "external_foo" would be done like this on a UNIX
1343     system prompt:
1344  
1345        # cd /your/phorum/dir
1346        # php ./script.php --module=external_foo
1347  
1348     For easy use, you can of course put these commands in a script file.
1349  
1350     ----------------------------------------------------------------------------
1351     failed_login
1352  
1353     Where  : login.php
1354     When   : When a user login fails.
1355     Input  : An array containing three fields: username, password and location.
1356              The location field specifies where the login failure occurred and
1357              its value can be either "forum" or "admin".
1358     Return : Same as Input
1359  
1360     This hook can be used for tracking failing login attempts. This can be used
1361     for things like logging or implementing login failure penalties (like
1362     temporary denying access after X login attempts).
1363  
1364     ----------------------------------------------------------------------------
1365     file
1366  
1367     Where  : file.php
1368     When   : When attachments are requested.
1369     Input  : Two part array where the first element is the mime type already
1370              detected by file.php and the second part is the file array that
1371              contains the filename, file_data, filesize, etc.
1372     Return : Same as Input
1373  
1374     This hook could be used to count file downloads, or along with after_attach
1375     an alternate file data storage mechanism could be created.
1376  
1377     ----------------------------------------------------------------------------
1378     format
1379  
1380     Where  : phorum_format_messages() in include/format_functions.php
1381     When   : Everytime phorum_format_messages() is called for formatting
1382              a message, just before it is sent to the templates.
1383     Input  : Array of messages.
1384     Return : Same as Input
1385  
1386     This hook can be used for applying custom formatting to messages. The
1387     message fields that are most applicable for this are "body" and "author".
1388     When writing a module using this hook, you probably want to format
1389     those fields. In practice you can apply formatting to all the fields
1390     you want.
1391  
1392     The changes you make to the messages are for displaying purposes
1393     only, so the changes are not stored in the database.
1394  
1395     ----------------------------------------------------------------------------
1396     hide
1397  
1398     Where  : moderation.php
1399     When   : Right after a message has been hidden by a moderator.
1400     Input  : The id of the message that has been hidden (read-only).
1401     Return : Same as Input
1402  
1403     This hook can be used for performing actions like sending notifications
1404     or making log entries after hiding a message.
1405  
1406     ----------------------------------------------------------------------------
1407     index
1408  
1409     Where  : include/index_new.php and include/index_classic.php
1410     When   : Right before the list of forums is displayed.
1411     Input  : Array of forums.
1412     Return : Same as Input
1413  
1414     This hook can be used for changing or adding data to the forums
1415     in the list.
1416  
1417     ----------------------------------------------------------------------------
1418     lang
1419  
1420     The lang hook is a only a 'marker'. It flags Phorum that your module
1421     supports multiple languages. It does not take a hook function in
1422     your module information. If you do define a hook function, it will
1423     never be called.
1424  
1425     Read section 2.3 for information on the use of multiple languages.
1426  
1427     ----------------------------------------------------------------------------
1428     list
1429  
1430     Where  : list.php
1431     When   : Right before the messages are formatted and displayed.
1432     Input  : Array of threads (or messages in threaded mode).
1433     Return : Same as Input
1434  
1435     This hook can be used for changing or adding data to the messages
1436     in the list.
1437  
1438     ----------------------------------------------------------------------------
1439     moderation
1440  
1441     Where  : moderation.php
1442     When   : At the start of moderation.php
1443     Input  : The id of the moderation step which is run (read-only).
1444     Return : none
1445  
1446     This hook can be used for logging moderator actions. You can
1447     use the $PHORUM-array to retrieve additional info like the
1448     moderating user's id and similar.
1449  
1450     The moderation step id is the variable $mod_step that is used in
1451     moderation.php. Please read that script to see what moderation
1452     steps are available and for what moderation actions they stand.
1453  
1454     When checking the moderation step id for a certain step, always use
1455     the contstants that are defined for this in include/constants.php.
1456     The numerical value of this id can change between Phorum releases.
1457  
1458     ----------------------------------------------------------------------------
1459     move_thread
1460  
1461     Where  : moderation.php
1462     When   : Right after a thread has been moved by a moderator.
1463     Input  : The id of the thread that has been moved (read-only).
1464     Return : none
1465  
1466     This hook can be used for performing actions like sending notifications
1467     or for making log entries after moving a thread.
1468  
1469     ----------------------------------------------------------------------------
1470     pm_sent
1471  
1472     Where  : include/controlcenter/pm.php
1473     When   : Right after a PM and its email notifications have been sent.
1474     Input  : Array containing the private message data (read-only).
1475     Return : none
1476  
1477     This hook can be used for performing actions after sending a PM. Before
1478     PM notification by email was put in the Phorum core, this hook was
1479     used to send those notifications.
1480  
1481     ----------------------------------------------------------------------------
1482     post_edit
1483  
1484     Where  : include/moderation_functions.php
1485     When   : Right after storing an edited message in the database.
1486     Input  : Array containing message data (read-only).
1487     Return : none
1488  
1489     This hook can be used for sending notifications or for making log entries
1490     in the database when editing takes place.
1491  
1492     ----------------------------------------------------------------------------
1493     post_post
1494  
1495     Where  : post.php
1496     When   : After all posting work is done and just before the user is
1497              redirected back to the list.
1498     Input  : Array containing message data (read-only).
1499     Return : none
1500  
1501     This hook can be used for performing actions based on what the message
1502     contained.
1503  
1504     ----------------------------------------------------------------------------
1505     posting_custom_action
1506  
1507     Where  : posting.php
1508     When   : Right after all the initialization tasks are done and
1509              just before the posting script starts its own action processing.
1510     Input  : Array containing message data.
1511     Return : Same as Input
1512  
1513     This hook can be used by modules to handle (custom) data coming from the
1514     posting form. The module is allowed to change the data that is in the
1515     input message. When a module needs to change the meta data for a
1516     message, then this is the designated hook for that task.
1517  
1518     ----------------------------------------------------------------------------
1519     posting_init
1520  
1521     Where  : posting.php
1522     When   : Right after the posting.php script's configuration setup and
1523              before starting the posting script processing.
1524     Input  : none
1525     Return : none
1526  
1527     This hook can be used for doing modifications to the environment
1528     of the posting scripts at an early stage. One of the intended purposes
1529     of this hook is to give mods a chance to change the configuration
1530     of the posting fields in $PHORUM["posting_fields"].
1531  
1532     ----------------------------------------------------------------------------
1533     posting_permission
1534  
1535     Where  : posting.php
1536     When   : Right after Phorum has determined all abilities that apply
1537              to the logged in user.
1538     Input  : none
1539     Ouput  : none
1540  
1541     This hook can be used for setting up custom abilities and permissions
1542     for users, by updating the applicable fields in $GLOBALS["PHORUM"]["DATA"]
1543     (e.g. for giving certain users the right to make postings sticky, without
1544     having to make the full moderator for a forum).
1545  
1546     Read the code in posting.php before this hook is called to find out
1547     what fields can be used.
1548  
1549     Beware: Only use this hook if you know what you are doing and understand
1550     Phorum's editor permission code. If used wrong, you can open up security
1551     holes in your Phorum installation!
1552  
1553     ----------------------------------------------------------------------------
1554     pre_edit
1555  
1556     Where  : include/moderation_functions.php
1557     When   : Right before storing an edited message in the database.
1558     Input  : Array containing message data.
1559     Return : Same as Input
1560  
1561     This hook can be used for changing the message data before storing it
1562     in the database.
1563  
1564     ----------------------------------------------------------------------------
1565     pre_post
1566  
1567     Where  : post.php
1568     When   : Right before storing a new message in the database.
1569     Input  : Array containing message data.
1570     Return : Same as Input
1571  
1572     This hook can be used for changing the message data before storing it
1573     in the database.
1574  
1575     ----------------------------------------------------------------------------
1576     profile
1577  
1578     Where  : profile.php and include/controlcenter/summary.php
1579     When   : Right before a user profile is displayed.
1580     Input  : Array containing user profile data.
1581     Return : Same as Input
1582  
1583     This hook can be used for making changes to the profile data. This
1584     is for displaying purposes only, so the changes are not stored in the
1585     database.
1586  
1587     ----------------------------------------------------------------------------
1588     quote
1589  
1590     Where  : reply.php, read.php (for inline reply form support)
1591     When   : Right after the message to reply to has been loaded.
1592     Input  : Array containing:
1593              0 => The message author
1594              1 => The message body
1595     Return : The quoted body to use in the post form.
1596  
1597     When quoting a message for reply, by default Phorum formats quoted
1598     messages using an old school email style of quoting. By using the quote
1599     hook, you can implement a different quoting mechanism.
1600  
1601     Your hook function will retrieve an array containing two elements:
1602     the author and the body of the message to be quoted. The return
1603     value for your hook function must be the quoted body that will
1604     be pre-filled into the reply form.
1605  
1606     The BBCode module that is distributed with Phorum has a quote hook
1607     function. Because it does not make sense to have more than one quote
1608     hook active, the BBCode module has an option to disable its quote hook
1609     function. You need to make sure that its quote hook function is disabled
1610     when using your own quote hook.
1611  
1612     ----------------------------------------------------------------------------
1613     read
1614  
1615     Where  : read.php
1616     When   : Right before messages are formatted for displaying.
1617     Input  : Array of messages.
1618     Return : Same as Input
1619  
1620     This hook can be used for making changes to the message data when
1621     reading messages. This is for displaying purposes only, so the
1622     changes are not stored in the database.
1623  
1624     ----------------------------------------------------------------------------
1625     read_user_info
1626  
1627     Where  : read.php post.php include/moderation_functions.php
1628     When   : Right after retrieving user data.
1629     Input  : Array of users.
1630     Return : Same as Input
1631  
1632     This hook can be used for changing information for the users before
1633     being displayed. For example: add a border around user signatures.
1634     This is for displaying purposes only, so the changes are not stored
1635     in the database.  This hook modifies the MESSAGES->user (in read.tpl)
1636     and MESSAGE->user (read_threads.tpl) data that is available in the
1637     templates.
1638  
1639     ----------------------------------------------------------------------------
1640     readthreads
1641  
1642     Where  : read.php
1643     When   : At the start of the threaded read handling, just before
1644              sorting and displaying the threads.
1645     Input  : Array of messages.
1646     Return : Same as Input
1647  
1648     This hook does exactly the same as the read hook, except that this
1649     one is only applied to messages when viewing the message list in
1650     threaded mode.
1651  
1652     ----------------------------------------------------------------------------
1653     reopen_thread
1654  
1655     Where  : moderation.php
1656     When   : Right after a thread has been reopened by a moderator.
1657     Input  : The id of the thread that has been reopened (read-only).
1658     Return : Same as Input
1659  
1660     This hook can be used for performing actions like sending notifications
1661     or making log entries after reopening threads.
1662  
1663     ----------------------------------------------------------------------------
1664     report
1665  
1666     Where  : report.php
1667     When   : Just before a reported message is sent to the moderators.
1668     Input  : Array with maildata (see report.php for the exact contents).
1669     Return : Same as Input
1670  
1671     This hook can be used for changing the report data that will be
1672     sent to the moderators or for performing actions like making log
1673     entries.
1674  
1675     ----------------------------------------------------------------------------
1676     sanity_checks
1677  
1678     Where  : include/admin/sanity_checks.php
1679     When   : Just before the admin interface's sanity checks are run
1680     Input  : Array with sanity checks. Each sanity check is an array with:
1681              function    => The function that runs the sanity check
1682              description => A description to show in the admin interface
1683     Return : Same as Input
1684  
1685     This hook can be used to add custom sanity checks to the admin
1686     interface option "System Sanity Checks".
1687  
1688     Each checking function is expected to return an array containing
1689     two elements:
1690  
1691        [0] A status, which can be one of
1692            PHORUM_SANITY_OK     No problem found
1693            PHORUM_SANITY_WARN   Problem found, but no fatal one
1694            PHORUM_SANITY_CRIT   Critical problem found
1695  
1696        [1] A description of the problem that was found or NULL.
1697  
1698     A general checking function looks like this:
1699  
1700        function check_foo() {
1701           $check_ok = ...some check...;
1702           if (!$check_ok) {
1703              return array(PHORUM_SANITY_CRIT, "Foo went wrong because ...");
1704           } else {
1705              return array(PHORUM_SANITY_OK, NULL);
1706           }
1707        }
1708  
1709     ----------------------------------------------------------------------------
1710     scheduled
1711  
1712     Scheduled hook functions are similar to external ones, except these
1713     functions do not require any input from the command line. The modules
1714     containing a scheduled hook are invoked by running script.php with
1715     the --scheduled argument (no module name is taken; this argument
1716     will run all scheduled hooks for all available modules).
1717  
1718     Like the name of the hook already suggests, this hook can be used for
1719     creating tasks which have to be executed on a regular basis. To
1720     archieve this, you can let script.php run from a scheduling
1721     service (like a cron job on a UNIX system).
1722  
1723     In general, scheduled hooks are used for automating tasks you want
1724     to execute without having to perform any manual action. Practical
1725     uses for a scheduled hook could be housekeeping (cleanup of
1726     stale/old data), daily content generation (like sending daily digests
1727     containing all posted messages for that day) or forum statistics
1728     generation.
1729  
1730     Mind that for using a scheduled hook, the module in which it is
1731     handled must be enabled in your admin interface. So if a scheduled
1732     hook is not running, the containing module might be disabled.
1733  
1734     To run the scheduled hook from the command line or from a scheduling
1735     service, you have to be in the phorum installation directory. So
1736     running the scheduled hooks for your Phorum installation would
1737     be done like this on a UNIX system prompt:
1738  
1739        # cd /your/phorum/dir
1740        # php ./script.php --scheduled
1741  
1742     When creating a scheduling service entry for running this
1743     automatically, then remind to change the directory as well.
1744     You might also have to use the full path to your PHP binary
1745     (/usr/bin/php or whatever it is on your system), because
1746     the scheduling service might not know the path to it. An entry
1747     for the cron system on UNIX could look like this:
1748  
1749     0 0 * * * cd /your/phorum/dir && /usr/bin/php ./script.php --scheduled
1750  
1751     Please refer to your system's documentation to see how to
1752     use your system's scheduling service.
1753  
1754     ----------------------------------------------------------------------------
1755     search
1756  
1757     Where  : search.php
1758     When   : Right before messages are formatted for displaying.
1759     Input  : Array of messages.
1760     Return : Same as Input
1761  
1762     This hook can be used for making changes to the message data when
1763     searching for messages. This is for displaying purposes only, so the
1764     changes are not stored in the database.
1765  
1766     ----------------------------------------------------------------------------
1767     search_action
1768  
1769     Where  : search.php
1770     When   : Right before the search request to the database
1771     Input  : Array of search-request data and a continue flag
1772     Return : Same as Input, continue flag can be set to 0 to avoid the db-call
1773  
1774     This hook can be used for using another search application / layer instead
1775     of the buildin one.
1776  
1777     ----------------------------------------------------------------------------
1778     send_mail
1779  
1780     Where  : include/email_functions.php in the function phorum_email_user()
1781     When   : Right before email is sent using PHP's mail() function.
1782     Input  : Array with maildata (read-only) containing:
1783              addresses => Array of e-mail addresses,
1784              from      => The sender address,
1785              subject   => The mail subject,
1786              body      => The mail body,
1787              bcc       => Whether to use Bcc for mailing multiple recipients
1788     Return : true/false - see description
1789  
1790     This hook can be used for implementing an alternative mail sending
1791     system (e.g. like the SMTP module does). The hook should return true if
1792     Phorum should still send the mails himself. If you do not want to have
1793     Phorum send the mails also, return false.
1794  
1795     ----------------------------------------------------------------------------
1796     user_check_login
1797  
1798     Where  : include/users.php
1799     When   : Whenever phorum_user_check_login() is called.
1800     Input  : Array containing:
1801              username    => the username to check
1802              password    => the password to check
1803              user_id     => empty value
1804     Return : Same as input
1805  
1806     This hook can be used to check user authentication against an external
1807     source. If the hook decides that the username and password are okay,
1808     then it can set the user_id field to the user_id of the authenticated
1809     user. If the hook wants to let Phorum use its standard authentication
1810     mechanism, then it can set user_id to FALSE.
1811  
1812     Here is an example (not too useful) hook function:
1813  
1814        function phorum_mod_foo_user_check_login($login)
1815        {
1816            // Logging in with john / doe will authenticate the user with
1817            // user_id 1234.
1818            if ($login["username"] == "john" && $login["password"] == "doe") {
1819                $login["user_id"] = 1234;
1820            }
1821            // For all other users, we let Phorum do the authentication.
1822            else
1823            {
1824                $login["user_id"] = FALSE;
1825            }
1826  
1827            return $login;
1828        }
1829  
1830     Mind that when returning a user_id using this hook, the user data for
1831     the user must be available in Phorum's users table. This hook only
1832     handles the authentication step. So if this hook is used for
1833     authenticating against an external source, somehow the user data
1834     has to be put in Phorum's users table. There are multiple ways of
1835     handling this. Here's two of them:
1836  
1837     1) Synchronize the data from the external system when it has changed
1838        there. So if a user is created, changed or deleted on the
1839        external system, that system has to update the Phorum users
1840        table with the new information. The advantage of this method, is
1841        that the users table only is updated when changes occur and that
1842        the users table is always up-to-date with the latest information.
1843  
1844     2) Synchronize the data on-the-fly from the user_check_login hook.
1845        As long as the user data is available before that hook has
1846        ended, it will be okay for Phorum. The advantage of this method
1847        is that updating the user data is done in an easy way at the
1848        moment a user logs into Phorum. Disadvantages are that the user
1849        data is only updated at the moment the user logs in and that a
1850        user in only known to Phorum after the first time logging in.
1851  
1852        Here's an example of how a hook function that uses on-the-fly
1853        updates could look:
1854  
1855        function phorum_mod_foo_user_check_login($login)
1856        {
1857            // Check the authentication against the external system.
1858            $username = $login["username"];
1859            $password = $login["password"];
1860            if (! externalsystem_checkauth($username, $password)) {
1861                return $login;
1862            }
1863  
1864            // Synchronize the external system with Phorum's users table.
1865            $externaluser =  externalsystem_getuser($username);
1866            ...code to put $externaluser in Phorum's user table ...
1867            ...and determine the Phorum $user_id to return ...
1868  
1869            // Set the user_id to tell Phorum which user logged in.
1870            $login["user_id"] = $user_id;
1871  
1872            return $login;
1873        }
1874  
1875     ----------------------------------------------------------------------------
1876     user_list
1877  
1878     Where  : include/users.php include/controlcenter/groupmod.php
1879     When   : Whenever phorum_user_get_list() is called.
1880     Input  : Array containing:
1881              <user_id> => <data>
1882              Where <data> is an array containing:
1883              username    => the username for the user
1884              displayname => the way to display the username
1885     Return : Same as Input
1886  
1887      This hook can be used for reformatting the list of users in some
1888      way, such as changing the sort order or changing the format of
1889      the displayed names.
1890  
1891  
1892   4.2 Template hooks
1893   ------------------
1894  
1895     Template hooks are called from within Phorum's template files.
1896     These hooks can be used to extend the user interface with custom
1897     elements. From a hook function for one of these template hooks, the
1898     module writer can print the HTML code that has to be added to the
1899     interface at the postition of the hook call in the template.
1900  
1901  
1902     ----------------------------------------------------------------------------
1903     tpl_editor_after_subject
1904  
1905     Where  : posting_messageform.tpl
1906     When   : After the Subject: field in the message editor.
1907     Input  : none
1908     Return : none
1909  
1910     This hook can be used to add custom form fields to the message editor.
1911     In the default template, the hook is run from within a two column table.
1912     Column one contains the labels and column two the form fields. So your
1913     hook function for adding a field to the editor could look like this:
1914  
1915        function phorum_mod_foo_tpl_editor_after_subject()
1916        {
1917           $value = isset($_POST["mod_foo"]) ? $_POST["mod_foo"] : "";
1918           ?>
1919           <tr>
1920             <td>
1921               Foo field
1922             </td>
1923             <td>
1924               <input type="text" name="mod_foo"
1925                value="<?php print htmlspecialchars($value) ?>"/>
1926             </td>
1927           </tr>
1928           <?php
1929        }
1930  
1931     ----------------------------------------------------------------------------
1932     tpl_cc_usersettings
1933  
1934     Where  : cc_usersettings.tpl
1935     When   : After the built-in usersettings fields.
1936     Input  : Array containing the user's current profile.
1937     Return : Same as Input
1938  
1939     This hook can be used to add extra fields to the settings pages in the
1940     user's control center. Here's an example hook function that will add
1941     an extra field to the "Edit My Profile" page.
1942  
1943        function phorum_mod_foo_tpl_cc_usersettings($profile)
1944        {
1945            // Check if we're on the userprofile page of cc_usersettings.tpl.
1946            if (! isset($profile["USERPROFILE"]) || ! $profile["USERPROFILE"])
1947               return;
1948  
1949            $value = isset($profile["shoesize"])
1950                   ? htmlspecialchars($profile["shoesize"]) : "";
1951            ?>
1952            <tr>
1953              <td>Shoe size</td>
1954              <td><input name="shoesize" type="text" value="<?=$value?>"></td>
1955            </tr>
1956            <?php
1957        }
1958  
1959     ----------------------------------------------------------------------------
1960     tpl_editor_attachment_buttons
1961  
1962     Where  : posting_attachments_list.tpl
1963     When   : Before the delete button for an attachment.
1964     Input  : Array containing attachment information.
1965     Return : Same as Input
1966  
1967     This hook can be used to add extra buttons to each attachment in the
1968     editor, so you can do custom actions for attachments.
1969  
1970     To make your buttons look the same as Phorum's buttons, use the
1971     CSS class "PhorumSubmit".
1972  
1973     Here's an example hook function that will add a button to the attachments,
1974     which will send a javascript alert to the user when clicked.
1975  
1976        function phorum_mod_foo_tpl_editor_attachment_buttons($data)
1977        {
1978           $id = $data["file_id"];
1979           ?>
1980           <input type="submit" class="PhorumSubmit" value="Say it!"
1981            onclick="alert('You clicked attachment id <?php print $id ?>')" />
1982           <?php
1983        }
1984  
1985     ----------------------------------------------------------------------------
1986     tpl_editor_before_textarea
1987  
1988     Where  : posting_messageform.tpl
1989     When   : Before the textarea.
1990     Input  : none
1991     Return : none
1992  
1993     This hook can be used to add custom user interface elements before the
1994     textarea in the message editor.
1995  
1996     ----------------------------------------------------------------------------
1997     tpl_editor_buttons
1998  
1999     Where  : posting_buttons.tpl
2000     When   : Before the main editor buttons (like Preview, Post and Cancel).
2001     Input  : none
2002     Return : none
2003  
2004     This hook can be used to add extra buttons to the editor buttons.
2005  
2006     To make your buttons look the same as Phorum's buttons, use the
2007     CSS class "PhorumSubmit".
2008  
2009     Here's an example hook function that will add a button to the editor,
2010     which will send a javascript alert to the user when clicked.
2011  
2012        function phorum_mod_foo_tpl_editor_buttons()
2013        { ?>
2014           <input type="submit" class="PhorumSubmit" value="Say it!"
2015            onclick="alert('Hello, foo!')" />
2016          <?php
2017        }
2018  
2019  
2020  6. Support
2021  -------------------------------------------------------------------------------
2022  
2023     If you have questions about creating modules for Phorum, please visit
2024     the website http://phorum.org/ and ask the development team for help in
2025     the Development forum.
2026  


Généré le : Thu Nov 29 12:22:27 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics