639 lines
20 KiB
PHP
639 lines
20 KiB
PHP
<?php
|
|
/**
|
|
* ---------------------------------------------------------------------
|
|
* GLPI - Gestionnaire Libre de Parc Informatique
|
|
* Copyright (C) 2015-2020 Teclib' and contributors.
|
|
*
|
|
* http://glpi-project.org
|
|
*
|
|
* based on GLPI - Gestionnaire Libre de Parc Informatique
|
|
* Copyright (C) 2003-2014 by the INDEPNET Development Team.
|
|
*
|
|
* ---------------------------------------------------------------------
|
|
*
|
|
* LICENSE
|
|
*
|
|
* This file is part of GLPI.
|
|
*
|
|
* GLPI is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* GLPI is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with GLPI. If not, see <http://www.gnu.org/licenses/>.
|
|
* ---------------------------------------------------------------------
|
|
*/
|
|
|
|
if (!defined('GLPI_ROOT')) {
|
|
die("Sorry. You can't access this file directly");
|
|
}
|
|
|
|
/// Criteria Rule class
|
|
class RuleCriteria extends CommonDBChild {
|
|
|
|
// From CommonDBChild
|
|
static public $itemtype = 'Rule';
|
|
static public $items_id = 'rules_id';
|
|
public $dohistory = true;
|
|
public $auto_message_on_action = false;
|
|
|
|
|
|
|
|
/**
|
|
* @since 0.84
|
|
**/
|
|
function getForbiddenStandardMassiveAction() {
|
|
|
|
$forbidden = parent::getForbiddenStandardMassiveAction();
|
|
$forbidden[] = 'update';
|
|
return $forbidden;
|
|
}
|
|
|
|
|
|
/**
|
|
* @param $rule_type (default 'Rule)
|
|
**/
|
|
function __construct($rule_type = 'Rule') {
|
|
static::$itemtype = $rule_type;
|
|
}
|
|
|
|
|
|
/**
|
|
* @since 0.84.3
|
|
*
|
|
* @see CommonDBTM::post_getFromDB()
|
|
*/
|
|
function post_getFromDB() {
|
|
|
|
// Get correct itemtype if defult one is used
|
|
if (static::$itemtype == 'Rule') {
|
|
$rule = new Rule();
|
|
if ($rule->getFromDB($this->fields['rules_id'])) {
|
|
static::$itemtype = $rule->fields['sub_type'];
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Get title used in rule
|
|
*
|
|
* @param $nb integer for singular or plural (default 0)
|
|
*
|
|
* @return Title of the rule
|
|
**/
|
|
static function getTypeName($nb = 0) {
|
|
return _n('Criterion', 'Criteria', $nb);
|
|
}
|
|
|
|
protected function computeFriendlyName() {
|
|
|
|
if ($rule = getItemForItemtype(static::$itemtype)) {
|
|
return Html::clean($rule->getMinimalCriteriaText($this->fields));
|
|
}
|
|
return '';
|
|
}
|
|
|
|
/**
|
|
* @since 0.84
|
|
*
|
|
* @see CommonDBChild::post_addItem()
|
|
**/
|
|
function post_addItem() {
|
|
|
|
parent::post_addItem();
|
|
if (isset($this->input['rules_id'])
|
|
&& ($realrule = Rule::getRuleObjectByID($this->input['rules_id']))) {
|
|
$realrule->update(['id' => $this->input['rules_id'],
|
|
'date_mod' => $_SESSION['glpi_currenttime']]);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* @since 0.84
|
|
*
|
|
* @see CommonDBTM::post_purgeItem()
|
|
**/
|
|
function post_purgeItem() {
|
|
|
|
parent::post_purgeItem();
|
|
if (isset($this->fields['rules_id'])
|
|
&& ($realrule = Rule::getRuleObjectByID($this->fields['rules_id']))) {
|
|
$realrule->update(['id' => $this->fields['rules_id'],
|
|
'date_mod' => $_SESSION['glpi_currenttime']]);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* @since 0.84
|
|
**/
|
|
function prepareInputForAdd($input) {
|
|
|
|
if (!isset($input['criteria']) || empty($input['criteria'])) {
|
|
return false;
|
|
}
|
|
return parent::prepareInputForAdd($input);
|
|
}
|
|
|
|
|
|
function rawSearchOptions() {
|
|
$tab = [];
|
|
|
|
$tab[] = [
|
|
'id' => '1',
|
|
'table' => $this->getTable(),
|
|
'field' => 'criteria',
|
|
'name' => __('Name'),
|
|
'massiveaction' => false,
|
|
'datatype' => 'specific',
|
|
'additionalfields' => ['rules_id']
|
|
];
|
|
|
|
$tab[] = [
|
|
'id' => '2',
|
|
'table' => $this->getTable(),
|
|
'field' => 'condition',
|
|
'name' => __('Condition'),
|
|
'massiveaction' => false,
|
|
'datatype' => 'specific',
|
|
'additionalfields' => ['rules_id', 'criteria']
|
|
];
|
|
|
|
$tab[] = [
|
|
'id' => '3',
|
|
'table' => $this->getTable(),
|
|
'field' => 'pattern',
|
|
'name' => __('Reason'),
|
|
'massiveaction' => false,
|
|
'datatype' => 'specific',
|
|
'additionalfields' => ['rules_id', 'criteria', 'condition'],
|
|
'autocomplete' => true,
|
|
];
|
|
|
|
return $tab;
|
|
}
|
|
|
|
|
|
/**
|
|
* @since 0.84
|
|
*
|
|
* @param $field
|
|
* @param $values
|
|
* @param $options array
|
|
**/
|
|
static function getSpecificValueToDisplay($field, $values, array $options = []) {
|
|
|
|
if (!is_array($values)) {
|
|
$values = [$field => $values];
|
|
}
|
|
switch ($field) {
|
|
case 'criteria' :
|
|
$generic_rule = new Rule;
|
|
if (isset($values['rules_id'])
|
|
&& !empty($values['rules_id'])
|
|
&& $generic_rule->getFromDB($values['rules_id'])) {
|
|
if ($rule = getItemForItemtype($generic_rule->fields["sub_type"])) {
|
|
return $rule->getCriteriaName($values[$field]);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 'condition' :
|
|
$generic_rule = new Rule;
|
|
if (isset($values['rules_id'])
|
|
&& !empty($values['rules_id'])
|
|
&& $generic_rule->getFromDB($values['rules_id'])) {
|
|
if (isset($values['criteria']) && !empty($values['criteria'])) {
|
|
$criterion = $values['criteria'];
|
|
}
|
|
return self::getConditionByID($values[$field], $generic_rule->fields["sub_type"], $criterion);
|
|
}
|
|
break;
|
|
|
|
case 'pattern' :
|
|
if (!isset($values["criteria"]) || !isset($values["condition"])) {
|
|
return NOT_AVAILABLE;
|
|
}
|
|
$generic_rule = new Rule;
|
|
if (isset($values['rules_id'])
|
|
&& !empty($values['rules_id'])
|
|
&& $generic_rule->getFromDB($values['rules_id'])) {
|
|
if ($rule = getItemForItemtype($generic_rule->fields["sub_type"])) {
|
|
return $rule->getCriteriaDisplayPattern($values["criteria"], $values["condition"],
|
|
$values[$field]);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
return parent::getSpecificValueToDisplay($field, $values, $options);
|
|
}
|
|
|
|
|
|
/**
|
|
* @since 0.84
|
|
*
|
|
* @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 'criteria' :
|
|
$generic_rule = new Rule;
|
|
if (isset($values['rules_id'])
|
|
&& !empty($values['rules_id'])
|
|
&& $generic_rule->getFromDB($values['rules_id'])) {
|
|
if ($rule = getItemForItemtype($generic_rule->fields["sub_type"])) {
|
|
$options['value'] = $values[$field];
|
|
$options['name'] = $name;
|
|
return $rule->dropdownCriteria($options);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 'condition' :
|
|
$generic_rule = new Rule;
|
|
if (isset($values['rules_id'])
|
|
&& !empty($values['rules_id'])
|
|
&& $generic_rule->getFromDB($values['rules_id'])) {
|
|
if (isset($values['criteria']) && !empty($values['criteria'])) {
|
|
$options['criterion'] = $values['criteria'];
|
|
}
|
|
$options['value'] = $values[$field];
|
|
$options['name'] = $name;
|
|
return $rule->dropdownConditions($generic_rule->fields["sub_type"], $options);
|
|
}
|
|
break;
|
|
|
|
case 'pattern' :
|
|
if (!isset($values["criteria"]) || !isset($values["condition"])) {
|
|
return NOT_AVAILABLE;
|
|
}
|
|
$generic_rule = new Rule;
|
|
if (isset($values['rules_id'])
|
|
&& !empty($values['rules_id'])
|
|
&& $generic_rule->getFromDB($values['rules_id'])) {
|
|
if ($rule = getItemForItemtype($generic_rule->fields["sub_type"])) {
|
|
/// TODO : manage display param to this function : need to send ot to all under functions
|
|
$rule->displayCriteriaSelectPattern($name, $values["criteria"],
|
|
$values["condition"], $values[$field]);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
return parent::getSpecificValueToSelect($field, $name, $values, $options);
|
|
}
|
|
|
|
|
|
/**
|
|
* Get all criterias for a given rule
|
|
*
|
|
* @param $rules_id the rule ID
|
|
*
|
|
* @return an array of RuleCriteria objects
|
|
**/
|
|
function getRuleCriterias($rules_id) {
|
|
global $DB;
|
|
|
|
$rules_list = [];
|
|
$params = ['FROM' => $this->getTable(),
|
|
'WHERE' => [static::$items_id => $rules_id],
|
|
'ORDER' => 'id'
|
|
];
|
|
foreach ($DB->request($params) as $rule) {
|
|
$tmp = new self();
|
|
$tmp->fields = $rule;
|
|
$rules_list[] = $tmp;
|
|
}
|
|
return $rules_list;
|
|
}
|
|
|
|
|
|
/**
|
|
* Try to match a defined rule
|
|
*
|
|
* @param &$criterion RuleCriteria object
|
|
* @param $field the field to match
|
|
* @param &$criterias_results
|
|
* @param &$regex_result
|
|
*
|
|
* @return true if the field match the rule, false if it doesn't match
|
|
**/
|
|
static function match(RuleCriteria &$criterion, $field, &$criterias_results, &$regex_result) {
|
|
|
|
$condition = $criterion->fields['condition'];
|
|
$pattern = $criterion->fields['pattern'];
|
|
$criteria = $criterion->fields['criteria'];
|
|
|
|
//If pattern is wildcard, don't check the rule and return true
|
|
//or if the condition is "already present in GLPI" : will be processed later
|
|
if (($pattern == Rule::RULE_WILDCARD)
|
|
|| ($condition == Rule::PATTERN_FIND)) {
|
|
return true;
|
|
}
|
|
|
|
$pattern = trim($pattern);
|
|
|
|
switch ($condition) {
|
|
case Rule::PATTERN_EXISTS :
|
|
return (!empty($field));
|
|
|
|
case Rule::PATTERN_DOES_NOT_EXISTS :
|
|
return (empty($field));
|
|
|
|
case Rule::PATTERN_IS :
|
|
if (is_array($field)) {
|
|
// Special case (used only by UNIQUE_PROFILE, for now)
|
|
// $pattern is an ID
|
|
if (in_array($pattern, $field)) {
|
|
$criterias_results[$criteria] = $pattern;
|
|
return true;
|
|
}
|
|
} else {
|
|
//Perform comparison with fields in lower case
|
|
$field = Toolbox::strtolower($field);
|
|
$pattern = Toolbox::strtolower($pattern);
|
|
if ($field == $pattern) {
|
|
$criterias_results[$criteria] = $pattern;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
|
|
case Rule::PATTERN_IS_NOT :
|
|
//Perform comparison with fields in lower case
|
|
$field = Toolbox::strtolower($field);
|
|
$pattern = Toolbox::strtolower($pattern);
|
|
if ($field != $pattern) {
|
|
$criterias_results[$criteria] = $pattern;
|
|
return true;
|
|
}
|
|
return false;
|
|
|
|
case Rule::PATTERN_UNDER :
|
|
$table = getTableNameForForeignKeyField($criteria);
|
|
$values = getSonsOf($table, $pattern);
|
|
if (isset($values[$field])) {
|
|
return true;
|
|
}
|
|
return false;
|
|
|
|
case Rule::PATTERN_NOT_UNDER :
|
|
$table = getTableNameForForeignKeyField($criteria);
|
|
$values = getSonsOf($table, $pattern);
|
|
if (isset($values[$field])) {
|
|
return false;
|
|
}
|
|
return true;
|
|
|
|
case Rule::PATTERN_END :
|
|
$value = "/".$pattern."$/i";
|
|
if (preg_match($value, $field) > 0) {
|
|
$criterias_results[$criteria] = $pattern;
|
|
return true;
|
|
}
|
|
return false;
|
|
|
|
case Rule::PATTERN_BEGIN :
|
|
if (empty($pattern)) {
|
|
return false;
|
|
}
|
|
$value = mb_stripos($field, $pattern, 0, 'UTF-8');
|
|
if (($value !== false) && ($value == 0)) {
|
|
$criterias_results[$criteria] = $pattern;
|
|
return true;
|
|
}
|
|
return false;
|
|
|
|
case Rule::PATTERN_CONTAIN :
|
|
if (empty($pattern)) {
|
|
return false;
|
|
}
|
|
$value = mb_stripos($field, $pattern, 0, 'UTF-8');
|
|
if (($value !== false) && ($value >= 0)) {
|
|
$criterias_results[$criteria] = $pattern;
|
|
return true;
|
|
}
|
|
return false;
|
|
|
|
case Rule::PATTERN_NOT_CONTAIN :
|
|
if (empty($pattern)) {
|
|
return false;
|
|
}
|
|
$value = mb_stripos($field, $pattern, 0, 'UTF-8');
|
|
if ($value === false) {
|
|
$criterias_results[$criteria] = $pattern;
|
|
return true;
|
|
}
|
|
return false;
|
|
|
|
case Rule::REGEX_MATCH :
|
|
$results = [];
|
|
// Permit use < and >
|
|
$pattern = Toolbox::unclean_cross_side_scripting_deep($pattern);
|
|
if (preg_match_all($pattern."i", $field, $results)>0) {
|
|
// Drop $result[0] : complete match result
|
|
array_shift($results);
|
|
// And add to $regex_result array
|
|
$res = [];
|
|
foreach ($results as $data) {
|
|
$res[] = $data[0];
|
|
}
|
|
$regex_result[] = $res;
|
|
$criterias_results[$criteria] = $pattern;
|
|
return true;
|
|
}
|
|
return false;
|
|
|
|
case Rule::REGEX_NOT_MATCH :
|
|
// Permit use < and >
|
|
$pattern = Toolbox::unclean_cross_side_scripting_deep($pattern);
|
|
if (preg_match($pattern."i", $field) == 0) {
|
|
$criterias_results[$criteria] = $pattern;
|
|
return true;
|
|
}
|
|
return false;
|
|
|
|
case Rule::PATTERN_FIND :
|
|
case Rule::PATTERN_IS_EMPTY :
|
|
// Global criteria will be evaluated later
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
/**
|
|
* Return the condition label by giving his ID
|
|
*
|
|
* @param $ID condition's ID
|
|
* @param $itemtype itemtype
|
|
* @param $criterion (default '')
|
|
*
|
|
* @return condition's label
|
|
**/
|
|
static function getConditionByID($ID, $itemtype, $criterion = '') {
|
|
|
|
$conditions = self::getConditions($itemtype, $criterion);
|
|
if (isset($conditions[$ID])) {
|
|
return $conditions[$ID];
|
|
}
|
|
return "";
|
|
}
|
|
|
|
|
|
/**
|
|
* @param $itemtype itemtype
|
|
* @param $criterion (default '')
|
|
*
|
|
* @return array of criteria
|
|
**/
|
|
static function getConditions($itemtype, $criterion = '') {
|
|
|
|
$criteria = [Rule::PATTERN_IS => __('is'),
|
|
Rule::PATTERN_IS_NOT => __('is not'),
|
|
Rule::PATTERN_CONTAIN => __('contains'),
|
|
Rule::PATTERN_NOT_CONTAIN => __('does not contain'),
|
|
Rule::PATTERN_BEGIN => __('starting with'),
|
|
Rule::PATTERN_END => __('finished by'),
|
|
Rule::REGEX_MATCH => __('regular expression matches'),
|
|
Rule::REGEX_NOT_MATCH => __('regular expression does not match'),
|
|
Rule::PATTERN_EXISTS => __('exists'),
|
|
Rule::PATTERN_DOES_NOT_EXISTS => __('does not exist')];
|
|
|
|
$extra_criteria = call_user_func([$itemtype, 'addMoreCriteria'], $criterion);
|
|
|
|
foreach ($extra_criteria as $key => $value) {
|
|
$criteria[$key] = $value;
|
|
}
|
|
|
|
/// Add Under criteria if tree dropdown table used
|
|
if ($item = getItemForItemtype($itemtype)) {
|
|
$crit = $item->getCriteria($criterion);
|
|
|
|
if (isset($crit['type']) && ($crit['type'] == 'dropdown')) {
|
|
$crititemtype = getItemTypeForTable($crit['table']);
|
|
|
|
if (($item = getItemForItemtype($crititemtype))
|
|
&& $item instanceof CommonTreeDropdown) {
|
|
$criteria[Rule::PATTERN_UNDER] = __('under');
|
|
$criteria[Rule::PATTERN_NOT_UNDER] = __('not under');
|
|
}
|
|
}
|
|
}
|
|
|
|
return $criteria;
|
|
}
|
|
|
|
|
|
/**
|
|
* Display a dropdown with all the criterias
|
|
*
|
|
* @param $itemtype
|
|
* @param $params array
|
|
**/
|
|
static function dropdownConditions($itemtype, $params = []) {
|
|
|
|
$p['name'] = 'condition';
|
|
$p['criterion'] = '';
|
|
$p['allow_conditions'] = [];
|
|
$p['value'] = '';
|
|
$p['display'] = true;
|
|
|
|
foreach ($params as $key => $value) {
|
|
$p[$key] = $value;
|
|
}
|
|
$elements = [];
|
|
foreach (self::getConditions($itemtype, $p['criterion']) as $pattern => $label) {
|
|
if (empty($p['allow_conditions'])
|
|
|| (!empty($p['allow_conditions']) && in_array($pattern, $p['allow_conditions']))) {
|
|
$elements[$pattern] = $label;
|
|
}
|
|
}
|
|
return Dropdown::showFromArray($p['name'], $elements, ['value' => $p['value']]);
|
|
}
|
|
|
|
|
|
/** form for rule criteria
|
|
*
|
|
* @since 0.85
|
|
*
|
|
* @param $ID integer Id of the criteria
|
|
* @param $options array of possible options:
|
|
* - rule Object : the rule
|
|
**/
|
|
function showForm($ID, $options = []) {
|
|
global $CFG_GLPI;
|
|
|
|
// Yllen: you always have parent for criteria
|
|
$rule = $options['parent'];
|
|
|
|
if ($ID > 0) {
|
|
$this->check($ID, READ);
|
|
} else {
|
|
// Create item
|
|
$options[static::$items_id] = $rule->getField('id');
|
|
|
|
//force itemtype of parent
|
|
static::$itemtype = get_class($rule);
|
|
|
|
$this->check(-1, CREATE, $options);
|
|
}
|
|
$this->showFormHeader($options);
|
|
|
|
echo "<tr class='tab_bg_1'>";
|
|
echo "<td class='center'>"._n('Criterion', 'Criteria', 1) . "</td><td colspan='3'>";
|
|
echo "<input type='hidden' name='".$rule->getRuleIdField()."' value='".
|
|
$this->fields[$rule->getRuleIdField()]."'>";
|
|
|
|
$rand = $rule->dropdownCriteria(['value' => $this->fields['criteria']]);
|
|
$params = ['criteria' => '__VALUE__',
|
|
'rand' => $rand,
|
|
'sub_type' => $rule->getType()];
|
|
|
|
Ajax::updateItemOnSelectEvent("dropdown_criteria$rand", "criteria_span",
|
|
$CFG_GLPI["root_doc"]."/ajax/rulecriteria.php", $params);
|
|
|
|
if (isset($this->fields['criteria']) && !empty($this->fields['criteria'])) {
|
|
$params['criteria'] = $this->fields['criteria'];
|
|
$params['condition'] = $this->fields['condition'];
|
|
$params['pattern'] = $this->fields['pattern'];
|
|
echo "<script type='text/javascript' >\n";
|
|
echo "$(function() {";
|
|
Ajax::updateItemJsCode("criteria_span",
|
|
$CFG_GLPI["root_doc"]."/ajax/rulecriteria.php",
|
|
$params);
|
|
echo '});</script>';
|
|
}
|
|
|
|
if ($rule->specific_parameters) {
|
|
$itemtype = get_class($rule).'Parameter';
|
|
echo "<span title=\"".__s('Add a criterion')."\" class='fa fa-plus pointer' " .
|
|
" onClick=\"".Html::jsGetElementbyID('addcriterion'.$rand).".dialog('open');\">".
|
|
"<span class='sr-only'>" . __s('Add a criterion') . "</span></span>";
|
|
Ajax::createIframeModalWindow('addcriterion'.$rand,
|
|
$itemtype::getFormURL(),
|
|
['reloadonclose' => true]);
|
|
}
|
|
|
|
echo "</td></tr>";
|
|
echo "<tr><td colspan='4'><span id='criteria_span'>\n";
|
|
echo "</span></td></tr>\n";
|
|
$this->showFormButtons($options);
|
|
}
|
|
|
|
}
|