From 70941a6c42168f23fade7d550a6c0a5a5ae530e5 Mon Sep 17 00:00:00 2001 From: Rom1-B <8530352+Rom1-B@users.noreply.github.com> Date: Fri, 28 Aug 2026 08:08:17 +0200 Subject: [PATCH 1/3] Fix(CI): rector --- ajax/dropdownChooseField.php | 2 +- ajax/dropdownMandatory.php | 2 +- ajax/dropdownSelectModel.php | 2 +- ajax/injection.php | 2 +- ajax/results.php | 2 +- front/clientinjection.form.php | 1 + front/info.form.php | 2 + front/mapping.form.php | 1 + front/model.form.php | 5 +- hook.php | 22 +- inc/backend.class.php | 10 +- inc/backendcsv.class.php | 26 +- inc/categoryinjection.class.php | 2 +- inc/clientinjection.class.php | 17 +- inc/commoninjectionlib.class.php | 227 +++++++++++------- inc/computer_iteminjection.class.php | 37 +-- inc/contact_supplierinjection.class.php | 11 +- inc/contract_iteminjection.class.php | 28 +-- inc/contract_supplierinjection.class.php | 15 +- inc/data.class.php | 4 +- inc/devicecaseinjection.class.php | 1 + inc/devicecontrolinjection.class.php | 1 + inc/devicedriveinjection.class.php | 1 + inc/deviceharddriveinjection.class.php | 1 + inc/devicememoryinjection.class.php | 1 + inc/devicemotherboardinjection.class.php | 1 + inc/devicenetworkcardinjection.class.php | 1 + inc/deviceprocessorinjection.class.php | 1 + inc/dropdown.class.php | 71 +----- inc/engine.class.php | 20 +- inc/entityinjection.class.php | 16 +- inc/info.class.php | 45 ++-- inc/infocollection.class.php | 9 +- inc/infocominjection.class.php | 2 +- inc/injectiontype.class.php | 28 ++- inc/interfacetypeinjection.class.php | 1 + inc/item_operatingsysteminjection.class.php | 6 +- inc/item_softwarelicenseinjection.class.php | 33 +-- inc/item_softwareversioninjection.class.php | 34 +-- inc/mapping.class.php | 3 + inc/mappingcollection.class.php | 12 +- inc/menu.class.php | 2 +- inc/model.class.php | 129 +++++----- inc/modelcsv.class.php | 3 + inc/monitorinjection.class.php | 1 + inc/networknameinjection.class.php | 6 +- inc/networkportinjection.class.php | 18 +- inc/notepadinjection.class.php | 6 +- inc/peripheralinjection.class.php | 1 + inc/phoneinjection.class.php | 1 + inc/printerinjection.class.php | 3 + inc/profile.class.php | 11 +- inc/profileinjection.class.php | 35 +-- inc/session.class.php | 23 +- inc/softwareinjection.class.php | 5 + inc/softwarelicenseinjection.class.php | 4 +- inc/softwareversioninjection.class.php | 11 +- inc/userinjection.class.php | 3 +- rector.php | 87 ++----- setup.php | 5 +- tests/unit/CommonInjectionLibDateTimeTest.php | 1 + .../CommonInjectionLibFloatDetectionTest.php | 4 +- tests/unit/GroupInjectionTest.php | 5 + 63 files changed, 475 insertions(+), 595 deletions(-) diff --git a/ajax/dropdownChooseField.php b/ajax/dropdownChooseField.php index 765bd9c8..4ccde6e0 100644 --- a/ajax/dropdownChooseField.php +++ b/ajax/dropdownChooseField.php @@ -29,7 +29,7 @@ */ // Direct access to file -if (strpos($_SERVER['PHP_SELF'], "dropdownChooseField.php")) { +if (strpos((string) $_SERVER['PHP_SELF'], "dropdownChooseField.php")) { header("Content-Type: text/html; charset=UTF-8"); Html::header_nocache(); } diff --git a/ajax/dropdownMandatory.php b/ajax/dropdownMandatory.php index 6fd57756..1dc0e8f4 100644 --- a/ajax/dropdownMandatory.php +++ b/ajax/dropdownMandatory.php @@ -29,7 +29,7 @@ */ // Direct access to file -if (strpos($_SERVER['PHP_SELF'], "dropdownMandatory.php")) { +if (strpos((string) $_SERVER['PHP_SELF'], "dropdownMandatory.php")) { header("Content-Type: text/html; charset=UTF-8"); Html::header_nocache(); } diff --git a/ajax/dropdownSelectModel.php b/ajax/dropdownSelectModel.php index 5fe9b305..ca7844f4 100644 --- a/ajax/dropdownSelectModel.php +++ b/ajax/dropdownSelectModel.php @@ -29,7 +29,7 @@ */ // Direct access to file -if (strpos($_SERVER['PHP_SELF'], "dropdownSelectModel.php")) { +if (strpos((string) $_SERVER['PHP_SELF'], "dropdownSelectModel.php")) { header("Content-Type: text/html; charset=UTF-8"); Html::header_nocache(); } diff --git a/ajax/injection.php b/ajax/injection.php index 76581502..b8980c12 100644 --- a/ajax/injection.php +++ b/ajax/injection.php @@ -29,7 +29,7 @@ */ // Direct access to file -if (strpos($_SERVER['PHP_SELF'], "injection.php")) { +if (strpos((string) $_SERVER['PHP_SELF'], "injection.php")) { header("Content-Type: text/html; charset=UTF-8"); Html::header_nocache(); } diff --git a/ajax/results.php b/ajax/results.php index 1d64dfb7..6c76fde5 100644 --- a/ajax/results.php +++ b/ajax/results.php @@ -29,7 +29,7 @@ */ // Direct access to file -if (strpos($_SERVER['PHP_SELF'], "results.php")) { +if (strpos((string) $_SERVER['PHP_SELF'], "results.php")) { header("Content-Type: text/html; charset=UTF-8"); Html::header_nocache(); } diff --git a/front/clientinjection.form.php b/front/clientinjection.form.php index 303e3404..4610c796 100644 --- a/front/clientinjection.form.php +++ b/front/clientinjection.form.php @@ -98,6 +98,7 @@ if (isset($_GET['id'])) { // Allow link to a model PluginDatainjectionSession::setParam('models_id', $_GET['id']); } + $clientInjection = new PluginDatainjectionClientInjection(); $clientInjection->title(); $clientInjection->showForm(0); diff --git a/front/info.form.php b/front/info.form.php index 9c0f1f53..5f21cb55 100644 --- a/front/info.form.php +++ b/front/info.form.php @@ -44,7 +44,9 @@ $info->delete($input); } } + Html::back(); } + Session::setActiveTab('PluginDatainjectionModel', 'PluginDatainjectionModel$5'); Html::back(); diff --git a/front/mapping.form.php b/front/mapping.form.php index 5ce50cd5..8e99af94 100644 --- a/front/mapping.form.php +++ b/front/mapping.form.php @@ -80,6 +80,7 @@ ), ); } + unset($_SESSION['datainjection']['lines']); } } diff --git a/front/model.form.php b/front/model.form.php index 0c9d38b6..95f32e3c 100644 --- a/front/model.form.php +++ b/front/model.form.php @@ -48,7 +48,7 @@ //Set display to the advanced options tab Session::setActiveTab('PluginDatainjectionModel', 'PluginDatainjectionModel$3'); - Html::redirect(Toolbox::getItemTypeFormURL('PluginDatainjectionModel') . "?id=$newID"); + Html::redirect(Toolbox::getItemTypeFormURL('PluginDatainjectionModel') . ('?id=' . $newID)); } elseif (isset($_POST["delete"])) { /* delete */ $model->check($_POST['id'], DELETE); @@ -74,7 +74,7 @@ $model->switchReadyToUse(); Html::back(); } elseif (isset($_POST['upload'])) { - if (!empty($_FILES)) { + if ($_FILES !== []) { $model->check($_POST['id'], UPDATE); if ( @@ -95,6 +95,7 @@ ); } } + Html::back(); } elseif (isset($_GET['sample'])) { $model->check($_GET['sample'], READ); diff --git a/hook.php b/hook.php index 9232cc49..05a0a021 100644 --- a/hook.php +++ b/hook.php @@ -251,7 +251,7 @@ function plugin_datainjection_migration_2158_2159(Migration $migration) 'glpi_plugin_datainjection_models', 'entities_id', 'entities_id', - "int {$default_key_sign} NOT NULL default '0'", + sprintf("int %s NOT NULL default '0'", $default_key_sign), ); $migration->executeMigration(); @@ -404,7 +404,7 @@ function plugin_datainjection_update131_14() 'glpi_plugin_data_injection_models', 'user_id', 'FK_users', - "int {$default_key_sign} NOT NULL default '0'", + sprintf("int %s NOT NULL default '0'", $default_key_sign), ); $migration->changeField( 'glpi_plugin_data_injection_models', @@ -510,7 +510,7 @@ function plugin_datainjection_update170_20() 'glpi_plugin_datainjection_models', 'FK_entities', 'entities_id', - "int {$default_key_sign} NOT NULL default '0'", + sprintf("int %s NOT NULL default '0'", $default_key_sign), ); $migration->changeField( 'glpi_plugin_datainjection_models', @@ -522,7 +522,7 @@ function plugin_datainjection_update170_20() 'glpi_plugin_datainjection_models', 'FK_users', 'users_id', - "int {$default_key_sign} NOT NULL default '0'", + sprintf("int %s NOT NULL default '0'", $default_key_sign), ); $migration->changeField( 'glpi_plugin_datainjection_models', @@ -532,6 +532,7 @@ function plugin_datainjection_update170_20() ); $migration->migrationOneTable('glpi_plugin_datainjection_models'); + $query = "UPDATE `glpi_plugin_datainjection_models` SET `step` = '5'"; $DB->doQuery($query); @@ -551,7 +552,7 @@ function plugin_datainjection_update170_20() 'glpi_plugin_datainjection_modelcsvs', 'model_id', 'models_id', - "int {$default_key_sign} NOT NULL default '0'", + sprintf("int %s NOT NULL default '0'", $default_key_sign), ); $migration->changeField( 'glpi_plugin_datainjection_modelcsvs', @@ -585,7 +586,7 @@ function plugin_datainjection_update170_20() 'glpi_plugin_datainjection_mappings', 'model_id', 'models_id', - "int {$default_key_sign} NOT NULL default '0'", + sprintf("int %s NOT NULL default '0'", $default_key_sign), ); $migration->changeField( @@ -599,7 +600,7 @@ function plugin_datainjection_update170_20() 'glpi_plugin_datainjection_infos', 'model_id', 'models_id', - "int {$default_key_sign} NOT NULL default '0'", + sprintf("int %s NOT NULL default '0'", $default_key_sign), ); $migration->changeField( 'glpi_plugin_datainjection_infos', @@ -1854,6 +1855,7 @@ function plugin_datainjection_update170_20() ]; $foreignkeys = Plugin::doHookFunction("plugin_datainjection_migratefields", $foreignkeys); + $query = "SELECT `itemtype`, `value` FROM `glpi_plugin_datainjection_mappings` WHERE `itemtype` NOT IN ('none') @@ -1908,6 +1910,7 @@ function plugin_datainjection_update210_220() $DB->doQuery($query); } } + function plugin_datainjection_update220_230() { /** @var DBmysql $DB */ @@ -1942,7 +1945,7 @@ function plugin_datainjection_loadHook($hook_name, $params = []) ); } elseif (isset($PLUGIN_HOOKS['plugin_types'])) { //Browse all plugins - foreach ($PLUGIN_HOOKS['plugin_types'] as $type => $name) { + foreach ($PLUGIN_HOOKS['plugin_types'] as $name) { Plugin::doOneHook($name, 'datainjection_' . $hook_name); } } @@ -1988,6 +1991,7 @@ function plugin_datainjection_addDefaultWhere($itemtype) foreach ($models as $model) { $tab[] = $model['id']; } + return "`glpi_plugin_datainjection_models`.`id` IN ('" . implode("','", $tab) . "')"; } else { return "1 = 0"; //no model available -> force WHERE clause to get no result @@ -1996,4 +2000,6 @@ function plugin_datainjection_addDefaultWhere($itemtype) default: break; } + + return null; } diff --git a/inc/backend.class.php b/inc/backend.class.php index be68d99c..9e49c18f 100644 --- a/inc/backend.class.php +++ b/inc/backend.class.php @@ -37,13 +37,19 @@ abstract class PluginDatainjectionBackend { protected $file = ""; + protected $delimiter = ""; + protected $encoding; + protected $errmsg; + protected $numberOfLines = 0; public const ENCODING_ISO8859_1 = 0; + public const ENCODING_UFT8 = 1; + public const ENCODING_AUTO = 2; @@ -67,6 +73,7 @@ public static function getHeader($injectionData, $header_present) for ($i = 0; $i < $nb; $i++) { $header[] = $i; } + return $header; } @@ -83,7 +90,7 @@ public static function getInstance($type) ]; if (!isset($allowedBackends[$type])) { - throw new InvalidArgumentException("Unknown backend type: $type"); + throw new InvalidArgumentException('Unknown backend type: ' . $type); } return new $allowedBackends[$type](); @@ -118,6 +125,7 @@ public static function toUTF8($string) if (!self::is_utf8($string)) { return Toolbox::encodeInUtf8($string); } + return $string; } } diff --git a/inc/backendcsv.class.php b/inc/backendcsv.class.php index a2863be3..2c579b63 100644 --- a/inc/backendcsv.class.php +++ b/inc/backendcsv.class.php @@ -37,7 +37,8 @@ class PluginDatainjectionBackendcsv extends PluginDatainjectionBackend implements PluginDatainjectionBackendInterface { private $isHeaderPresent = true; - private $file_handler = null; + + private $file_handler; public function __construct() @@ -95,20 +96,14 @@ public static function parseLine($fic, $data, $encoding = 1) $num = count($data); for ($c = 0; $c < $num; $c++) { - $tmp = trim($data[$c]); - switch ($encoding) { - case PluginDatainjectionBackend::ENCODING_ISO8859_1: - $csv[0][] = $tmp === '' || $tmp === '0' ? Toolbox::encodeInUtf8($tmp) : $tmp; - break; - - case PluginDatainjectionBackend::ENCODING_UFT8: - $csv[0][] = $tmp; - break; - - default: - $csv[0][] = PluginDatainjectionBackend::toUTF8($tmp); - } + $tmp = trim((string) $data[$c]); + $csv[0][] = match ($encoding) { + PluginDatainjectionBackend::ENCODING_ISO8859_1 => $tmp === '' || $tmp === '0' ? Toolbox::encodeInUtf8($tmp) : $tmp, + PluginDatainjectionBackend::ENCODING_UFT8 => $tmp, + default => PluginDatainjectionBackend::toUTF8($tmp), + }; } + return $csv; } @@ -175,6 +170,7 @@ public function storeNumberOfLines() } } } + fclose($fic); if ($this->isHeaderPresent) { @@ -229,6 +225,7 @@ public function getNextLine() if ($data === false) { return false; } + $line = []; if ( (count($data) > 1) @@ -236,6 +233,7 @@ public function getNextLine() ) { $line = self::parseLine($this->file_handler, $data, $this->encoding); } + return $line; } diff --git a/inc/categoryinjection.class.php b/inc/categoryinjection.class.php index e5807ee4..192230b1 100644 --- a/inc/categoryinjection.class.php +++ b/inc/categoryinjection.class.php @@ -50,7 +50,7 @@ public function connectedTo() public function isNullable($field) { - return !in_array($field, ['illustration']); + return $field != 'illustration'; } /** diff --git a/inc/clientinjection.class.php b/inc/clientinjection.class.php index 3531b5da..661b8d47 100644 --- a/inc/clientinjection.class.php +++ b/inc/clientinjection.class.php @@ -47,7 +47,9 @@ class PluginDatainjectionClientInjection public static $rightname = "plugin_datainjection_use"; public const STEP_UPLOAD = 0; + public const STEP_PROCESS = 1; + public const STEP_RESULT = 2; /** @@ -153,6 +155,7 @@ public static function showInjectionForm(PluginDatainjectionModel $model, $entit $lines[] = $line; $line = $backend->getNextLine(); } + $backend->closeFile(); //Store lines in session for batch processing @@ -188,14 +191,15 @@ public static function processBatch(int $offset, int $batch_size): array { try { ini_set("max_execution_time", "0"); - } catch (InfoException $e) { - ErrorHandler::logCaughtException($e); + } catch (InfoException $infoException) { + ErrorHandler::logCaughtException($infoException); } Profile::getCurrent()->disable(); $model = PluginDatainjectionSession::unserialize($_SESSION['datainjection']['currentmodel']); $model->loadSpecificModel(); + $entities_id = $_SESSION['glpiactive_entity']; $lines_json = PluginDatainjectionSession::getParam('injection_lines'); $lines = json_decode($lines_json, true); @@ -226,6 +230,7 @@ public static function processBatch(int $offset, int $batch_size): array 'line' => $injectionline, ]; } + $results[] = $result; if ($result['status'] != PluginDatainjectionCommonInjectionLib::SUCCESS) { @@ -314,7 +319,7 @@ public static function showResultsForm(PluginDatainjectionModel $model) 'popup_url' => plugin_datainjection_geturl() . "front/popup.php?popup=log&models_id=" . $model->fields['id'], 'model_id' => $model->fields['id'], 'has_pdf' => $plugin->isActivated('pdf'), - 'has_errors' => !empty($error_lines), + 'has_errors' => !in_array($error_lines, ['', '0', []], true), ]; TemplateRenderer::getInstance()->display('@datainjection/clientinjection_result.html.twig', $data); @@ -325,6 +330,7 @@ private static function escapeCsvFormula(mixed $value): mixed if (is_string($value) && isset($value[0]) && in_array($value[0], ['=', '+', '-', '@'], true)) { return "'" . $value; } + return $value; } @@ -334,7 +340,7 @@ public static function exportErrorsInCSV() $error_lines = json_decode(PluginDatainjectionSession::getParam('error_lines'), true); self::stripslashes_array($error_lines); - if (!empty($error_lines)) { + if (!in_array($error_lines, ['', '0', []], true)) { $model = PluginDatainjectionSession::unserialize(PluginDatainjectionSession::getParam('currentmodel')); $file = PLUGIN_DATAINJECTION_UPLOAD_DIR . basename(PluginDatainjectionSession::getParam('file_name')); @@ -349,8 +355,9 @@ public static function exportErrorsInCSV() //Write lines foreach ($error_lines as $line) { - fputcsv($tmpfile, array_map([self::class, 'escapeCsvFormula'], $line), $model->getBackend()->getDelimiter()); + fputcsv($tmpfile, array_map(self::escapeCsvFormula(...), $line), $model->getBackend()->getDelimiter()); } + fclose($tmpfile); $name = "Error-" . basename(PluginDatainjectionSession::getParam('file_name')); diff --git a/inc/commoninjectionlib.class.php b/inc/commoninjectionlib.class.php index 0464274a..d0b75ea6 100644 --- a/inc/commoninjectionlib.class.php +++ b/inc/commoninjectionlib.class.php @@ -41,17 +41,11 @@ class PluginDatainjectionCommonInjectionLib //Injection results private $results = []; - //Values to inject - private $values = []; - //Fields mandatory for injection private $mandatory_fields = []; private $optional_infos = []; - //Injection class to use - private $injectionClass; - //Primary type to inject private $primary_type; @@ -71,51 +65,76 @@ class PluginDatainjectionCommonInjectionLib //Type of action to perform public const IMPORT_ADD = 0; + public const IMPORT_UPDATE = 1; + public const IMPORT_DELETE = 2; //Action return constants - public const SUCCESS = 10; //Injection OK - public const FAILED = 11; //Error during injection + public const SUCCESS = 10; + + //Injection OK + public const FAILED = 11; + + //Error during injection public const WARNING = 12; //Injection ok but partial //Field check return constants public const TYPE_MISMATCH = 22; + public const MANDATORY = 23; + public const ITEM_NOT_FOUND = 24; //Injection Message public const ERROR_CANNOT_IMPORT = 31; + public const ERROR_CANNOT_UPDATE = 32; + public const WARNING_NOTFOUND = 33; + public const ERROR_FIELDSIZE_EXCEEDED = 37; + public const ERROR_IMPORT_REFUSED = 39; //Dictionnary explicitly refuse import //Empty values public const EMPTY_VALUE = ''; + public const DROPDOWN_EMPTY_VALUE = 0; //Format constants - public const FLOAT_TYPE_COMMA = 0; //xxxx,xx - public const FLOAT_TYPE_DOT = 1; //xxxx.xx + public const FLOAT_TYPE_COMMA = 0; + + //xxxx,xx + public const FLOAT_TYPE_DOT = 1; + + //xxxx.xx public const FLOAT_TYPE_DOT_AND_COM = 2; //xx,xxx.xx //Date management constants public const DATE_TYPE_DDMMYYYY = "dd-mm-yyyy"; + public const DATE_TYPE_MMDDYYYY = "mm-dd-yyyy"; + public const DATE_TYPE_YYYYMMDD = "yyyy-mm-dd"; //Port unicity constants public const UNICITY_NETPORT_LOGICAL_NUMBER = 0; + public const UNICITY_NETPORT_NAME = 1; + public const UNICITY_NETPORT_MACADDRESS = 2; + public const UNICITY_NETPORT_LOGICAL_NUMBER_NAME = 3; + public const UNICITY_NETPORT_LOGICAL_NUMBER_MAC = 4; + public const UNICITY_NETPORT_LOGICAL_NUMBER_NAME_MAC = 5; //Field status must evolve when ticket #2216 will be resolved public const FIELD_INJECTABLE = 1; + public const FIELD_VIRTUAL = 2; @@ -164,7 +183,7 @@ public function setDefaultValues(): void * * @return void nothing **/ - public function __construct($injectionClass, $values = [], $injection_options = []) + public function __construct(private $injectionClass, private $values = [], $injection_options = []) { $this->setDefaultValues(); @@ -180,6 +199,7 @@ public function __construct($injectionClass, $values = [], $injection_options = $this->checks[$key] = $value; } } + if (isset($injection_options['rights'])) { foreach ($injection_options['rights'] as $key => $value) { $this->rights[$key] = $value; @@ -203,12 +223,7 @@ public function __construct($injectionClass, $values = [], $injection_options = ]; } - //Store values to inject - $this->values = $values; - - //Store injectClass & primary_type - $this->injectionClass = $injectionClass; - $this->primary_type = self::getItemtypeByInjectionClass($injectionClass); + $this->primary_type = self::getItemtypeByInjectionClass($this->injectionClass); //If entity is given stores it, then use root entity $this->entity = $injection_options['entities_id'] ?? 0; @@ -268,6 +283,7 @@ public function areTypeMandatoryFieldsOK($injectionClass) __('No mandatory field is defined for this model', 'datainjection'), ]; } + return $status_check; } @@ -303,10 +319,12 @@ public static function getItemtypeInstanceByInjection($injectionClassName) if (!is_a($injectionClassName, PluginDatainjectionInjectionInterface::class, true)) { throw new HttpException(500, 'Class ' . $injectionClassName . ' is not a valid class'); } + $injection = self::getItemtypeByInjectionClass(new $injectionClassName()); if (!is_a($injection, CommonDBTM::class, true)) { throw new HttpException(500, 'Class ' . $injection . ' is not a valid class'); } + return new $injection(); } @@ -323,6 +341,7 @@ public static function getItemtypeByInjection($injectionClassName) if (!is_a($injectionClassName, CommonDBTM::class, true)) { throw new HttpException(500, 'Class ' . $injectionClassName . ' is not a valid class'); } + return self::getItemtypeByInjectionClass(new $injectionClassName()); } @@ -361,6 +380,7 @@ public static function getInjectionClassInstance($itemtype) if (!is_a($injectionClass, PluginDatainjectionInjectionInterface::class, true)) { throw new HttpException(500, 'Class ' . $injectionClass . ' is not a valid class'); } + return new $injectionClass(); } @@ -432,6 +452,7 @@ public static function getBlacklistedOptions($itemtype) if (!is_numeric($raw_option['id'])) { continue; } + $blacklist[] = $raw_option['id']; } @@ -506,7 +527,7 @@ private function getFloatFormat() private function getItemInstance() { - $classname = get_class($this->injectionClass); + $classname = $this->injectionClass::class; return self::getItemtypeInstanceByInjection($classname); } @@ -586,8 +607,6 @@ private function getFieldValue( switch ($searchOption['displaytype']) { case 'tree': - $this->setValueForItemtype($itemtype, $linkfield, $value); - break; case 'decimal': case 'text': @@ -605,6 +624,7 @@ private function getFieldValue( $this->setValueForItemtype($itemtype, $linkfield . "2", $value); } } + break; case 'dropdown': @@ -613,6 +633,7 @@ private function getFieldValue( if (!is_a($tmptype, CommonDBTM::class, true)) { return; } + $item = new $tmptype(); if ($item instanceof CommonTreeDropdown) { // use findID instead of getID @@ -627,6 +648,7 @@ private function getFieldValue( if (strpos($input['completename'], '>')) { $crit = 'completename'; } + $entity = new Entity(); $result = $entity->getFromDBByCrit( [ @@ -637,6 +659,7 @@ private function getFieldValue( if ($result !== false) { $input['entities_id'] = $entity->fields['id']; } + $sons = getSonsOf('glpi_entities', $input['entities_id']); if ($result === false && !empty($sons)) { foreach ($sons as $son_id) { @@ -652,6 +675,7 @@ private function getFieldValue( } } } + $id = $input['entities_id']; } elseif ($item->canCreate() && $this->rights['add_dropdown']) { $id = $item->import($input); @@ -668,34 +692,38 @@ private function getFieldValue( $canadd, ); } else { - $id = self::findSingle($item, $searchOption, $this->entity, $value); + $id = $this->findSingle($item, $searchOption, $this->entity, $value); } + // Use EMPTY_VALUE for Mandatory field check $this->setValueForItemtype($itemtype, $linkfield, ($id > 0 ? $id : self::EMPTY_VALUE)); if ($value && $id <= 0) { $this->results['status'] = self::WARNING; $this->results[self::ACTION_CHECK]['status'] = self::WARNING; $this->results[self::ACTION_CHECK][] = [self::WARNING_NOTFOUND, - $searchOption['name'] . "='$value'", + $searchOption['name'] . sprintf("='%s'", $value), ]; } + break; case 'template': - $id = self::getTemplateIDByName($itemtype, $value); + $id = $this->getTemplateIDByName($itemtype, $value); if ($id) { //Template id is stored into the item's id : when adding the object //glpi will understand that it needs to take fields from the template $this->setValueForItemtype($itemtype, '_oldID', $id); } + break; case 'contact': if ($value === self::EMPTY_VALUE || $value == self::DROPDOWN_EMPTY_VALUE || $value === Dropdown::EMPTY_VALUE) { $id = self::DROPDOWN_EMPTY_VALUE; } else { - $id = self::findContact($value, $this->entity); + $id = $this->findContact($value, $this->entity); } + $this->setValueForItemtype($itemtype, $linkfield, $id); break; @@ -703,8 +731,9 @@ private function getFieldValue( if ($value === self::EMPTY_VALUE || $value == self::DROPDOWN_EMPTY_VALUE || $value === Dropdown::EMPTY_VALUE) { $id = self::DROPDOWN_EMPTY_VALUE; } else { - $id = self::findUser($value, $this->entity); + $id = $this->findUser($value, $this->entity); } + $this->setValueForItemtype($itemtype, $linkfield, $id); break; @@ -763,6 +792,7 @@ private function addExternalDropdownParameters($itemtype) $external[$addvalue] = ''; } } + return $external; } @@ -775,7 +805,7 @@ private function addExternalDropdownParameters($itemtype) * * @return int|string the user ID if found or '' **/ - private static function findUser($value, $entity) + private function findUser($value, $entity) { /** @var DBmysql $DB */ global $DB; @@ -786,9 +816,9 @@ private static function findUser($value, $entity) 'FROM' => 'glpi_users', 'WHERE' => [ 'OR' => [ - new QueryExpression("LOWER(`name`) = $safe_lower"), - new QueryExpression("CONCAT(LOWER(`realname`),' ',LOWER(`firstname`)) = $safe_lower"), - new QueryExpression("CONCAT(LOWER(`firstname`),' ',LOWER(`realname`)) = $safe_lower"), + new QueryExpression('LOWER(`name`) = ' . $safe_lower), + new QueryExpression("CONCAT(LOWER(`realname`),' ',LOWER(`firstname`)) = " . $safe_lower), + new QueryExpression("CONCAT(LOWER(`firstname`),' ',LOWER(`realname`)) = " . $safe_lower), ], ], ]); @@ -799,8 +829,10 @@ private static function findUser($value, $entity) if (in_array($entity, $entities)) { return $ID; } + return self::DROPDOWN_EMPTY_VALUE; } + return self::DROPDOWN_EMPTY_VALUE; } @@ -813,7 +845,7 @@ private static function findUser($value, $entity) * * @return int|string the user ID if found or '' */ - private static function findContact($value, $entity) + private function findContact($value, $entity) { /** @var DBmysql $DB */ global $DB; @@ -825,9 +857,9 @@ private static function findContact($value, $entity) 'WHERE' => [ 'entities_id' => $entity, 'OR' => [ - new QueryExpression("LOWER(`name`) = $safe_lower"), - new QueryExpression("CONCAT(LOWER(`name`),' ',LOWER(`firstname`)) = $safe_lower"), - new QueryExpression("CONCAT(LOWER(`firstname`),' ',LOWER(`name`)) = $safe_lower"), + new QueryExpression('LOWER(`name`) = ' . $safe_lower), + new QueryExpression("CONCAT(LOWER(`name`),' ',LOWER(`firstname`)) = " . $safe_lower), + new QueryExpression("CONCAT(LOWER(`firstname`),' ',LOWER(`name`)) = " . $safe_lower), ], ], ]); @@ -835,6 +867,7 @@ private static function findContact($value, $entity) if (count($result) > 0) { return $result->current()['id']; } + return self::DROPDOWN_EMPTY_VALUE; } @@ -849,7 +882,7 @@ private static function findContact($value, $entity) * * @return int|string the id of the item found **/ - private static function findSingle($item, $searchOption, $entity, $value) + private function findSingle($item, $searchOption, $entity, $value) { /** @var DBmysql $DB */ global $DB; @@ -880,6 +913,7 @@ private static function findSingle($item, $searchOption, $entity, $value) if (count($result) > 0) { return $result->current()['id']; } + return self::DROPDOWN_EMPTY_VALUE; } @@ -911,6 +945,7 @@ private function getValueByItemtypeAndName($itemtype, $field) if ($values) { return ($values[$field] ?? false); } + return false; } @@ -944,6 +979,7 @@ private function setValueForItemtype($itemtype, $field, $value, $fromdb = false) if ($itemtype === User::class && $field === "pdffont" && $fromdb) { return; } + $injectionClass = self::getInjectionClassInstance($itemtype); // TODO awfull hack, text ftom CSV set more than once, so check if "another" value if (isset($this->values[$itemtype][$field]) && $this->values[$itemtype][$field] != $value) { @@ -1004,13 +1040,14 @@ private function setValueForItemtype($itemtype, $field, $value, $fromdb = false) * * @return string|false name of the template or false is no template found **/ - private static function getTemplateIDByName($itemtype, $name) + private function getTemplateIDByName($itemtype, $name) { /** @var DBmysql $DB */ global $DB; if (!is_a($itemtype, CommonDBTM::class, true)) { throw new HttpException(500, 'Class ' . $itemtype . ' is not a valid class'); } + new $itemtype(); $result = $DB->request([ 'SELECT' => ['id'], @@ -1024,6 +1061,7 @@ private static function getTemplateIDByName($itemtype, $name) if (count($result) > 0) { return $result->current()['id']; } + return false; } @@ -1111,22 +1149,22 @@ private function reformatThirdPass() case "date": //If the value is a date, try to reformat it if it's not the good type //(dd-mm-yyyy instead of yyyy-mm-dd) - $date = self::reformatDate($value, $this->getDateFormat()); + $date = $this->reformatDate($value, $this->getDateFormat()); $this->setValueForItemtype($itemtype, $field, $date); break; case "datetime": //Normalize to "Y-m-d H:i:s", stripping ISO8601 microseconds/timezone if present - $datetime = self::reformatDateTime($value, $this->getDateFormat()); + $datetime = $this->reformatDateTime($value, $this->getDateFormat()); $this->setValueForItemtype($itemtype, $field, $datetime); break; case "mac": - $this->setValueForItemtype($itemtype, $field, self::reformatMacAddress($value)); + $this->setValueForItemtype($itemtype, $field, $this->reformatMacAddress($value)); break; case "float": - $float = self::reformatFloat($value, $this->getFloatFormat()); + $float = $this->reformatFloat($value, $this->getFloatFormat()); $this->setValueForItemtype($itemtype, $field, (string) $float); break; @@ -1165,7 +1203,7 @@ private function reformat() * * @return float|array modified as expected in GLPI **/ - private static function reformatFloat($value, $format) + private function reformatFloat($value, $format) { if ($value == self::EMPTY_VALUE) { @@ -1173,23 +1211,17 @@ private static function reformatFloat($value, $format) } //TODO : replace str_replace by a regex - switch ($format) { - case self::FLOAT_TYPE_COMMA: - $value = str_replace( - [" ", ","], - ["","."], - $value, - ); - break; - - case self::FLOAT_TYPE_DOT: - $value = str_replace(" ", "", $value); - break; + $value = match ($format) { + self::FLOAT_TYPE_COMMA => str_replace( + [" ", ","], + ["","."], + $value, + ), + self::FLOAT_TYPE_DOT => str_replace(" ", "", $value), + self::FLOAT_TYPE_DOT_AND_COM => str_replace(",", "", $value), + default => $value, + }; - case self::FLOAT_TYPE_DOT_AND_COM: - $value = str_replace(",", "", $value); - break; - } return $value; } @@ -1202,12 +1234,13 @@ private static function reformatFloat($value, $format) * * @return string the date reformated, if needed **/ - private static function reformatDate($original_date, $date_format) + private function reformatDate($original_date, $date_format) { if (empty($original_date)) { return "NULL"; // required to avoid "0000-00-00" in the DB } + $new_date = ""; switch ($date_format) { case self::DATE_TYPE_YYYYMMDD: @@ -1235,9 +1268,10 @@ private static function reformatDate($original_date, $date_format) break; } - if (preg_match('/[0-9]{2,4}-[0-9]{1,2}-[0-9]{1,2}/', $new_date) !== 0) { + if (preg_match('/\d{2,4}-\d{1,2}-\d{1,2}/', $new_date) !== 0) { return $new_date; } + return $original_date; } @@ -1252,7 +1286,7 @@ private static function reformatDate($original_date, $date_format) * * @return string the datetime reformated, if needed **/ - private static function reformatDateTime($original_datetime, $date_format) + private function reformatDateTime($original_datetime, $date_format) { if (empty($original_datetime)) { @@ -1271,7 +1305,7 @@ private static function reformatDateTime($original_datetime, $date_format) $time_part = '00:00:00'; } - $new_date = self::reformatDate($date_part, $date_format); + $new_date = $this->reformatDate($date_part, $date_format); if ($new_date === "NULL") { return "NULL"; } @@ -1287,7 +1321,7 @@ private static function reformatDateTime($original_datetime, $date_format) * * @return string the mac address modified, if needed **/ - private static function reformatMacAddress($mac) + private function reformatMacAddress($mac) { $pattern = "/^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})"; @@ -1300,10 +1334,11 @@ private static function reformatMacAddress($mac) unset($results[0]); foreach ($results as $result) { - $mac .= (!$first ? ":" : "") . $result; + $mac .= ($first ? "" : ":") . $result; $first = false; } } + return $mac; } @@ -1357,7 +1392,7 @@ private function check() $mandatory, ); $this->results[self::ACTION_CHECK][] = [$check_result, - $field . "='$value'", + $field . sprintf("='%s'", $value), ]; if ($check_result != self::SUCCESS) { @@ -1417,7 +1452,7 @@ private function checkType($injectionClass, $option, $field_name, $data, $mandat //If no data provided AND this mapping is not mandatory if ( !$mandatory - && ($data == null || $data == "NULL" || $data == self::EMPTY_VALUE) + && (in_array($data, [null, "NULL", self::EMPTY_VALUE])) ) { return self::SUCCESS; } @@ -1428,9 +1463,11 @@ private function checkType($injectionClass, $option, $field_name, $data, $mandat if (isset($option['displaytype']) && $option['displaytype'] == 'multiline_text') { return self::SUCCESS; } - if (strlen($data) > 255) { + + if (strlen((string) $data) > 255) { return self::ERROR_FIELDSIZE_EXCEEDED; } + return self::SUCCESS; case 'integer': @@ -1442,18 +1479,18 @@ private function checkType($injectionClass, $option, $field_name, $data, $mandat case 'date': // Date is already "reformat" according to getDateFormat() - $pat = '/^([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})$/'; + $pat = '/^(\d{4})-(\d{1,2})-(\d{1,2})$/'; $res = preg_match($pat, $data, $regs); return ($res !== 0 ? self::SUCCESS : self::TYPE_MISMATCH); case 'datetime': // Datetime is already reformated to "Y-m-d H:i:s" by reformatThirdPass() - $pat = '/^([0-9]{4})-([0-9]{1,2})-([0-9]{1,2}) ([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})$/'; + $pat = '/^(\d{4})-(\d{1,2})-(\d{1,2}) (\d{1,2}):(\d{1,2}):(\d{1,2})$/'; $res = preg_match($pat, $data, $regs); return ($res !== 0 ? self::SUCCESS : self::TYPE_MISMATCH); case 'ip': - preg_match("/([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/", $data, $regs); + preg_match("/(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/", $data, $regs); return ((count($regs) > 0) ? self::SUCCESS : self::TYPE_MISMATCH); case 'mac': @@ -1468,6 +1505,7 @@ private function checkType($injectionClass, $option, $field_name, $data, $mandat if (!is_numeric($data)) { return self::TYPE_MISMATCH; } + if ($data == 0 || $data == 1) { return self::SUCCESS; } else { @@ -1481,9 +1519,11 @@ private function checkType($injectionClass, $option, $field_name, $data, $mandat if (method_exists($injectionClass, 'checkType')) { return $injectionClass->checkType($field_name, $data, $mandatory); } + return self::SUCCESS; } } + return self::SUCCESS; } @@ -1503,6 +1543,7 @@ private function addNecessaryFields() if (!isset($this->values[$this->primary_type]['entities_id'])) { $this->setValueForItemtype($this->primary_type, 'entities_id', $this->entity); } + if (method_exists($this->injectionClass, 'addSpecificNeededFields')) { $specific_fields = $this->injectionClass->addSpecificNeededFields( $this->primary_type, @@ -1561,7 +1602,7 @@ private function addNeededFields($injectionClass, $itemtype) * * @return bool **/ - private function lastCheckBeforeProcess($injectionClass, $values) + private function lastCheckBeforeProcess($injectionClass) { //Specific reformat action is itemtype needs it @@ -1662,6 +1703,7 @@ public function processAddOrUpdate() //If needed, manage templates $this->addTemplateFields($this->primary_type); } + $values = $this->getValuesForItemtype($this->primary_type); $newID = $this->effectiveAddOrUpdate($this->injectionClass, $item, $values, $add); @@ -1674,7 +1716,7 @@ public function processAddOrUpdate() //If type needs it : process more data after type import $this->processAfterInsertOrUpdate($this->injectionClass, $add); //$this->results['status'] = self::SUCCESS; - $this->results[get_class($item)] = $newID; + $this->results[$item::class] = $newID; //Process other types @@ -1682,7 +1724,7 @@ public function processAddOrUpdate() if (isset($this->values['NetworkPort']) && isset($this->values['NetworkName'])) { $nw = $this->values['NetworkPort']; unset($this->values['NetworkPort']); - $networkNameIndex = array_search('NetworkName', array_keys($this->values)); + $networkNameIndex = array_search('NetworkName', array_keys($this->values), true); $this->values = array_merge( array_slice($this->values, 0, $networkNameIndex), ['NetworkPort' => $nw], @@ -1692,7 +1734,7 @@ public function processAddOrUpdate() foreach ($this->values as $itemtype => $data) { //Do not process primary_type - if ($itemtype != get_class($item)) { + if ($itemtype != $item::class) { $injectionClass = self::getInjectionClassInstance($itemtype); if (is_a($itemtype, CommonDBTM::class, true)) { $item = new $itemtype(); @@ -1706,8 +1748,9 @@ public function processAddOrUpdate() } else { $add = false; } + $values = $this->getValuesForItemtype($itemtype); - if ($this->lastCheckBeforeProcess($injectionClass, $values)) { + if ($this->lastCheckBeforeProcess($injectionClass)) { $tmpID = $this->effectiveAddOrUpdate($injectionClass, $item, $values, $add); $this->processAfterInsertOrUpdate($injectionClass, $add); } @@ -1717,6 +1760,7 @@ public function processAddOrUpdate() } } } + return $this->results; } @@ -1761,6 +1805,7 @@ private function effectiveAddOrUpdate($injectionClass, $item, $values, $add = tr // Skip this field during update if value is empty and field is not nullable continue; } + $toinject[$key] = $value; } @@ -1800,6 +1845,7 @@ private function effectiveAddOrUpdate($injectionClass, $item, $values, $add = tr } else { $toinject['_groups_id'] = [$normalized_value]; } + unset($toinject[$key]); } @@ -1811,12 +1857,7 @@ private function effectiveAddOrUpdate($injectionClass, $item, $values, $add = tr $newID = null; if (method_exists($injectionClass, 'customimport')) { - $newID = call_user_func( - [$injectionClass, 'customimport'], - $toinject, - $add, - $this->rights, - ); + $newID = $injectionClass->customimport($toinject, $add, $this->rights); } elseif ($item instanceof CommonDropdown && $add && !($item instanceof SoftwareLicense)) { $newID = $item->import($toinject); } elseif ($add) { @@ -1829,12 +1870,14 @@ private function effectiveAddOrUpdate($injectionClass, $item, $values, $add = tr if ($item->maybeDynamic()) { unset($toinject['is_dynamic']); } + if ($item->update($toinject)) { $newID = $toinject['id']; self::logAddOrUpdate($item, $add); } } - $this->setValueForItemtype(get_class($item), 'id', $newID); + + $this->setValueForItemtype($item::class, 'id', $newID); return $newID; } @@ -1866,6 +1909,7 @@ private function addOptionalInfos() } else { $this->setValueForItemtype($itemtype, $field, $value); } + $this->addSpecificOptionalInfos($itemtype, $field, $value); } } @@ -1912,7 +1956,7 @@ private function manageRelations() //Get search options associated with the injectionClass $searchOptions = $injectionClass->getOptions($this->primary_type); - foreach ($searchOptions as $id => $option) { + foreach ($searchOptions as $option) { //If it's a relation if ( isset($option['displaytype']) @@ -1979,6 +2023,7 @@ private function dataAlreadyInDB($injectionClass, $itemtype) if (!is_a($itemtype, CommonDBTM::class, true)) { throw new HttpException(500, 'Class ' . $itemtype . ' is not a valid class'); } + $item = new $itemtype(); $where = []; @@ -2000,6 +2045,7 @@ private function dataAlreadyInDB($injectionClass, $itemtype) $source_itemtype = $item::$itemtype_1; $destination_itemtype = $item::$itemtype_2; } + $where[$source_id] = $this->getValueByItemtypeAndName($itemtype, $source_id); $where[$destination_id] = $this->getValueByItemtypeAndName($itemtype, $destination_id); if ($item->isField('itemtype')) { @@ -2068,14 +2114,14 @@ private function dataAlreadyInDB($injectionClass, $itemtype) if (method_exists($injectionClass, 'checkPresent')) { $extra = $injectionClass->checkPresent($this->values, $options); if (is_array($extra)) { - if (count($extra) > 0) { + if ($extra !== []) { $where = array_merge($where, $extra); } } elseif (!empty($extra)) { trigger_error( sprintf( '%s::checkPresent() must return an array, %s returned instead.', - get_class($injectionClass), + $injectionClass::class, gettype($extra), ), E_USER_WARNING, @@ -2094,6 +2140,7 @@ private function dataAlreadyInDB($injectionClass, $itemtype) foreach ($db_fields as $key => $value) { $this->setValueForItemtype($itemtype, $key, $value, true); } + $this->setValueForItemtype($itemtype, 'id', $db_fields['id']); } else { $this->setValueForItemtype($itemtype, 'id', self::ITEM_NOT_FOUND); @@ -2118,6 +2165,7 @@ private function addTemplateFields($itemtype) if (!is_a($itemtype, CommonDBTM::class, true)) { throw new HttpException(500, 'Class ' . $itemtype . ' is not a valid class'); } + $template = new $itemtype(); $template_id = $this->getValueByItemtypeAndName($itemtype, '_oldID'); @@ -2138,6 +2186,7 @@ private function addTemplateFields($itemtype) $this->setValueForItemtype($itemtype, $key, $value); } } + if (isset($this->values[$itemtype]['name'])) { $name = autoName( $this->values[$itemtype]['name'], @@ -2148,6 +2197,7 @@ private function addTemplateFields($itemtype) ); $this->setValueForItemtype($itemtype, 'name', $name); } + if (isset($this->values[$itemtype]['otherserial'])) { $otherserial = autoName( $this->values[$itemtype]['otherserial'], @@ -2179,7 +2229,7 @@ public static function logAddOrUpdate($item, $add = true) $changes[2] = $add ? __('Add from CSV file', 'datainjection') : __('Update from CSV file', 'datainjection'); $changes[1] = ""; - Log::history($item->fields['id'], get_class($item), $changes); + Log::history($item->fields['id'], $item::class, $changes); } } @@ -2289,22 +2339,25 @@ public static function addToSearchOptions( } if (!in_array($id, $options['ignore_fields']) && $id < 1000) { - $type_searchOptions[$id]['injectable'] = !isset($tmp['linkfield']) ? self::FIELD_VIRTUAL : self::FIELD_INJECTABLE; + $type_searchOptions[$id]['injectable'] = isset($tmp['linkfield']) ? self::FIELD_INJECTABLE : self::FIELD_VIRTUAL; //Some injection.class files are missing dropdown options. Set displaytype as dropdown if datatype is dropdown //$tmp['displaytype'] is still empty. Set to prevent overwriting on next IF if ((isset($tmp['datatype']) && $tmp['datatype'] == 'dropdown') && !isset($tmp['displaytype'])) { $type_searchOptions[$id]['displaytype'] = 'dropdown'; $tmp['displaytype'] = 'dropdown'; } + //Some injection.class files are missing checktype for datetime fields. //Without it, the value is never reformated/validated before being sent to the DB. if ((isset($tmp['datatype']) && $tmp['datatype'] == 'datetime') && !isset($tmp['checktype'])) { $type_searchOptions[$id]['checktype'] = 'datetime'; $tmp['checktype'] = 'datetime'; } + if (isset($tmp['linkfield']) && !isset($tmp['displaytype'])) { $type_searchOptions[$id]['displaytype'] = 'text'; } + if (isset($tmp['linkfield']) && !isset($tmp['checktype'])) { $type_searchOptions[$id]['checktype'] = 'text'; } @@ -2359,7 +2412,7 @@ public static function addToSearchOptions( ); $main_itemtype = self::getItemtypeByInjectionClass($injectionClass); - foreach ($type_searchOptions as $key => &$value) { + foreach ($type_searchOptions as &$value) { $value_itemtype = getItemTypeForTable($value['table']); $value_itemtype_name_singular = $value_itemtype::getTypeName(1); $value_itemtype_name_plural = $value_itemtype::getTypeName(Session::getPluralNumber()); @@ -2370,6 +2423,7 @@ public static function addToSearchOptions( ) { continue; } + $value['name'] = $value['name'] . " (" . $value_itemtype_name_singular . ")"; } @@ -2392,6 +2446,7 @@ public static function addTemplateSearchOptions($injectionClass, &$tab) if (!is_a($itemtype, CommonDBTM::class, true)) { throw new HttpException(500, 'Class ' . $itemtype . ' is not a valid class'); } + $item = new $itemtype(); if ($item->maybeTemplate()) { diff --git a/inc/computer_iteminjection.class.php b/inc/computer_iteminjection.class.php index ea4597dd..ee479413 100644 --- a/inc/computer_iteminjection.class.php +++ b/inc/computer_iteminjection.class.php @@ -71,35 +71,7 @@ public function isNullable($field) **/ public function getOptions($primary_type = '') { - - $tab[110]['table'] = 'glpi_computers'; - $tab[110]['field'] = 'name'; - $tab[110]['linkfield'] = 'name'; - $tab[110]['name'] = __('Name'); - $tab[110]['injectable'] = true; - $tab[110]['displaytype'] = 'dropdown'; - $tab[110]['checktype'] = 'text'; - $tab[110]['storevaluein'] = 'computers_id'; - - $tab[111]['table'] = 'glpi_computers'; - $tab[111]['field'] = 'serial'; - $tab[111]['linkfield'] = 'serial'; - $tab[111]['name'] = __('Serial number'); - $tab[111]['injectable'] = true; - $tab[111]['displaytype'] = 'dropdown'; - $tab[111]['checktype'] = 'text'; - $tab[112]['storevaluein'] = 'computers_id'; - - $tab[112]['table'] = 'glpi_computers'; - $tab[112]['field'] = 'otherserial'; - $tab[112]['linkfield'] = 'otherserial'; - $tab[112]['name'] = __('Inventory number'); - $tab[112]['injectable'] = true; - $tab[112]['displaytype'] = 'dropdown'; - $tab[112]['checktype'] = 'text'; - $tab[112]['storevaluein'] = 'computers_id'; - - return $tab; + return [110 => ['table' => 'glpi_computers', 'field' => 'name', 'linkfield' => 'name', 'name' => __('Name'), 'injectable' => true, 'displaytype' => 'dropdown', 'checktype' => 'text', 'storevaluein' => 'computers_id'], 111 => ['table' => 'glpi_computers', 'field' => 'serial', 'linkfield' => 'serial', 'name' => __('Serial number'), 'injectable' => true, 'displaytype' => 'dropdown', 'checktype' => 'text'], 112 => ['storevaluein' => 'computers_id', 'table' => 'glpi_computers', 'field' => 'otherserial', 'linkfield' => 'otherserial', 'name' => __('Inventory number'), 'injectable' => true, 'displaytype' => 'dropdown', 'checktype' => 'text']]; } @@ -121,11 +93,6 @@ public function addOrUpdateObject($values = [], $options = []) **/ public function addSpecificNeededFields($primary_type, $values) { - $fields['items_id_asset'] = $values['id']; - $fields['itemtype_asset'] = Computer::class; - - $fields['items_id_peripheral'] = $values[$primary_type]['id']; - $fields['itemtype_peripheral'] = $primary_type; - return $fields; + return ['items_id_asset' => $values['id'], 'itemtype_asset' => Computer::class, 'items_id_peripheral' => $values[$primary_type]['id'], 'itemtype_peripheral' => $primary_type]; } } diff --git a/inc/contact_supplierinjection.class.php b/inc/contact_supplierinjection.class.php index cedc85ce..e822c5ac 100644 --- a/inc/contact_supplierinjection.class.php +++ b/inc/contact_supplierinjection.class.php @@ -64,16 +64,7 @@ public function isNullable($field) **/ public function getOptions($primary_type = '') { - - $tab[100]['table'] = 'glpi_suppliers'; - $tab[100]['field'] = 'name'; - $tab[100]['linkfield'] = 'suppliers_id'; - $tab[100]['name'] = __('Associated suppliers'); - $tab[100]['displaytype'] = 'relation'; - $tab[100]['relationclass'] = 'Contact_Supplier'; - $tab[100]['injectable'] = true; - - return $tab; + return [100 => ['table' => 'glpi_suppliers', 'field' => 'name', 'linkfield' => 'suppliers_id', 'name' => __('Associated suppliers'), 'displaytype' => 'relation', 'relationclass' => 'Contact_Supplier', 'injectable' => true]]; } diff --git a/inc/contract_iteminjection.class.php b/inc/contract_iteminjection.class.php index 568a2c92..000b304b 100644 --- a/inc/contract_iteminjection.class.php +++ b/inc/contract_iteminjection.class.php @@ -71,28 +71,7 @@ public function isNullable($field) **/ public function getOptions($primary_type = '') { - - $tab[100]['table'] = 'glpi_contracts'; - $tab[100]['field'] = 'name'; - $tab[100]['linkfield'] = 'name'; - $tab[100]['name'] = __('Name'); - $tab[100]['injectable'] = true; - $tab[100]['checktype'] = 'text'; - $tab[100]['displaytype'] = 'relation'; - $tab[100]['relationclass'] = 'Contract_Item'; - $tab[100]['storevaluein'] = 'contracts_id'; - - $tab[101]['table'] = 'glpi_contracts'; - $tab[101]['field'] = 'num'; - $tab[101]['linkfield'] = 'num'; - $tab[101]['name'] = __('Serial number'); - $tab[101]['injectable'] = true; - $tab[101]['checktype'] = 'text'; - $tab[101]['displaytype'] = 'relation'; - $tab[101]['relationclass'] = 'Contract_Item'; - $tab[101]['storevaluein'] = 'contracts_id'; - - return $tab; + return [100 => ['table' => 'glpi_contracts', 'field' => 'name', 'linkfield' => 'name', 'name' => __('Name'), 'injectable' => true, 'checktype' => 'text', 'displaytype' => 'relation', 'relationclass' => 'Contract_Item', 'storevaluein' => 'contracts_id'], 101 => ['table' => 'glpi_contracts', 'field' => 'num', 'linkfield' => 'num', 'name' => __('Serial number'), 'injectable' => true, 'checktype' => 'text', 'displaytype' => 'relation', 'relationclass' => 'Contract_Item', 'storevaluein' => 'contracts_id']]; } @@ -114,9 +93,6 @@ public function addOrUpdateObject($values = [], $options = []) **/ public function addSpecificNeededFields($primary_type, $values) { - - $fields['items_id'] = $values[$primary_type]['id']; - $fields['itemtype'] = $primary_type; - return $fields; + return ['items_id' => $values[$primary_type]['id'], 'itemtype' => $primary_type]; } } diff --git a/inc/contract_supplierinjection.class.php b/inc/contract_supplierinjection.class.php index 65258286..2a11de71 100644 --- a/inc/contract_supplierinjection.class.php +++ b/inc/contract_supplierinjection.class.php @@ -64,20 +64,7 @@ public function isNullable($field) **/ public function getOptions($primary_type = '') { - - $tab[4]['table'] = 'glpi_contracts'; - $tab[4]['field'] = 'name'; - $tab[4]['name'] = __('Contract'); - $tab[4]['checktype'] = 'text'; - $tab[4]['displaytype'] = 'dropdown'; - - $tab[5]['table'] = 'glpi_suppliers'; - $tab[5]['field'] = 'name'; - $tab[5]['name'] = __('Supplier'); - $tab[5]['checktype'] = 'text'; - $tab[5]['displaytype'] = 'dropdown'; - - return $tab; + return [4 => ['table' => 'glpi_contracts', 'field' => 'name', 'name' => __('Contract'), 'checktype' => 'text', 'displaytype' => 'dropdown'], 5 => ['table' => 'glpi_suppliers', 'field' => 'name', 'name' => __('Supplier'), 'checktype' => 'text', 'displaytype' => 'dropdown']]; } diff --git a/inc/data.class.php b/inc/data.class.php index c6813d8f..a95f013d 100644 --- a/inc/data.class.php +++ b/inc/data.class.php @@ -33,9 +33,6 @@ class PluginDatainjectionData private $injectionData; - public function __construct() {} - - /** * @param array $newData **/ @@ -62,6 +59,7 @@ public function getDataAtLine($line_id) if (count($this->injectionData) >= $line_id) { return $this->injectionData[$line_id][0]; } + return []; } } diff --git a/inc/devicecaseinjection.class.php b/inc/devicecaseinjection.class.php index 6349c34f..35ba7328 100644 --- a/inc/devicecaseinjection.class.php +++ b/inc/devicecaseinjection.class.php @@ -93,6 +93,7 @@ public function processAfterInsertOrUpdate($values, $add = true, $rights = []) if (!is_a($class, CommonDBTM::class, true)) { throw new HttpException(500, 'Class ' . $class . ' is not a valid class'); } + $item = new $class(); $foreign = getForeignKeyFieldForTable(getTableForItemType(get_parent_class($this))); diff --git a/inc/devicecontrolinjection.class.php b/inc/devicecontrolinjection.class.php index 93390851..a6992267 100644 --- a/inc/devicecontrolinjection.class.php +++ b/inc/devicecontrolinjection.class.php @@ -94,6 +94,7 @@ public function processAfterInsertOrUpdate($values, $add = true, $rights = []) if (!is_a($class, CommonDBTM::class, true)) { throw new HttpException(500, 'Class ' . $class . ' is not a valid class'); } + $item = new $class(); $foreign = getForeignKeyFieldForTable(getTableForItemType(get_parent_class($this))); diff --git a/inc/devicedriveinjection.class.php b/inc/devicedriveinjection.class.php index 5829840b..83789b35 100644 --- a/inc/devicedriveinjection.class.php +++ b/inc/devicedriveinjection.class.php @@ -94,6 +94,7 @@ public function processAfterInsertOrUpdate($values, $add = true, $rights = []) if (!is_a($class, CommonDBTM::class, true)) { throw new HttpException(500, 'Class ' . $class . ' is not a valid class'); } + $item = new $class(); $foreign = getForeignKeyFieldForTable(getTableForItemType(get_parent_class($this))); diff --git a/inc/deviceharddriveinjection.class.php b/inc/deviceharddriveinjection.class.php index 32defcef..74d6ba83 100644 --- a/inc/deviceharddriveinjection.class.php +++ b/inc/deviceharddriveinjection.class.php @@ -95,6 +95,7 @@ public function processAfterInsertOrUpdate($values, $add = true, $rights = []) if (!is_a($class, CommonDBTM::class, true)) { throw new HttpException(500, 'Class ' . $class . ' is not a valid class'); } + $item = new $class(); $foreign = getForeignKeyFieldForTable(getTableForItemType(get_parent_class($this))); diff --git a/inc/devicememoryinjection.class.php b/inc/devicememoryinjection.class.php index 6d3c8415..0d2cdfa8 100644 --- a/inc/devicememoryinjection.class.php +++ b/inc/devicememoryinjection.class.php @@ -95,6 +95,7 @@ public function processAfterInsertOrUpdate($values, $add = true, $rights = []) if (!is_a($class, CommonDBTM::class, true)) { throw new HttpException(500, 'Class ' . $class . ' is not a valid class'); } + $item = new $class(); $foreign = getForeignKeyFieldForTable(getTableForItemType(get_parent_class($this))); diff --git a/inc/devicemotherboardinjection.class.php b/inc/devicemotherboardinjection.class.php index f48a1ce6..a5276073 100644 --- a/inc/devicemotherboardinjection.class.php +++ b/inc/devicemotherboardinjection.class.php @@ -95,6 +95,7 @@ public function processAfterInsertOrUpdate($values, $add = true, $rights = []) if (!is_a($class, CommonDBTM::class, true)) { throw new HttpException(500, 'Class ' . $class . ' is not a valid class'); } + $item = new $class(); $foreign = getForeignKeyFieldForTable(getTableForItemType(get_parent_class($this))); diff --git a/inc/devicenetworkcardinjection.class.php b/inc/devicenetworkcardinjection.class.php index c64dd880..1b1f089b 100644 --- a/inc/devicenetworkcardinjection.class.php +++ b/inc/devicenetworkcardinjection.class.php @@ -93,6 +93,7 @@ public function processAfterInsertOrUpdate($values, $add = true, $rights = []) if (!is_a($class, CommonDBTM::class, true)) { throw new HttpException(500, 'Class ' . $class . ' is not a valid class'); } + $item = new $class(); $foreign = getForeignKeyFieldForTable(getTableForItemType(get_parent_class($this))); diff --git a/inc/deviceprocessorinjection.class.php b/inc/deviceprocessorinjection.class.php index c237697d..75f0fdb9 100644 --- a/inc/deviceprocessorinjection.class.php +++ b/inc/deviceprocessorinjection.class.php @@ -95,6 +95,7 @@ public function processAfterInsertOrUpdate($values, $add = true, $rights = []) if (!is_a($class, CommonDBTM::class, true)) { throw new HttpException(500, 'Class ' . $class . ' is not a valid class'); } + $item = new $class(); $foreign = getForeignKeyFieldForTable(getTableForItemType(get_parent_class($this))); diff --git a/inc/dropdown.class.php b/inc/dropdown.class.php index ccd4d0d0..8358fa16 100644 --- a/inc/dropdown.class.php +++ b/inc/dropdown.class.php @@ -32,15 +32,7 @@ class PluginDatainjectionDropdown { public static function dateFormats() { - - $date_format[PluginDatainjectionCommonInjectionLib::DATE_TYPE_DDMMYYYY] - = __('dd-mm-yyyy', 'datainjection'); - $date_format[PluginDatainjectionCommonInjectionLib::DATE_TYPE_MMDDYYYY] - = __('mm-dd-yyyy', 'datainjection'); - $date_format[PluginDatainjectionCommonInjectionLib::DATE_TYPE_YYYYMMDD] - = __('yyyy-mm-dd', 'datainjection'); - - return $date_format; + return ['dd-mm-yyyy' => __('dd-mm-yyyy', 'datainjection'), 'mm-dd-yyyy' => __('mm-dd-yyyy', 'datainjection'), 'yyyy-mm-dd' => __('yyyy-mm-dd', 'datainjection')]; } @@ -54,15 +46,7 @@ public static function getDateFormat($date) public static function floatFormats() { - - $float_format[PluginDatainjectionCommonInjectionLib::FLOAT_TYPE_DOT] - = __('1 234.56', 'datainjection'); - $float_format[PluginDatainjectionCommonInjectionLib::FLOAT_TYPE_COMMA] - = __('1 234,56', 'datainjection'); - $float_format[PluginDatainjectionCommonInjectionLib::FLOAT_TYPE_DOT_AND_COM] - = __('1,234.56', 'datainjection'); - - return $float_format; + return [1 => __('1 234.56', 'datainjection'), 0 => __('1 234,56', 'datainjection'), __('1,234.56', 'datainjection')]; } @@ -79,20 +63,13 @@ public static function getFloatFormat($format) public static function statusLabels() { - - $states[0] = Dropdown::EMPTY_VALUE; - //$states[PluginDatainjectionModel::INITIAL_STEP] = __('Creation of the model on going', 'datainjection'); - $states[PluginDatainjectionModel::FILE_STEP] = __('File to inject', 'datainjection'); - $states[PluginDatainjectionModel::MAPPING_STEP] = __('Mappings', 'datainjection'); - $states[PluginDatainjectionModel::OTHERS_STEP] = __( + return [Dropdown::EMPTY_VALUE, 2 => __('File to inject', 'datainjection'), 3 => __('Mappings', 'datainjection'), 4 => __( 'Additional Information', 'datainjection', - ); - $states[PluginDatainjectionModel::READY_TO_USE_STEP] = __( + ), 5 => __( 'Model available for use', 'datainjection', - ); - return $states; + )]; } @@ -110,46 +87,24 @@ public static function getStatusLabel($step) public static function getStatusColor($step) { - switch ($step) { - case PluginDatainjectionModel::MAPPING_STEP: - case PluginDatainjectionModel::OTHERS_STEP: - return "#ffb832"; - case PluginDatainjectionModel::READY_TO_USE_STEP: - return "#2ec41f"; - default: - return "#ff4e4e"; - } + return match ($step) { + PluginDatainjectionModel::MAPPING_STEP, PluginDatainjectionModel::OTHERS_STEP => "#ffb832", + PluginDatainjectionModel::READY_TO_USE_STEP => "#2ec41f", + default => "#ff4e4e", + }; } public static function getFileEncodingValue() { - - $values[PluginDatainjectionBackend::ENCODING_AUTO] = __('Automatic detection', 'datainjection'); - $values[PluginDatainjectionBackend::ENCODING_UFT8] = __('UTF-8', 'datainjection'); - $values[PluginDatainjectionBackend::ENCODING_ISO8859_1] = __('ISO8859-1', 'datainjection'); - - return $values; + return [2 => __('Automatic detection', 'datainjection'), __('UTF-8', 'datainjection'), 0 => __('ISO8859-1', 'datainjection')]; } public static function portUnicityValues() { - - $values[PluginDatainjectionCommonInjectionLib::UNICITY_NETPORT_LOGICAL_NUMBER] - = __('Port number'); - $values[PluginDatainjectionCommonInjectionLib::UNICITY_NETPORT_NAME] - = __('Name'); - $values[PluginDatainjectionCommonInjectionLib::UNICITY_NETPORT_MACADDRESS] - = __('Mac address'); - $values[PluginDatainjectionCommonInjectionLib::UNICITY_NETPORT_LOGICAL_NUMBER_NAME] - = __('Port number') . "+" . __('Name'); - $values[PluginDatainjectionCommonInjectionLib::UNICITY_NETPORT_LOGICAL_NUMBER_MAC] - = __('Port number') . "+" . __('Mac address'); - $values[PluginDatainjectionCommonInjectionLib::UNICITY_NETPORT_LOGICAL_NUMBER_NAME_MAC] - = __('Port number') . "+" . __('Name') . "+" . - __('Mac address'); - return $values; + return [__('Port number'), __('Name'), __('Mac address'), __('Port number') . "+" . __('Name'), __('Port number') . "+" . __('Mac address'), __('Port number') . "+" . __('Name') . "+" . + __('Mac address')]; } diff --git a/inc/engine.class.php b/inc/engine.class.php index 6018cbc3..810b93f1 100644 --- a/inc/engine.class.php +++ b/inc/engine.class.php @@ -30,15 +30,6 @@ class PluginDatainjectionEngine { - //Model informations - private $model; - - //Current entity - private $entity; - - //Additional infos to be added - private $infos = []; - //Lines in error private $error_lines = []; @@ -48,18 +39,13 @@ class PluginDatainjectionEngine * @param array $infos array * @param int|string $entity (default 0) */ - public function __construct($model, $infos = [], $entity = 0) + public function __construct(private $model, private $infos = [], private $entity = 0) { - //Instanciate model - $this->model = $model; - //Load model and mappings informations $this->getModel()->loadMappings(); $this->getModel()->populateSeveraltimesMappedFields(); $this->getModel()->loadInfos(); - $this->infos = $infos; - $this->entity = $entity; } @@ -160,6 +146,7 @@ public function injectLine($line, $index) if ($results['status'] != PluginDatainjectionCommonInjectionLib::SUCCESS) { $this->error_lines[] = $line; } + return $results; } @@ -217,8 +204,10 @@ public function addValueToInject( if (isset($fields_toinject[$mapping->getItemtype()][$mapping->getValue()])) { $return_value .= $fields_toinject[$mapping->getItemtype()][$mapping->getValue()]; } + $return_value .= $mapping->getMappingName() . "=" . $value . "\n"; } + $fields_toinject[$mapping->getItemtype()][$mapping->getValue()] = $return_value; } @@ -241,6 +230,7 @@ public function addAdditionalInformations() = $this->infos[$info->getValue()]; } } + return $additional_infos; } diff --git a/inc/entityinjection.class.php b/inc/entityinjection.class.php index 20e45981..34421311 100644 --- a/inc/entityinjection.class.php +++ b/inc/entityinjection.class.php @@ -93,11 +93,12 @@ public function addOrUpdateObject($values = [], $options = []) // Only the `name`, `entities_id`, and `comment` fields are taken into account when creating an entity. // The IF forces an update of the entity to insert the other fields. if ( - count(array_diff_key($values, array_flip(['name', 'entities_id', 'comment']))) > 0 + array_diff_key($values, array_flip(['name', 'entities_id', 'comment'])) !== [] && $data['type'] === PluginDatainjectionCommonInjectionLib::IMPORT_ADD ) { $lib->processAddOrUpdate(); } + return $lib->getInjectionResults(); } @@ -129,8 +130,8 @@ public function customimport($input = [], $add = true, $rights = []) // Check if search start by root entity $root = self::getRootEntityName(); - if (!str_starts_with($search, $root)) { - $search = "$root > $search"; + if (!str_starts_with((string) $search, (string) $root)) { + $search = sprintf('%s > %s', $root, $search); } $results = $em->find(['completename' => $search]); @@ -148,13 +149,13 @@ public function importEntity($input) $em = new Entity(); // Import a full tree from completename - $names = explode('>', $input['completename']); + $names = explode('>', (string) $input['completename']); $i = count($names); $parent = 0; $level = 0; // Remove root entity if specified - if (strcmp(trim($names[0]), trim(self::getRootEntityName())) === 0) { + if (strcmp(trim($names[0]), trim((string) self::getRootEntityName())) === 0) { unset($names[0]); } @@ -163,10 +164,11 @@ public function importEntity($input) $i--; $level++; - if (empty($name)) { + if ($name === '' || $name === '0') { // Skip empty name (completename starting/endind with >, double >, ...) continue; } + $tmp['name'] = $name; if ($i === 0) { @@ -177,6 +179,7 @@ public function importEntity($input) } } } + $tmp['level'] = $level; $tmp['entities_id'] = $parent; @@ -224,6 +227,7 @@ public function customDataAlreadyInDB($injectionClass, $values, $options) if (!isset($values['completename'])) { return false; } + $results = getAllDataFromTable( 'glpi_entities', ['completename' => $values['completename']], diff --git a/inc/info.class.php b/inc/info.class.php index 92150701..c2ffe04f 100644 --- a/inc/info.class.php +++ b/inc/info.class.php @@ -104,8 +104,8 @@ public static function showAddInfo(PluginDatainjectionModel $model, $canedit = f ], ); echo ""; - echo "