Skip to content

Commit

Permalink
Generate itemtypes without numbers; fixes pluginsGLPI#305
Browse files Browse the repository at this point in the history
  • Loading branch information
cedric-anne committed Apr 18, 2019
1 parent 9db449e commit 4ddb361
Show file tree
Hide file tree
Showing 7 changed files with 207 additions and 14 deletions.
4 changes: 2 additions & 2 deletions hook.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,10 @@ function plugin_fields_install() {
echo "<td align='center'>";

//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");
Expand All @@ -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)) {
Expand Down
50 changes: 43 additions & 7 deletions inc/container.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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']]);
Expand Down
3 changes: 3 additions & 0 deletions inc/dropdown.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
9 changes: 7 additions & 2 deletions inc/field.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ static function install(Migration $migration, $version) {
}
$migration->executeMigration();

$toolbox = new PluginFieldsToolbox();
$toolbox->fixFieldsNames($migration, ['NOT' => ['type' => 'dropdown']]);

return true;
}

Expand Down Expand Up @@ -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
Expand All @@ -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++;
}

Expand Down
148 changes: 148 additions & 0 deletions inc/toolbox.class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
<?php

class PluginFieldsToolbox {

/**
* Get a clean system name from a label.
*
* @param string $label
*
* @return string
*/
public function getSystemNameFromLabel($label) {

$name = strtolower($label);

// 1. remove trailing "s" (plural forms)
$name = getSingular($name);

// 2. keep only alphanum
$name = preg_replace('/[^\da-z]/i', '', $name);

// 3. if empty, uses a random number
if (strlen($name) == 0) {
$name = rand();
}

// 4. replace numbers by letters
$name = $this->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']);
}
}
}
}
}
5 changes: 3 additions & 2 deletions tests/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,18 @@

//install plugin
$plugin = new \Plugin();
$plugin->checkStates(true);
$plugin->getFromDBbyDir('fields');
//check from prerequisites as Plugin::install() does not!
if (!plugin_fields_check_prerequisites()) {
echo "\nPrerequisites are not met!";
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';
2 changes: 1 addition & 1 deletion tests/units/PluginFieldsContainer.php
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down

0 comments on commit 4ddb361

Please sign in to comment.