. * --------------------------------------------------------------------- */ if (!defined('GLPI_ROOT')) { die("Sorry. You can't access this file directly"); } class RuleDictionnaryPrinterCollection extends RuleCollection { // From RuleCollection public $stop_on_first_match = true; public $can_replay_rules = true; public $menu_type = 'dictionnary'; public $menu_option = 'printer'; static $rightname = 'rule_dictionnary_printer'; /** * @see RuleCollection::getTitle() **/ function getTitle() { return __('Dictionnary of printers'); } /** * @see RuleCollection::cleanTestOutputCriterias() **/ function cleanTestOutputCriterias(array $output) { //If output array contains keys begining with _ : drop it foreach ($output as $criteria => $value) { if (($criteria[0] == '_') && ($criteria != '_ignore_import')) { unset ($output[$criteria]); } } return $output; } /** * @see RuleCollection::replayRulesOnExistingDB() **/ function replayRulesOnExistingDB($offset = 0, $maxtime = 0, $items = [], $params = []) { global $DB; if (isCommandLine()) { printf(__('Replay rules on existing database started on %s')."\n", date("r")); } $nb = 0; $i = $offset; //Select all the differents software $criteria = [ 'SELECT' => [ 'glpi_printers.name', 'glpi_manufacturers.name AS manufacturer', 'glpi_printers.manufacturers_id AS manufacturers_id', 'glpi_printers.comment AS comment' ], 'DISTINCT' => true, 'FROM' => 'glpi_printers', 'LEFT JOIN' => [ 'glpi_manufacturers' => [ 'ON' => [ 'glpi_manufacturers' => 'id', 'glpi_printers' => 'manufacturers_id' ] ] ], 'WHERE' => [ // Do not replay on trashbin and templates 'glpi_printers.is_deleted' => 0, 'glpi_printers.is_template' => 0 ] ]; if ($offset) { $criteria['START'] = (int)$offset; $criteria['LIMIT'] = 999999999; } $iterator = $DB->request($criteria); $nb = count($iterator) + $offset; $step = (($nb > 1000) ? 50 : (($nb > 20) ? floor(count($iterator) / 20) : 1)); while ($input = $iterator->next()) { if (!($i % $step)) { if (isCommandLine()) { //TRANS: %1$s is a date, %2$s is a row, %3$s is total row, %4$s is memory printf(__('%1$s - replay rules on existing database: %2$s/%3$s (%4$s Mio)')."\n", date("H:i:s"), $i, $nb, round(memory_get_usage() / (1024 * 1024), 2)); } else { Html::changeProgressBarPosition($i, $nb, "$i / $nb"); } } //Replay printer dictionnary rules $res_rule = $this->processAllRules($input, [], []); foreach (['manufacturer', 'is_global', 'name'] as $attr) { if (isset($res_rule[$attr]) && ($res_rule[$attr] == '')) { unset($res_rule[$attr]); } } //If the software's name or version has changed if (self::somethingHasChanged($res_rule, $input)) { $IDs = []; //Find all the printers in the database with the same name and manufacturer $print_iterator = $DB->request([ 'SELECT' => 'id', 'FROM' => 'glpi_printers', 'WHERE' => [ 'name' => $input['name'], 'manufacturers_id' => $input['manufacturers_id'] ] ]); if (count($print_iterator)) { //Store all the printer's IDs in an array while ($result = $print_iterator->next()) { $IDs[] = $result["id"]; } //Replay dictionnary on all the printers $this->replayDictionnaryOnPrintersByID($IDs, $res_rule); } } $i++; if ($maxtime) { $crt = explode(" ", microtime()); if ($crt[0] + $crt[1] > $maxtime) { break; } } } if (isCommandLine()) { printf(__('Replay rules on existing database: %1$s/%2$s')."\n", $i, $nb); } else { Html::changeProgressBarPosition($i, $nb, "$i / $nb"); } if (isCommandLine()) { printf(__('Replay rules on existing database ended on %s')."\n", date("r")); } return (($i == $nb) ? -1 : $i); } /** * @param $res_rule array * @param $input array **/ static function somethingHasChanged(array $res_rule, array $input) { if ((isset($res_rule["name"]) && ($res_rule["name"] != $input["name"])) || (isset($res_rule["manufacturer"]) && ($res_rule["manufacturer"] != '')) || (isset($res_rule['is_global']) && ($res_rule['is_global'] != ''))) { return true; } return false; } /** * Replay dictionnary on several printers * * @param $IDs array of printers IDs to replay * @param $res_rule array of rule results * * @return Query result handler **/ function replayDictionnaryOnPrintersByID(array $IDs, $res_rule = []) { global $DB; $new_printers = []; $delete_ids = []; $iterator = $DB->request([ 'SELECT' => [ 'glpi_printers.id', 'glpi_printers.name', 'glpi_printers.entities_id AS entities_id', 'glpi_printers.is_global AS is_global', 'glpi_manufacturers.name AS manufacturer' ], 'FROM' => 'glpi_printers', 'LEFT JOIN' => [ 'glpi_manufacturers' => [ 'FKEY' => [ 'glpi_printers' => 'manufacturers_id', 'glpi_manufacturers' => 'id' ] ] ], 'WHERE' => [ 'glpi_printers.is_template' => 0, 'glpi_printers.id' => $IDs ] ]); while ($printer = $iterator->next()) { //For each printer $this->replayDictionnaryOnOnePrinter($new_printers, $res_rule, $printer, $delete_ids); } //Delete printer if needed $this->putOldPrintersInTrash($delete_ids); } /** * @param $IDS array */ function putOldPrintersInTrash($IDS = []) { $printer = new Printer(); foreach ($IDS as $id) { $printer->delete(['id' => $id]); } } /** * Replay dictionnary on one printer * * @param &$new_printers array containing new printers already computed * @param $res_rule array of rule results * @param $params array * @param &$printers_ids array containing replay printer need to be put in trashbin **/ function replayDictionnaryOnOnePrinter(array &$new_printers, array $res_rule, array $params, array &$printers_ids) { $p['id'] = 0; $p['name'] = ''; $p['manufacturer'] = ''; $p['is_global'] = ''; $p['entity'] = 0; foreach ($params as $key => $value) { $p[$key] = $value; } $input["name"] = $p['name']; $input["manufacturer"] = $p['manufacturer']; if (empty($res_rule)) { $res_rule = $this->processAllRules($input, [], []); } $printer = new Printer(); //Printer's name has changed if (isset($res_rule["name"]) && ($res_rule["name"] != $p['name'])) { $manufacturer = ""; if (isset($res_rule["manufacturer"])) { $manufacturer = addslashes(Dropdown::getDropdownName("glpi_manufacturers", $res_rule["manufacturer"])); } else { $manufacturer = addslashes($p['manufacturer']); } //New printer not already present in this entity if (!isset($new_printers[$p['entity']][$res_rule["name"]])) { // create new printer or restore it from trashbin $new_printer_id = $printer->addOrRestoreFromTrash($res_rule["name"], $manufacturer, $p['entity']); $new_printers[$p['entity']][$res_rule["name"]] = $new_printer_id; } else { $new_printer_id = $new_printers[$p['entity']][$res_rule["name"]]; } // Move direct connections $this->moveDirectConnections($p['id'], $new_printer_id); } else { $new_printer_id = $p['id']; $res_rule["id"] = $p['id']; if (isset($res_rule["manufacturer"])) { if ($res_rule["manufacturer"] != '') { $res_rule["manufacturers_id"] = $res_rule["manufacturer"]; } unset($res_rule["manufacturer"]); } $printer->update($res_rule); } // Add to printer to deleted list if ($new_printer_id != $p['id']) { $printers_ids[] = $p['id']; } } /** * Move direct connections from old printer to the new one * * @param $ID the old printer's id * @param $new_printers_id the new printer's id * * @return void **/ function moveDirectConnections($ID, $new_printers_id) { $computeritem = new Computer_Item(); //For each direct connection of this printer $connections = getAllDataFromTable( 'glpi_computers_items', [ 'itemtype' => 'Printer', 'items_id' => $ID ] ); foreach ($connections as $connection) { //Direct connection exists in the target printer ? if (!countElementsInTable("glpi_computers_items", ['itemtype' => 'Printer', 'items_id' => $new_printers_id, 'computers_id' => $connection["computers_id"]])) { //Direct connection doesn't exists in the target printer : move it $computeritem->update(['id' => $connection['id'], 'items_id' => $new_printers_id]); } else { //Direct connection already exists in the target printer : delete it $computeritem->delete($connection); } } } }