. * --------------------------------------------------------------------- */ if (!defined('GLPI_ROOT')) { die("Sorry. You can't access this file directly"); } /** * Rule Class store all information about a GLPI rule : * - description * - criterias * - actions **/ class Rule extends CommonDBTM { use Glpi\Features\Clonable; public $dohistory = true; // Specific ones ///Actions affected to this rule public $actions = []; ///Criterias affected to this rule public $criterias = []; /// Rules can be sorted ? public $can_sort = false; /// field used to order rules public $orderby = 'ranking'; /// restrict matching to self::AND_MATCHING or self::OR_MATCHING : specify value to activate public $restrict_matching = false; protected $rules_id_field = 'rules_id'; protected $ruleactionclass = 'RuleAction'; protected $rulecriteriaclass = 'RuleCriteria'; public $specific_parameters = false; public $regex_results = []; public $criterias_results = []; static $rightname = 'config'; const RULE_NOT_IN_CACHE = -1; const RULE_WILDCARD = '*'; //Generic rules engine const PATTERN_IS = 0; const PATTERN_IS_NOT = 1; const PATTERN_CONTAIN = 2; const PATTERN_NOT_CONTAIN = 3; const PATTERN_BEGIN = 4; const PATTERN_END = 5; const REGEX_MATCH = 6; const REGEX_NOT_MATCH = 7; const PATTERN_EXISTS = 8; const PATTERN_DOES_NOT_EXISTS = 9; const PATTERN_FIND = 10; // Global criteria const PATTERN_UNDER = 11; const PATTERN_NOT_UNDER = 12; const PATTERN_IS_EMPTY = 30; // Global criteria const AND_MATCHING = "AND"; const OR_MATCHING = "OR"; public function getCloneRelations() :array { return [ RuleAction::class, RuleCriteria::class ]; } static function getTable($classname = null) { return parent::getTable(__CLASS__); } static function getTypeName($nb = 0) { return _n('Rule', 'Rules', $nb); } /** * Get correct Rule object for specific rule * * @since 0.84 * * @param $rules_id ID of the rule **/ static function getRuleObjectByID($rules_id) { $rule = new self(); if ($rule->getFromDB($rules_id)) { $realrule = new $rule->fields['sub_type'](); return $realrule; } return null; } /** * Get condition array for rule. If empty array no condition used * maybe overridden to define conditions using binary combination : * example array(1 => Condition1, * 2 => Condition2, * 3 => Condition1&Condition2) * * @since 0.85 * * @return array of conditions **/ static function getConditionsArray() { return []; } /** * Is this rule use condition * **/ function useConditions() { return (count($this->getConditionsArray()) > 0); } /** * Display a dropdown with all the rule conditions * * @since 0.85 * * @param $options array of parameters **/ static function dropdownConditions($options = []) { $p['name'] = 'condition'; $p['value'] = 0; $p['display'] = true; $p['on_change'] = ''; if (is_array($options) && count($options)) { foreach ($options as $key => $val) { $p[$key] = $val; } } $elements = static::getConditionsArray(); if (count($elements)) { return Dropdown::showFromArray($p['name'], $elements, $p); } return false; } /** * Get rule condition type Name * * @param $value condition ID **/ static function getConditionName($value) { $cond = static::getConditionsArray(); if (isset($cond[$value])) { return $cond[$value]; } return NOT_AVAILABLE; } /** * @see CommonGLPI::getMenuContent() * * @since 0.85 **/ static function getMenuContent() { global $CFG_GLPI; $menu = []; if (Session::haveRight("rule_ldap", READ) || Session::haveRight("rule_import", READ) || Session::haveRight("rule_ticket", READ) || Session::haveRight("rule_softwarecategories", READ) || Session::haveRight("rule_mailcollector", READ)) { $menu['rule']['title'] = static::getTypeName(Session::getPluralNumber()); $menu['rule']['page'] = static::getSearchURL(false); $menu['rule']['icon'] = static::getIcon(); foreach ($CFG_GLPI["rulecollections_types"] as $rulecollectionclass) { $rulecollection = new $rulecollectionclass(); if ($rulecollection->canList()) { $ruleclassname = $rulecollection->getRuleClassName(); $menu['rule']['options'][$rulecollection->menu_option]['title'] = $rulecollection->getRuleClass()->getTitle(); $menu['rule']['options'][$rulecollection->menu_option]['page'] = $ruleclassname::getSearchURL(false); $menu['rule']['options'][$rulecollection->menu_option]['links']['search'] = $ruleclassname::getSearchURL(false); if ($rulecollection->canCreate()) { $menu['rule']['options'][$rulecollection->menu_option]['links']['add'] = $ruleclassname::getFormURL(false); } } } } if (Transfer::canView() && Session::isMultiEntitiesMode()) { $menu['rule']['title'] = static::getTypeName(Session::getPluralNumber()); $menu['rule']['page'] = static::getSearchURL(false); $menu['rule']['icon'] = static::getIcon(); $menu['rule']['options']['transfer']['title'] = __('Transfer'); $menu['rule']['options']['transfer']['page'] = "/front/transfer.php"; $menu['rule']['options']['transfer']['links']['search'] = "/front/transfer.php"; if (Session::haveRightsOr("transfer", [CREATE, UPDATE])) { $menu['rule']['options']['transfer']['links']['summary'] = "/front/transfer.action.php"; $menu['rule']['options']['transfer']['links']['add'] = Transfer::getFormURL(false); } } if (Session::haveRight("rule_dictionnary_dropdown", READ) || Session::haveRight("rule_dictionnary_software", READ) || Session::haveRight("rule_dictionnary_printer", READ)) { $menu['dictionnary']['title'] = _n('Dictionary', 'Dictionaries', Session::getPluralNumber()); $menu['dictionnary']['shortcut'] = ''; $menu['dictionnary']['page'] = '/front/dictionnary.php'; $menu['dictionnary']['icon'] = static::getIcon(); $menu['dictionnary']['options']['manufacturers']['title'] = _n('Manufacturer', 'Manufacturers', Session::getPluralNumber()); $menu['dictionnary']['options']['manufacturers']['page'] = '/front/ruledictionnarymanufacturer.php'; $menu['dictionnary']['options']['manufacturers']['links']['search'] = '/front/ruledictionnarymanufacturer.php'; if (RuleDictionnaryDropdown::canCreate()) { $menu['dictionnary']['options']['manufacturers']['links']['add'] = '/front/ruledictionnarymanufacturer.form.php'; } $menu['dictionnary']['options']['software']['title'] = _n('Software', 'Software', Session::getPluralNumber()); $menu['dictionnary']['options']['software']['page'] = '/front/ruledictionnarysoftware.php'; $menu['dictionnary']['options']['software']['links']['search'] = '/front/ruledictionnarysoftware.php'; if (RuleDictionnarySoftware::canCreate()) { $menu['dictionnary']['options']['software']['links']['add'] = '/front/ruledictionnarysoftware.form.php'; } $menu['dictionnary']['options']['model.computer']['title'] = _n('Computer model', 'Computer models', Session::getPluralNumber()); $menu['dictionnary']['options']['model.computer']['page'] = '/front/ruledictionnarycomputermodel.php'; $menu['dictionnary']['options']['model.computer']['links']['search'] = '/front/ruledictionnarycomputermodel.php'; if (RuleDictionnaryDropdown::canCreate()) { $menu['dictionnary']['options']['model.computer']['links']['add'] = '/front/ruledictionnarycomputermodel.form.php'; } $menu['dictionnary']['options']['model.monitor']['title'] = _n('Monitor model', 'Monitor models', Session::getPluralNumber()); $menu['dictionnary']['options']['model.monitor']['page'] = '/front/ruledictionnarymonitormodel.php'; $menu['dictionnary']['options']['model.monitor']['links']['search'] = '/front/ruledictionnarymonitormodel.php'; if (RuleDictionnaryDropdown::canCreate()) { $menu['dictionnary']['options']['model.monitor']['links']['add'] = '/front/ruledictionnarymonitormodel.form.php'; } $menu['dictionnary']['options']['model.printer']['title'] = _n('Printer model', 'Printer models', Session::getPluralNumber()); $menu['dictionnary']['options']['model.printer']['page'] = '/front/ruledictionnaryprintermodel.php'; $menu['dictionnary']['options']['model.printer']['links']['search'] = '/front/ruledictionnaryprintermodel.php'; if (RuleDictionnaryDropdown::canCreate()) { $menu['dictionnary']['options']['model.printer']['links']['add'] = '/front/ruledictionnaryprintermodel.form.php'; } $menu['dictionnary']['options']['model.peripheral']['title'] = _n('Peripheral model', 'Peripheral models', Session::getPluralNumber()); $menu['dictionnary']['options']['model.peripheral']['page'] = '/front/ruledictionnaryperipheralmodel.php'; $menu['dictionnary']['options']['model.peripheral']['links']['search'] = '/front/ruledictionnaryperipheralmodel.php'; if (RuleDictionnaryDropdown::canCreate()) { $menu['dictionnary']['options']['model.peripheral']['links']['add'] = '/front/ruledictionnaryperipheralmodel.form.php'; } $menu['dictionnary']['options']['model.networking']['title'] = _n('Networking equipment model', 'Networking equipment models', Session::getPluralNumber()); $menu['dictionnary']['options']['model.networking']['page'] = '/front/ruledictionnarynetworkequipmentmodel.php'; $menu['dictionnary']['options']['model.networking']['links']['search'] = '/front/ruledictionnarynetworkequipmentmodel.php'; if (RuleDictionnaryDropdown::canCreate()) { $menu['dictionnary']['options']['model.networking']['links']['add'] = '/front/ruledictionnarynetworkequipmentmodel.form.php'; } $menu['dictionnary']['options']['model.phone']['title'] = _n('Phone model', 'Phone models', Session::getPluralNumber()); $menu['dictionnary']['options']['model.phone']['page'] = '/front/ruledictionnaryphonemodel.php'; $menu['dictionnary']['options']['model.phone']['links']['search'] = '/front/ruledictionnaryphonemodel.php'; if (RuleDictionnaryDropdown::canCreate()) { $menu['dictionnary']['options']['model.phone']['links']['add'] = '/front/ruledictionnaryphonemodel.form.php'; } $menu['dictionnary']['options']['type.computer']['title'] = _n('Computer type', 'Computer types', Session::getPluralNumber()); $menu['dictionnary']['options']['type.computer']['page'] = '/front/ruledictionnarycomputertype.php'; $menu['dictionnary']['options']['type.computer']['links']['search'] = '/front/ruledictionnarycomputertype.php'; if (RuleDictionnaryDropdown::canCreate()) { $menu['dictionnary']['options']['type.computer']['links']['add'] = '/front/ruledictionnarycomputertype.form.php'; } $menu['dictionnary']['options']['type.monitor']['title'] = _n('Monitor type', 'Monitors types', Session::getPluralNumber()); $menu['dictionnary']['options']['type.monitor']['page'] = '/front/ruledictionnarymonitortype.php'; $menu['dictionnary']['options']['type.monitor']['links']['search'] = '/front/ruledictionnarymonitortype.php'; if (RuleDictionnaryDropdown::canCreate()) { $menu['dictionnary']['options']['type.monitor']['links']['add'] = '/front/ruledictionnarymonitortype.form.php'; } $menu['dictionnary']['options']['type.printer']['title'] = _n('Printer type', 'Printer types', Session::getPluralNumber()); $menu['dictionnary']['options']['type.printer']['page'] = '/front/ruledictionnaryprintertype.php'; $menu['dictionnary']['options']['type.printer']['links']['search'] = '/front/ruledictionnaryprintertype.php'; if (RuleDictionnaryDropdown::canCreate()) { $menu['dictionnary']['options']['type.printer']['links']['add'] = '/front/ruledictionnaryprintertype.form.php'; } $menu['dictionnary']['options']['type.peripheral']['title'] = _n('Peripheral type', 'Peripheral types', Session::getPluralNumber()); $menu['dictionnary']['options']['type.peripheral']['page'] = '/front/ruledictionnaryperipheraltype.php'; $menu['dictionnary']['options']['type.peripheral']['links']['search'] = '/front/ruledictionnaryperipheraltype.php'; if (RuleDictionnaryDropdown::canCreate()) { $menu['dictionnary']['options']['type.peripheral']['links']['add'] = '/front/ruledictionnaryperipheraltype.form.php'; } $menu['dictionnary']['options']['type.networking']['title'] = _n('Networking equipment type', 'Networking equipment types', Session::getPluralNumber()); $menu['dictionnary']['options']['type.networking']['page'] = '/front/ruledictionnarynetworkequipmenttype.php'; $menu['dictionnary']['options']['type.networking']['links']['search'] = '/front/ruledictionnarynetworkequipmenttype.php'; if (RuleDictionnaryDropdown::canCreate()) { $menu['dictionnary']['options']['type.networking']['links']['add'] = '/front/ruledictionnarynetworkequipmenttype.form.php'; } $menu['dictionnary']['options']['type.phone']['title'] = _n('Phone type', 'Phone types', Session::getPluralNumber()); $menu['dictionnary']['options']['type.phone']['page'] = '/front/ruledictionnaryphonetype.php'; $menu['dictionnary']['options']['type.phone']['links']['search'] = '/front/ruledictionnaryphonetype.php'; if (RuleDictionnaryDropdown::canCreate()) { $menu['dictionnary']['options']['type.phone']['links']['add'] = '/front/ruledictionnaryphonetype.form.php'; } $menu['dictionnary']['options']['os']['title'] = OperatingSystem::getTypeName(1); $menu['dictionnary']['options']['os']['page'] = '/front/ruledictionnaryoperatingsystem.php'; $menu['dictionnary']['options']['os']['links']['search'] = '/front/ruledictionnaryoperatingsystem.php'; if (RuleDictionnaryDropdown::canCreate()) { $menu['dictionnary']['options']['os']['links']['add'] = '/front/ruledictionnaryoperatingsystem.form.php'; } $menu['dictionnary']['options']['os_sp']['title'] = OperatingSystemServicePack::getTypeName(1); $menu['dictionnary']['options']['os_sp']['page'] = '/front/ruledictionnaryoperatingsystemservicepack.php'; $menu['dictionnary']['options']['os_sp']['links']['search'] = '/front/ruledictionnaryoperatingsystemservicepack.php'; if (RuleDictionnaryDropdown::canCreate()) { $menu['dictionnary']['options']['os_sp']['links']['add'] = '/front/ruledictionnaryoperatingsystemservicepack.form.php'; } $menu['dictionnary']['options']['os_version']['title'] = OperatingSystemVersion::getTypeName(1); $menu['dictionnary']['options']['os_version']['page'] = '/front/ruledictionnaryoperatingsystemversion.php'; $menu['dictionnary']['options']['os_version']['links']['search'] = '/front/ruledictionnaryoperatingsystemversion.php'; if (RuleDictionnaryDropdown::canCreate()) { $menu['dictionnary']['options']['os_version']['links']['add'] = '/front/ruledictionnaryoperatingsystemversion.form.php'; } $menu['dictionnary']['options']['os_arch']['title'] = OperatingSystemArchitecture::getTypeName(1); $menu['dictionnary']['options']['os_arch']['page'] = '/front/ruledictionnaryoperatingsystemarchitecture.php'; $menu['dictionnary']['options']['os_arch']['links']['search'] = '/front/ruledictionnaryoperatingsystemarchitecture.php'; if (RuleDictionnaryDropdown::canCreate()) { $menu['dictionnary']['options']['os_arch']['links']['add'] = '/front/ruledictionnaryoperatingsystemarchitecture.form.php'; } $menu['dictionnary']['options']['printer']['title'] = _n('Printer', 'Printers', Session::getPluralNumber()); $menu['dictionnary']['options']['printer']['page'] = '/front/ruledictionnaryprinter.php'; $menu['dictionnary']['options']['printer']['links']['search'] = '/front/ruledictionnaryprinter.php'; if (RuleDictionnaryPrinter::canCreate()) { $menu['dictionnary']['options']['printer']['links']['add'] = '/front/ruledictionnaryprinter.form.php'; } } if (count($menu)) { $menu['is_multi_entries'] = true; return $menu; } return false; } /** * @since versin 0.84 **/ function getRuleActionClass () { return $this->ruleactionclass; } /** * @since versin 0.84 **/ function getRuleCriteriaClass () { return $this->rulecriteriaclass; } /** * @since versin 0.84 **/ function getRuleIdField () { return $this->rules_id_field; } function isEntityAssign() { return false; } function post_getEmpty() { $this->fields['is_active'] = 0; } /** * Get title used in rule * * @return Title of the rule **/ function getTitle() { return __('Rules management'); } /** * @since 0.84 * * @return string **/ function getCollectionClassName() { return $this->getType().'Collection'; } /** * @see CommonDBTM::getSpecificMassiveActions() **/ function getSpecificMassiveActions($checkitem = null) { $isadmin = static::canUpdate(); $actions = parent::getSpecificMassiveActions($checkitem); $collectiontype = $this->getCollectionClassName(); if ($collection = getItemForItemtype($collectiontype)) { if ($isadmin && ($collection->orderby == "ranking")) { $actions[__CLASS__.MassiveAction::CLASS_ACTION_SEPARATOR.'move_rule'] = "". __('Move'); } $actions[__CLASS__.MassiveAction::CLASS_ACTION_SEPARATOR.'export'] = "". _x('button', 'Export'); } return $actions; } /** * @since 0.85 * * @see CommonDBTM::showMassiveActionsSubForm() **/ static function showMassiveActionsSubForm(MassiveAction $ma) { switch ($ma->getAction()) { case 'move_rule' : $input = $ma->getInput(); $values = ['after' => __('After'), 'before' => __('Before')]; Dropdown::showFromArray('move_type', $values, ['width' => '20%']); if (isset($input['entity'])) { $entity = $input['entity']; } else { $entity = ""; } if (isset($input['condition'])) { $condition = $input['condition']; } else { $condition = 0; } echo Html::hidden('rule_class_name', ['value' => $input['rule_class_name']]); Rule::dropdown(['sub_type' => $input['rule_class_name'], 'name' => "ranking", 'condition' => $condition, 'entity' => $entity, 'width' => '50%']); echo "

\n"; return true; } return parent::showMassiveActionsSubForm($ma); } /** * @since 0.85 * * @see CommonDBTM::processMassiveActionsForOneItemtype() **/ static function processMassiveActionsForOneItemtype(MassiveAction $ma, CommonDBTM $item, array $ids) { switch ($ma->getAction()) { case 'export': if (count($ids)) { $_SESSION['exportitems'] = $ids; $ma->itemDone($item->getType(), $ids, MassiveAction::ACTION_OK); $ma->setRedirect('rule.backup.php?action=download&itemtype='.$item->getType()); } break; case 'move_rule' : $input = $ma->getInput(); $collectionname = $input['rule_class_name'].'Collection'; $rulecollection = new $collectionname(); if ($rulecollection->canUpdate()) { foreach ($ids as $id) { if ($item->getFromDB($id)) { if ($rulecollection->moveRule($id, $input['ranking'], $input['move_type'])) { $ma->itemDone($item->getType(), $id, MassiveAction::ACTION_OK); } else { $ma->itemDone($item->getType(), $id, MassiveAction::ACTION_KO); $ma->addMessage($item->getErrorMessage(ERROR_ON_ACTION)); } } else { $ma->itemDone($item->getType(), $id, MassiveAction::ACTION_KO); $ma->addMessage($item->getErrorMessage(ERROR_NOT_FOUND)); } } } else { $ma->itemDone($item->getType(), $ids, MassiveAction::ACTION_NORIGHT); $ma->addMessage($item->getErrorMessage(ERROR_RIGHT)); } break; } parent::processMassiveActionsForOneItemtype($ma, $item, $ids); } function rawSearchOptions() { $tab = []; $tab[] = [ 'id' => '1', 'table' => $this->getTable(), 'field' => 'name', 'name' => __('Name'), 'datatype' => 'itemlink', 'massiveaction' => false, 'autocomplete' => true, ]; $tab[] = [ 'id' => '2', 'table' => $this->getTable(), 'field' => 'id', 'name' => __('ID'), 'massiveaction' => false, 'datatype' => 'number' ]; $tab[] = [ 'id' => '3', 'table' => $this->getTable(), 'field' => 'ranking', 'name' => __('Ranking'), 'datatype' => 'number', 'massiveaction' => false ]; $tab[] = [ 'id' => '4', 'table' => $this->getTable(), 'field' => 'description', 'name' => __('Description'), 'datatype' => 'text', 'autocomplete' => true, ]; $tab[] = [ 'id' => '5', 'table' => $this->getTable(), 'field' => 'match', 'name' => __('Logical operator'), 'datatype' => 'specific', 'massiveaction' => false ]; $tab[] = [ 'id' => '8', 'table' => $this->getTable(), 'field' => 'is_active', 'name' => __('Active'), 'datatype' => 'bool' ]; $tab[] = [ 'id' => '16', 'table' => $this->getTable(), 'field' => 'comment', 'name' => __('Comments'), 'datatype' => 'text' ]; $tab[] = [ 'id' => '80', 'table' => 'glpi_entities', 'field' => 'completename', 'name' => Entity::getTypeName(1), 'massiveaction' => false, 'datatype' => 'dropdown' ]; $tab[] = [ 'id' => '86', 'table' => $this->getTable(), 'field' => 'is_recursive', 'name' => __('Child entities'), 'datatype' => 'bool', 'massiveaction' => false ]; $tab[] = [ 'id' => '19', 'table' => $this->getTable(), 'field' => 'date_mod', 'name' => __('Last update'), 'datatype' => 'datetime', 'massiveaction' => false ]; $tab[] = [ 'id' => '121', 'table' => $this->getTable(), 'field' => 'date_creation', 'name' => __('Creation date'), 'datatype' => 'datetime', 'massiveaction' => false ]; return $tab; } /** * @param $field * @param $values * @param $options array * * @return string **/ static function getSpecificValueToDisplay($field, $values, array $options = []) { if (!is_array($values)) { $values = [$field => $values]; } switch ($field) { case 'match' : switch ($values[$field]) { case self::AND_MATCHING : return __('and'); case self::OR_MATCHING : return __('or'); default : return NOT_AVAILABLE; } break; } return parent::getSpecificValueToDisplay($field, $values, $options); } /** * @param $field * @param $name (default '') * @param $values (default '') * @param $options array **/ static function getSpecificValueToSelect($field, $name = '', $values = '', array $options = []) { if (!is_array($values)) { $values = [$field => $values]; } $options['display'] = false; switch ($field) { case 'match' : if (isset($values['itemtype']) && !empty($values['itemtype'])) { $options['value'] = $values[$field]; $options['name'] = $name; $rule = new static(); return $rule->dropdownRulesMatch($options); } break; } return parent::getSpecificValueToSelect($field, $name, $values, $options); } /** * Show the rule * * @param $ID ID of the rule * @param $options array of possible options: * - target filename : where to go when done. * - withtemplate boolean : template or basic item * * @return void **/ function showForm($ID, $options = []) { global $CFG_GLPI; if (!$this->isNewID($ID)) { $this->check($ID, READ); } else { // Create item $this->checkGlobal(UPDATE); } $canedit = $this->canEdit(static::$rightname); $rand = mt_rand(); $this->showFormHeader($options); echo ""; echo "".__('Name').""; echo ""; Html::autocompletionTextField($this, "name"); echo ""; echo "".__('Description').""; echo ""; Html::autocompletionTextField($this, "description"); echo "\n"; echo ""; echo "".__('Logical operator').""; echo ""; $this->dropdownRulesMatch(['value' => $this->fields["match"]]); echo ""; echo "".__('Active').""; echo ""; Dropdown::showYesNo("is_active", $this->fields["is_active"]); echo "\n"; if ($this->useConditions()) { echo ""; echo "".__('Use rule for').""; echo ""; $this->dropdownConditions(['value' => $this->fields["condition"]]); echo ""; echo ""; echo "\n"; } echo ""; echo "".__('Comments').""; echo ""; echo ""; if (!$this->isNewID($ID)) { if ($this->fields["date_mod"]) { echo "
"; printf(__('Last update on %s'), Html::convDateTime($this->fields["date_mod"])); } } if ($canedit) { if (!$this->isNewID($ID)) { echo ""; } echo ""; } echo "\n"; if ($canedit) { if ($ID > 0) { if ($plugin = isPluginItemType($this->getType())) { $url = $CFG_GLPI["root_doc"]."/plugins/".strtolower($plugin['plugin']); } else { $url = $CFG_GLPI["root_doc"]; } echo ""; echo "". _x('button', 'Test').""; Ajax::createIframeModalWindow('ruletest'.$rand, $url."/front/rule.test.php?". "sub_type=".$this->getType(). "&rules_id=".$this->fields["id"], ['title' => _x('button', 'Test')]); echo "\n"; } } $this->showFormButtons($options); return true; } /** * Display a dropdown with all the rule matching * * @since 0.84 new proto * * @param $options array of parameters **/ function dropdownRulesMatch($options = []) { $p['name'] = 'match'; $p['value'] = ''; $p['restrict'] = $this->restrict_matching; $p['display'] = true; if (is_array($options) && count($options)) { foreach ($options as $key => $val) { $p[$key] = $val; } } if (!$p['restrict'] || ($p['restrict'] == self::AND_MATCHING)) { $elements[self::AND_MATCHING] = __('and'); } if (!$p['restrict'] || ($p['restrict'] == self::OR_MATCHING)) { $elements[self::OR_MATCHING] = __('or'); } return Dropdown::showFromArray($p['name'], $elements, $p); } /** * Get all criterias for a given rule * * @param $ID the rule_description ID * @param $withcriterias 1 to retrieve all the criterias for a given rule (default 0) * @param $withactions 1 to retrive all the actions for a given rule (default 0) **/ function getRuleWithCriteriasAndActions($ID, $withcriterias = 0, $withactions = 0) { if ($ID == "") { return $this->getEmpty(); } if ($ret = $this->getFromDB($ID)) { if ($withactions && ($RuleAction = getItemForItemtype($this->ruleactionclass))) { $this->actions = $RuleAction->getRuleActions($ID); } if ($withcriterias && ($RuleCriterias = getItemForItemtype($this->rulecriteriaclass))) { $this->criterias = $RuleCriterias->getRuleCriterias($ID); } return true; } return false; } /** * display title for action form **/ function getTitleAction() { foreach ($this->getActions() as $key => $val) { if (isset($val['force_actions']) && (in_array('regex_result', $val['force_actions']) || in_array('append_regex_result', $val['force_actions']))) { echo ""; echo "\n"; echo "
". __('It is possible to affect the result of a regular expression using the string #0'). "

"; return; } } } /** * Get maximum number of Actions of the Rule (0 = unlimited) * * @return the maximum number of actions **/ function maxActionsCount() { return count(array_filter($this->getAllActions(), function($action_obj) { return !isset($action_obj['duplicatewith']); })); } /** * Display all rules actions * * @param $rules_id rule ID * @param $options array of options : may be readonly **/ function showActionsList($rules_id, $options = []) { global $CFG_GLPI; $rand = mt_rand(); $p['readonly'] = false; if (is_array($options) && count($options)) { foreach ($options as $key => $val) { $p[$key] = $val; } } $canedit = $this->canEdit($rules_id); $style = "class='tab_cadre_fixehov'"; if ($p['readonly']) { $canedit = false; $style = "class='tab_cadrehov'"; } $this->getTitleAction(); if ($canedit) { echo "
\n"; } if ($canedit && (($this->maxActionsCount() == 0) || (sizeof($this->actions) < $this->maxActionsCount()))) { echo "\n"; echo "
". ""; echo __('Add a new action')."
\n"; } $nb = count($this->actions); echo "
"; if ($canedit && $nb) { Html::openMassiveActionsForm('mass'.$this->ruleactionclass.$rand); $massiveactionparams = ['num_displayed' => min($_SESSION['glpilist_limit'], $nb), 'check_itemtype' => get_class($this), 'check_items_id' => $rules_id, 'container' => 'mass'.$this->ruleactionclass.$rand, 'extraparams' => ['rule_class_name' => $this->getType()]]; Html::showMassiveActions($massiveactionparams); } echo ""; echo ""; echo ""; $header_begin = ""; $header_top = ''; $header_bottom = ''; $header_end = ''; if ($canedit && $nb) { $header_top .= ""; $header_bottom .= ""; } $header_end .= ""; $header_end .= ""; $header_end .= ""; $header_end .= "\n"; echo $header_begin.$header_top.$header_end; foreach ($this->actions as $action) { $this->showMinimalActionForm($action->fields, $canedit, $rand); } if ($nb) { echo $header_begin.$header_bottom.$header_end; } echo "
" . _n('Action', 'Actions', Session::getPluralNumber()) . "
"; $header_top .= Html::getCheckAllAsCheckbox('mass'.$this->ruleactionclass.$rand).""; $header_bottom .= Html::getCheckAllAsCheckbox('mass'.$this->ruleactionclass.$rand).""._n('Field', 'Fields', Session::getPluralNumber())."".__('Action type')."".__('Value')."
\n"; if ($canedit && $nb) { $massiveactionparams['ontop'] = false; Html::showMassiveActions($massiveactionparams); Html::closeForm(); } echo "
"; } function maybeRecursive() { return false; } /** * Display all rules criterias * * @param $rules_id * @param $options array of options : may be readonly **/ function showCriteriasList($rules_id, $options = []) { global $CFG_GLPI; $rand = mt_rand(); $p['readonly'] = false; if (is_array($options) && count($options)) { foreach ($options as $key => $val) { $p[$key] = $val; } } $canedit = $this->canEdit($rules_id); $style = "class='tab_cadre_fixehov'"; if ($p['readonly']) { $canedit = false; $style = "class='tab_cadrehov'"; } if ($canedit) { echo "
\n"; echo "\n"; echo "
". ""; echo __('Add a new criterion')."
\n"; } echo "
"; $nb = sizeof($this->criterias); if ($canedit && $nb) { Html::openMassiveActionsForm('mass'.$this->rulecriteriaclass.$rand); $massiveactionparams = ['num_displayed' => min($_SESSION['glpilist_limit'], $nb), 'check_itemtype' => get_class($this), 'check_items_id' => $rules_id, 'container' => 'mass'.$this->rulecriteriaclass.$rand, 'extraparams' => ['rule_class_name' => $this->getType()]]; Html::showMassiveActions($massiveactionparams); } echo ""; echo "". "". "\n"; $header_begin = ""; $header_top = ''; $header_bottom = ''; $header_end = ''; if ($canedit && $nb) { $header_top .= ""; $header_bottom .= ""; } $header_end .= "\n"; $header_end .= "\n"; $header_end .= "\n"; $header_end .= "\n"; echo $header_begin.$header_top.$header_end; foreach ($this->criterias as $criterion) { $this->showMinimalCriteriaForm($criterion->fields, $canedit, $rand); } if ($nb) { echo $header_begin.$header_bottom.$header_end; } echo "
". _n('Criterion', 'Criteria', Session::getPluralNumber())."
"; $header_top .= Html::getCheckAllAsCheckbox('mass'.$this->rulecriteriaclass.$rand); $header_top .= ""; $header_bottom .= Html::getCheckAllAsCheckbox('mass'.$this->rulecriteriaclass.$rand); $header_bottom .= ""._n('Criterion', 'Criteria', 1)."".__('Condition')."".__('Reason')."
\n"; if ($canedit && $nb) { $massiveactionparams['ontop'] = false; Html::showMassiveActions($massiveactionparams); Html::closeForm(); } echo "
\n"; } /** * Display the dropdown of the criteria for the rule * * @since 0.84 new proto * * @param $options array of options : may be readonly * * @return the initial value (first) **/ function dropdownCriteria($options = []) { $p['name'] = 'criteria'; $p['display'] = true; $p['value'] = ''; $p['display_emptychoice'] = true; if (is_array($options) && count($options)) { foreach ($options as $key => $val) { $p[$key] = $val; } } $group = []; $groupname = _n('Criterion', 'Criteria', Session::getPluralNumber()); foreach ($this->getAllCriteria() as $ID => $crit) { // Manage group system if (!is_array($crit)) { if (count($group)) { asort($group); $items[$groupname] = $group; } $group = []; $groupname = $crit; } else { $group[$ID] = $crit['name']; } } if (count($group)) { asort($group); $items[$groupname] = $group; } return Dropdown::showFromArray($p['name'], $items, $p); } /** * Display the dropdown of the actions for the rule * * @param $options already used actions * * @return the initial value (first non used) **/ function dropdownActions($options = []) { $p['name'] = 'field'; $p['display'] = true; $p['used'] = []; $p['value'] = ''; $p['display_emptychoice'] = true; if (is_array($options) && count($options)) { foreach ($options as $key => $val) { $p[$key] = $val; } } $actions = $this->getAllActions(); // For each used actions see if several set is available // Force actions to available actions for several foreach ($p['used'] as $key => $ID) { if (isset($actions[$ID]['permitseveral'])) { unset($p['used'][$key]); } } // Complete used array with duplicate items // add duplicates of used items foreach ($p['used'] as $ID) { if (isset($actions[$ID]['duplicatewith'])) { $p['used'][$actions[$ID]['duplicatewith']] = $actions[$ID]['duplicatewith']; } } // Parse for duplicates of already used items foreach ($actions as $ID => $act) { if (isset($actions[$ID]['duplicatewith']) && in_array($actions[$ID]['duplicatewith'], $p['used'])) { $p['used'][$ID] = $ID; } } $value = ''; foreach ($actions as $ID => $act) { $items[$ID] = $act['name']; if (empty($value) && !isset($used[$ID])) { $value = $ID; } } return Dropdown::showFromArray($p['name'], $items, $p); } /** * Get a criteria description by his ID * * @param $ID the criteria's ID * * @return the criteria array **/ function getCriteria($ID) { $criteria = $this->getAllCriteria(); if (isset($criteria[$ID])) { return $criteria[$ID]; } return []; } /** * Get a action description by his ID * * @param $ID the action's ID * * @return the action array **/ function getAction($ID) { $actions = $this->getAllActions(); if (isset($actions[$ID])) { return $actions[$ID]; } return []; } /** * Get a criteria description by his ID * * @param $ID the criteria's ID * * @return the criteria's description **/ function getCriteriaName($ID) { $criteria = $this->getCriteria($ID); if (isset($criteria['name'])) { return $criteria['name']; } return __('Unavailable')." "; } /** * Get a action description by his ID * * @param $ID the action's ID * * @return the action's description **/ function getActionName($ID) { $action = $this->getAction($ID); if (isset($action['name'])) { return $action['name']; } return " "; } /** * Process the rule * * @param &$input the input data used to check criteria * @param &$output the initial output array used to be manipulate by actions * @param &$params parameters for all internal functions * @param &options array options: * - only_criteria : only react on specific criteria * * @return the output array updated by actions. * If rule matched add field _rule_process to return value **/ function process(&$input, &$output, &$params, &$options = []) { if ($this->validateCriterias($options)) { $this->regex_results = []; $this->criterias_results = []; $input = $this->prepareInputDataForProcess($input, $params); if ($this->checkCriterias($input)) { unset($output["_no_rule_matches"]); $refoutput = $output; $output = $this->executeActions($output, $params, $input); $this->updateOnlyCriteria($options, $refoutput, $output); //Hook $hook_params["sub_type"] = $this->getType(); $hook_params["ruleid"] = $this->fields["id"]; $hook_params["input"] = $input; $hook_params["output"] = $output; Plugin::doHook("rule_matched", $hook_params); $output["_rule_process"] = true; } } } /** * Update Only criteria options if needed * * @param &options options : * - only_criteria : only react on specific criteria * @param $refoutput the initial output array used to be manipulate by actions * @param $newoutput the output array after actions process * * @return the options array updated. **/ function updateOnlyCriteria(&$options, $refoutput, $newoutput) { if (count($this->actions)) { if (isset($options['only_criteria']) && !is_null($options['only_criteria']) && is_array($options['only_criteria'])) { foreach ($this->actions as $action) { if (!isset($refoutput[$action->fields["field"]]) || ($refoutput[$action->fields["field"]] != $newoutput[$action->fields["field"]])) { if (!in_array($action->fields["field"], $options['only_criteria'])) { $options['only_criteria'][] = $action->fields["field"]; } // Add linked criteria if available $crit = $this->getCriteria($action->fields["field"]); if (isset($crit['linked_criteria'])) { $tmp = $crit['linked_criteria']; if (!is_array($crit['linked_criteria'])) { $tmp = [$tmp]; } foreach ($tmp as $toadd) { if (!in_array($toadd, $options['only_criteria'])) { $options['only_criteria'][] = $toadd; } } } } } } } } /** * Are criteria valid to be processed * * @since 0.85 * * @param array $options * * @return boolean **/ function validateCriterias($options) { if (count($this->criterias)) { if (isset($options['only_criteria']) && !is_null($options['only_criteria']) && is_array($options['only_criteria'])) { foreach ($this->criterias as $criterion) { if (in_array($criterion->fields['criteria'], $options['only_criteria'])) { return true; } } return false; } return true; } return false; } /** * Check criteria * * @param aray $input the input data used to check criteri * * @return boolean if criteria match **/ function checkCriterias($input) { reset($this->criterias); if ($this->fields["match"] == self::AND_MATCHING) { $doactions = true; foreach ($this->criterias as $criterion) { $definition_criterion = $this->getCriteria($criterion->fields['criteria']); if (!isset($definition_criterion['is_global']) || !$definition_criterion['is_global']) { $doactions &= $this->checkCriteria($criterion, $input); if (!$doactions) { break; } } } } else { // OR MATCHING $doactions = false; foreach ($this->criterias as $criterion) { $definition_criterion = $this->getCriteria($criterion->fields['criteria']); if (!isset($definition_criterion['is_global']) || !$definition_criterion['is_global']) { $doactions |= $this->checkCriteria($criterion, $input); if ($doactions) { break; } } } } //If all simple criteria match, and if necessary, check complex criteria if ($doactions) { return $this->findWithGlobalCriteria($input); } return false; } /** * Check criteria * * @param array $input the input data used to check criteria * @param array &$check_results * * @return boolean if criteria match **/ function testCriterias($input, &$check_results) { reset($this->criterias); foreach ($this->criterias as $criterion) { $result = $this->checkCriteria($criterion, $input); $check_results[$criterion->fields["id"]]["name"] = $criterion->fields["criteria"]; $check_results[$criterion->fields["id"]]["value"] = $criterion->fields["pattern"]; $check_results[$criterion->fields["id"]]["result"] = ((!$result)?0:1); $check_results[$criterion->fields["id"]]["id"] = $criterion->fields["id"]; } } /** * Process a criteria of a rule * * @param &$criteria criteria to check * @param &$input the input data used to check criteria **/ function checkCriteria(&$criteria, &$input) { $partial_regex_result = []; // Undefine criteria field : set to blank if (!isset($input[$criteria->fields["criteria"]])) { $input[$criteria->fields["criteria"]] = ''; } //If the value is not an array if (!is_array($input[$criteria->fields["criteria"]])) { $value = $this->getCriteriaValue($criteria->fields["criteria"], $criteria->fields["condition"], $input[$criteria->fields["criteria"]]); $res = RuleCriteria::match($criteria, $value, $this->criterias_results, $partial_regex_result); } else { //If the value is, in fact, an array of values // Negative condition : Need to match all condition (never be) if (in_array($criteria->fields["condition"], [self::PATTERN_IS_NOT, self::PATTERN_NOT_CONTAIN, self::REGEX_NOT_MATCH, self::PATTERN_DOES_NOT_EXISTS])) { $res = true; foreach ($input[$criteria->fields["criteria"]] as $tmp) { $value = $this->getCriteriaValue($criteria->fields["criteria"], $criteria->fields["condition"], $tmp); $res &= RuleCriteria::match($criteria, $value, $this->criterias_results, $partial_regex_result); if (!$res) { break; } } } else { // Positive condition : Need to match one $res = false; foreach ($input[$criteria->fields["criteria"]] as $crit) { $value = $this->getCriteriaValue($criteria->fields["criteria"], $criteria->fields["condition"], $crit); $res |= RuleCriteria::match($criteria, $value, $this->criterias_results, $partial_regex_result); } } } // Found regex on this criteria if (count($partial_regex_result)) { // No regex existing : put found if (!count($this->regex_results)) { $this->regex_results = $partial_regex_result; } else { // Already existing regex : append found values $temp_result = []; foreach ($partial_regex_result as $new) { foreach ($this->regex_results as $old) { $temp_result[] = array_merge($old, $new); } } $this->regex_results = $temp_result; } } return $res; } /** * @param $input **/ function findWithGlobalCriteria($input) { return true; } /** * Specific prepare input datas for the rule * * @param $input the input data used to check criteria * @param $params parameters * * @return the updated input datas **/ function prepareInputDataForProcess($input, $params) { return $input; } /** * Get all data needed to process rules (core + plugins) * * @since 0.84 * @param $input the input data used to check criteria * @param $params parameters * * @return the updated input datas **/ function prepareAllInputDataForProcess($input, $params) { global $PLUGIN_HOOKS; $input = $this->prepareInputDataForProcess($input, $params); if (isset($PLUGIN_HOOKS['use_rules'])) { foreach ($PLUGIN_HOOKS['use_rules'] as $plugin => $val) { if (!Plugin::isPluginActive($plugin)) { continue; } if (is_array($val) && in_array($this->getType(), $val)) { $results = Plugin::doOneHook($plugin, "rulePrepareInputDataForProcess", ['input' => $input, 'params' => $params]); if (is_array($results)) { foreach ($results as $result) { $input[] = $result; } } } } } return $input; } /** * Execute plugins actions if needed. * * @since 9.3.2 Added $input parameter * @since 0.84 * * @param RuleAction $action * @param array $output rule execution output * @param array $params parameters * @param array $input the input data * * @return array Updated output */ function executePluginsActions($action, $output, $params, array $input = []) { global $PLUGIN_HOOKS; if (isset($PLUGIN_HOOKS['use_rules'])) { $params['criterias_results'] = $this->criterias_results; $params['rule_itemtype'] = $this->getType(); foreach ($PLUGIN_HOOKS['use_rules'] as $plugin => $val) { if (!Plugin::isPluginActive($plugin)) { continue; } if (is_array($val) && in_array($this->getType(), $val)) { $results = Plugin::doOneHook($plugin, "executeActions", ['output' => $output, 'params' => $params, 'action' => $action, 'input' => $input]); if (is_array($results)) { foreach ($results as $id => $result) { $output[$id] = $result; } } } } } return $output; } /** * Execute the actions as defined in the rule. * * @since 9.3.2 Added $input parameter * * @param array $output the fields to manipulate * @param array $params parameters * @param array $input the input data * * @return array Updated output **/ function executeActions($output, $params, array $input = []) { if (count($this->actions)) { foreach ($this->actions as $action) { switch ($action->fields["action_type"]) { case "assign" : $output[$action->fields["field"]] = $action->fields["value"]; break; case "append" : $actions = $this->getActions(); $value = $action->fields["value"]; if (isset($actions[$action->fields["field"]]["appendtoarray"]) && isset($actions[$action->fields["field"]]["appendtoarrayfield"])) { $value = $actions[$action->fields["field"]]["appendtoarray"]; $value[$actions[$action->fields["field"]]["appendtoarrayfield"]] = $action->fields["value"]; } $output[$actions[$action->fields["field"]]["appendto"]][] = $value; break; case "regex_result" : case "append_regex_result" : //Regex result : assign value from the regex //Append regex result : append result from a regex if (isset($this->regex_results[0])) { $res = RuleAction::getRegexResultById($action->fields["value"], $this->regex_results[0]); } else { $res = $action->fields["value"]; } if ($action->fields["action_type"] == "append_regex_result") { if (isset($params[$action->fields["field"]])) { $res = $params[$action->fields["field"]] . $res; } else { //keep rule value to append in a separate entry $output[$action->fields['field'] . '_append'] = $res; } } $output[$action->fields["field"]] = $res; break; default: //plugins actions $executeaction = clone $this; $output = $executeaction->executePluginsActions($action, $output, $params, $input); break; } } } return $output; } function cleanDBonPurge() { // Delete a rule and all associated criteria and actions if (!empty($this->ruleactionclass)) { $ruleactionclass = $this->ruleactionclass; $ra = new $ruleactionclass(); $ra->deleteByCriteria([$this->rules_id_field => $this->fields['id']]); } if (!empty($this->rulecriteriaclass)) { $rulecriteriaclass = $this->rulecriteriaclass; $rc = new $rulecriteriaclass(); $rc->deleteByCriteria([$this->rules_id_field => $this->fields['id']]); } } /** * Show the minimal form for the rule * * @param $target link to the form page * @param $first is it the first rule ?(false by default) * @param $last is it the last rule ? (false by default) * @param $display_entities display entities / make it read only display (false by default) * @param $active_condition active condition used (default 0) **/ function showMinimalForm($target, $first = false, $last = false, $display_entities = false, $active_condition = 0) { global $CFG_GLPI; $canedit = (self::canUpdate() && !$display_entities); echo ""; if ($canedit) { echo ""; Html::showMassiveActionCheckBox($this->getType(), $this->fields["id"]); echo ""; } else { echo " "; } $link = $this->getLink(); if (!empty($this->fields["comment"])) { $link = sprintf(__('%1$s %2$s'), $link, Html::showToolTip($this->fields["comment"], ['display' => false])); } echo "".$link.""; echo "".$this->fields["description"].""; if ($this->useConditions()) { echo "".$this->getConditionName($this->fields["condition"]).""; } echo "".Dropdown::getYesNo($this->fields["is_active"]).""; if ($display_entities) { $entname = Dropdown::getDropdownName('glpi_entities', $this->fields['entities_id']); if ($this->maybeRecursive() && $this->fields['is_recursive']) { $entname = sprintf(__('%1$s %2$s'), $entname, "(".__('R').")"); } echo "".$entname.""; } if (!$display_entities) { if ($this->can_sort && !$first && $canedit) { echo ""; Html::showSimpleForm($target, ['action' => 'up', 'condition' => $active_condition], '', ['type' => $this->fields["sub_type"], 'id' => $this->fields["id"],], $CFG_GLPI["root_doc"]."/pics/deplier_up.png"); echo ""; } else { echo " "; } } if (!$display_entities) { if ($this->can_sort && !$last && $canedit) { echo ""; Html::showSimpleForm($target, ['action' => 'down', 'condition' => $active_condition], '', ['type' => $this->fields["sub_type"], 'id' => $this->fields["id"]], $CFG_GLPI["root_doc"]."/pics/deplier_down.png"); echo ""; } else { echo " "; } } echo "\n"; } /** * @see CommonDBTM::prepareInputForAdd() **/ function prepareInputForAdd($input) { // Before adding, add the ranking of the new rule $input["ranking"] = $input['ranking'] ?? $this->getNextRanking(); //If no uuid given, generate a new one if (!isset($input['uuid'])) { $input["uuid"] = self::getUuid(); } if ($this->getType() == 'Rule' && !isset($input['sub_type'])) { \Toolbox::logError('Sub type not specified creating a new rule'); return false; } if (!isset($input['sub_type'])) { $input['sub_type'] = $this->getType(); } else if ($this->getType() != 'Rule' && $input['sub_type'] != $this->getType()) { \Toolbox::logWarning( sprintf( 'Creating a %s rule with %s subtype.', $this->getType(), $input['sub_type'] ) ); } return $input; } /** * Get the next ranking for a specified rule **/ function getNextRanking() { global $DB; $iterator = $DB->request([ 'SELECT' => ['MAX' => 'ranking AS rank'], 'FROM' => self::getTable(), 'WHERE' => ['sub_type' => $this->getType()] ]); if (count($iterator)) { $data = $iterator->next(); return $data["rank"] + 1; } return 0; } /** * Show the minimal form for the action rule * * @param $fields datas used to display the action * @param $canedit can edit the actions rule ? * @param $rand random value of the form **/ function showMinimalActionForm($fields, $canedit, $rand) { global $CFG_GLPI; $edit = ($canedit ? "style='cursor:pointer' onClick=\"viewEditAction". $fields[$this->rules_id_field].$fields["id"]."$rand();\"" : ''); echo ""; if ($canedit) { echo ""; Html::showMassiveActionCheckBox($this->ruleactionclass, $fields["id"]); echo "\n\n"; echo ""; } echo $this->getMinimalActionText($fields, $edit); echo "\n"; } /** * Show preview result of a rule * * @param $target where to go if action * @param $input input data array * @param $params params used (see addSpecificParamsForPreview) **/ function showRulePreviewResultsForm($target, $input, $params) { $actions = $this->getAllActions(); $check_results = []; $output = []; //Test all criteria, without stopping at the first good one $this->testCriterias($input, $check_results); //Process the rule $this->process($input, $output, $params); if (!$criteria = getItemForItemtype($this->rulecriteriaclass)) { return; } echo "
"; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo "\n"; foreach ($check_results as $ID => $criteria_result) { echo ""; $criteria->getFromDB($criteria_result["id"]); echo $this->getMinimalCriteriaText($criteria->fields); if ($criteria->fields['condition'] != self::PATTERN_FIND) { echo "\n"; } else { echo "\n"; } } echo "
" . __('Result details') . "
"._n('Criterion', 'Criteria', 1)."".__('Condition')."".__('Reason').""._n('Validation', 'Validations', 1)."
".Dropdown::getYesNo($criteria_result["result"])."
".Dropdown::EMPTY_VALUE."
"; $global_result = (isset($output["_rule_process"])?1:0); echo "
"; echo ""; echo ""; echo ""; echo ""; $output = $this->preProcessPreviewResults($output); foreach ($output as $criteria => $value) { if (isset($actions[$criteria])) { echo ""; echo ""; if (isset($actions[$criteria]['type'])) { $actiontype = $actions[$criteria]['type']; } else { $actiontype =''; } echo "\n"; } } //If a regular expression was used, and matched, display the results if (count($this->regex_results)) { echo ""; echo ""; echo "\n"; } echo "\n"; echo "
" . __('Rule results') . "
"._n('Validation', 'Validations', 1).""; echo Dropdown::getYesNo($global_result)."
".$actions[$criteria]["name"]."".$this->getActionValue($criteria, $actiontype, $value); echo "
".__('Result of the regular expression').""; if (!empty($this->regex_results[0])) { echo ""; echo ""; foreach ($this->regex_results[0] as $key => $value) { echo ""; echo ""; } echo "
".__('Key')."".__('Value')."
$key$value
"; } echo "
"; } /** * Show the minimal form for the criteria rule * * @param $fields datas used to display the criteria * @param $canedit can edit the criteria rule? * @param $rand random value of the form **/ function showMinimalCriteriaForm($fields, $canedit, $rand) { global $CFG_GLPI; $edit = ($canedit ? "style='cursor:pointer' onClick=\"viewEditCriteria". $fields[$this->rules_id_field].$fields["id"]."$rand();\"" : ''); echo ""; if ($canedit) { echo ""; Html::showMassiveActionCheckBox($this->rulecriteriaclass, $fields["id"]); echo "\n\n"; echo ""; } echo $this->getMinimalCriteriaText($fields, $edit); echo "\n"; } /** * @param $fields * @param $addtotd (default '') **/ function getMinimalCriteriaText($fields, $addtotd = '') { $text = "" . $this->getCriteriaName($fields["criteria"]) . ""; $text .= "" . RuleCriteria::getConditionByID($fields["condition"], get_class($this), $fields["criteria"]).""; $text .= "" . $this->getCriteriaDisplayPattern($fields["criteria"], $fields["condition"], $fields["pattern"]) . ""; return $text; } /** * @param $fields * @param $addtotd (default '') **/ function getMinimalActionText($fields, $addtotd = '') { $text = "" . $this->getActionName($fields["field"]) . ""; $text .= "" . RuleAction::getActionByID($fields["action_type"]) . ""; if (isset($fields["value"])) { $text .= "" . $this->getActionValue($fields["field"], $fields['action_type'], $fields["value"]) . ""; } else { $text .= " "; } return $text; } /** * Return a value associated with a pattern associated to a criteria to display it * * @param $ID the given criteria * @param $condition condition used * @param $pattern the pattern **/ function getCriteriaDisplayPattern($ID, $condition, $pattern) { if (($condition == self::PATTERN_EXISTS) || ($condition == self::PATTERN_DOES_NOT_EXISTS) || ($condition == self::PATTERN_FIND)) { return __('Yes'); } else if (in_array($condition, [self::PATTERN_IS, self::PATTERN_IS_NOT, self::PATTERN_NOT_UNDER, self::PATTERN_UNDER])) { $crit = $this->getCriteria($ID); if (isset($crit['type'])) { switch ($crit['type']) { case "yesonly" : case "yesno" : return Dropdown::getYesNo($pattern); case "dropdown" : $addentity = Dropdown::getDropdownName($crit["table"], $pattern); if ($this->isEntityAssign()) { $itemtype = getItemTypeForTable($crit["table"]); $item = getItemForItemtype($itemtype); if ($item && $item->getFromDB($pattern) && $item->isEntityAssign()) { $addentity = sprintf(__('%1$s (%2$s)'), $addentity, Dropdown::getDropdownName('glpi_entities', $item->getEntityID())); } } $tmp = $addentity; return (($tmp == ' ') ? NOT_AVAILABLE : $tmp); case "dropdown_users" : return getUserName($pattern); case "dropdown_assets_itemtype" : case "dropdown_tracking_itemtype" : if ($item = getItemForItemtype($pattern)) { return $item->getTypeName(1); } if (empty($pattern)) { return __('General'); } break; case "dropdown_status" : return Ticket::getStatus($pattern); case "dropdown_priority" : return Ticket::getPriorityName($pattern); case "dropdown_urgency" : return Ticket::getUrgencyName($pattern); case "dropdown_impact" : return Ticket::getImpactName($pattern); case "dropdown_tickettype" : return Ticket::getTicketTypeName($pattern); } } } if ($result = $this->getAdditionalCriteriaDisplayPattern($ID, $condition, $pattern)) { return $result; } return $pattern; } /** * Used to get specific criteria patterns * * @param $ID the given criteria * @param $condition condition used * @param $pattern the pattern * * @return a value associated with the criteria, or false otherwise **/ function getAdditionalCriteriaDisplayPattern($ID, $condition, $pattern) { return false; } /** * Display item used to select a pattern for a criteria * * @param $name criteria name * @param $ID the given criteria * @param $condition condition used * @param $value the pattern (default '') * @param $test Is to test rule ? (false by default) **/ function displayCriteriaSelectPattern($name, $ID, $condition, $value = "", $test = false) { global $CFG_GLPI; $crit = $this->getCriteria($ID); $display = false; $tested = false; if (isset($crit['type']) && ($test || in_array($condition, [self::PATTERN_IS, self::PATTERN_IS_NOT, self::PATTERN_NOT_UNDER, self::PATTERN_UNDER]))) { $tested = true; switch ($crit['type']) { case "yesonly" : Dropdown::showYesNo($name, $crit['table'], 0); $display = true; break; case "yesno" : Dropdown::showYesNo($name, $value); $display = true; break; case "dropdown" : $param = ['name' => $name, 'value' => $value]; if (isset($crit['condition'])) { $param['condition'] = $crit['condition']; } Dropdown::show(getItemTypeForTable($crit['table']), $param); $display = true; break; case "dropdown_users" : User::dropdown(['value' => $value, 'name' => $name, 'right' => 'all']); $display = true; break; case "dropdown_tracking_itemtype" : Dropdown::showItemTypes($name, array_keys(Ticket::getAllTypesForHelpdesk())); $display = true; break; case "dropdown_assets_itemtype" : Dropdown::showItemTypes($name, $CFG_GLPI['asset_types'], ['value' => $value]); $display = true; break; case "dropdown_import_type" : RuleAsset::dropdownImportType($name, $value); $display = true; break; case "dropdown_urgency" : Ticket::dropdownUrgency(['name' => $name, 'value' => $value]); $display = true; break; case "dropdown_impact" : Ticket::dropdownImpact(['name' => $name, 'value' => $value]); $display = true; break; case "dropdown_priority" : Ticket::dropdownPriority(['name' => $name, 'value' => $value, 'withmajor' => true]); $display = true; break; case "dropdown_status" : Ticket::dropdownStatus(['name' => $name, 'value' => $value]); $display = true; break; case "dropdown_tickettype" : Ticket::dropdownType($name, ['value' => $value]); $display = true; break; default: $tested = false; break; } } //Not a standard condition if (!$tested) { $display = $this->displayAdditionalRuleCondition($condition, $crit, $name, $value, $test); } if (($condition == self::PATTERN_EXISTS) || ($condition == self::PATTERN_DOES_NOT_EXISTS)) { echo ""; $display = true; } if (!$display && ($rc = getItemForItemtype($this->rulecriteriaclass))) { Html::autocompletionTextField($rc, "pattern", ['name' => $name, 'value' => $value, 'size' => 70]); } } /** * Return a "display" value associated with a pattern associated to a criteria * * @param $ID the given action * @param $type the type of action * @param $value the value **/ function getActionValue($ID, $type, $value) { $action = $this->getAction($ID); if (isset($action['type'])) { switch ($action['type']) { case "dropdown" : if ($type=='defaultfromuser' || $type=='fromuser' || $type=='fromitem') { return Dropdown::getYesNo($value); } // $type == assign $tmp = Dropdown::getDropdownName($action["table"], $value); return (($tmp == ' ') ? NOT_AVAILABLE : $tmp); case "dropdown_status" : return Ticket::getStatus($value); case "dropdown_assign" : case "dropdown_users" : case "dropdown_users_validate" : return getUserName($value); case "dropdown_groups_validate" : return Dropdown::getDropdownName('glpi_groups', $value); case "dropdown_validation_percent" : return Dropdown::getValueWithUnit($value, '%'); case "yesonly" : case "yesno" : return Dropdown::getYesNo($value); case "dropdown_urgency" : return Ticket::getUrgencyName($value); case "dropdown_impact" : return Ticket::getImpactName($value); case "dropdown_priority" : return Ticket::getPriorityName($value); case "dropdown_tickettype" : return Ticket::getTicketTypeName($value); case "dropdown_management" : return Dropdown::getGlobalSwitch($value); default : return $this->displayAdditionRuleActionValue($value); } } return $value; } /** * Return a value associated with a pattern associated to a criteria to display it * * @param $ID the given criteria * @param $condition condition used * @param $value the pattern **/ function getCriteriaValue($ID, $condition, $value) { if (!in_array($condition, [self::PATTERN_DOES_NOT_EXISTS, self::PATTERN_EXISTS, self::PATTERN_IS, self::PATTERN_IS_NOT, self::PATTERN_NOT_UNDER, self::PATTERN_UNDER])) { $crit = $this->getCriteria($ID); if (isset($crit['type'])) { switch ($crit['type']) { case "dropdown" : $tmp = Dropdown::getDropdownName($crit["table"], $value, false, false); //$tmp = Dropdown::getDropdownName($crit["table"], $value); // return empty string to be able to check if set if ($tmp == ' ') { return ''; } return $tmp; case "dropdown_assign" : case "dropdown_users" : return getUserName($value); case "yesonly" : case "yesno" : return Dropdown::getYesNo($value); case "dropdown_impact" : return Ticket::getImpactName($value); case "dropdown_urgency" : return Ticket::getUrgencyName($value); case "dropdown_priority" : return Ticket::getPriorityName($value); } } } return $value; } /** * Function used to display type specific criteria during rule's preview * * @param $fields fields values **/ function showSpecificCriteriasForPreview($fields) { } /** * Function used to add specific params before rule processing * * @param $params parameters **/ function addSpecificParamsForPreview($params) { return $params; } /** * Criteria form used to preview rule * * @param $target target of the form * @param $rules_id ID of the rule **/ function showRulePreviewCriteriasForm($target, $rules_id) { $criteria = $this->getAllCriteria(); if ($this->getRuleWithCriteriasAndActions($rules_id, 1, 0)) { echo "
\n"; echo "
"; echo ""; echo ""; $type_match = (($this->fields["match"] == self::AND_MATCHING) ?__('and') :__('or')); $already_displayed = []; $first = true; //Brower all criteria foreach ($this->criterias as $criterion) { //Look for the criteria in the field of already displayed criteria : //if present, don't display it again if (!in_array($criterion->fields["criteria"], $already_displayed)) { $already_displayed[] = $criterion->fields["criteria"]; echo ""; echo ""; $criteria_constants = $criteria[$criterion->fields["criteria"]]; echo ""; echo "\n"; } } $this->showSpecificCriteriasForPreview($_POST); echo "\n"; echo "
" . _n('Criterion', 'Criteria', Session::getPluralNumber()) . "
"; if ($first) { echo " "; $first = false; } else { echo $type_match; } echo "".$criteria_constants["name"].""; $value = ""; if (isset($_POST[$criterion->fields["criteria"]])) { $value = $_POST[$criterion->fields["criteria"]]; } $this->displayCriteriaSelectPattern($criterion->fields['criteria'], $criterion->fields['criteria'], $criterion->fields['condition'], $value, true); echo "
"; echo ""; echo ""; echo ""; echo "
\n"; Html::closeForm(); } } /** * @param $output **/ function preProcessPreviewResults($output) { global $PLUGIN_HOOKS; if (isset($PLUGIN_HOOKS['use_rules'])) { $params['criterias_results'] = $this->criterias_results; $params['rule_itemtype'] = $this->getType(); foreach ($PLUGIN_HOOKS['use_rules'] as $plugin => $val) { if (!Plugin::isPluginActive($plugin)) { continue; } if (is_array($val) && in_array($this->getType(), $val)) { $results = Plugin::doOneHook($plugin, "preProcessRulePreviewResults", ['output' => $output, 'params' => $params]); if (is_array($results)) { foreach ($results as $id => $result) { $output[$id] = $result; } } } } } return $output; } /** * Dropdown rules for a defined sub_type of rule * * @param $options array of possible options: * - name : string / name of the select (default is depending itemtype) * - sub_type : integer / sub_type of rule **/ static function dropdown($options = []) { $p['sub_type'] = ''; $p['name'] = 'rules_id'; $p['entity'] = ''; $p['condition'] = 0; if (is_array($options) && count($options)) { foreach ($options as $key => $val) { $p[$key] = $val; } } if ($p['sub_type'] == '') { return false; } $conditions = [ 'sub_type' => $p['sub_type'] ]; if ($p['condition'] > 0) { $conditions['condition'] = ['&', (int)$p['condition']]; } $p['condition'] = $conditions; return Dropdown::show($p['sub_type'], $p); } /** * @since 0.84 **/ function getAllCriteria() { return self::doHookAndMergeResults("getRuleCriteria", $this->getCriterias(), $this->getType()); } function getCriterias() { return []; } /** * @since 0.84 * @return array */ function getAllActions() { return self::doHookAndMergeResults("getRuleActions", $this->getActions(), $this->getType()); } function getActions() { return []; } /** * Execute a hook if necessary and merge results * * @since 0.84 * * @param $hook the hook to execute * @param $params array input parameters * @param $itemtype (default '') * * @return input parameters merged with hook parameters **/ static function doHookAndMergeResults($hook, $params = [], $itemtype = '') { global $PLUGIN_HOOKS; if (empty($itemtype)) { $itemtype = static::getType(); } //Agregate all plugins criteria for this rules engine $toreturn = $params; if (isset($PLUGIN_HOOKS['use_rules'])) { foreach ($PLUGIN_HOOKS['use_rules'] as $plugin => $val) { if (!Plugin::isPluginActive($plugin)) { continue; } if (is_array($val) && in_array($itemtype, $val)) { $results = Plugin::doOneHook($plugin, $hook, ['rule_itemtype' => $itemtype, 'values' => $params]); if (is_array($results)) { foreach ($results as $id => $result) { $toreturn[$id] = $result; } } } } } return $toreturn; } /** * @param $sub_type **/ static function getActionsByType($sub_type) { if ($rule = getItemForItemtype($sub_type)) { return $rule->getAllActions(); } return []; } /** * Return all rules from database * * @param $crit array of criteria (at least, 'field' and 'value') * * @return array of Rule objects **/ function getRulesForCriteria($crit) { global $DB; $rules = []; /// TODO : not working for SLALevels : no sub_type //Get all the rules whose sub_type is $sub_type and entity is $ID $query = [ 'SELECT' => $this->getTable() . '.id', 'FROM' => [ getTableForItemType($this->ruleactionclass), $this->getTable() ], 'WHERE' => [ getTableForItemType($this->ruleactionclass).".".$this->rules_id_field => new \QueryExpression(DBmysql::quoteName($this->getTable().'.id')), $this->getTable().'.sub_type' => get_class($this) ] ]; foreach ($crit as $field => $value) { $query['WHERE'][getTableForItemType($this->ruleactionclass).'.'.$field] = $value; } $iterator = $DB->request($query); while ($rule = $iterator->next()) { $affect_rule = new Rule(); $affect_rule->getRuleWithCriteriasAndActions($rule["id"], 0, 1); $rules[] = $affect_rule; } return $rules; } /** * @param $ID **/ function showNewRuleForm($ID) { echo ""; echo ""; echo "\n"; echo ""; echo "\n"; echo "
" . $this->getTitle() . "
".__('Name') . ""; Html::autocompletionTextField($this, "name", ['value' => '', 'size' => 33]); echo "".__('Description') . ""; Html::autocompletionTextField($this, "description", ['value' => '', 'size' => 33]); echo "".__('Logical operator') . ""; $this->dropdownRulesMatch(); echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo "
"; Html::closeForm(); } /** * @param $item **/ function showAndAddRuleForm($item) { $rand = mt_rand(); $canedit = self::canUpdate(); if ($canedit && ($item->getType() == 'Entity')) { $this->showNewRuleForm($item->getField('id')); } //Get all rules and actions $crit = ['field' => getForeignKeyFieldForTable($item->getTable()), 'value' => $item->getField('id')]; $rules = $this->getRulesForCriteria($crit); $nb = count($rules); echo "
"; if (!$nb) { echo ""; echo ""; echo "\n"; echo "
" . __('No item found') . "
\n"; } else { if ($canedit) { Html::openMassiveActionsForm('mass'.get_called_class().$rand); $massiveactionparams = ['num_displayed' => min($_SESSION['glpilist_limit'], $nb), 'specific_actions' => ['update' => _x('button', 'Update'), 'purge' => _x('button', 'Delete permanently')]]; // 'extraparams' // => array('rule_class_name' => $this->getRuleClassName())); Html::showMassiveActions($massiveactionparams); } echo ""; $header_begin = ""; $header_top = ''; $header_bottom = ''; $header_end = ''; if ($canedit) { $header_begin .= ""; } $header_end .= ""; $header_end .= ""; $header_end .= ""; $header_end .= "\n"; echo $header_begin.$header_top.$header_end; Session::initNavigateListItems(get_class($this), //TRANS: %1$s is the itemtype name, // %2$s is the name of the item (used for headings of a list) sprintf(__('%1$s = %2$s'), $item->getTypeName(1), $item->getName())); foreach ($rules as $rule) { Session::addToNavigateListItems(get_class($this), $rule->fields["id"]); echo ""; if ($canedit) { echo ""; echo ""; } else { echo ""; } echo ""; echo ""; echo "\n"; } echo $header_begin.$header_bottom.$header_end; echo "
"; $header_top .= Html::getCheckAllAsCheckbox('mass'.get_called_class().$rand); $header_bottom .= Html::getCheckAllAsCheckbox('mass'.get_called_class().$rand); $header_end .= "" . $this->getTitle() . "" . __('Description') . "" . __('Active') . "
"; Html::showMassiveActionCheckBox(__CLASS__, $rule->fields["id"]); echo "" .$rule->fields["name"] ."" . $rule->fields["name"] . "" . $rule->fields["description"] . "" . Dropdown::getYesNo($rule->fields["is_active"]) . "
\n"; if ($canedit) { $massiveactionparams['ontop'] = false; Html::showMassiveActions($massiveactionparams); Html::closeForm(); } } echo "
"; } /** * @see CommonGLPI::defineTabs() **/ function defineTabs($options = []) { $ong = []; $this->addDefaultFormTab($ong); $this->addStandardTab(__CLASS__, $ong, $options); $this->addStandardTab('Log', $ong, $options); return $ong; } /** * Add more criteria specific to this type of rule **/ static function addMoreCriteria() { return []; } /** * Add more actions specific to this type of rule * * @param $value **/ function displayAdditionRuleActionValue($value) { return $value; } /** * @param $condition * @param $criteria * @param $name * @param $value * @param $test (false by default) **/ function displayAdditionalRuleCondition($condition, $criteria, $name, $value, $test = false) { return false; } /** * @param $action array * @param $value value to display (default '') **/ function displayAdditionalRuleAction(array $action, $value = '') { return false; } /** * Clean Rule with Action or Criteria linked to an item * * @param $item Object * @param $field string name (default is FK to item) * @param $ruleitem object (instance of Rules of SlaLevel) * @param $table string (glpi_ruleactions, glpi_rulescriterias or glpi_slalevelcriterias) * @param $valfield string (value or pattern) * @param $fieldfield string (criteria of field) **/ private static function cleanForItemActionOrCriteria($item, $field, $ruleitem, $table, $valfield, $fieldfield) { global $DB; $fieldid = getForeignKeyFieldForTable($ruleitem->getTable()); if (empty($field)) { $field = getForeignKeyFieldForTable($item->getTable()); } if (isset($item->input['_replace_by']) && ($item->input['_replace_by'] > 0)) { $DB->update( $table, [ $valfield => $item->input['_replace_by'] ], [ $valfield => $item->getField('id'), $fieldfield => ['LIKE', $field] ] ); } else { $iterator = $DB->request([ 'SELECT' => [$fieldid], 'FROM' => $table, 'WHERE' => [ $valfield => $item->getField('id'), $fieldfield => ['LIKE', $field] ] ]); if (count($iterator) > 0) { $input['is_active'] = 0; while ($data = $iterator->next()) { $input['id'] = $data[$fieldid]; $ruleitem->update($input); } Session::addMessageAfterRedirect(__('Rules using the object have been disabled.'), true); } } } /** * Clean Rule with Action is assign to an item * * @param $item Object * @param $field string name (default is FK to item) (default '') **/ static function cleanForItemAction($item, $field = '') { self::cleanForItemActionOrCriteria($item, $field, new self(), 'glpi_ruleactions', 'value', 'field'); self::cleanForItemActionOrCriteria($item, $field, new SlaLevel(), 'glpi_slalevelactions', 'value', 'field'); self::cleanForItemActionOrCriteria($item, $field, new OlaLevel(), 'glpi_olalevelactions', 'value', 'field'); } /** * Clean Rule with Criteria on an item * * @param $item Object * @param $field string name (default is FK to item) (default '') **/ static function cleanForItemCriteria($item, $field = '') { self::cleanForItemActionOrCriteria($item, $field, new self(), 'glpi_rulecriterias', 'pattern', 'criteria'); } /** * @see CommonGLPI::getTabNameForItem() **/ function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { if (!$withtemplate) { $nb = 0; switch ($item->getType()) { case 'Entity' : if ($_SESSION['glpishow_count_on_tabs']) { $types = []; $collection = new RuleRightCollection(); if ($collection->canList()) { $types[] = 'RuleRight'; } $collection = new RuleImportEntityCollection(); if ($collection->canList()) { $types[] = 'RuleImportEntity'; } $collection = new RuleMailCollectorCollection(); if ($collection->canList()) { $types[] = 'RuleMailCollector'; } if (count($types)) { $nb = countElementsInTable( ['glpi_rules', 'glpi_ruleactions'], [ 'glpi_ruleactions.rules_id' => new \QueryExpression(DB::quoteName('glpi_rules.id')), 'glpi_rules.sub_type' => $types, 'glpi_ruleactions.field' => 'entities_id', 'glpi_ruleactions.value' => $item->getID() ]); } } return self::createTabEntry(self::getTypeName(Session::getPluralNumber()), $nb); case 'SLA' : case 'OLA' : if ($_SESSION['glpishow_count_on_tabs']) { $nb = countElementsInTable('glpi_ruleactions', ['field' => $item::getFieldNames($item->fields['type'])[1], 'value' => $item->getID()]); } return self::createTabEntry(self::getTypeName($nb), $nb); default: if ($item instanceof Rule) { $ong = []; $nbcriteria = 0; $nbaction = 0; if ($_SESSION['glpishow_count_on_tabs']) { $nbcriteria = countElementsInTable(getTableForItemType($item->getRuleCriteriaClass()), [$item->getRuleIdField() => $item->getID()]); $nbaction = countElementsInTable(getTableForItemType($item->getRuleActionClass()), [$item->getRuleIdField() => $item->getID()]); } $ong[1] = self::createTabEntry(RuleCriteria::getTypeName(Session::getPluralNumber()), $nbcriteria); $ong[2] = self::createTabEntry(RuleAction::getTypeName(Session::getPluralNumber()), $nbaction); return $ong; } } } return ''; } /** * @param $item CommonGLPI object * @param $tabnum (default 1) * @param $withtemplate (default 0) **/ static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { if ($item->getType() == 'Entity') { $collection = new RuleRightCollection(); if ($collection->canList()) { $ldaprule = new RuleRight(); $ldaprule->showAndAddRuleForm($item); } $collection = new RuleImportEntityCollection(); if ($collection->canList()) { $importrule = new RuleImportEntity(); $importrule->showAndAddRuleForm($item); } $collection = new RuleMailCollectorCollection(); if ($collection->canList()) { $mailcollector = new RuleMailCollector(); $mailcollector->showAndAddRuleForm($item); } } else if ($item instanceof LevelAgreement) { $item->showRulesList(); } else if ($item instanceof Rule) { $item->getRuleWithCriteriasAndActions($item->getID(), 1, 1); switch ($tabnum) { case 1 : $item->showCriteriasList($item->getID()); break; case 2 : $item->showActionsList($item->getID()); break; } } return true; } /** * Generate unique id for rule based on server name, glpi directory and basetime * * @since 0.85 * * @return uuid **/ static function getUuid() { //encode uname -a, ex Linux localhost 2.4.21-0.13mdk #1 Fri Mar 14 15:08:06 EST 2003 i686 $serverSubSha1 = substr(sha1(php_uname('a')), 0, 8); // encode script current dir, ex : /var/www/glpi_X $dirSubSha1 = substr(sha1(__FILE__), 0, 8); return uniqid("$serverSubSha1-$dirSubSha1-", true); } /** * Display debug information for current object * * @since 0.85 **/ function showDebug() { echo "
"; printf(__('%1$s: %2$s'), "UUID", $this->fields['uuid']); echo "
"; } public static function canCreate() { return static::canUpdate(); } public static function canPurge() { return static::canUpdate(); } static function getIcon() { return "fas fa-book"; } public function prepareInputForClone($input) { //get ranking $nextRanking = $this->getNextRanking(); //Update fields of the new collection $input['name'] = sprintf(__('Copy of %s'), $input['name']); $input['is_active'] = 0; $input['ranking'] = $nextRanking; $input['uuid'] = static::getUuid(); $input = Toolbox::addslashes_deep($input); return parent::prepareInputForClone($input); } }