From 3c0d5ce6be829485e87757cd056a425fb9f0f00e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Anne?= Date: Thu, 7 Mar 2019 17:22:52 +0100 Subject: [PATCH] Generate itemtypes without numbers; fixes #305 --- hook.php | 4 +- inc/container.class.php | 50 +++++++-- inc/dropdown.class.php | 3 + inc/field.class.php | 9 +- inc/toolbox.class.php | 148 ++++++++++++++++++++++++++ tests/bootstrap.php | 5 +- tests/units/PluginFieldsContainer.php | 2 +- 7 files changed, 207 insertions(+), 14 deletions(-) create mode 100644 inc/toolbox.class.php diff --git a/hook.php b/hook.php index ac0f7c98..45aaf360 100644 --- a/hook.php +++ b/hook.php @@ -61,9 +61,10 @@ function plugin_fields_install() { echo ""; //load all classes + $dir = GLPI_ROOT . "/plugins/fields/inc/"; + include_once ("{$dir}toolbox.class.php"); foreach ($classesToInstall as $class) { if ($plug = isPluginItemType($class)) { - $dir = GLPI_ROOT . "/plugins/fields/inc/"; $item = strtolower($plug['class']); if (file_exists("$dir$item.class.php")) { include_once ("$dir$item.class.php"); @@ -74,7 +75,6 @@ function plugin_fields_install() { //install foreach ($classesToInstall as $class) { if ($plug = isPluginItemType($class)) { - $dir = GLPI_ROOT . "/plugins/fields/inc/"; $item =strtolower($plug['class']); if (file_exists("$dir$item.class.php")) { if (!call_user_func([$class,'install'], $migration, $version)) { diff --git a/inc/container.class.php b/inc/container.class.php index 921adf0b..0db30066 100644 --- a/inc/container.class.php +++ b/inc/container.class.php @@ -68,6 +68,47 @@ static function install(Migration $migration, $version) { $migration->migrationOneTable($table); } + // Fix containers names that were generated prior to Fields 1.9.2. + $glpi_version = preg_replace('/^((\d+\.?)+).*$/', '$1', GLPI_VERSION); + $bad_named_containers = $DB->request( + [ + 'FROM' => self::getTable(), + 'WHERE' => [ + 'name' => [ + 'REGEXP', + // Regex will be escaped by PDO in GLPI 10+, but has to be escaped for GLPI < 10 + version_compare($glpi_version, '10.0', '>=') ? '\d+' : $DB->escape('\d+') + ], + ], + ] + ); + + if ($bad_named_containers->count() > 0) { + $migration->displayMessage(__("Fix container names", "fields")); + + foreach ($bad_named_containers as $container) { + $old_name = $container['name']; + + // Update container name + $toolbox = new PluginFieldsToolbox(); + $container['name'] = $toolbox->getSystemNameFromLabel($container['label']); + $container_obj = new PluginFieldsContainer(); + $container_obj->update( + $container, + false + ); + + // Rename container tables + foreach (json_decode($container['itemtypes']) as $itemtype) { + $old_table = getTableForItemType(self::getClassname($itemtype, $old_name)); + $new_table = getTableForItemType(self::getClassname($itemtype, $container['name'])); + if ($DB->tableExists($old_table)) { + $migration->renameTable($old_table, $new_table); + } + } + } + } + //Computer OS tab is no longer part of computer object. Moving to main $ostab = self::findContainer(Computer::getType(), 'domtab', Computer::getType() . '$1'); if ($ostab) { @@ -355,13 +396,8 @@ function prepareInputForAdd($input) { } } - // construct field name by processing label - // (remove non alphanumeric char and any trailing spaces) - $input['name'] = strtolower(preg_replace("/[^\da-z]/i", "", preg_replace('/s*$/', '', $input['label']))); - // if empty, uses a random number - if (strlen($input['name']) == 0) { - $input['name'] = rand(); - } + $toolbox = new PluginFieldsToolbox(); + $input['name'] = $toolbox->getSystemNameFromLabel($input['label']); //check for already existing container with same name $found = $this->find(['name' => $input['name']]); diff --git a/inc/dropdown.class.php b/inc/dropdown.class.php index e149ec64..edb8f311 100644 --- a/inc/dropdown.class.php +++ b/inc/dropdown.class.php @@ -13,6 +13,9 @@ class PluginFieldsDropdown { * @return void */ static function install(Migration $migration, $version) { + $toolbox = new PluginFieldsToolbox(); + $toolbox->fixFieldsNames($migration, ['type' => 'dropdown']); + $migration->displayMessage(__("Updating generated dropdown files", "fields")); // -> 0.90-1.3: generated class moved // OLD path: GLPI_ROOT."/plugins/fields/inc/$class_filename" diff --git a/inc/field.class.php b/inc/field.class.php index 1683fd58..8b5da257 100644 --- a/inc/field.class.php +++ b/inc/field.class.php @@ -57,6 +57,9 @@ static function install(Migration $migration, $version) { } $migration->executeMigration(); + $toolbox = new PluginFieldsToolbox(); + $toolbox->fixFieldsNames($migration, ['NOT' => ['type' => 'dropdown']]); + return true; } @@ -182,9 +185,11 @@ function post_purgeItem() { * @return string the parsed name */ function prepareName($input) { + $toolbox = new PluginFieldsToolbox(); + //contruct field name by processing label (remove non alphanumeric char) if (empty($input['name'])) { - $input['name'] = strtolower(preg_replace("/[^\da-z]/i", "", $input['label']))."field"; + $input['name'] = $toolbox->getSystemNameFromLabel($input['label']) . 'field'; } //for dropdown, if already exist, link to it @@ -203,7 +208,7 @@ function prepareName($input) { $field_name = $input['name']; $i = 2; while (count($field->find(['name' => $field_name])) > 0) { - $field_name = $input['name'].$i; + $field_name = $toolbox->getIncrementedSystemName($input['name'], $i); $i++; } diff --git a/inc/toolbox.class.php b/inc/toolbox.class.php new file mode 100644 index 00000000..7b4abc47 --- /dev/null +++ b/inc/toolbox.class.php @@ -0,0 +1,148 @@ +replaceIntByLetters($name); + + return $name; + } + + /** + * Return system name incremented by given increment. + * + * @param string $name + * @param integer $increment + * + * @return string + */ + public function getIncrementedSystemName($name, $increment) { + return $name . $this->replaceIntByLetters((string)$increment); + } + + /** + * Replace integers by corresponding letters inside given string. + * + * @param string $str + * + * @return mixed + */ + private function replaceIntByLetters($str) { + return str_replace( + ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'], + ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'], + $str + ); + } + + /** + * Fix dropdown names that were generated prior to Fields 1.9.2. + * + * @param Migration $migration + * @param mixed $condition + * + * @return void + */ + public function fixFieldsNames(Migration $migration, $condition) { + global $DB; + + $glpi_version = preg_replace('/^((\d+\.?)+).*$/', '$1', GLPI_VERSION); + $bad_named_fields = $DB->request( + [ + 'FROM' => PluginFieldsField::getTable(), + 'WHERE' => [ + 'name' => [ + 'REGEXP', + // Regex will be escaped by PDO in GLPI 10+, but has to be escaped for GLPI < 10 + version_compare($glpi_version, '10.0', '>=') ? '\d+' : $DB->escape('\d+') + ], + $condition, + ], + ] + ); + + if ($bad_named_fields->count() === 0) { + return; + } + + $migration->displayMessage(__("Fix fields names", "fields")); + + foreach ($bad_named_fields as $field) { + $old_name = $field['name']; + + // Update field name + $field_obj = new PluginFieldsField(); + $field['name'] = null; + $field['name'] = $field_obj->prepareName($field); + $field_obj->update( + $field, + false + ); + + $sql_fields_to_rename = [ + $old_name => $field['name'], + ]; + + if ('dropdown' === $field['type']) { + // Rename dropdown table + $old_table = getTableForItemType(PluginFieldsDropdown::getClassname($old_name)); + $new_table = getTableForItemType(PluginFieldsDropdown::getClassname($field['name'])); + if ($DB->tableExists($old_table)) { + $migration->renameTable($old_table, $new_table); + } + + // Rename foreign keys in containers tables + $old_fk = getForeignKeyFieldForTable($old_table); + $new_fk = getForeignKeyFieldForTable($new_table); + $sql_fields_to_rename[$old_fk] = $new_fk; + } + + // Rename columns in plugin tables + foreach ($sql_fields_to_rename as $old_field_name => $new_field_name) { + $tables_to_update = $DB->request( + [ + 'SELECT DISTINCT' => 'TABLE_NAME', + 'FROM' => 'INFORMATION_SCHEMA.COLUMNS', + 'WHERE' => [ + 'TABLE_NAME' => ['LIKE', 'glpi_plugin_fields_%'], + 'COLUMN_NAME' => $old_field_name + ], + ] + ); + + foreach ($tables_to_update as $table_to_update) { + $sql_type = PluginFieldsMigration::getSQLType($field['type']); + $migration->changeField( + $table_to_update['TABLE_NAME'], + $old_field_name, + $new_field_name, + $sql_type + ); + $migration->migrationOneTable($table_to_update['TABLE_NAME']); + } + } + } + } +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 177dde78..74bed30e 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -13,6 +13,7 @@ //install plugin $plugin = new \Plugin(); +$plugin->checkStates(true); $plugin->getFromDBbyDir('fields'); //check from prerequisites as Plugin::install() does not! if (!plugin_fields_check_prerequisites()) { @@ -20,10 +21,10 @@ die(1); } if (!$plugin->isInstalled('fields')) { - call_user_func([$plugin, 'install'], $plugin->getID()); + $plugin->install($plugin->getID()); } if (!$plugin->isActivated('fields')) { - call_user_func([$plugin, 'activate'], $plugin->getID()); + $plugin->activate($plugin->getID()); } include_once __DIR__ . '/FieldsDbTestCase.php'; diff --git a/tests/units/PluginFieldsContainer.php b/tests/units/PluginFieldsContainer.php index e624f242..dae95802 100644 --- a/tests/units/PluginFieldsContainer.php +++ b/tests/units/PluginFieldsContainer.php @@ -30,7 +30,7 @@ public function testNewContainer() { $newid = $container->add($data); $this->integer($newid)->isGreaterThan(0); - $this->boolean(class_exists('PluginFieldsComputercontainerlabel1'))->isTrue(); + $this->boolean(class_exists('PluginFieldsComputercontainerlabelOne'))->isTrue(); } public function testGetTypes() {