function plugin_init_webservices()
{
    global $PLUGIN_HOOKS, $CFG_GLPI, $WEBSERVICE_LINKED_OBJECTS;
    Plugin::registerClass('PluginWebservicesClient');
    $PLUGIN_HOOKS['csrf_compliant']['webservices'] = true;
    $PLUGIN_HOOKS["menu_toadd"]['webservices'] = array('config' => 'PluginWebservicesClient');
    $PLUGIN_HOOKS['webservices']['webservices'] = 'plugin_webservices_registerMethods';
    //Store objects that can be retrieved when querying another object
    $WEBSERVICE_LINKED_OBJECTS = array('with_infocom' => array('help' => 'bool, optional', 'itemtype' => 'Infocom', 'allowed_types' => $CFG_GLPI['infocom_types'], 'class' => 'PluginWebservicesMethodInventaire'), 'with_networkport' => array('help' => 'bool, optional', 'itemtype' => 'NetworkPort', 'allowed_types' => plugin_webservices_getNetworkPortItemtypes(), 'class' => 'PluginWebservicesMethodInventaire'), 'with_phone' => array('help' => 'bool, optional (Computer only)', 'itemtype' => 'Phone', 'allowed_types' => array('Computer'), 'class' => 'PluginWebservicesMethodInventaire'), 'with_printer' => array('help' => 'bool', 'optional (Computer only)', 'itemtype' => 'Printer', 'allowed_types' => array('Computer'), 'class' => 'PluginWebservicesMethodInventaire'), 'with_monitor' => array('help' => 'bool', 'optional (Computer only)', 'itemtype' => 'Monitor', 'allowed_types' => array('Computer'), 'class' => 'PluginWebservicesMethodInventaire'), 'with_peripheral' => array('help' => 'bool', 'optional (Computer only)', 'itemtype' => 'Peripheral', 'allowed_types' => array('Computer'), 'class' => 'PluginWebservicesMethodInventaire'), 'with_document' => array('help' => 'bool', 'optional', 'itemtype' => 'Document', 'allowed_types' => plugin_webservices_getDocumentItemtypes(), 'class' => 'PluginWebservicesMethodInventaire'), 'with_ticket' => array('help' => 'bool', 'optional', 'itemtype' => 'Ticket', 'allowed_types' => plugin_webservices_getTicketItemtypes(), 'class' => 'PluginWebservicesMethodHelpdesk'), 'with_tickettask' => array('help' => 'bool', 'optional (Ticket only)', 'itemtype' => 'TicketTask', 'allowed_types' => array('Ticket'), 'class' => 'PluginWebservicesMethodHelpdesk'), 'with_ticketfollowup' => array('help' => 'bool', 'optional (Ticket only)', 'itemtype' => 'TicketFollowup', 'allowed_types' => array('Ticket'), 'class' => 'PluginWebservicesMethodHelpdesk'), 'with_ticketvalidation' => array('help' => 'bool', 'optional (Ticket only)', 'itemtype' => 'TicketValidation', 'allowed_types' => array('Ticket'), 'class' => 'PluginWebservicesMethodHelpdesk'), 'with_reservation' => array('help' => 'bool', 'itemtype' => 'Reservation', 'allowed_types' => $CFG_GLPI['reservation_types'], 'class' => 'PluginWebservicesMethodInventaire'), 'with_software' => array('help' => 'bool', 'itemtype' => 'Software', 'allowed_types' => array('Computer'), 'class' => 'PluginWebservicesMethodInventaire'), 'with_softwareversion' => array('help' => 'bool', 'itemtype' => 'SoftwareVersion', 'allowed_types' => array('Software'), 'class' => 'PluginWebservicesMethodInventaire'), 'with_softwarelicense' => array('help' => 'bool', 'itemtype' => 'SoftwareLicense', 'allowed_types' => array('Software'), 'class' => 'PluginWebservicesMethodInventaire'), 'with_contract' => array('help' => 'bool', 'itemtype' => 'Contract', 'allowed_types' => $CFG_GLPI['contract_types'], 'class' => 'PluginWebservicesMethodInventaire'));
}
 /**
  * List inventory objects (global search)
  *
  * @param $params    the input parameters
  * @param $protocol  the commonication protocol used
  *
  **/
 static function methodListInventoryObjects($params, $protocol)
 {
     global $DB, $CFG_GLPI;
     //Display help for this function
     if (isset($params['help'])) {
         foreach (Search::getOptions('State') as $itemtype => $option) {
             if (!isset($option['common'])) {
                 if (isset($option['linkfield']) && $option['linkfield'] != '') {
                     if (in_array($option['field'], array('name', 'completename'))) {
                         $fields[$option['linkfield']] = 'integer,optional';
                         $name_associated = str_replace("s_id", "_name", $option['linkfield']);
                         if (!isset($option['datatype']) || $option['datatype'] == 'text') {
                             $fields[$name_associated] = 'string,optional';
                         }
                     } else {
                         $fields[$option['field']] = 'string,optional';
                     }
                 } else {
                     $fields[$option['field']] = 'string,optional';
                 }
             }
         }
         $fields['start'] = 'integer,optional';
         $fields['limit'] = 'integer,optional';
         return $fields;
     }
     if (!Session::getLoginUserID()) {
         return self::Error($protocol, WEBSERVICES_ERROR_NOTAUTHENTICATED);
     }
     //Must be superadmin to use this method
     if (!Session::haveRight('config', UPDATE)) {
         return self::Error($protocol, WEBSERVICES_ERROR_NOTALLOWED);
     }
     $resp = array();
     $itemtypes = array();
     //If several itemtypes given, build an array
     if (isset($params['itemtype'])) {
         if (!is_array($params['itemtype'])) {
             $itemtypes = array($params['itemtype']);
         } else {
             $itemtypes = $params['itemtype'];
         }
     } else {
         $itemtypes = plugin_webservices_getTicketItemtypes();
     }
     //Check read right on each itemtype
     foreach ($itemtypes as $itemtype) {
         $item = new $itemtype();
         if (!$item->canView()) {
             $key = array_search($itemtype, $itemtypes);
             unset($itemtypes[$key]);
             $resp[] = self::Error($protocol, WEBSERVICES_ERROR_NOTALLOWED, '', $itemtype);
         }
     }
     //If nothing in the array, no need to go further !
     if (empty($itemtypes)) {
         return $resp;
     }
     $resp = array();
     $start = 0;
     $limit = $_SESSION['glpilist_limit'];
     if (isset($params['limit']) && is_numeric($params['limit'])) {
         $limit = $params['limit'];
     }
     if (isset($params['start']) && is_numeric($params['start'])) {
         $start = $params['start'];
     }
     $first = true;
     $query = "";
     foreach ($itemtypes as $itemtype) {
         if (in_array($itemtype, $itemtypes)) {
             $item = new $itemtype();
             $item->getEmpty();
             $table = getTableForItemType($itemtype);
             $already_joined = array();
             if (!$first) {
                 $query .= " UNION ";
             }
             $query .= "\nSELECT `" . Toolbox::addslashes_deep($table) . "`.`name`,\n                               `" . Toolbox::addslashes_deep($table) . "`.`id`,\n                               `glpi_entities`.`completename` AS entities_name,\n                               `glpi_entities`.`id` AS entities_id,\n                               '" . Toolbox::addslashes_deep($itemtype) . "' AS itemtype";
             if (FieldExists($table, 'serial')) {
                 $query .= ", `" . Toolbox::addslashes_deep($table) . "`.`serial`";
             } else {
                 $query .= ", '' as `serial`";
             }
             if (FieldExists($table, 'otherserial')) {
                 $query .= ", `" . Toolbox::addslashes_deep($table) . "`.`otherserial`";
             } else {
                 $query .= ", '' as `otherserial`";
             }
             $query .= " FROM `" . Toolbox::addslashes_deep($table) . "`";
             if (!in_array($table, $already_joined)) {
                 $query .= " LEFT JOIN `glpi_entities` ON (`" . Toolbox::addslashes_deep($table) . "`.`entities_id` = `glpi_entities`.`id`)";
                 $already_joined[] = 'glpi_entities';
             }
             $query .= self::listInventoryObjectsRequestLeftJoins($params, $item, $table, $already_joined) . getEntitiesRestrictRequest(" AND ", $table);
             if ($item->maybeTemplate()) {
                 $query .= " AND `" . Toolbox::addslashes_deep($table) . "`.`is_template`='0' ";
             }
             if ($item->maybeDeleted()) {
                 $query .= " AND `" . Toolbox::addslashes_deep($table) . "`.`is_deleted`='0' ";
             }
             $query .= self::listInventoryObjectsRequestParameters($params, $item, $table);
             $first = false;
         }
         $first = false;
     }
     $query .= " ORDER BY `name`\n                  LIMIT {$start}, {$limit}";
     foreach ($DB->request($query) as $data) {
         if (!($item = getItemForItemtype($data['itemtype']))) {
             continue;
         }
         $data['itemtype_name'] = Html::clean($item->getTypeName());
         $resp[] = $data;
     }
     return $resp;
 }