User Tools

  • Logged in as: anonymous (anonymous)
  • Log Out

Site Tools


mantisbt:plugins_overview

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
mantisbt:plugins_overview [2007/11/28 14:21] jreesemantisbt:plugins_overview [2011/12/30 10:35] (current) tandler
Line 41: Line 41:
  
 The default event type is designed to be as flexible and generic as possible.  The parameter to the event is passed directly to each hooked callback, and the return value from the callback is placed in an array with the callback name as the key.  The resulting array is then passed back to the originator.  Any event that doesn't fit one of the other event types can use this type to do anything. The default event type is designed to be as flexible and generic as possible.  The parameter to the event is passed directly to each hooked callback, and the return value from the callback is placed in an array with the callback name as the key.  The resulting array is then passed back to the originator.  Any event that doesn't fit one of the other event types can use this type to do anything.
 +
 +
  
  
Line 46: Line 48:
  
 ===== Developing Plugins ===== ===== Developing Plugins =====
 +
 +The plugin system for Mantis utilizes a class-based hierarchy for plugins, with all plugins deriving from the ''MantisPlugin'' class.  There are a few [[#plugin classes|pre-defined plugin classes]] which make it simpler and easier to develop certain types of plugins, but these classes simply extend ''MantisPlugin'' itself, and add any simplicity on top of that.
  
 This section covers the major topics needed to get started with plugin development.  Anything else will be in the [[plugins_overview#advanced_plugin_topics|Advanced Topics]] section. This section covers the major topics needed to get started with plugin development.  Anything else will be in the [[plugins_overview#advanced_plugin_topics|Advanced Topics]] section.
Line 54: Line 58:
  
  
-==== Registering a Plugin ==== 
  
-The most important step of getting a plugin to actually //work// with Mantis is properly advertising your plugin to the plugin manager, so that it may discover your plugin and allow the administrator to install it.  This is done not only by creating the proper directory structure for your plugin, but by creating the right files with the right callback functions.  Due to the use of [[#inversion_of_control|Inversion of Control]], you need not know much of the [[plugins_api|Plugin API]] to accomplish this task.+ 
 +==== Getting Started ==== 
 + 
 +The most important step of getting a plugin to actually //work// with Mantis is properly advertising your plugin to the plugin manager, so that it may discover your plugin and allow the administrator to install it.  This is done not only by creating the proper directory structure for your plugin, but by creating the right files with the right classes.  Due to the use of [[#inversion_of_control|Inversion of Control]], you need not know much of the [[plugins_api|Plugin API]] to accomplish this task.
  
 An example plugin with just the basic structure and registration can be seen with the [[plugins_sample#super_cow_powers|Super Cow Powers sample]]. An example plugin with just the basic structure and registration can be seen with the [[plugins_sample#super_cow_powers|Super Cow Powers sample]].
Line 62: Line 68:
 === Basic Structure === === Basic Structure ===
  
-In order to have a valid plugin, you must choose a succinct, one-word 'basename' for your plugin.  This basename should only contain upper- and lower-case letters, dashes, and underscores, and should not include versions or anything more specific than the plugin name.  You must then create a directory in the ''plugins/'' directory of Mantis with this basename, which will contain everything for your plugin.  You will also need to have a file in this directory named ''register.php''which will both provide Mantis with the appropriate information and form the core of your plugin.+In order to have a valid plugin, you must choose a succinct, camelcase 'basename' for your plugin.  This basename should only contain upper- and lower-case letters, and should not include versions or anything more specific than the plugin name.  You must then create a directory in the ''plugins/'' directory of Mantis with this basename, which will contain everything for your plugin.  You will also need to have a file in this directory named '''<basename>.php''which will both provide Mantis with the appropriate information and form the core of your plugin.
  
-A barebones plugin named ''testing'' will have a structure like this:+A barebones plugin named '''Testing''' will have a structure like this:
 <code> <code>
 plugins/ plugins/
-  testing+  Testing
-    register.php+    Testing.php
 </code> </code>
  
  
-=== register.php ===+=== <basename>.php ===
  
-This is the single most essential file for a plugin;  Mantis will look for this file in your plugin directory, and it must contain two specific callback functions:+This is the single most essential file for a plugin;  Mantis will look for this file in your plugin directory, and it must contain a class declaration for your plugin.  Your plugin's class definition must be name in the form of '''<basename>Plugin''', and must extend from the '''MantisPlugin''' class, either directly, or through one of the pre-defined [[#plugin classes]].  In order to have a valid plugin, your class must at least override the abstract ''register()'' function, but there are other basic functions that you can also override.
  
-== plugin_callback_<basename>_info() == +== register() == 
  
-This callback must exist for Mantis to recognize your plugin, and it gives your plugin the chance to tell Mantis more about itselfincluding its name, authors, and dependencies.  This function must return an array of key/value pairs with some (or all) of the following items:+This class function must be overridden in order to have a valid extension class (it is marked ''abstract'' in MantisPlugin), and in order to have a valid plugin, this function must set at least some of properties on your class:
  
-  * ''name'' - Your plugin's full name.+  * ''name'' - Your plugin's full name.  **Required value.**
   * ''description'' - A full description of your plugin.   * ''description'' - A full description of your plugin.
-  * ''version'' - Your plugin's version string.+  * ''page'' - The name of a plugin page for further information and administration. 
 +  * ''version'' - Your plugin's version string.  **Required value.** 
 +  * ''requires'' - An array of key/value pairs of basename/version plugin dependencies.  Prefixing a version with '''<''' will allow your plugin to specify a maximum version (non-inclusive) for a dependency. 
 +  * ''uses'' - Similar to 'requires', but soft dependencies; only fails if the soft dependency is registered, but not yet initialized
   * ''author'' - Your name, or an array of names.   * ''author'' - Your name, or an array of names.
   * ''contact'' - An email address where you can be contacted.   * ''contact'' - An email address where you can be contacted.
   * ''url'' - A web address for your plugin.   * ''url'' - A web address for your plugin.
-  * ''page'' - The name of a plugin page for further information and administration. 
-  * ''requires'' - An array of key/value pairs of basename/version plugin dependencies.  Prefixing a version with '''<''' will allow your plugin to specify a maximum version (non-inclusive) for a dependency. 
  
-== plugin_callback_<basename>_init() ==+== init() ==
  
-This callback allows your plugin to set itself up, include any necessary API's, declare or hook events, etc.  The only restriction is that anything beyond basic setup should be extracted to a callback hooked to ''EVENT_PLUGIN_INIT'', in order to lessen the task of registering plugins.+Overriding this function allows your plugin to set itself up, include any necessary API's, declare or hook events, etc.  Alternatively, your can plugin can hook the ''EVENT_PLUGIN_INIT'' event that will be called after all plugins have be initialized.
  
  
 +==== Using the Event System ====
  
 +The event system is what makes Mantis plugins flexible and extensible.  Events can be utilized in many ways and from many locations, but there is a standard 'acceptable' method suggested for using events within plugins.
  
 +For more detailed information on the event system, see the [[event_system]].
  
 +=== Hooking Events ===
  
-==== Using the Event System ====+There are two ways to hook events in your plugins.  Once you've hooked an event, the appropriate callback function will be called whenever the event is triggered. 
  
-The event system is what makes Mantis plugins flexible and extensible.  Events can be utilized in many ways and from many locations, but there is a standard 'acceptable' method suggested for using events within plugins.+== hook() ==
  
-=== Basic Structure ===+The first way is with 'batch' event hooking, where all of the events needed by your plugin are hooked automatically during plugin initilization.  This can be achieved by overriding the ''hook()'' function of your plugin class and returning an array of event => callback pairs.  If you need multiple callbacks for a single event, use an array of function names as the value for an event pair.
  
-To conform to the recommended event usage patterns, there should be a file in in your plugin's root directory named ''events.php'', which should contain all of the hooked events' callback functions.+<code php> 
 +<?php
  
-Building from the example above, your plugin should have the following structure: +class ... { 
-<code+  ... 
-plugins+ 
-  testing+  function hook() { 
-    events.php +    return array( 
-    register.php+      // single callback per event 
 +      'EVENT_PLUGIN_INIT' ='test', 
 + 
 +      /multiple callbacks per event 
 +      'EVENT_PLUGIN_INIT' => array( 'test', 'test' ), 
 +    ); 
 +  
 + 
 +  /Callback function 
 +  function test( $p_event, $p_params ) {} 
 +}
 </code> </code>
  
-=== events.php ===+== plugin_event_hook() ==
  
-This file will be included automatically by Mantis at runtimebut only when an event hooked by your plugin has been triggered.  Therefore, you should **not** rely on this file to do anything but declare functions of the following form:+Howeverthe simplest way for a plugin to hook a individual function to an event is by calling **''plugin_event_hook( event, function )''**, passing the full event name and the name of the class's callback function.  An event can be hooked at any time, even after the normal hook initialization.  
  
-== plugin_event_<basename>_<function>( event, params ) ==+<code php> 
 +<?php
  
-This is the generic format for hooked event functions The ''event'' parameter will be passed the entire event name, to differentiate between calls from multiple events ''params'' is an arbitrary value passed by the event originator, and may vary wildly depending upon the event type and the specific event being hooked.  The value this function should return may also vary by event type and the event itself Documentation for core events (and especially that of events from other plugins) should be read carefully to properly receive and return values.+class ... 
 +  ...
  
-=== Hooking Events ===+  function hook() { 
 +    return array( 
 +      'EVENT_PLUGIN_INIT' => 'test', 
 +    ); 
 +  }
  
-The simplest way for a plugin to hook a function to an event is by calling ''plugin_event_hookeventfunction )'', passing the full event name and the ''<function>'' portion of the callback function from the section above.  An event can be hooked at any time, even after the normal hook initialization.  Once you've hooked the event, your function will be called whenever the event is triggered.  For plugins that need hook many events or callbacks at once, there is a convenience function ''plugin_event_hook_manyarray )'' which takes an array of event name keys mapping to callback functions.+  function test$p_event$p_params 
 +    plugin_event_hook( 'EVENT_PAGE_LAYOUT', 'test2); 
 +  
 + 
 +  function test2() {} 
 +
 +</code>
  
 === Declaring Events === === Declaring Events ===
Line 133: Line 167:
  
 This function will declare a single event with a given name and type.  The only types currently allowed are: This function will declare a single event with a given name and type.  The only types currently allowed are:
-  * EVENT_TYPE_EXECUTE +  * ''EVENT_TYPE_EXECUTE'' 
-  * EVENT_TYPE_OUTPUT +  * ''EVENT_TYPE_OUTPUT'' 
-  * EVENT_TYPE_CHAIN +  * ''EVENT_TYPE_CHAIN'' 
-  * EVENT_TYPE_DEFAULT+  * ''EVENT_TYPE_DEFAULT''
  
 For example: For example:
-<code>+<code php>
 <?php <?php
 event_declare( 'EVENT_PLUGIN_TESTING_1', EVENT_TYPE_DEFAULT ); event_declare( 'EVENT_PLUGIN_TESTING_1', EVENT_TYPE_DEFAULT );
Line 146: Line 180:
 == event_declare_many( events ) == == event_declare_many( events ) ==
  
-This function will declare multiple events at once, taking a key/value array of event name/type pairs.  For example: +This function will declare multiple events at once, taking an array of event name => type pairs.  For example: 
-<code>+<code php>
 <?php <?php
 event_declare_many( array( event_declare_many( array(
Line 194: Line 228:
 echo lang_get( 'plugin_testing_title' ); echo lang_get( 'plugin_testing_title' );
 </code> </code>
 +
 +
  
 ==== Configuration ==== ==== Configuration ====
  
 +Many plugins will likely have some elements that can or need to be configurable by the site admin or end-user, such as access thresholds or behavioral preferences.  As Mantis has a powerful configuration system already, plugins can take advantage of the existing configuration system by using the plugin API, which will ensure simplicity and separation of configurations between multiple plugins.
 +
 +=== Default Configurations ===
 +
 +To allow the usage of default configurations for plugins, developers can create a callback method in the plugin's ''register.php'' file named **''plugin_callback_<basename>_config()''**.  This callback should return an array of configuration option name/value pairs, which will be set as default global configuration values.  These values will be overridden by any value stored in the database as shown below, so any persistent configuration will not be affected.
 +
 +=== General Usage ===
 +
 +To retrieve a plugin configuration value, your plugin can call **''plugin_config_get( name )''** to get value from the database (if explicitly set), or from the default configuration as explained above.  In order to store configuration values in the database, your plugin will need to call **''plugin_config_set( name, value )''**, which will create or overwrite the existing value.  After this call, then any subsequent call to ''plugin_config_get()'' should return this value.
  
 ==== Creating Pages ==== ==== Creating Pages ====
Line 241: Line 286:
  
 ===== Advanced Plugin Topics ===== ===== Advanced Plugin Topics =====
 +
 +
 +
  
 ==== Schema Management ==== ==== Schema Management ====
  
-==== Installation / Uninstallation ====+For plugins that need to store information in the database, managing database schema across multiple versions and changes can be difficult, so the Mantis plugin system uses the same type of schema management system as the full application to track and upgrade the database schema for plugins. 
 + 
 +=== Declaring a Schema === 
 + 
 +In the world of Mantis, a database schema is defined by a list of schema changes that are applied sequentially starting from nothing, such as adding tables, adding or modifying columns, etc.  The schema history must be linear, and **previous schema entries must not change for the upgrade process to work correctly**.  Fixing existing schema entries may be done by creating new entries in the list which make the necessary modifications. 
 + 
 +== plugin_callback_<basename>_schema() == 
 + 
 +This callback function will contain the schema information for a plugin.  This function must return an array of schema entries (as defined below), which the plugin system will use for installation and automated schema upgrades. 
 + 
 +== Table Names == 
 + 
 +So that plugins will not have conflicting table names and schema entries, the plugin API includes the **''plugin_table( name )''** function, which will return a full table name for your plugin, including the standard prefix and postfix as defined by the Mantis installation.  This function should be used for //all// table names. 
 + 
 +=== Schema Entries === 
 + 
 +All schema entries follow a standard pattern: 
 +<code> 
 +<?php 
 +$schema[] = array( entryType, entryData ); 
 +</code> 
 + 
 +''entryType'' is a string defining how the ''entryData'' will be interpreted to modify the schema.  All schema strings use the ADOdb 'DataDict' string syntaxes, which can be found in the [[http://phplens.com/lens/adodb/docs-datadict.htm|ADOdb Data Dictionary Manual]]. 
 + 
 +//For an example of how schema entries should be used, please see the ''admin/schema.php'' file.// 
 + 
 +== Adding/Creating a Table == 
 + 
 +<code> 
 +<?php 
 +$schema[] = array( 'CreateTableSQL', array( tableName, tableDeclaration ) ); 
 +</code> 
 + 
 +== Adding a Column == 
 + 
 +<code> 
 +<?php 
 +$schema[] = array( 'AddColumnSQL', array( tableName, columnDeclaration ) ); 
 +</code> 
 + 
 +== Altering a Column == 
 + 
 +<code> 
 +<?php 
 +$schema[] = array( 'AlterColumnSQL', array( tableName, columnDeclaration ) ); 
 +</code> 
 + 
 +== Adding an Index == 
 + 
 +<code> 
 +<?php 
 +$schema[] = array( 'CreateIndexSQL', array( indexName, tableName, columnNames ) ); 
 +</code> 
 + 
 +== Inserting Data == 
 + 
 +<code> 
 +<?php 
 +$schema[] = array( 'InsertData', array( tableName, rowDeclarations ) ); 
 +</code> 
 + 
 +== Dropping a Column == 
 + 
 +<code> 
 +<?php 
 +$schema[] = array( 'DropColumnSQL', array( tableName, columnName ) ); 
 +</code> 
 + 
 +== Dropping a Table == 
 + 
 +<code> 
 +<?php 
 +$schema[] = array( 'DropTableSQL', array( tableName ) ); 
 +</code> 
 + 
 +==== Installation / Upgrade / Uninstallation ==== 
 + 
 +In order to allow more advanced plugins the ability to handle the process of installing, upgrading, or uninstalling, the Mantis plugin system has defined some custom callback functions for each task: 
 + 
 +=== plugin_callback_<basename>_install() === 
 + 
 +This callback is executed before the normal plugin installation process has started.  This should be used for checking conditions in Mantis to see if the plugin can be used, or for other general setup procedures.  //This callback must return TRUE if the installation should continue, or FALSE if installation should be halted.//  This allows your plugin to prevent installation in case of errors or other hazardous situations. 
 + 
 +=== plugin_callback_<basename>_upgrade() === 
 + 
 +This callback is executed after the normal schema upgrade process has executed.  This gives your plugin the chance to convert or normalize data after an upgrade.  Your callback will receive a single parameter: the schema version from *before* the upgrade took place, allowing your plugin to know how much upgrade work needs to be done (eg. switch/case statements are perfect here).  //By definition of the install process, this function will also be called during installation when the plugin schema is 'upgraded' from nothing.// 
 + 
 +=== plugin_callback_<basename>_uninstall() === 
 + 
 +This callback is executed after the normal uninstallation process, and should handle such operations as reverting database schemas, removing unnecessary data, etc.  This callback should be used only if Mantis would break when this plugin is uninstalled without any other actions taken, as users may not want to lose data, or be able to re-install the plugin later. 
mantisbt/plugins_overview.1196277709.txt.gz · Last modified: 2008/10/29 04:31 (external edit)

Driven by DokuWiki