- Install / uninstall a plugin
- Rights Management
- Management DropdownsTo use the functions dropdown.function.php as dropdownValue, define the function plugin_<plugin_name>_getDropdown :
- Using the helpdesk
- Authentication Hooks
- Hook to pull additional information from the directory
- Using the search engine
- Mass Actions
- Actions for core GLPI objects
- Actions for moving objects
- Actions for core GPLI - item headings
- Planning
- Cron
- Custom exports
The use of these functions are defined in advance setup.php : en_howtosetup
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` ( `ID` int(11) NOT NULL auto_increment, `name` varchar(255) collate utf8_unicode_ci default NULL, `serial` varchar(255) collate utf8_unicode_ci NOT NULL, `FK_dropdown` int(11) NOT NULL default '0', `deleted` smallint(6) NOT NULL default '0', `is_template` smallint(6) NOT NULL default '0', `tplname` varchar(255) collate utf8_unicode_ci default NULL, 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`, `FK_dropdown`, `deleted`, `is_template`, `tplname`) 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_dropdown_plugin_example")) { $query="CREATE TABLE `glpi_dropdown_plugin_example` ( `ID` int(11) NOT NULL auto_increment, `name` varchar(255) collate utf8_unicode_ci default NULL, `comments` text collate utf8_unicode_ci, PRIMARY KEY (`ID`), KEY `name` (`name`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;"; $DB->query($query) or die("error creating glpi_dropdown_plugin_example". $DB->error()); $query="INSERT INTO `glpi_dropdown_plugin_example` (`ID`, `name`, `comments`) VALUES (1, 'dp 1', 'comment 1'), (2, 'dp2', 'comment 2');"; $DB->query($query) or die("error populate glpi_dropdown_plugin_example". $DB->error()); } return true; }
// Uninstall process for plugin : need to return true if succeeded function plugin_example_uninstall() { global $DB; if (TableExists("glpi_plugin_example")) { $query="DROP TABLE `glpi_plugin_example`;"; $DB->query($query) or die("error creating glpi_plugin_example"); } if (TableExists("glpi_dropdown_plugin_example")) { $query="DROP TABLE `glpi_dropdown_plugin_example`;"; $DB->query($query) or die("error creating glpi_dropdown_plugin_example"); } return true; }
Rights Management¶
Example : use core GLPI rights to determine the rights of the plugin. Each plugin can have its own rights management
function plugin_change_profile_example() { // For example : same right of computer if (haveRight('computer','w')) { $_SESSION["glpi_plugin_example_profile"]=array('example'=>'w'); } else if (haveRight('computer','r')) { $_SESSION["glpi_plugin_example_profile"]=array('example'=>'r'); } else { unset($_SESSION["glpi_plugin_example_profile"]); } }
Management Dropdowns
To use the functions dropdown.function.php as dropdownValue, define the function plugin_<plugin_name>_getDropdown :¶
// Define Dropdown tables to be managed in GLPI : function plugin_example_getDropdown() { // Table => Name return array("glpi_dropdown_plugin_example"=>"Plugin Example Dropdown"); }
The code above of sufficient for a simple dropdown. For a dropdown tree, you must specify that the table isof this type in the setup.php - [wiki:en_howtosetup setup.php] :
array_push($CFG_GLPI["dropdowntree_tables"],"glpi_dropdown_plugin_<plugin_name>");
If it is a separate dropdown for each entity :
array_push($CFG_GLPI["specif_entities_tables"],"glpi_dropdown_plugin_<plugin_name>");
To manage automatic editing features with the dropdown replacement or deletion of values in case of cancellation you can describe the existing relationships between tables in your plugins by adding the function :
// Define dropdown relations function plugin_example_getDatabaseRelations() { // return array("glpi_dropdown_plugin_example"=>array("glpi_plugin_example"=>"FK_dropdown")); }
Here the field FK_dropdown of glpi_plugin_example is bound to the table glpi_dropdown_plugin_example.
Using the helpdesk¶
Defines whether you can use the plugin with the helpdesk
function plugin_example_AssignToTicket($types) { $types[PLUGIN_EXAMPLE_TYPE] = "Example"; return $types; }
Authentication Hooks¶
function plugin_authentication_action_check_group_<plugin_name> ($infos) { return 1; }
The variable $infos contains all data read from user input to the LDAP directory. Your function must return a value indicating whether the user is authenticated or not: * return 0: User is NOT authenticated. * Return 1: the user is authenticated.
Hook to pull additional information from the directory¶
function plugin_authentication_action_retrieve_more_attributes_<plugin_name> ($infos) { return $infos; }
The variable $infos contains all information stored in the GLPI user profile. To add attributes, just add data into $infos. Return $infos so that the variable is reinjected into GLPI.
Using the search engine¶
You must first define a new type (see setup.php - [wiki:en_howtosetup setup.php]).
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_dropdown_plugin_example'; $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
function plugin_example_giveItem($type,$ID,$data,$num) { global $CFG_GLPI, $INFOFORM_PAGES,$SEARCH_OPTION; $table=$SEARCH_OPTION[$type][$ID]["table"]; $field=$SEARCH_OPTION[$type][$ID]["field"]; switch ($table.'.'.$field) { case "glpi_plugin_example.name" : $out= "<a href=\"".$CFG_GLPI["root_doc"]."/".$INFOFORM_PAGES[$type]."?ID=".$data['ID']."\">"; $out.= $data["ITEM_$num"]; if ($CFG_GLPI["view_ID"]||empty($data["ITEM_$num"])) $out.= " (".$data["ID"].")"; $out.= "</a>"; return $out; break; } 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_dropdown_plugin_example" : return " LEFT JOIN $new_table ON ($ref_table.$linkfield = $new_table.ID) "; break; } return ""; } function plugin_example_forceGroupBy($type) { switch ($type) { case PLUGIN_EXAMPLE_TYPE : // Force add GROUP BY IN REQUEST return true; break; } return false; } function plugin_example_addWhere($link,$nott,$type,$ID,$val) { global $SEARCH_OPTION; $table=$SEARCH_OPTION[$type][$ID]["table"]; $field=$SEARCH_OPTION[$type][$ID]["field"]; $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.name" : // $ADD=""; // if ($nott&&$val!="NULL") { // $ADD=" OR $table.$field IS NULL"; // } // return $link." ($table.$field $SEARCH ".$ADD." ) "; // break; // } 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) { global $SEARCH_OPTION; $table=$SEARCH_OPTION[$type][$ID]["table"]; $field=$SEARCH_OPTION[$type][$ID]["field"]; $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 ) "; break; } return ""; } function plugin_example_addSelect($type,$ID,$num) { global $SEARCH_OPTION; $table=$SEARCH_OPTION[$type][$ID]["table"]; $field=$SEARCH_OPTION[$type][$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, "; // break; // } return ""; } function plugin_example_addOrderBy($type,$ID,$order,$key=0) { global $SEARCH_OPTION; $table=$SEARCH_OPTION[$type][$ID]["table"]; $field=$SEARCH_OPTION[$type][$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 "; // break; // } return ""; }
Mass Actions¶
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 ? function plugin_example_MassiveActionsFieldsDisplay($type,$table,$field,$linkfield) { global $LINK_ID_TABLE; if ($table==$LINK_ID_TABLE[$type]) { // Table fields switch ($table.".".$field) { case 'glpi_plugin_example.serial': echo "Not really specific - Just for example "; autocompletionTextField($linkfield,$table,$field); // dropdownYesNo($linkfield); // Need to return true if specific display return true; break; } } else { // Linked Fields switch ($table.".".$field) { case "glpi_dropdown_plugin_example.name" : echo "Not really specific - Just for example "; dropdown($table,$linkfield,1,$_SESSION["glpiactive_entity"]); //dropdownUsers($linkfield,0,"own_ticket",0,1,$_SESSION["glpiactive_entity"]); // Need to return true if specific display return true; break; } } // 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) { global $LANG; switch ($type) { // New action for core and other plugin types : name = plugin_<plugin_name>_actionname case COMPUTER_TYPE : return array( "plugin_example_DoIt"=>"plugin_example_DoIt", ); break; // Actions for types provided by the plugin case PLUGIN_EXAMPLE_TYPE : return array( // GLPI core one "add_document"=>$LANG["document"][16], // Specific one "do_nothing"=>'Do Nothing - just for fun' ); break; } return array(); } // How to display specific actions ? function plugin_example_MassiveActionsDisplay($type,$action) { global $LANG; switch ($type){ case COMPUTER_TYPE: switch ($action) { case "plugin_example_DoIt": echo " <input type=\"submit\" name=\"massiveaction\" class=\"submit\" value=\"".$LANG["buttons"][2]."\" > but do nothing :)"; break; } break; case PLUGIN_EXAMPLE_TYPE: switch ($action) { // No case for add_document : use GLPI core one case "do_nothing": echo " <input type=\"submit\" name=\"massiveaction\" class=\"submit\" value=\"".$LANG["buttons"][2]."\" > but do nothing :)"; break; } break; } return ""; } // How to process specific actions ? function plugin_example_MassiveActionsProcess($data) { global $LANG; switch ($data['action']) { case 'plugin_example_DoIt': if ($data['device_type']==COMPUTER_TYPE) { $ci =new CommonItem(); addMessageAfterRedirect("Right it is the type I want..."); addMessageAfterRedirect("But... I say I will do nothing for :"); foreach ($data['item'] as $key => $val) { if ($val==1) { if ($ci->getFromDB($data["device_type"],$key)){ addMessageAfterRedirect("- ".$ci->getField("name")); } } } } break; case 'do_nothing': if ($data['device_type']==PLUGIN_EXAMPLE_TYPE) { $ci =new CommonItem(); addMessageAfterRedirect("Right it is the type I want..."); addMessageAfterRedirect("But... I say I will do nothing for :"); foreach ($data['item'] as $key => $val) { if ($val==1) { if ($ci->getFromDB($data["device_type"],$key)) { addMessageAfterRedirect("- ".$ci->getField("name")); } } } } break; } }
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.
// Hook done on add item case function plugin_pre_item_add_example($input) { if (isset($input["_item_type_"])) switch ($input["_item_type_"]) { case COMPUTER_TYPE : // Manipulate data if needed addMessageAfterRedirect("Pre Add Computer Hook",true); break; } return $input; }
Actions for moving objects¶
// Hook done on restore item case function plugin_item_transfer_example($parm) { addMessageAfterRedirect("Transfer Computer Hook ".$parm['type']." ".$parm['ID']." -> ".$parm['newID']); return false; }
Actions for core GPLI - item headings¶
Defining tab headings¶
// Define headings added by the plugin function plugin_get_headings_example($type,$ID,$withtemplate) { switch ($type) { case PROFILE_TYPE: $prof = new Profile(); if ($ID>0 && $prof->getFromDB($ID) && $prof->fields['interface']=='central') { return array( 1 => "Test PLugin", ); } else { return array(); } break; case COMPUTER_TYPE : // new object / template case if ($withtemplate) { return array(); // Non template case / editing an existing object } else { return array( 1 => "Test PLugin", ); } break; case COMPUTERDISK_TYPE : case ENTERPRISE_TYPE : if ($ID>0) { // Not in create mode return array( 1 => "Test PLugin", 2 => "Test PLugin 2", ); } break; case "central": return array( 1 => "Test PLugin", ); break; case "prefs": return array( 1 => "Test PLugin", ); break; case "mailing": return array( 1 => "Test PLugin", ); break; } return false; }
Define functions called when displaying the form¶
// Define headings actions added by the plugin function plugin_headings_actions_example($type) { switch ($type) { case PROFILE_TYPE : case COMPUTER_TYPE : return array( 1 => "plugin_headings_example", ); break; case COMPUTERDISK_TYPE : case ENTERPRISE_TYPE : return array( 1 => "plugin_headings_example", 2 => "plugin_headings_example", ); break; case "central" : return array( 1 => "plugin_headings_example", ); break; case "prefs" : return array( 1 => "plugin_headings_example", ); break; case "mailing" : return array( 1 => "plugin_headings_example", ); break; } return false; }
Details of the called function¶
function plugin_headings_example($type,$ID,$withtemplate=0) { global $LANG; if (!$withtemplate) { echo "<div align='center'>"; switch ($type){ case "central": echo "Plugin central action ".$LANG['plugin_example']["test"]; break; case "prefs": // Complete form display $data=plugin_version_example(); echo "<form action='Where to post form'>"; echo "<table class='tab_cadre_fixe'>"; echo "<tr><th colspan='3'>".$data['name']; echo " - ".$data['version']; echo "</th></tr>"; echo "<tr class='tab_bg_1'><td>Name of the pref"; echo "</td><td>Input to set the pref</td>"; echo "<td><input class='submit' type='submit' name='submit' value='submit'></td>"; echo "</tr>"; echo "</table>"; echo "</form>"; break; case "mailing": echo "Plugin mailing action ".$LANG['plugin_example']["test"]; break; default : echo "Plugin function with headings TYPE=".$type." ID=".$ID; break; } echo "</div>"; } }
Planning¶
Populate planning¶
The function defines and fills an array whose elements can be sorted according to their keys.
For example:
// Parm contains begin, end and who // Create data to be displayed in the planning of $parm["who"] or $parm["who_group"] between $parm["begin"] and $parm["end"] function plugin_planning_populate_example($parm) { // Add items in the items fields of the parm array // Items need to have an unique index beginning by the begin date of the item to display // needed to be correcly displayed $parm["items"][$parm["begin"]."$$$"."plugin_example1"]["plugin"]="example"; $parm["items"][$parm["begin"]."$$$"."plugin_example1"]["begin"]=date("Y-m-d 17:00:00"); $parm["items"][$parm["begin"]."$$$"."plugin_example1"]["end"]=date("Y-m-d 18:00:00"); $parm["items"][$parm["begin"]."$$$"."plugin_example1"]["name"]="test planning example 1 "; // Set the ID using the ID of the item in the database to have unique ID $ID=date("Ymd"); // Current date for example $parm["items"][$parm["begin"]."$$$"."plugin_example1"]["planningID"]="plugin_example".$ID; return $parm; }
display planning¶
// Display the planning item function plugin_display_planning_example($parm) { // $parm["type"] say begin end in or from type // Add items in the items fields of the parm array global $LANG; switch ($parm["type"]) { case "in": echo date("H:i",strtotime($parm["begin"]))." -> ".date("H:i",strtotime($parm["end"])).": "; break; case "from": break; case "begin"; echo $LANG["buttons"][33]." ".date("H:i",strtotime($parm["begin"])).": "; break; case "end"; echo $LANG["buttons"][32]." ".date("H:i",strtotime($parm["end"])).": "; break; } echo $parm["name"]; }
Cron¶
// Cron function : name= cron_plugin_<plugin_name> function cron_plugin_example() { logInFile('example',"cron called\n"); // >0 : done // <0 : to be run again (not finished) // 0 : nothing to do return 1; }
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"]==PLUGIN_EXAMPLE_TYPE) { // 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>"; 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 printPager in search system function plugin_example_addParamFordynamicReport($device_type) { if ($device_type==PLUGIN_EXAMPLE_TYPE) { // 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'][$device_type]['order'], 'add2' => array('tutu'=>'Second Add','Other Data')); } // Return false or a non array data if not needed return false; }