How to hook
The use of these functions are defined in advance setup.php : How to setup
Install / uninstall a plugin
// Install process for plugin : need to return true if succeeded function plugin_example_install() { global $DB; if (!TableExists("glpi_plugin_example")){ $query="CREATE TABLE `glpi_plugin_example_examples` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `name` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci', `serial` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci', `plugin_example_dropdowns_id` INT(11) NOT NULL DEFAULT '0', `is_deleted` TINYINT(1) NOT NULL DEFAULT '0', `is_template` TINYINT(1) NOT NULL DEFAULT '0', `template_name` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci', PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; "; $DB->query($query) or die("error creating glpi_plugin_example ". $DB->error()); $query="INSERT INTO `glpi_plugin_example` (`id`, `name`, `serial`, `plugin_example_dropdowns_id`, `deleted`, `is_template`, `template_name`) VALUES (1, 'example 1', 'serial 1', 1, 0, 0, NULL), (2, 'example 2', 'serial 2', 2, 0, 0, NULL), (3, 'example 3', 'serial 3', 1, 0, 0, NULL);"; $DB->query($query) or die("error populate glpi_plugin_example ". $DB->error()); } if (!TableExists("glpi_plugin_example_dropdowns")) { $query="CREATE TABLE `glpi_plugin_example_dropdowns` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `name` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci', `comment` TEXT NULL COLLATcreatingE 'utf8_unicode_ci', PRIMARY KEY (`id`), INDEX `name` (`name`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;"; $DB->query($query) or die("error creating glpi_plugin_example_dropdowns". $DB->error()); $query="INSERT INTO `glpi_plugin_example_dropdowns` (`id`, `name`, `comments`) VALUES (1, 'dp1', 'comment 1'), (2, 'dp2', 'comment 2');"; $DB->query($query) or die("error populate glpi_plugin_example_dropdowns". $DB->error()); } return true; }
// Uninstall process for plugin : need to return true if succeeded function plugin_example_uninstall() {creating global $DB; if (TableExists("glpi_plugin_example")) { $query="DROP TABLE `glpi_plugin_example`;"; $DB->query($query) or die("error deleting glpi_plugin_example"); } if (TableExists("glpi_plugin_example_dropdowns")) { $query="DROP TABLE `glpi_plugin_example_dropdowns`;"; $DB->query($query) or die("error deleting glpi_plugin_example_dropdowns"); } return true; }
Rights Management
Example : use core GLPI rights to determine the rights of the plugin. Each plugin can have its own rights management
TODO...
Management Dropdowns
To display your custom dropdowns in Setup > Dropdown, you should specify it :
// Define Dropdown tables to be managed in GLPI :
function plugin_example_getDropdown() {
// Classname => label
return array("PluginExampleDropdown"=>"Plugin Example Dropdown");
}
Using the helpdesk
Defines whether you can use the plugin with the helpdesk
function plugin_example_AssignToTicket($types) { $types['PluginExampleExample'] = "Example"; return $types; }
Hook to pull additional information from the directory
function plugin_retrieve_more_data_from_ldap_example(array $datas) { return $datas; }
The variables $datas contains all information stored in the GLPI user profile.
To add attributes, just add data into $datas.
Return $datas so that the variable is reinjected into GLPI.
function plugin_retrieve_more_field_from_ldap_example($fields) { return $fields; }
Using the search engine
TODO: need review and moving to another file...
You can then set the items displayed in your search by defining the function plugin_<plugin_name>_getSearchOption :
function plugin_example_getSearchOption() { global $LANG; $sopt=array(); // header shared $sopt[PLUGIN_EXAMPLE_TYPE]['common']="Header Needed"; $sopt[PLUGIN_EXAMPLE_TYPE][1]['table']='glpi_plugin_example'; $sopt[PLUGIN_EXAMPLE_TYPE][1]['field']='name'; $sopt[PLUGIN_EXAMPLE_TYPE][1]['linkfield']='name'; $sopt[PLUGIN_EXAMPLE_TYPE][1]['name']=$LANG['plugin_example']["name"]; $sopt[PLUGIN_EXAMPLE_TYPE][1]['datatype']='itemlink'; $sopt[PLUGIN_EXAMPLE_TYPE][2]['table']='glpi_plugin_example_dropdows'; $sopt[PLUGIN_EXAMPLE_TYPE][2]['field']='name'; $sopt[PLUGIN_EXAMPLE_TYPE][2]['linkfield']='FK_dropdown'; $sopt[PLUGIN_EXAMPLE_TYPE][2]['name']='Dropdown'; $sopt[PLUGIN_EXAMPLE_TYPE][3]['table']='glpi_plugin_example'; $sopt[PLUGIN_EXAMPLE_TYPE][3]['field']='serial'; $sopt[PLUGIN_EXAMPLE_TYPE][3]['linkfield']='serial'; $sopt[PLUGIN_EXAMPLE_TYPE][3]['name']='Serial'; $sopt[PLUGIN_EXAMPLE_TYPE][3]['usehaving']=true; $sopt[PLUGIN_EXAMPLE_TYPE][30]['table']='glpi_plugin_example'; $sopt[PLUGIN_EXAMPLE_TYPE][30]['field']='ID'; $sopt[PLUGIN_EXAMPLE_TYPE][30]['linkfield']=''; $sopt[PLUGIN_EXAMPLE_TYPE][30]['name']=$LANG["common"][2]; // if a table exists to link the type COMPUTER $sopt[COMPUTER_TYPE][1002]['table']='glpi_plugin_example'; $sopt[COMPUTER_TYPE][1002]['field']='name'; $sopt[COMPUTER_TYPE][1002]['linkfield']=''; $sopt[COMPUTER_TYPE][1002]['name']="plugin_example"; $sopt[COMPUTER_TYPE][1002]['forcegroupby']='1'; $sopt[COMPUTER_TYPE][1002]['datatype']='itemlink'; $sopt[COMPUTER_TYPE][1002]['itemlink_type']=PLUGIN_EXAMPLE_TYPE; return $sopt; }
Usable Datatypes
- itemlink
- text
- bool
- weblink
- number
- decimal
- date
- datetime
- date_delay
The search engine then simply calls a PHP page, for example :
$NEEDED_ITEMS=array("search"); define('GLPI_ROOT', '../..'); include (GLPI_ROOT . "/inc/includes.php"); checkTypeRight(PLUGIN_EXAMPLE_TYPE,"r"); manageGetValuesInSearch(PLUGIN_EXAMPLE_TYPE); searchForm(PLUGIN_EXAMPLE_TYPE,$_GET); showList(PLUGIN_EXAMPLE_TYPE,$_GET);
You can also define special cases of research by defining one or more of the following if necessary (the datatype are automatically managed):
TODO
// See also PluginExampleExample::getSpecificValueToDisplay() function plugin_example_giveItem($type,$ID,$data,$num) { $searchopt = &Search::getOptions($type); $table = $searchopt[$ID]["table"]; $field = $searchopt[$ID]["field"]; switch ($table.'.'.$field) { case "glpi_plugin_example_examples.name" : $out = "<a href='".Toolbox::getItemTypeFormURL('PluginExampleExample')."?id=".$data['id']."'>"; $out .= $data["ITEM_$num"]; if ($_SESSION["glpiis_ids_visible"] || empty($data["ITEM_$num"])) { $out .= " (".$data["id"].")"; } $out .= "</a>"; return $out; } return ""; } function plugin_example_addLeftJoin($type, $ref_table, $new_table, $linkfield) { // Example of standard LEFT JOIN clause but use it ONLY for specific LEFT JOIN // No need of the function if you do not have specific cases switch ($new_table) { case "glpi_plugin_example_dropdowns" : return " LEFT JOIN `$new_table` ON (`$ref_table`.`$linkfield` = `$new_table`.`id`) "; } return ""; } function plugin_example_forceGroupBy($type) { switch ($type) { case 'PluginExampleExample' : // Force add GROUP BY IN REQUEST return true; } return false; } function plugin_example_addWhere($link, $nott, $type, $ID, $val, $searchtype) { $searchopt = &Search::getOptions($type); $table = $searchopt[$ID]["table"]; $field = $searchopt[$ID]["field"]; $SEARCH = Search::makeTextSearch($val,$nott); // Example of standard Where clause but use it ONLY for specific Where // No need of the function if you do not have specific cases switch ($table.".".$field) { case "glpi_plugin_example_examples.serial" : return $link." `$table`.`$field` = '$val' "; } return ""; } // This is not a real example because the use of Having condition in this case is not suitable function plugin_example_addHaving($link, $nott, $type, $ID, $val, $num) { $searchopt = &Search::getOptions($type); $table = $searchopt[$ID]["table"]; $field = $searchopt[$ID]["field"]; $SEARCH = Search::makeTextSearch($val,$nott); // Example of standard Having clause but use it ONLY for specific Having // No need of the function if you do not have specific cases switch ($table.".".$field) { case "glpi_plugin_example.serial" : $ADD = ""; if (($nott && $val!="NULL") || $val == '^$') { $ADD = " OR ITEM_$num IS NULL"; } return " $LINK ( ITEM_".$num.$SEARCH." $ADD ) "; } return ""; } function plugin_example_addSelect($type,$ID,$num) { $searchopt = &Search::getOptions($type); $table = $searchopt[$ID]["table"]; $field = $searchopt[$ID]["field"]; // Example of standard Select clause but use it ONLY for specific Select // No need of the function if you do not have specific cases // switch ($table.".".$field) { // case "glpi_plugin_example.name" : // return $table.".".$field." AS ITEM_$num, "; // } return ""; } function plugin_example_addOrderBy($type,$ID,$order,$key=0) { $searchopt = &Search::getOptions($type); $table = $searchopt[$ID]["table"]; $field = $searchopt[$ID]["field"]; // Example of standard OrderBy clause but use it ONLY for specific order by // No need of the function if you do not have specific cases // switch ($table.".".$field) { // case "glpi_plugin_example.name" : // return " ORDER BY $table.$field $order "; // } return ""; }
Mass Actions
TODO : need review
You can hide fields by defining the function : plugin_<plugin_name>_MassiveActionsFieldsDisplay($type,$table,$field,$linkfield). This function should return TRUE if the element should be displayed, or false to use the default visibility. An example:
// How to display specific update fields ? // options must contain at least itemtype and options array function plugin_example_MassiveActionsFieldsDisplay($options=array()) { //$type,$table,$field,$linkfield $table = $options['options']['table']; $field = $options['options']['field']; $linkfield = $options['options']['linkfield']; if ($table == getTableForItemType($options['itemtype'])) { // Table fields switch ($table.".".$field) { case 'glpi_plugin_example_examples.serial' : _e("Not really specific - Just for example", 'example'); //Html::autocompletionTextField($linkfield,$table,$field); // Dropdown::showYesNo($linkfield); // Need to return true if specific display return true; } } else { // Linked Fields switch ($table.".".$field) { case "glpi_plugin_example_dropdowns.name" : _e("Not really specific - Just for example", 'example'); // Need to return true if specific display return true; } } // Need to return false on non display item return false; }
You can also define new actions for mass changes by defining the following functions :
// Define actions : function plugin_example_MassiveActions($type) { switch ($type) { // New action for core and other plugin types : name = plugin_PLUGINNAME_actionname case 'Computer' : return array('PluginExampleExample'.MassiveAction::CLASS_ACTION_SEPARATOR.'DoIt' => __("plugin_example_DoIt", 'example')); // Actions for types provided by the plugin are included inside the classes } return array(); }
TODO : need to add from example class
- showMassiveActionsSubForm
- processMassiveActionsForOneItemtype
Actions for core GLPI objects
These functions use the following prototype ($parm containing 2 fields, "type" and "ID", which define the type and ID of the element of the element on which the action should perform.
Todo need compelte review
Actions for moving objects
// Hook done on restore item case function plugin_item_transfer_example($parm) { //TRANS: %1$s is the source type, %2$d is the source ID, %3$d is the destination ID Session::addMessageAfterRedirect(sprintf(__('Transfer Computer Hook %1$s %2$d -> %3$d', 'example'), $parm['type'], $parm['id'], $parm['newID'])); return false; }
Actions for core GPLI - item headings
TODO : Need complete review (now in class)
Planning
TODO : Need complete review (now in class)
Cron
TODO : Need complete review (now in class)
Custom exports
It is possible to customize the exports by defining the function plugin_<plugin_name>_dynamicReport($parm). $parm as the parameters passed in from $_GET (function printPager).
// Do special actions for dynamic report function plugin_example_dynamicReport($parm) { if ($parm["item_type"] == 'PluginExampleExample') { // Do all what you want for export depending on $parm echo "Personalized export for type ".$parm["display_type"]; echo 'with additional datas : <br>'; echo "Single data : add1 <br>"; print $parm['add1'].'<br>'; echo "Array data : add2 <br>"; Html::printCleanArray($parm['add2']); // Return true if personalized display is done return true; } // Return false if no specific display is done, then use standard display return false; }
Additional data can be exported by defining the function : plugin_<plugin_name>_addParamFordynamicReport. The search parameters are accessible via session variables
// Add parameters to Html::printPager in search system function plugin_example_addParamFordynamicReport($itemtype) { if ($itemtype == 'PluginExampleExample') { // Return array data containing all params to add : may be single data or array data // Search config are available from session variable return array('add1' => $_SESSION['glpisearch'][$itemtype]['order'], 'add2' => array('tutu' => 'Second Add', 'Other Data')); } // Return false or a non array data if not needed return false; }