Ganteng Doang Upload Shell Gak Bisa


Linux server.jmdstrack.com 3.10.0-1160.119.1.el7.tuxcare.els10.x86_64 #1 SMP Fri Oct 11 21:40:41 UTC 2024 x86_64
/ home/ jmdstrac/ public_html/ devices/ src/

/home/jmdstrac/public_html/devices/src/RuleCollection.php

<?php

/**
 * ---------------------------------------------------------------------
 *
 * GLPI - Gestionnaire Libre de Parc Informatique
 *
 * http://glpi-project.org
 *
 * @copyright 2015-2023 Teclib' and contributors.
 * @copyright 2003-2014 by the INDEPNET Development Team.
 * @licence   https://www.gnu.org/licenses/gpl-3.0.html
 *
 * ---------------------------------------------------------------------
 *
 * LICENSE
 *
 * This file is part of GLPI.
 *
 * This program 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 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 * ---------------------------------------------------------------------
 */

use Glpi\Event;

class RuleCollection extends CommonDBTM
{
    public const MOVE_BEFORE = 'before';
    public const MOVE_AFTER = 'after';

   /// Rule type
    public $sub_type;
   /// process collection stop on first matched rule
    public $stop_on_first_match                   = false;
   /// field used to order rules
    public $orderby                               = "ranking";
   /// Processing several rules : use result of the previous one to computer the current one
    public $use_output_rule_process_as_next_input = false;
   /// Rule collection can be replay (for dictionnary)
    public $can_replay_rules                      = false;
   /// List of rules of the rule collection
    public $RuleList                              = null;
   /// Menu type
    public $menu_type                             = "rule";
   /// Menu option
    public $menu_option                           = "";

    public $entity                                = 0;

    public static $rightname                             = 'config';


   /// Tab orientation : horizontal or vertical
    public $taborientation = 'horizontal';

    public static function getTable($classname = null)
    {
        return parent::getTable('Rule');
    }


    /**
     * @param $entity (default 0)
     **/
    public function setEntity($entity = 0)
    {
        $this->entity = $entity;
    }


    public function canList()
    {
        return static::canView();
    }


    public function isEntityAssign()
    {
        return false;
    }


    /**
     * Get Collection Size : retrieve the number of rules
     *
     * @param boolean $recursive (true by default)
     * @param integer $condition (0 by default)
     * @param integer $children (0 by default)
     *
     * @return integer number of rules
     **/
    public function getCollectionSize(
        $recursive = true,
        $condition = 0,
        $children = 0
    ) {
        global $DB;

        $restrict = $this->getRuleListCriteria([
            'condition' => $condition,
            'active'    => false,
            'inherited' => $recursive,
            'childrens' => $children,
        ]);

        $iterator = $DB->request($restrict);
        return count($iterator);
    }


    /**
     * Get rules list criteria
     *
     * @param array $options Options
     *
     * @return array
     **/
    public function getRuleListCriteria($options = [])
    {
        $p['active']    = true;
        $p['start']     = 0;
        $p['limit']     = 0;
        $p['inherited'] = 1;
        $p['childrens'] = 0;
        $p['condition'] = 0;

        foreach ($options as $key => $value) {
            $p[$key] = $value;
        }

        $criteria = [
            'SELECT' => Rule::getTable() . '.*',
            'FROM'   => Rule::getTable(),
            'ORDER'  => [
                $this->orderby . ' ASC'
            ]
        ];

        $where = [];
        if ($p['active']) {
            $where['is_active'] = 1;
        }

        if ($p['condition'] > 0) {
            $where['condition'] = ['&', (int)$p['condition']];
        }

       //Select all the rules of a different type
        $where['sub_type'] = $this->getRuleClassName();
        if ($this->isRuleRecursive()) {
            $criteria['LEFT JOIN'] = [
                Entity::getTable() => [
                    'ON' => [
                        Entity::getTable()   => 'id',
                        Rule::getTable()     => 'entities_id'
                    ]
                ]
            ];

            if (!$p['childrens']) {
                $where += getEntitiesRestrictCriteria(
                    Rule::getTable(),
                    'entities_id',
                    $this->entity,
                    $p['inherited']
                );
            } else {
                $sons = getSonsOf('glpi_entities', $this->entity);
                $where[Rule::getTable() . '.entities_id'] = $sons;
            }

            $criteria['ORDER'] = [
                Entity::getTable() . '.level ASC',
                $this->orderby . ' ASC'
            ];
        }

        if ($p['limit']) {
            $criteria['LIMIT'] = (int)$p['limit'];
            $criteria['START'] = (int)$p['start'];
        }

        $criteria['WHERE'] = $where;

        if (method_exists($this, 'collectionFilter')) {
            $filter_opts = [];
            if (isset($options['_glpi_tab'])) {
                $filter_opts['_glpi_tab'] = $options['_glpi_tab'];
            }
            $criteria = $this->collectionFilter($criteria, $filter_opts);
        }

        return $criteria;
    }

    /**
     * Get Collection Part : retrieve descriptions of a range of rules
     *
     * @param $options array of options may be :
     *         - start : first rule (in the result set - default 0)
     *         - limit : max number of rules to retrieve (default 0)
     *         - recursive : boolean get recursive rules
     *         - childirens : boolean get childrens rules
     **/
    public function getCollectionPart($options = [])
    {
        global $DB;

        $p['start']     = 0;
        $p['limit']     = 0;
        $p['recursive'] = true;
        $p['childrens'] = 0;
        $p['condition'] = 0;

        foreach ($options as $key => $value) {
            $p[$key] = $value;
        }

       // no need to use SingletonRuleList::getInstance because we read only 1 page
        $this->RuleList       = new SingletonRuleList();
        $this->RuleList->list = [];

       //Select all the rules of a different type
        $criteria   = $this->getRuleListCriteria($p);

        $iterator   = $DB->request($criteria);

        $active_tab = Session::getActiveTab($this->getType());
        $can_sort = !(str_starts_with($this->getType() . '$', $active_tab));

        foreach ($iterator as $data) {
           //For each rule, get a Rule object with all the criterias and actions
            $tempRule               = $this->getRuleClass();
            $tempRule->fields       = $data;
            $tempRule->can_sort = $can_sort;

            $this->RuleList->list[] = $tempRule;
        }
    }


    /**
     * Get Collection Datas : retrieve descriptions and rules
     *
     * @param $retrieve_criteria  Retrieve the criterias of the rules ? (default 0)
     * @param $retrieve_action    Retrieve the action of the rules ? (default 0)
     * @param $condition          Retrieve with a specific condition
     **/
    public function getCollectionDatas($retrieve_criteria = 0, $retrieve_action = 0, $condition = 0)
    {
        global $DB;

        if ($this->RuleList === null) {
            $this->RuleList = SingletonRuleList::getInstance(
                $this->getRuleClassName(),
                $this->entity
            );
        }
        $need = 1 + ($retrieve_criteria ? 2 : 0) + ($retrieve_action ? 4 : 0) + (8 * $condition);

       // check if load required
        if (($need & $this->RuleList->load) != $need) {
           //Select all the rules of a different type
            $criteria = $this->getRuleListCriteria(['condition' => $condition]);
            $iterator = $DB->request($criteria);

            if (count($iterator)) {
                $this->RuleList->list = [];
                $active_tab = Session::getActiveTab($this->getType());
                $can_sort = !(str_starts_with($this->getType() . '$', $active_tab));

                foreach ($iterator as $rule) {
                    //For each rule, get a Rule object with all the criterias and actions
                    $tempRule = $this->getRuleClass();

                    if (
                        $tempRule->getRuleWithCriteriasAndActions(
                            $rule["id"],
                            $retrieve_criteria,
                            $retrieve_action
                        )
                    ) {
                        $tempRule->can_sort = $can_sort;

                      //Add the object to the list of rules
                        $this->RuleList->list[] = $tempRule;
                    }
                }

                $this->RuleList->load = $need;
            }
        }
    }


    public function getRuleClassName()
    {

        if (preg_match('/(.*)Collection/', get_class($this), $rule_class)) {
            return $rule_class[1];
        }
        return "";
    }


    /**
     * Get a instance of the class to manipulate rule of this collection
     **/
    public function getRuleClass()
    {

        $name = $this->getRuleClassName();
        if ($name !=  '') {
            return new $name();
        }
        return null;
    }


    /**
     * Is a confirmation needed before replay on DB ?
     * If needed need to send 'replay_confirm' in POST
     *
     * @param $target filename : where to go when done
     *
     * @return  true if confirmtion is needed, else false
     **/
    public function warningBeforeReplayRulesOnExistingDB($target)
    {
        return false;
    }


    /**
     * Replay Collection on DB
     *
     * @param $offset             first row to work on (default 0)
     * @param $maxtime   float    max system time to stop working (default 0)
     * @param $items     array    containg items to replay. If empty -> all
     * @param $params    array    additional parameters if needed
     *
     * @return int|false -1 if all rows done, else offset for next run, or false on error
     **/
    public function replayRulesOnExistingDB($offset = 0, $maxtime = 0, $items = [], $params = [])
    {
        return false;
    }


    /**
     * Get title used in list of rules
     *
     * @return Title of the rule collection
     **/
    public function getTitle()
    {
        return __('Rules list');
    }


    /**
     * Indicates if the rule can be affected to an entity or if it's global
     **/
    public function isRuleEntityAssigned()
    {

        $rule = $this->getRuleClass();
        return $rule->isEntityAssign();
    }


    /**
     * Indicates if the rule can be affected to an entity or if it's global
     **/
    public function isRuleRecursive()
    {

        $rule = $this->getRuleClass();
        return $rule->maybeRecursive();
    }

    /**
     * Indicates if the rule use conditions
     **/
    public function isRuleUseConditions()
    {

        $rule = $this->getRuleClass();
        return $rule->useConditions();
    }

    /**
     * Indicates if the rule use conditions
     **/
    public function getDefaultRuleConditionForList()
    {

        $rule = $this->getRuleClass();
        $cond = $rule->getConditionsArray();
       // Get max value
        if (count($cond)) {
            return max(array_keys($cond));
        }
        return 0;
    }

    public function showEngineSummary()
    {

        echo "<table class='tab_cadre_fixe'><tr><th>";

       //Display information about the how the rules engine process the rules
        if ($this->stop_on_first_match) {
           //The engine stop on the first matched rule
            echo "<span class='center b'>" . __('The engine stops on the first checked rule.') .
              "</span><br>";
        } else {
           //The engine process all the rules
            echo "<span class='center b'>" . __('The engine treats all the rules.') . "</span><br>";
        }

        if ($this->use_output_rule_process_as_next_input) {
           //The engine keep the result of a rule to be processed further
            echo "<span class='center b'>" .
                __('The engine passes the result of a rule to the following one.') . "</span><br>";
        }

        if ($this->isRuleUseConditions()) {
           //The engine keep the result of a rule to be processed further
            echo "<span class='center b'>" .
                __('Rules are conditionals. Each one can be used on multiple actions.');
            echo "</span><br>";
        }

        echo "</th></tr>";
        echo "</table>\n";
    }


    /**
     * Show the list of rules
     *
     * @param $target
     * @param $options   array
     *
     * @return void
     **/
    public function showListRules($target, $options = [])
    {
        global $CFG_GLPI;

        $p['inherited'] = 1;
        $p['childrens'] = 0;
        $p['active']    = false;
        $p['condition'] = 0;
        $p['_glpi_tab'] = $options['_glpi_tab'];
        $rand           = mt_rand();
        $p['display_criterias'] = false;
        $p['display_actions']   = false;

        foreach (['inherited','childrens', 'condition'] as $param) {
            if (
                isset($options[$param])
                && $this->isRuleRecursive()
            ) {
                $p[$param] = $options[$param];
            }
        }

        foreach (['display_criterias', 'display_actions'] as $param) {
            if (
                isset($options[$param])
            ) {
                $p[$param] = $options[$param];
            }
        }

        $rule              = $this->getRuleClass();
        $display_entities  = ($this->isRuleRecursive()
                            && ($p['inherited'] || $p['childrens']));
        $display_criterias = $p['display_criterias'];
        $display_actions   = $p['display_actions'];

       // Do not know what it is ?
        $canedit    = (self::canUpdate()
                     && !$display_entities);

        $use_conditions = false;
        if ($rule->useConditions()) {
            // First get saved option
            $p['condition'] = Session::getSavedOption($this->getType(), 'condition', 0);
            if ($p['condition'] == 0) {
                $p['condition'] = $this->getDefaultRuleConditionForList();
            }
            $use_conditions = true;
            // Mini Search engine
            echo "<table class='tab_cadre_fixe'>";
            echo "<tr class='tab_bg_1'><td class='center' width='50%'>";
            echo __('Rules used for') . "</td><td>";
            $rule->dropdownConditions(['value' => $p['condition'],
                'on_change'  => 'reloadTab("start=0&inherited=' . $p['inherited']
                                                         . '&childrens=' . $p['childrens'] . '&condition="+this.value)'
            ]);
            echo "</td></tr></table>";
        }

        $nb         = $this->getCollectionSize($p['inherited'], $p['condition'], $p['childrens']);
        $p['start'] = (isset($options["start"]) ? $options["start"] : 0);

        if ($p['start'] >= $nb) {
            $p['start'] = 0;
        }

        $p['limit'] = $_SESSION['glpilist_limit'];
        $this->getCollectionPart($p);

        Html::printAjaxPager('', $p['start'], $nb);

        Html::openMassiveActionsForm('mass' . __CLASS__ . $rand);
        echo "\n<div class='spaced'>";

        if ($canedit && $nb) {
            $massiveactionparams = ['num_displayed' => min($p['limit'], $nb),
                'container'     => 'mass' . __CLASS__ . $rand,
                'extraparams'   => ['entity' => $this->entity,
                    'condition' => $p['condition'],
                    'rule_class_name'
                                                                 => $this->getRuleClassName()
                ]
            ];
            Html::showMassiveActions($massiveactionparams);
        }

        echo "<table class='table table-striped table-hover card-table'>";
        $colspan = 4;

        if ($display_entities) {
            $colspan++;
        }
        if ($use_conditions) {
            $colspan++;
        }
        if ($display_criterias) {
            $colspan++;
        }
        if ($display_actions) {
            $colspan++;
        }

        $ruletype = $this->getRuleClassName();
        $can_sort = $canedit && $nb;
        if (count($this->RuleList->list)) {
            $can_sort = $this->RuleList->list[0]->can_sort && $canedit && $nb;
            Session::initNavigateListItems($ruletype);
        }

        if ($can_sort) {
            $colspan += 2;
        }

        echo "<tr><th colspan='$colspan'>" . $this->getTitle() . "</th></tr>";
        $header_row = "<tr>";
        $header_row .= "<th>";
        if ($canedit) {
            $header_row .= Html::getCheckAllAsCheckbox('mass' . __CLASS__ . $rand);
        }
        $header_row .= "</th>";
        $header_row .= "<th>" . __('Name') . "</th>";
        $header_row .= "<th>" . __('Description') . "</th>";
        if ($use_conditions) {
            $header_row .= "<th>" . __('Use rule for') . "</th>";
        }
        if ($display_criterias) {
            $header_row .= "<th>" . RuleCriteria::getTypeName(2) . "</th>";
        }
        if ($display_actions) {
            $header_row .= "<th>" . RuleAction::getTypeName(2) . "</th>";
        }
        $header_row .= "<th>" . __('Active') . "</th>";
        if ($display_entities) {
            $header_row .= "<th>" . Entity::getTypeName(1) . "</th>";
        }
        if ($nb && $canedit && $can_sort) {
            $header_row .= "<th></th><th></th>";
        }
        $header_row .= "</tr>";
        echo $header_row;

        echo "<tbody class='sortable-rules'>";
        for ($i = $p['start'],$j = 0; isset($this->RuleList->list[$j]); $i++,$j++) {
            $this->RuleList->list[$j]->showMinimalForm(
                $target,
                $i == 0,
                $i == $nb - 1,
                $display_entities,
                $p['condition'],
                $display_criterias,
                $display_actions
            );
            Session::addToNavigateListItems($ruletype, $this->RuleList->list[$j]->fields['id']);
        }
        echo "</tbody>";

        if ($nb) {
            echo $header_row;
        }
        echo "</table>";

        if ($canedit && $nb) {
            $collection_classname = $this->getType();
            $js = <<<JAVASCRIPT
         $(function() {
            sortable('.sortable-rules', {
               handle: '.grip-rule',
               placeholder: '<tr><td colspan="7" class="sortable-placeholder">&nbsp;</td></tr>'
            })[0].addEventListener('sortupdate', function(e) {
               var sort_detail          = e.detail;
               var rule_id              = sort_detail.item.dataset.ruleId;
               var collection_classname = "{$collection_classname}";
               var new_index            = sort_detail.destination.index;
               var old_index            = sort_detail.origin.index;
               var ref_id               = sort_detail.destination.itemsBeforeUpdate[new_index].dataset.ruleId;
               var sort_action          = 'after';

               if (old_index > new_index) {
                  sort_action = 'before';
               }

               $.post(CFG_GLPI['root_doc']+'/ajax/rule.php', {
                  'action': 'move_rule',
                  'rule_id': rule_id,
                  'collection_classname': collection_classname,
                  'sort_action': sort_action,
                  'ref_id': ref_id,
               });

               displayAjaxMessageAfterRedirect();
            });
         });
JAVASCRIPT;
            echo Html::scriptBlock($js);

            $massiveactionparams['ontop'] = false;
            Html::showMassiveActions($massiveactionparams);
        }

        echo "</div>";
        Html::closeForm();

        Html::printAjaxPager('', $p['start'], $nb);

        echo "<div class='spaced center'>";

        if ($plugin = isPluginItemType($this->getType())) {
            $url = Plugin::getWebDir($plugin['plugin']);
        } else {
            $url = $CFG_GLPI["root_doc"];
        }

        // if rules provides has default rules, then we're able to reset them
        $ruleclass = $this->getRuleClass();
        if ($ruleclass instanceof Rule && $ruleclass->hasDefaultRules()) {
            echo "<a class='btn btn-primary' id='reset_rules' href='" . $rule->getSearchURL() . "?reinit=true&subtype=" . $ruleclass->getType() . "' " .
            "onClick='if(confirm(\"" . __s('Rules will be erased and recreated from default. Are you sure?') . "\"))
            { return true } else { return false; };' " .
            "title='" . __s("Delete all rules and recreate them by default") . "'" .
            ">" . __('Reset rules') . "</a>&nbsp;";
        }
        echo "<a class='btn btn-primary' href='#' data-bs-toggle='modal' data-bs-target='#allruletest$rand'>" .
                  __('Test rules engine') . "</a>";
        Ajax::createIframeModalWindow(
            'allruletest' . $rand,
            $url . "/front/rulesengine.test.php?" .
                                          "sub_type=" . $ruleclass->getType() .
                                          "&condition=" . $p['condition'],
            ['title' => __('Test rules engine')]
        );
        echo "</div>";

        if ($this->can_replay_rules) {
            echo "<div class='spaced center'>";
            echo "<a class='btn btn-primary' href='" . $rule->getSearchURL() . "?replay_rule=replay_rule'>" .
               __s('Replay the dictionary rules') . "</a>";
            echo "</div>";
        }

        echo "<div class='spaced'>";
        $this->showAdditionalInformationsInForm($target);
        echo "</div>";
    }


    /**
     * Show the list of rules
     *
     * @param $target
     *
     * @return void
     **/
    public function showAdditionalInformationsInForm($target)
    {
    }


    /**
     * Modify rule's ranking and automatically reorder all rules
     *
     * @param $ID     the rule ID whose ranking must be modified
     * @param $action up or down
     * @param $condition action on a specific condition
     **/
    public function changeRuleOrder($ID, $action, $condition = 0)
    {
        global $DB;

        $criteria = [
            'SELECT' => 'ranking',
            'FROM'   => 'glpi_rules',
            'WHERE'  => ['id' => $ID]
        ];

        $add_condition = [];
        if ($condition > 0) {
            $add_condition = ['condition' => ['&', (int)$condition]];
        }

        $iterator = $DB->request($criteria);
        if (count($iterator) == 1) {
            $result = $iterator->current();
            $current_rank = $result['ranking'];
           // Search rules to switch
            $criteria = [
                'SELECT' => ['id', 'ranking'],
                'FROM'   => 'glpi_rules',
                'WHERE'  => [
                    'sub_type'  => $this->getRuleClassName()
                ] + $add_condition,
                'LIMIT'  => 1
            ];

            switch ($action) {
                case "up":
                    $criteria['WHERE']['ranking'] = ['<', $current_rank];
                    $criteria['ORDERBY'] = 'ranking DESC';
                    break;

                case "down":
                    $criteria['WHERE']['ranking'] = ['>', $current_rank];
                    $criteria['ORDERBY'] = 'ranking ASC';
                    break;

                default:
                    return false;
            }

            $iterator2 = $DB->request($criteria);
            if (count($iterator2) == 1) {
                $result2 = $iterator2->current();
                $other_ID = $result2['id'];
                $new_rank = $result2['ranking'];
                echo $current_rank . ' ' . $ID . '<br>';
                echo $new_rank . ' ' . $other_ID . '<br>';

                $rule = $this->getRuleClass();
                $result = false;
                $criteria = [
                    'SELECT' => ['id', 'ranking'],
                    'FROM'   => 'glpi_rules',
                    'WHERE'  => ['sub_type' => $this->getRuleClassName()]
                ];
                $diff = $new_rank - $current_rank;
                switch ($action) {
                    case "up":
                        $criteria['WHERE'] = array_merge(
                            $criteria['WHERE'],
                            [
                                ['ranking' => ['>', $new_rank]],
                                ['ranking' => ['<=', $current_rank]]
                            ]
                        );
                        $diff += 1;
                        break;

                    case "down":
                        $criteria['WHERE'] = array_merge(
                            $criteria['WHERE'],
                            [
                                ['ranking' => ['>=', $current_rank]],
                                ['ranking' => ['<', $new_rank]]
                            ]
                        );
                        $diff -= 1;
                        break;

                    default:
                        return false;
                }

                if ($diff != 0) {
                   // Move several rules
                    $iterator3 = $DB->request($criteria);
                    foreach ($iterator3 as $data) {
                        $data['ranking'] += $diff;
                        $result = $rule->update($data);
                    }
                } else {
                   // Only move one
                    $result = $rule->update([
                        'id'      => $ID,
                        'ranking' => $new_rank
                    ]);
                }

               // Update reference
                if ($result) {
                    $result = $rule->update([
                        'id'      => $other_ID,
                        'ranking' => $current_rank
                    ]);
                }
                return $result;
            }
        }
        return false;
    }


    /**
     * Update Rule Order when deleting a rule
     *
     * @param $ranking rank of the deleted rule
     *
     * @return true if all ok
     **/
    public function deleteRuleOrder($ranking)
    {
        global $DB;

        $result = $DB->update(
            'glpi_rules',
            [
                'ranking' => new \QueryExpression($DB->quoteName('ranking') . ' - 1')
            ],
            [
                'sub_type'  => $this->getRuleClassName(),
                'ranking'   => ['>', $ranking]
            ]
        );
        return $result;
    }


    /**
     * Move a rule in an ordered collection
     *
     * @param integer $ID        ID of the rule to move
     * @param integer $ref_ID    ID of the rule position  (0 means all, so before all or after all)
     * @param string  $type      Movement type, one of self::MOVE_AFTER or self::MOVE_BEFORE
     *
     * @return boolean
     **/
    public function moveRule($ID, $ref_ID, $type = self::MOVE_AFTER)
    {
        global $DB;

        $ruleDescription = new Rule();

       // Get actual ranking of Rule to move
        $ruleDescription->getFromDB($ID);
        $old_rank = $ruleDescription->fields["ranking"];

       // Compute new ranking
        if ($ref_ID) { // Move after/before an existing rule
            $ruleDescription->getFromDB($ref_ID);
            $rank = $ruleDescription->fields["ranking"];
        } else if ($type == self::MOVE_AFTER) {
           // Move after all
            $result = $DB->request([
                'SELECT' => ['MAX' => 'ranking AS maxi'],
                'FROM'   => 'glpi_rules',
                'WHERE'  => ['sub_type' => $this->getRuleClassName()]
            ])->current();
            $rank   = $result['maxi'];
        } else {
           // Move before all
            $rank = 1;
        }

        $rule   = $this->getRuleClass();

        $result = false;

       // Move others rules in the collection
        if ($old_rank < $rank) {
            if ($type == self::MOVE_BEFORE) {
                $rank--;
            }

           // Move back all rules between old and new rank
            $iterator = $DB->request([
                'SELECT' => ['id', 'ranking'],
                'FROM'   => 'glpi_rules',
                'WHERE'  => [
                    'sub_type'  => $this->getRuleClassName(),
                    ['ranking'  => ['>', $old_rank]],
                    ['ranking'  => ['<=', $rank]]
                ]
            ]);
            foreach ($iterator as $data) {
                $data['ranking']--;
                $result = $rule->update($data);
            }
        } else if ($old_rank > $rank) {
            if ($type == self::MOVE_AFTER) {
                $rank++;
            }

           // Move forward all rule  between old and new rank
            $iterator = $DB->request([
                'SELECT' => ['id', 'ranking'],
                'FROM'   => 'glpi_rules',
                'WHERE'  => [
                    'sub_type'  => $this->getRuleClassName(),
                    ['ranking'  => ['>=', $rank]],
                    ['ranking'  => ['<', $old_rank]]
                ]
            ]);
            foreach ($iterator as $data) {
                $data['ranking']++;
                $result = $rule->update($data);
            }
        } else { // $old_rank == $rank : nothing to do
            $result = false;
        }

       // Move the rule
        if ($result && ($old_rank != $rank)) {
            $result = $rule->update([
                'id'      => $ID,
                'ranking' => $rank
            ]);
        }
        return ($result ? true : false);
    }


    /**
     * Print a title for backup rules
     *
     * @since 0.85
     *
     * @return void
     **/
    public static function titleBackup()
    {
        global $CFG_GLPI;

        $base_url = "{$CFG_GLPI["root_doc"]}/front/rule.backup.php";
        $buttons  = [
            "{$base_url}?action=import" =>
            "<i class='fas fa-upload'></i><span>" . _x('button', 'Import') . "</span>",
            "{$base_url}?action=export" =>
            "<i class='fas fa-download'></i><span>" . _x('button', 'Export') . "</span>",
        ];

        echo "<div class='center mb-3'>";
        foreach ($buttons as $key => $val) {
            echo "<a class='btn btn-primary me-2' href='" . $key . "'>" . $val . "</a></td>";
        }
        echo "</div>";
    }


    /**
     * Export rules in a xml format
     *
     * @param items array the input data to transform to xml
     *
     * @since 0.85
     *
     * @return void send attachment to browser
     **/
    public static function exportRulesToXML($items = [])
    {

        if (!count($items)) {
            return false;
        }

        $rulecollection = new self();
        $rulecritera    = new RuleCriteria();
        $ruleaction     = new RuleAction();

       //create xml
        $xmlE           = new SimpleXMLElement('<rules/>');

       //parse all rules
        foreach ($items as $key => $ID) {
            $rulecollection->getFromDB($ID);
            if (!class_exists($rulecollection->fields['sub_type'])) {
                continue;
            }
            $rule = new $rulecollection->fields['sub_type']();
            unset($rulecollection->fields['id']);
            unset($rulecollection->fields['date_mod']);

            $name = Dropdown::getDropdownName(
                "glpi_entities",
                $rulecollection->fields['entities_id']
            );
            $rulecollection->fields['entities_id'] = $name;

           //add root node
            $xmlERule = $xmlE->addChild('rule');

           //convert rule direct indexes in XML
            foreach ($rulecollection->fields as $key => $val) {
                $xmlERule->$key = $val;
            }

           //find criterias
            $criterias = $rulecritera->find(['rules_id' => $ID]);
            foreach ($criterias as &$criteria) {
                unset($criteria['id']);
                unset($criteria['rules_id']);

                $available_criteria = $rule->getCriterias();
                $crit               = $criteria['criteria'];
                if (self::isCriteraADropdown($available_criteria, $criteria['condition'], $crit)) {
                    $criteria['pattern'] = Dropdown::getDropdownName(
                        $available_criteria[$crit]['table'],
                        $criteria['pattern'],
                        false,
                        true,
                        false,
                        ''
                    );
                }

               //convert criterias in XML
                $xmlECritiera = $xmlERule->addChild('rulecriteria');
                foreach ($criteria as $key => $val) {
                    $xmlECritiera->$key = $val;
                }
            }

           //find actions
            $actions = $ruleaction->find(['rules_id' => $ID]);
            foreach ($actions as &$action) {
                unset($action['id']);
                unset($action['rules_id']);

               //process FK (just in case of "assign" action)
                if (
                    ($action['action_type'] == "assign")
                    && (strpos($action['field'], '_id') !== false)
                    && !(($action['field'] == "entities_id")
                     && ($action['value'] == 0))
                ) {
                    $field = $action['field'];
                    if ($action['field'][0] == "_") {
                        $field = substr($action['field'], 1);
                    }
                    $table = getTableNameForForeignKeyField($field);

                    $action['value'] = Dropdown::getDropdownName(
                        $table,
                        $action['value'],
                        false,
                        true,
                        false,
                        ''
                    );
                }

               //convert actions in XML
                $xmlEAction = $xmlERule->addChild('ruleaction');
                foreach ($action as $key => $val) {
                    $xmlEAction->$key = $val;
                }
            }
        }

       //convert SimpleXMLElement to xml string
        $xml = $xmlE->asXML();

       //send attachment to browser
        header('Content-type: application/xml');
        header('Content-Disposition: attachment; filename="rules.xml"');
        echo $xml;

       //exit;
    }


    /**
     * Print a form to select a xml file for import rules
     *
     * @since 0.85
     *
     * @return void
     **/
    public static function displayImportRulesForm()
    {

        echo "<form name='form' method='post' action='rule.backup.php' " .
             "enctype='multipart/form-data' >";
        echo "<div class='center'>";

        echo "<h2>" . __("Import rules from a XML file") . "</h2>";
        echo "<input type='file' name='xml_file'>&nbsp;";
        echo "<input type='hidden' name='action' value='preview_import'>";
        echo "<input type='submit' name='import' value=\"" . _sx('button', 'Import') .
             "\" class='btn btn-primary'>";

       // Close for Form
        echo "</div>";
        Html::closeForm();
    }


    /**
     *
     * Check if a criterion is a dropdown or not
     *
     * @since 0.85
     *
     * @param $available_criteria    available criterai for this rule
     * @param $condition             the rulecriteria condition
     * @param $criterion             the criterion
     *
     * @return true if a criterion is a dropdown, false otherwise
     **/
    public static function isCriteraADropdown($available_criteria, $condition, $criterion)
    {

        if (isset($available_criteria[$criterion]['type'])) {
            $type = $available_criteria[$criterion]['type'];
        } else {
            $type = false;
        }
        return (in_array(
            $condition,
            [Rule::PATTERN_IS, Rule::PATTERN_IS_NOT, Rule::PATTERN_UNDER]
        )
              && ($type == 'dropdown'));
    }


    /**
     * Print a form to inform user when conflicts appear during the import of rules from a xml file
     *
     * @since 0.85
     *
     * @return true if all ok
     **/
    public static function previewImportRules()
    {
        global $DB;

        if (!isset($_FILES["xml_file"]) || ($_FILES["xml_file"]["size"] == 0)) {
            return false;
        }

        if ($_FILES["xml_file"]["error"] != UPLOAD_ERR_OK) {
            Session::addMessageAfterRedirect(__("No file was uploaded"));
            return false;
        }
       //get xml file content
        $xml           = file_get_contents($_FILES["xml_file"]["tmp_name"]);
       //convert a xml string into a SimpleXml object
        if (!$xmlE = simplexml_load_string($xml)) {
            Session::addMessageAfterRedirect(__('Unauthorized file type'), false, ERROR);
        }
       //convert SimpleXml object into an array and store it in session
        $rules         = json_decode(json_encode((array) $xmlE), true);
       //check rules (check if entities, criterias and actions is always good in this glpi)
        $entity        = new Entity();
        $rules_refused = [];

       //In case there's only one rule to import, recreate an array with key => value
        if (isset($rules['rule']['entities_id'])) {
            $rules['rule'] = [0 => $rules['rule']];
        }

        foreach ($rules['rule'] as $k_rule => &$rule) {
            $tmprule = new $rule['sub_type']();
           //check entities
            if ($tmprule->isEntityAssign()) {
                $rule['entities_id'] = $DB->escape(Html::entity_decode_deep($rule['entities_id']));
                $entities_found = $entity->find(['completename' => $rule['entities_id']]);
                if (empty($entities_found)) {
                    $rules_refused[$k_rule]['entity'] = true;
                }
            }

           //process direct attributes
            foreach ($rule as &$val) {
                if (
                    is_array($val)
                    && empty($val)
                ) {
                    $val = "";
                }
            }

           //check criterias
            if (isset($rule['rulecriteria'])) {
               //check and correct criterias array format
                if (isset($rule['rulecriteria']['criteria'])) {
                    $rule['rulecriteria'] = [$rule['rulecriteria']];
                }

                foreach ($rule['rulecriteria'] as $k_crit => $criteria) {
                    // Fix patterns decoded as empty arrays to prevent empty IN clauses in SQL generation.
                    if (is_array($criteria['pattern']) && empty($criteria['pattern'])) {
                        $criteria['pattern'] = '';
                    }

                    $available_criteria = $tmprule->getCriterias();
                    $crit               = $criteria['criteria'];
                   //check FK (just in case of "is", "is_not" and "under" criteria)
                    if (
                        self::isCriteraADropdown(
                            $available_criteria,
                            $criteria['condition'],
                            $crit
                        )
                    ) {
                       //escape pattern
                        $criteria['pattern'] = $DB->escape(Html::entity_decode_deep($criteria['pattern']));
                        $itemtype = getItemTypeForTable($available_criteria[$crit]['table']);
                        $item     = new $itemtype();
                        if ($item instanceof CommonTreeDropdown) {
                            $found = $item->find(['completename' => $criteria['pattern']]);
                        } else {
                            $found = $item->find(['name' => $criteria['pattern']]);
                        }
                        if (empty($found)) {
                            $rules_refused[$k_rule]['criterias'][] = $k_crit;
                        } else {
                            $tmp = array_pop($found);
                            $rules['rule'][$k_rule]['rulecriteria'][$k_crit]['pattern'] = $tmp['id'];
                        }
                    }
                }
            }

           //check actions
            if (isset($rule['ruleaction'])) {
               //check and correct actions array format
                if (isset($rule['ruleaction']['field'])) {
                    $rule['ruleaction'] = [$rule['ruleaction']];
                }

                foreach ($rule['ruleaction'] as $k_action => $action) {
                    // Fix values decoded as empty arrays to prevent empty IN clauses in SQL generation.
                    if (is_array($action['value']) && empty($action['value'])) {
                        $action['value'] = '';
                    }
                    $available_actions = $tmprule->getActions();
                    $act               = $action['field'];

                    if (
                        ($action['action_type'] == "assign")
                        && (isset($available_actions[$act]['type'])
                        && ($available_actions[$act]['type'] == 'dropdown'))
                    ) {
                       //pass root entity and empty array (N/A value)
                        if (
                            (in_array($action['value'], ['entities_id', 'new_entities_id'], true))
                            && (($action['value'] == 0)
                            || ($action['value'] == ''))
                        ) {
                            continue;
                        }

                       //escape value
                        $action['value'] = $DB->escape(Html::entity_decode_deep($action['value']));
                        $itemtype = getItemTypeForTable($available_actions[$act]['table']);
                        $item     = new $itemtype();
                        if ($item instanceof CommonTreeDropdown) {
                            $found = $item->find(['completename' => $action['value']]);
                        } else {
                            $found = $item->find(['name' => $action['value']]);
                        }
                        if (empty($found)) {
                            $rules_refused[$k_rule]['actions'][] = $k_action;
                        } else {
                            $tmp = array_pop($found);
                            $rules['rule'][$k_rule]['ruleaction'][$k_action]['value'] = $tmp['id'];
                        }
                    }
                }
            }
        }

       //save rules for ongoing processing
        $_SESSION['glpi_import_rules']         = $rules;
        $_SESSION['glpi_import_rules_refused'] = $rules_refused;

       //if no conflict detected, we can directly process the import
        if (!count($rules_refused)) {
            Html::redirect("rule.backup.php?action=process_import");
        }

       //print report
        echo "<form name='form' method='post' action='rule.backup.php' >";
        echo "<div class='spaced' id='tabsbody'>";
        echo "<table class='tab_cadre'>";
        echo "<input type='hidden' name='action' value='process_import'>";
        echo "<tr><th colspan='3'>" . __('Rules refused') . "</th></tr>";
        echo "<tr>";
        echo "<th>" . _n('Type', 'Type', 1) . "</th>";
        echo "<th>" . __('Name') . "</th>";
        echo "<th>" . __('Reason of rejection') . "</th>";
        echo "</tr>";

        $odd = true;
        foreach ($rules_refused as $k_rule => $refused) {
            $odd = !$odd;
            if ($odd) {
                $class = " class='tab_bg_1' ";
            } else {
                $class = " class='tab_bg_2' ";
            }

            $sub_type = $rules['rule'][$k_rule]['sub_type'];
            $item     = new $sub_type();

            echo "<tr $class>";
            echo "<td>" . $item->getTitle() . "</td>";
            echo "<td>" . $rules['rule'][$k_rule]['name'] . "</td>";
            echo "<td>";

            echo "<table class='tab_cadre' style='width:100%'>";
           //show entity select
            if (!isset($refused['criterias']) && !isset($refused['actions'])) {
                if (isset($refused['entity'])) {
                    echo "<tr class='tab_bg_1_2'>";
                    echo "<td>";
                    printf(
                        __('%1$s (%2$s)'),
                        __('Entity not found'),
                        $rules['rule'][$k_rule]['entities_id']
                    );
                    echo "</td>";
                    echo "<td>";
                    echo __('Select the desired entity') . "&nbsp;";
                    Dropdown::show(
                        'Entity',
                        ['comments' => false,
                            'name'     => "new_entities[" .
                        $rules['rule'][$k_rule]['uuid'] . "]"
                        ]
                    );
                    echo "</td>";
                    echo "</tr>";
                }
            }

           //show criterias refused for this rule
            if (isset($refused['criterias'])) {
                echo "<tr class='tab_bg_1_2'>";
                echo "<td>" . __('Criteria refused') . "</td>";
                echo "<td>";

                echo "<table class='tab_cadre' style='width:100%'>";
                echo "<tr class='tab_bg_2'>";
                echo "<th class='center b'>" . _n('Criterion', 'Criteria', 1) . "</th>\n";
                echo "<th class='center b'>" . __('Condition') . "</th>\n";
                echo "<th class='center b'>" . __('Reason') . "</th>\n";
                echo "</tr>\n";
                foreach ($refused['criterias'] as $k_criteria) {
                    $criteria = $rules['rule'][$k_rule]['rulecriteria'][$k_criteria];

                   //fix empty empty array values
                    if (empty($criteria['value'])) {
                        $criteria['value'] = null;
                    }
                    echo "<tr class='tab_bg_1'>";
                    echo "<td>" . $item->getCriteriaName($criteria["criteria"]) . "</td>";
                    echo "<td>" . RuleCriteria::getConditionByID(
                        $criteria["condition"],
                        get_class($item),
                        $criteria["criteria"]
                    ) . "</td>";
                    echo "<td>" . $criteria["pattern"] . "</td>";
                    echo "</tr>";
                }
                echo "</table>\n";
                echo "</td>";
                echo "</tr>";
            }

           //show actions refused for this rule
            if (isset($refused['actions'])) {
                echo "<tr class='tab_bg_1_2'>";
                echo "<td>" . __('Actions refused') . "</td>";
                echo "<td>";

                echo "<table class='tab_cadre' style='width:100%'>";
                echo "<tr class='tab_bg_2'>";
                echo "<th class='center b'>" . _n('Field', 'Fields', Session::getPluralNumber()) . "</th>";
                echo "<th class='center b'>" . __('Action type') . "</th>";
                echo "<th class='center b'>" . __('Value') . "</th>";
                echo "</tr>\n";
                foreach ($refused['actions'] as $k_action) {
                    $action = $rules['rule'][$k_rule]['ruleaction'][$k_action];
                   //fix empty empty array values
                    if (empty($action['value'])) {
                        $action['value'] = null;
                    }
                    echo "<tr class='tab_bg_1'>";
                    echo "<td>" . $item->getActionName($action["field"]) . "</td>";
                    echo "<td>" . RuleAction::getActionByID($action["action_type"]) . "</td>";
                    echo "<td>" . $action["value"] . "</td>";
                    echo "</tr>";
                }
                echo "</table>\n";
                echo "</td>";
                echo "</tr>";
            }
            echo "</table>\n";
            echo "</td></tr>";
        }

       //display buttons
        $class = ($odd ? " class='tab_bg_1' " : " class='tab_bg_2' ");
        echo "<tr $class><td colspan='3' class='center'>";
        echo "<input type='submit' name='import' value=\"" . _sx('button', 'Post') .
             "\" class='btn btn-primary'>";
        echo "</td></tr>";

       // Close for Form
        echo "</table></div>";
        Html::closeForm();

        return true;
    }


    /**
     * import rules in glpi after user validation
     *
     * @since 0.85
     *
     * @return true if all ok
     **/
    public static function processImportRules()
    {
        global $DB;
        $ruleCriteria = new RuleCriteria();
        $ruleAction   = new RuleAction();
        $entity       = new Entity();

       //get session vars
        $rules         = $_SESSION['glpi_import_rules'];
        $rules_refused = $_SESSION['glpi_import_rules_refused'];
        $rr_keys       = array_keys($rules_refused);
        unset($_SESSION['glpi_import_rules']);
        unset($_SESSION['glpi_import_rules_refused']);

       // unset all refused rules
        foreach ($rules['rule'] as $k_rule => &$rule) {
            if (in_array($k_rule, $rr_keys)) {
                //Do not process rule with actions or criterias refused
                if (
                    isset($rules_refused[$k_rule]['criterias'])
                    || isset($rules_refused[$k_rule]['actions'])
                ) {
                    unset($rules['rule'][$k_rule]);
                } else {// accept rule with only entity not found (change entity)
                    $rule['entities_id'] = $_REQUEST['new_entities'][$rule['uuid']];
                }
            }
        }

       //import all right rules
        while (!empty($rules['rule'])) {
            $current_rule             = array_shift($rules['rule']);
            $add_criteria_and_actions = false;
            $params                   = [];
            $itemtype                 = $current_rule['sub_type'];
            $item                     = new $itemtype();

           //Find a rule by it's uuid
            $found    = $item->find(['uuid' => $current_rule['uuid']]);
            $params   = Toolbox::addslashes_deep($current_rule);
            unset($params['rulecriteria']);
            unset($params['ruleaction']);

            if (!$item->isEntityAssign()) {
                $params['entities_id'] = 0;
            } else {
                $entities_found = $entity->find(['completename' => $DB->escape($current_rule['entities_id'])]);
                if (!empty($entities_found)) {
                    $entity_found          = array_shift($entities_found);
                    $params['entities_id'] = $entity_found['id'];
                } else {
                    $params['entities_id'] = 0;
                }
            }
            foreach (['is_recursive', 'is_active'] as $field) {
               //Should not be necessary but without it there's an sql error...
                if (!isset($params[$field]) || ($params[$field] == '')) {
                    $params[$field] = 0;
                }
            }

           //if uuid not exist, create rule
            if (empty($found)) {
               //Manage entity
                $params['_add'] = true;
                $rules_id       = $item->add($params);
                if ($rules_id) {
                    Event::log(
                        $rules_id,
                        "rules",
                        4,
                        "setup",
                        sprintf(__('%1$s adds the item %2$s'), $_SESSION["glpiname"], $rules_id)
                    );
                    $add_criteria_and_actions = true;
                }
            } else { //if uuid exists, then update the rule
                $tmp               = array_shift($found);
                $params['id']      = $tmp['id'];
                $params['_update'] = true;
                $rules_id          = $tmp['id'];
                if ($item->update($params)) {
                    Event::log(
                        $rules_id,
                        "rules",
                        4,
                        "setup",
                        sprintf(__('%s updates an item'), $_SESSION["glpiname"])
                    );

                   //remove all dependent criterias and action
                    $ruleCriteria->deleteByCriteria(["rules_id" => $rules_id]);
                    $ruleAction->deleteByCriteria(["rules_id" => $rules_id]);
                    $add_criteria_and_actions = true;
                }
            }

            if ($add_criteria_and_actions) {
               //Add criteria
                if (isset($current_rule['rulecriteria'])) {
                    foreach ($current_rule['rulecriteria'] as $criteria) {
                        $criteria['rules_id'] = $rules_id;
                        //fix array in value key
                        //(simplexml bug, empty xml node are converted in empty array instead of null)
                        if (is_array($criteria['pattern'])) {
                            $criteria['pattern'] = null;
                        }
                        $criteria = Toolbox::addslashes_deep($criteria);
                        $ruleCriteria->add($criteria);
                    }
                }

               //Add actions
                if (isset($current_rule['ruleaction'])) {
                    foreach ($current_rule['ruleaction'] as $action) {
                        $action['rules_id'] = $rules_id;
                       //fix array in value key
                       //(simplexml bug, empty xml node are converted in empty array instead of null)
                        if (is_array($action['value'])) {
                             $action['value'] = null;
                        }
                        $action = Toolbox::addslashes_deep($action);
                        $ruleAction->add($action);
                    }
                }
            }
        }

        Session::addMessageAfterRedirect(__('Successful importation'));

        return true;
    }


    /**
     * Process all the rules collection
     *
     * @param array $input    Input data used to check criterias (need to be clean slashes)
     * @param array $output   Initial ouput array used to be manipulate by actions (need to be clean slashes)
     * @param array $params   Parameters for all internal functions (need to be clean slashes)
     * @param array $options  Options :
     *                         - condition : specific condition to limit rule list
     *                         - only_criteria : only react on specific criteria
     *
     * @return array the output array updated by actions (addslashes datas)
     **/
    public function processAllRules($input = [], $output = [], $params = [], $options = [])
    {

        $p['condition']     = 0;
        $p['only_criteria'] = null;

        if (is_array($options) && count($options)) {
            foreach ($options as $key => $val) {
                $p[$key] = $val;
            }
        }

        // Get Collection datas
        $this->getCollectionDatas(1, 1, $p['condition']);
        $input                      = $this->prepareInputDataForProcessWithPlugins($input, $params);
        $output["_no_rule_matches"] = true;

        //Store rule type being processed (for plugins)
        $params['rule_itemtype']    = $this->getRuleClassName();

        if (count($this->RuleList->list)) {
            /** @var Rule $rule */
            foreach ($this->RuleList->list as $rule) {
                if ($p['condition'] && !($rule->fields['condition'] & $p['condition'])) {
                    // Rule is loaded in the cache but is not relevant for the current condition
                    continue;
                }

               //If the rule is active, process it

                if ($rule->fields["is_active"]) {
                    $output["_rule_process"] = false;
                    $rule->process($input, $output, $params, $p);

                    if (
                        (isset($output['_stop_rules_processing']) && (int) $output['_stop_rules_processing'] === 1)
                        || ($output["_rule_process"] && $this->stop_on_first_match)
                    ) {
                        unset($output["_stop_rules_processing"], $output["_rule_process"]);
                        $output["_ruleid"] = $rule->fields["id"];
                        return Toolbox::addslashes_deep($output);
                    }
                }

                if ($this->use_output_rule_process_as_next_input) {
                    $output = $this->prepareInputDataForProcessWithPlugins($output, $params);
                    $input  = $output;
                }
            }
        }

        return Toolbox::addslashes_deep($output);
    }


    /**
     * Show form displaying results for rule collection preview
     *
     * @param $target          where to go
     * @param $values    array of data
     * @param $condition       condition to limit rules (default 0)
     **/
    public function showRulesEnginePreviewCriteriasForm($target, array $values, $condition = 0)
    {
        $input = $this->prepareInputDataForTestProcess($condition);

        if (count($input)) {
            $rule      = $this->getRuleClass();
            $criterias = $rule->getAllCriteria();
            echo "<form name='testrule_form' id='testrulesengine_form' method='post' action='$target'>";
            echo "\n<div class='center'>";
            echo "<table class='tab_cadre_fixe'>";
            echo "<tr><th colspan='2'>" . _n('Criterion', 'Criteria', Session::getPluralNumber()) . "</th></tr>\n";

           //Brower all criterias
            foreach ($input as $criteria) {
                echo "<tr class='tab_bg_1'>";

                if (isset($criterias[$criteria])) {
                    $criteria_constants = $criterias[$criteria];
                    echo "<td>" . $criteria_constants["name"] . "</td>";
                } else {
                    echo "<td>" . $criteria . "</td>";
                }

                echo "<td>";
                $rule->displayCriteriaSelectPattern(
                    $criteria,
                    $criteria,
                    Rule::PATTERN_IS,
                    isset($values[$criteria]) ? $values[$criteria] : ''
                );
                echo "</td></tr>\n";
            }

           // Add all used criteria on rule as `Rule::showSpecificCriteriasForPreview()`
           // adapt its output depending on used criteria
            $rule->criterias = [];
            foreach ($input as $criteria) {
                $rule->criterias[] = (object)[
                    'fields' => ['criteria' => $criteria],
                ];
            }
            $rule->showSpecificCriteriasForPreview($_POST);

            echo "<tr><td class='tab_bg_2 center' colspan='2'>";
            echo "<input type='submit' name='test_all_rules' value='" . _sx('button', 'Test') . "'
                class='btn btn-primary'>";
            echo "<input type='hidden' name='sub_type' value='" . $this->getRuleClassName() . "'>";
            echo "<input type='hidden' name='condition' value='$condition'>";
            echo "</td></tr>\n";
            echo "</table></div>";
            Html::closeForm();
        } else {
            echo '<br><div class="center b">' . __('No element to be tested') . '</div>';
        }

        return $input;
    }


    /**
     * Test all the rules collection
     *
     * @param input      array the input data used to check criterias
     * @param output     array the initial ouput array used to be manipulate by actions
     * @param params     array parameters for all internal functions
     * @param $condition       condition to limit rules (DEFAULT 0)
     *
     * @return the output array updated by actions
     **/
    public function testAllRules($input = [], $output = [], $params = [], $condition = 0)
    {

       // Get Collection data
        $this->getCollectionDatas(1, 1, $condition);
        $input = $this->prepareInputDataForProcess($input, $params);

        $output["_no_rule_matches"] = true;

        if (count($this->RuleList->list)) {
            foreach ($this->RuleList->list as $rule) {
                //If the rule is active, process it
                if ($rule->fields["is_active"]) {
                    $output["_rule_process"]                     = false;
                    $output["result"][$rule->fields["id"]]["id"] = $rule->fields["id"];
                    $rule->process($input, $output, $params);

                    if ((isset($output['_stop_rules_processing']) && (int) $output['_stop_rules_processing'] === 1) || ($output["_rule_process"] && $this->stop_on_first_match)) {
                        unset($output["_stop_rules_processing"], $output["_rule_process"]);
                        $output["result"][$rule->fields["id"]]["result"] = 1;
                        $output["_ruleid"]                               = $rule->fields["id"];
                        return $output;
                    } else if ($output["_rule_process"]) {
                        $output["result"][$rule->fields["id"]]["result"] = 1;
                    } else {
                        $output["result"][$rule->fields["id"]]["result"] = 0;
                    }
                } else {
                   //Rule is inactive
                    $output["result"][$rule->fields["id"]]["result"] = 2;
                }

                if ($this->use_output_rule_process_as_next_input) {
                    $input = $output;
                }
            }
        }

        return $output;
    }


    /**
     * Prepare input datas for the rules collection
     *
     * @param $input  the input data used to check criterias
     * @param $params parameters
     *
     * @return the updated input datas
     **/
    public function prepareInputDataForProcess($input, $params)
    {
        return $input;
    }


    /**
     * Prepare input datas for the rules collection, also using plugins values
     *
     * @since 0.84
     *
     * @param $input  the input data used to check criterias
     * @param $params parameters
     *
     * @return the updated input datas
     **/
    public function prepareInputDataForProcessWithPlugins($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->getRuleClassName(), $val)) {
                    $results = Plugin::doOneHook(
                        $plugin,
                        'ruleCollectionPrepareInputDataForProcess',
                        ['rule_itemtype' => $this->getRuleClassName(),
                            'values'        => ['input' => $input,
                                'params' => $params
                            ]
                        ]
                    );
                    if (is_array($results)) {
                        foreach ($results as $id => $result) {
                            $input[$id] = $result;
                        }
                    }
                }
            }
        }
        return $input;
    }


    /**
     * Prepare input datas for the rules collection
     *
     * @param $condition condition to limit rules (DEFAULT 0)
     *
     * @return the updated input datas
     **/
    public function prepareInputDataForTestProcess($condition = 0)
    {
        global $DB;

        $limit = [];
        if ($condition > 0) {
            $limit = ['glpi_rules.condition' => ['&', (int)$condition]];
        }
        $input = [];

        $iterator = $DB->request([
            'SELECT'          => 'glpi_rulecriterias.criteria',
            'DISTINCT'        => true,
            'FROM'            => 'glpi_rulecriterias',
            'INNER JOIN'      => [
                'glpi_rules'   => [
                    'ON' => [
                        'glpi_rulecriterias' => 'rules_id',
                        'glpi_rules'         => 'id'
                    ]
                ]
            ],
            'WHERE'           => [
                'glpi_rules.is_active'  => 1,
                'glpi_rules.sub_type'   => $this->getRuleClassName()
            ] + $limit
        ]);

        foreach ($iterator as $data) {
            $input[] = $data["criteria"];
        }
        return $input;
    }


    /**
     * Show form displaying results for rule engine preview
     *
     * @param $target          where to go
     * @param $input     array of data
     * @param $condition       condition to limit rules (DEFAULT 0)
     **/
    public function showRulesEnginePreviewResultsForm($target, array $input, $condition = 0)
    {

        $output = [];

        if ($this->use_output_rule_process_as_next_input) {
            $output = $input;
        }

        $output = $this->testAllRules($input, $output, $input, $condition);

        $rule   = $this->getRuleClass();

        echo "<div class='center'>";

        if (isset($output["result"])) {
            echo "<table class='tab_cadrehov'>";
            echo "<tr><th colspan='2'>" . __('Result details') . "</th></tr>\n";

            foreach ($output["result"] as $ID => $rule_result) {
                echo "<tr class='tab_bg_1'>";
                $rule->getFromDB($ID);
                echo "<td>" . $rule->fields["name"] . "</td>";
                echo "<td class='b'>";

                switch ($rule_result["result"]) {
                    case 0:
                    case 1:
                        echo Dropdown::getYesNo($rule_result["result"]);
                        break;

                    case 2:
                        echo __('Inactive');
                        break;
                }

                echo "</td></tr>\n";
            }

            echo "</table>";
        }

        $output        = $this->cleanTestOutputCriterias($output);
        unset($output["result"]);
        $global_result = (count($output) ? 1 : 0);

        echo "<br><table class='tab_cadrehov'>";
        $this->showTestResults($rule, $output, $global_result);
        echo "</table></div>";
    }


    /**
     * Unset criterias from the rule's ouput results (begins by _)
     *
     * @param $output    array clean output array to clean
     *
     * @return cleaned array
     **/
    public function cleanTestOutputCriterias(array $output)
    {

        $rule   = $this->getRuleClass();
        $actions = $rule->getAllActions();

       //If output array contains keys begining with _ : drop it
        foreach ($output as $criteria => $value) {
            if ($criteria[0] == '_' && !isset($actions[$criteria])) {
                unset($output[$criteria]);
            }
        }
        return $output;
    }


    /**
     * Show test results for a rule
     *
     * @param $rule                     rule object
     * @param $output          array    output data array
     * @param $global_result   boolean  global result
     *
     * @return void
     **/
    public function showTestResults($rule, array $output, $global_result)
    {

        $actions = $rule->getAllActions();
        echo "<table class='tab_cadrehov'>";
        echo "<tr><th colspan='2'>" . __('Rule results') . "</th></tr>\n";
        echo "<tr class='tab_bg_1'>";
        echo "<td class='center'>" . _n('Validation', 'Validations', 1) . "</td>";
        echo "<td><span class='b'>" . Dropdown::getYesNo($global_result) . "</span></td>";

        $output = $this->preProcessPreviewResults($output);

        foreach ($output as $criteria => $value) {
            if (isset($actions[$criteria])) {
                echo "<tr class='tab_bg_2'>";
                echo "<td>" . $actions[$criteria]["name"] . "</td>";
                $action_type = (isset($actions[$criteria]['action_type']) ? $actions[$criteria]['action_type'] : '');
                echo "<td>" . $rule->getActionValue($criteria, $action_type, $value);
                echo "</td></tr>\n";
            }
        }
        echo "</tr></table>\n";
    }


    /**
     * @param $output
     **/
    public function preProcessPreviewResults($output)
    {
        global $PLUGIN_HOOKS;

        if (isset($PLUGIN_HOOKS['use_rules'])) {
            $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,
                        "preProcessRuleCollectionPreviewResults",
                        ['output' => $output,
                            'params' => $params
                        ]
                    );
                    if (is_array($results)) {
                        foreach ($results as $id => $result) {
                            $output[$id] = $result;
                        }
                    }
                }
            }
        }
        return $this->cleanTestOutputCriterias($output);
    }


    /**
     * Print a title if needed which will be displayed above list of rules
     *
     * @return void
     **/
    public function title()
    {
    }


    /**
     * Get rulecollection classname by giving his itemtype
     *
     * @param $itemtype                 itemtype
     * @param $check_dictionnary_type   check if the itemtype is a dictionnary or not
     *                                  (false by default)
     *
     * @return RuleCollection|null
     */
    public static function getClassByType($itemtype, $check_dictionnary_type = false)
    {
        global $CFG_GLPI;

        if ($plug = isPluginItemType($itemtype)) {
            $typeclass = 'Plugin' . $plug['plugin'] . $plug['class'] . 'Collection';
        } else {
            if (in_array($itemtype, $CFG_GLPI["dictionnary_types"])) {
                $typeclass = 'RuleDictionnary' . $itemtype . "Collection";
            } else {
                $typeclass = $itemtype . "Collection";
            }
        }

        if (
            ($check_dictionnary_type && in_array($itemtype, $CFG_GLPI["dictionnary_types"]))
            || !$check_dictionnary_type
        ) {
            if ($item = getItemForItemtype($typeclass)) {
                return $item;
            }
        }
        return null;
    }


    public function showInheritedTab()
    {
        return false;
    }


    public function showChildrensTab()
    {
        return false;
    }


    /**
     * Get all the fields needed to perform the rule
     **/
    public function getFieldsToLookFor()
    {
        global $DB;

        $params = [];

        $iterator = $DB->request([
            'SELECT'          => 'glpi_rulecriterias.criteria',
            'DISTINCT'        => true,
            'FROM'            => 'glpi_rulecriterias',
            'INNER JOIN'      => [
                'glpi_rules'   => [
                    'ON' => [
                        'glpi_rulecriterias' => 'rules_id',
                        'glpi_rules'         => 'id'
                    ]
                ]
            ],
            'WHERE'           => [
                'glpi_rules.is_active'  => 1,
                'glpi_rules.sub_type'   => $this->getRuleClassName()
            ]
        ]);

        foreach ($iterator as $data) {
             $params[] = Toolbox::strtolower($data["criteria"]);
        }
        return $params;
    }


    /**
     * For tabs management : force isNewItem
     *
     * @since 0.83
     **/
    public function isNewItem()
    {
        return false;
    }


    /**
     * @see CommonGLPI::defineTabs()
     **/
    public function defineTabs($options = [])
    {

        $ong               = [];
        $this->addStandardTab(__CLASS__, $ong, $options);
        $ong['no_all_tab'] = true;
        return $ong;
    }

    /**
     * Get label for main tab
     *
     * @return string
     */
    public function getMainTabLabel()
    {
        return _n('Rule', 'Rules', Session::getPluralNumber());
    }

    /**
     * @see CommonGLPI::getTabNameForItem()
     **/
    public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0)
    {

        if ($item instanceof RuleCollection) {
            $ong = [];
            if ($item->showInheritedTab()) {
                //TRANS: %s is the entity name
                $ong[1] = sprintf(
                    __('Rules applied: %s'),
                    Dropdown::getDropdownName(
                        'glpi_entities',
                        $_SESSION['glpiactive_entity']
                    )
                );
            }
            $title = $item->getMainTabLabel();
            if ($item->isRuleRecursive()) {
               //TRANS: %s is the entity name
                $title = sprintf(
                    __('Local rules: %s'),
                    Dropdown::getDropdownName(
                        'glpi_entities',
                        $_SESSION['glpiactive_entity']
                    )
                );
            }
            $ong[2] = $title;
            if ($item->showChildrensTab()) {
                $ong[3] = __('Rules applicable in the sub-entities');
            }
            return $ong;
        }
        return '';
    }


    public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0)
    {

        if ($item instanceof RuleCollection) {
            $options = $_GET;
            switch ($tabnum) {
                case 1:
                    $options['inherited'] = 1;
                    break;

                case 2:
                    $options['inherited'] = 0;
                    break;

                case 3:
                    $options['inherited'] = 0;
                    $options['childrens'] = 1;
                    break;
            }
            if ($item->isRuleEntityAssigned()) {
                $item->setEntity($_SESSION['glpiactive_entity']);
            }
            $item->title();
            $item->showEngineSummary();
            $item->showListRules(Toolbox::cleanTarget($_GET['_target']), $options);
            return true;
        }
        return false;
    }


    /**
     * Get list of Rules
     *
     * @return array
     */
    public static function getRules(): array
    {
        global $CFG_GLPI;

        $rules = [];
        foreach ($CFG_GLPI["rulecollections_types"] as $rulecollectionclass) {
            $rulecollection = new $rulecollectionclass();
            if ($rulecollection->canList()) {
                if ($plug = isPluginItemType($rulecollectionclass)) {
                    $title = sprintf(
                        __('%1$s - %2$s'),
                        Plugin::getInfo($plug['plugin'], 'name'),
                        $rulecollection->getTitle()
                    );
                } else {
                    $title = $rulecollection->getTitle();
                }
                $ruleClassName = $rulecollection->getRuleClassName();

                $rules[] = [
                    'label' => $title,
                    'link'  => $ruleClassName::getSearchURL(),
                    'icon'  => $ruleClassName::getIcon(),
                ];
            }
        }

        if (
            Session::haveRight("transfer", READ)
            && Session::isMultiEntitiesMode()
        ) {
            $rules[] = [
                'label' => __('Transfer'),
                'link'  => Transfer::getSearchURL(),
                'icon'  => Transfer::getIcon(),
            ];
        }

        if (Session::haveRight("config", READ)) {
            $rules[] = [
                'label' => _n('Blacklist', 'Blacklists', Session::getPluralNumber()),
                'link'  => Blacklist::getSearchURL(),
                'icon'  => Blacklist::getIcon(),
            ];
        }

        return $rules;
    }


    /**
     * Get list of dictionnaries
     *
     * @return array
     */
    public static function getDictionnaries(): array
    {
        $dictionnaries = [];

        $entries = [];

        if (Session::haveRight("rule_dictionnary_software", READ)) {
            $entries[] = [
                'label'  => Software::getTypeName(Session::getPluralNumber()),
                'link'   => 'ruledictionnarysoftware.php',
                'icon'   => Software::getIcon(),
            ];
        }

        if (Session::haveRight("rule_dictionnary_dropdown", READ)) {
            $entries[] = [
                'label'  => Manufacturer::getTypeName(Session::getPluralNumber()),
                'link'   => 'ruledictionnarymanufacturer.php',
                'icon'   => Manufacturer::getIcon(),
            ];
        }

        if (Session::haveRight("rule_dictionnary_printer", READ)) {
            $entries[] = [
                'label'  => Printer::getTypeName(Session::getPluralNumber()),
                'link'   => 'ruledictionnaryprinter.php',
                'icon'   => Printer::getIcon(),
            ];
        }

        if (count($entries)) {
            $dictionnaries[] = [
                'type'      => __('Global dictionary'),
                'entries'   => $entries
            ];
        }

        if (Session::haveRight("rule_dictionnary_dropdown", READ)) {
            $dictionnaries[] = [
                'type'      => _n('Model', 'Models', Session::getPluralNumber()),
                'entries'   => [
                    [
                        'label'  => ComputerModel::getTypeName(Session::getPluralNumber()),
                        'link'   => 'ruledictionnarycomputermodel.php',
                        'icon'   => ComputerModel::getIcon(),
                    ], [
                        'label'  => MonitorModel::getTypeName(Session::getPluralNumber()),
                        'link'   => 'ruledictionnarymonitormodel.php',
                        'icon'   => MonitorModel::getIcon(),
                    ], [
                        'label'  => PrinterModel::getTypeName(Session::getPluralNumber()),
                        'link'   => 'ruledictionnaryprintermodel.php',
                        'icon'   => PrinterModel::getIcon(),
                    ], [
                        'label'  => CommonDeviceModel::getTypeName(Session::getPluralNumber()),
                        'link'   => 'ruledictionnaryperipheralmodel.php',
                        'icon'   => CommonDeviceModel::getIcon(),
                    ], [
                        'label'  => NetworkEquipmentModel::getTypeName(Session::getPluralNumber()),
                        'link'   => 'ruledictionnarynetworkequipmentmodel.php',
                        'icon'   => NetworkEquipmentModel::getIcon(),
                    ], [
                        'label'  => PhoneModel::getTypeName(Session::getPluralNumber()),
                        'link'   => 'ruledictionnaryphonemodel.php',
                        'icon'   => PhoneModel::getIcon(),
                    ]
                ]
            ];
        }

        if (Session::haveRight("rule_dictionnary_dropdown", READ)) {
            $dictionnaries[] = [
                'type'      => _n('Type', 'Types', Session::getPluralNumber()),
                'entries'   => [
                    [
                        'label'  => ComputerType::getTypeName(Session::getPluralNumber()),
                        'link'   => 'ruledictionnarycomputertype.php',
                        'icon'   => ComputerType::getIcon(),
                    ], [
                        'label'  => MonitorType::getTypeName(Session::getPluralNumber()),
                        'link'   => 'ruledictionnarymonitortype.php',
                        'icon'   => MonitorType::getIcon(),
                    ], [
                        'label'  => PrinterType::getTypeName(Session::getPluralNumber()),
                        'link'   => 'ruledictionnaryprintertype.php',
                        'icon'   => PrinterType::getIcon(),
                    ], [
                        'label'  => CommonDeviceType::getTypeName(Session::getPluralNumber()),
                        'link'   => 'ruledictionnaryperipheraltype.php',
                        'icon'   => CommonDeviceType::getIcon(),
                    ], [
                        'label'  => NetworkEquipmentType::getTypeName(Session::getPluralNumber()),
                        'link'   => 'ruledictionnarynetworkequipmenttype.php',
                        'icon'   => NetworkEquipmentType::getIcon(),
                    ], [
                        'label'  => PhoneType::getTypeName(Session::getPluralNumber()),
                        'link'   => 'ruledictionnaryphonetype.php',
                        'icon'   => PhoneType::getIcon(),
                    ]
                ]
            ];
        }

        if (Session::haveRight("rule_dictionnary_dropdown", READ)) {
            $dictionnaries[] = [
                'type'      => OperatingSystem::getTypeName(Session::getPluralNumber()),
                'entries'   => [
                    [
                        'label'  => OperatingSystem::getTypeName(Session::getPluralNumber()),
                        'link'   => 'ruledictionnaryoperatingsystem.php',
                        'icon'   => OperatingSystem::getIcon(),
                    ], [
                        'label'  => OperatingSystemServicePack::getTypeName(Session::getPluralNumber()),
                        'link'   => 'ruledictionnaryoperatingsystemservicepack.php',
                        'icon'   => OperatingSystemServicePack::getIcon(),
                    ], [
                        'label'  => OperatingSystemVersion::getTypeName(Session::getPluralNumber()),
                        'link'   => 'ruledictionnaryoperatingsystemversion.php',
                        'icon'   => OperatingSystemVersion::getIcon(),
                    ], [
                        'label'  => OperatingSystemArchitecture::getTypeName(Session::getPluralNumber()),
                        'link'   => 'ruledictionnaryoperatingsystemarchitecture.php',
                        'icon'   => OperatingSystemArchitecture::getIcon(),
                    ], [
                        'label'  => OperatingSystemEdition::getTypeName(Session::getPluralNumber()),
                        'link'   => 'ruledictionnaryoperatingsystemedition.php',
                        'icon'   => OperatingSystemEdition::getIcon(),
                    ]
                ]
            ];
        }

        return $dictionnaries;
    }
}
			
			


Thanks For 0xGh05T - DSRF14 - Mr.Dan07 - Leri01 - FxshX7 - AlkaExploiter - xLoveSyndrome'z - Acep Gans'z

JMDS TRACK – Just Another Diagnostics Lab Site

Home

JMDS TRACK Cameroon

Boost the productivity of your mobile ressources


Make An Appointment


Fleet management

  1. Reduce the operting cost and the unavailability of your vehicles
  2. reduce the fuel consumption of your fleet
  3. Improve the driving dehavior and safety of your drivers
  4. optimize the utilization rate of your equipment 
  5. protect your vehicle against theft
  6. Improve the quality of your customer service


Find out more

Assets management

  1. Track the roaming of your equipment
  2. Optimise the management of your assets on site and during transport
  3. Secure the transport of your goods
  4. Make your team responsible for preventing the loss of tools, equipment
  5. Take a real-time inventory of your equipment on site
  6. Easily find your mobile objects or equipment



Find out more



Find out more

Antitheft solutions

  1. Secure your vehicles and machinery and increase your chances of recovering them in the event of theft
  2. Protect your assets and reduce the costs associated with their loss
  3. Combine immobiliser and driver identification and limit the risk of theft
  4. Identify fuel theft and reduce costs
  5. Protect your goods and take no more risks
  6. Be alerted to abnormal events

Our Location

 Douala BP cité 

     and

Yaoundé Total Essos


Make An Appointment


Get Directions

682230363/ 677481892

What makes us different from others

  • young and dynamic team
  • call center 24/24 7/7
  • roaming throughout Africa
  • team of developers who can develop customer-specific solutions
  • diversity of services
  • reactive and prompt after-sales service when soliciting a customer or a malfunction
  • Free Maintenance and installation in the cities of Douala and Yaounde

https://youtu.be/xI1cz_Jh2x8

15+
years of experience in GPS system development, production and deployment.

15 Collaborators

More than 15 employees dedicated to the research and development of new applications and to customer care

5 000 Vehicles and mobile assets

5 000 vehicles and mobile assets under management, in Africa

Our Partners










Latest Case Studies

Our current projects 

5/5
Bon SAV , SATISFAIT DU TRAITEMENT DES REQUETES

M DIPITA CHRISTIAN
Logistic Safety Manager Road Safety Manager
5/5
La réactivité de JMDS est excellente
Nous restons satisfait dans l’ensemble des prestations relatives a la couverture de notre parc automobile

Hervé Frédéric NDENGUE
Chef Service Adjoint de la Sécurité Générale (CNPS)
5/5
L’APPLICATION EMIXIS est convivial A L’utilisation
BEIG-3 SARL
DIRECTOR GENERAL
5/5
Nevertheless I am delighted with the service
MR. BISSE BENJAMIN
CUSTOMER

Subsribe To Our Newsletter

Stay in touch with us to get latest news and special offers.



Address JMDS TRACK

Douala bp cité



and

YAOUNDE Total Essos

Call Us

+237682230363



Email Us


info@jmdstrack.cm