From 13374f9ca8d7f724c107f5223405c6eb22cec1f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Anne?= Date: Fri, 3 Jun 2022 12:33:38 +0200 Subject: [PATCH] Switch to PSR-12 --- .github/workflows/continuous-integration.yml | 51 + .phpcs.xml | 17 + ajax/container_display_condition.php | 12 +- ajax/container_itemtypes_dropdown.php | 2 +- ajax/container_subtype_dropdown.php | 2 +- ajax/reorder.php | 90 +- ajax/status_override.php | 2 +- ajax/viewtranslations.php | 10 +- composer.json | 4 +- composer.lock | 115 +- front/commondropdown.form.php | 2 +- front/commondropdown.php | 2 +- front/container.form.php | 52 +- front/container.php | 11 +- front/containerdisplaycondition.form.php | 2 +- front/export_to_yaml.php | 17 +- front/field.form.php | 43 +- front/labeltranslation.form.php | 10 +- front/profile.form.php | 5 +- front/regenerate_files.php | 6 +- front/statusoverride.form.php | 2 +- hook.php | 449 +-- inc/autoload.php | 107 +- inc/container.class.php | 3303 +++++++++--------- inc/containerdisplaycondition.class.php | 119 +- inc/dropdown.class.php | 396 ++- inc/field.class.php | 1950 ++++++----- inc/inventory.class.php | 178 +- inc/labeltranslation.class.php | 541 +-- inc/menu.class.php | 69 +- inc/migration.class.php | 99 +- inc/profile.class.php | 275 +- inc/statusoverride.class.php | 120 +- inc/toolbox.class.php | 495 +-- setup.php | 526 +-- 35 files changed, 4763 insertions(+), 4321 deletions(-) create mode 100644 .github/workflows/continuous-integration.yml create mode 100644 .phpcs.xml diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml new file mode 100644 index 00000000..f8c7fae7 --- /dev/null +++ b/.github/workflows/continuous-integration.yml @@ -0,0 +1,51 @@ +name: "Continuous integration" + +on: + push: + branches: + - "master" + - "develop" + tags: + - "*" + pull_request: + workflow_dispatch: + +jobs: + lint: + name: "Lint" + runs-on: "ubuntu-latest" + strategy: + fail-fast: false + matrix: + include: + - {php-version: "7.4"} + steps: + - name: "Checkout" + uses: "actions/checkout@v3" + - name: "Setup PHP" + uses: "shivammathur/setup-php@v2" + with: + php-version: "${{ matrix.php-version }}" + coverage: "none" + tools: "composer, cs2pr" + - name: "Get Composer cache directory" + id: "composer-cache" + run: | + echo "::set-output name=dir::$(composer config cache-files-dir)" + - name: "Restore dependencies cache" + uses: "actions/cache@v3" + with: + path: "${{ steps.composer-cache.outputs.dir }}" + key: "${{ github.job }}-${{ matrix.php-version }}-dependencies-${{ hashFiles('**/composer.lock') }}" + - name: "Install Composer dependencies" + run: | + composer install --ansi --no-interaction --no-progress --prefer-dist + - name: "PHP Parallel Lint" + run: | + vendor/bin/parallel-lint --colors --checkstyle --exclude ./vendor/ . | cs2pr + - name: "PHP_CodeSniffer" + run: | + vendor/bin/phpcs -q --report=checkstyle | cs2pr + - name: "Check for missing/outdated headers" + run: | + vendor/bin/licence-headers-check --ansi --no-interaction diff --git a/.phpcs.xml b/.phpcs.xml new file mode 100644 index 00000000..6c5742f9 --- /dev/null +++ b/.phpcs.xml @@ -0,0 +1,17 @@ + + + . + /.git/ + ^vendor/ + + + + + + + + + + + + diff --git a/ajax/container_display_condition.php b/ajax/container_display_condition.php index d5d3853e..4dca8e8a 100644 --- a/ajax/container_display_condition.php +++ b/ajax/container_display_condition.php @@ -28,7 +28,7 @@ * ------------------------------------------------------------------------- */ -include ("../../../inc/includes.php"); +include("../../../inc/includes.php"); if (isset($_GET['action'])) { if ($_GET['action'] === 'get_add_form') { @@ -39,21 +39,19 @@ $status_override->getFromDB($_GET['id']); $status_override->showForm($_GET['id'], $_GET); } - } else if (isset($_POST['action'])) { - if($_POST['action'] === 'get_itemtype_so') { - if(isset($_POST['itemtype']) && class_exists($_POST['itemtype'])) { + if ($_POST['action'] === 'get_itemtype_so') { + if (isset($_POST['itemtype']) && class_exists($_POST['itemtype'])) { echo PluginFieldsContainerDisplayCondition::showItemtypeFieldForm($_POST['itemtype']) ; } else { echo ""; } - } else if($_POST['action'] === 'get_condition_switch_so') { - if(isset($_POST['search_option_id']) && (isset($_POST['itemtype']) && class_exists($_POST['itemtype']))) { + } else if ($_POST['action'] === 'get_condition_switch_so') { + if (isset($_POST['search_option_id']) && (isset($_POST['itemtype']) && class_exists($_POST['itemtype']))) { echo PluginFieldsContainerDisplayCondition::showSearchOptionCondition($_POST['search_option_id'], $_POST['itemtype']); } else { echo ""; } - } } else { http_response_code(400); diff --git a/ajax/container_itemtypes_dropdown.php b/ajax/container_itemtypes_dropdown.php index 9ef45a33..30aebf2c 100644 --- a/ajax/container_itemtypes_dropdown.php +++ b/ajax/container_itemtypes_dropdown.php @@ -28,6 +28,6 @@ * ------------------------------------------------------------------------- */ -include ("../../../inc/includes.php"); +include("../../../inc/includes.php"); PluginFieldsContainer::showFormItemtype($_REQUEST); diff --git a/ajax/container_subtype_dropdown.php b/ajax/container_subtype_dropdown.php index ed094b6f..9ac6e1d1 100644 --- a/ajax/container_subtype_dropdown.php +++ b/ajax/container_subtype_dropdown.php @@ -28,6 +28,6 @@ * ------------------------------------------------------------------------- */ -include ("../../../inc/includes.php"); +include("../../../inc/includes.php"); PluginFieldsContainer::showFormSubtype($_REQUEST, true); diff --git a/ajax/reorder.php b/ajax/reorder.php index cfbc228a..6f7ac26c 100644 --- a/ajax/reorder.php +++ b/ajax/reorder.php @@ -28,13 +28,15 @@ * ------------------------------------------------------------------------- */ -include ("../../../inc/includes.php"); +include("../../../inc/includes.php"); -if (!array_key_exists('container_id', $_POST) +if ( + !array_key_exists('container_id', $_POST) || !array_key_exists('old_order', $_POST) - || !array_key_exists('new_order', $_POST)) { - // Missing input - exit(); + || !array_key_exists('new_order', $_POST) +) { + // Missing input + exit(); } $table = PluginFieldsField::getTable(); @@ -44,57 +46,57 @@ // Retrieve id of field to update $field_iterator = $DB->request( - [ - 'SELECT' => 'id', - 'FROM' => $table, - 'WHERE' => [ - 'plugin_fields_containers_id' => $container_id, - 'ranking' => $old_order, - ], - ] + [ + 'SELECT' => 'id', + 'FROM' => $table, + 'WHERE' => [ + 'plugin_fields_containers_id' => $container_id, + 'ranking' => $old_order, + ], + ] ); if (0 === $field_iterator->count()) { - // Unknown field - exit(); + // Unknown field + exit(); } $field_id = $field_iterator->current()['id']; // Move all elements to their new ranking if ($old_order < $new_order) { - $DB->update( - $table, - [ - 'ranking' => new \QueryExpression($DB->quoteName('ranking') . ' - 1'), - ], - [ - 'plugin_fields_containers_id' => $container_id, - ['ranking' => ['>', $old_order]], - ['ranking' => ['<=', $new_order]], - ] - ); + $DB->update( + $table, + [ + 'ranking' => new \QueryExpression($DB->quoteName('ranking') . ' - 1'), + ], + [ + 'plugin_fields_containers_id' => $container_id, + ['ranking' => ['>', $old_order]], + ['ranking' => ['<=', $new_order]], + ] + ); } else { - $DB->update( - $table, - [ - 'ranking' => new \QueryExpression($DB->quoteName('ranking') . ' + 1'), - ], - [ - 'plugin_fields_containers_id' => $container_id, - ['ranking' => ['<', $old_order]], - ['ranking' => ['>=', $new_order]], - ] - ); + $DB->update( + $table, + [ + 'ranking' => new \QueryExpression($DB->quoteName('ranking') . ' + 1'), + ], + [ + 'plugin_fields_containers_id' => $container_id, + ['ranking' => ['<', $old_order]], + ['ranking' => ['>=', $new_order]], + ] + ); } // Update current element $DB->update( - $table, - [ - 'ranking' => $new_order, - ], - [ - 'id' => $field_id, - ] + $table, + [ + 'ranking' => $new_order, + ], + [ + 'id' => $field_id, + ] ); diff --git a/ajax/status_override.php b/ajax/status_override.php index f8ea6885..8a6e1f64 100644 --- a/ajax/status_override.php +++ b/ajax/status_override.php @@ -28,7 +28,7 @@ * ------------------------------------------------------------------------- */ -include ("../../../inc/includes.php"); +include("../../../inc/includes.php"); if (isset($_GET['action'])) { if ($_GET['action'] === 'get_status_dropdown') { diff --git a/ajax/viewtranslations.php b/ajax/viewtranslations.php index 8580393f..c31bd229 100644 --- a/ajax/viewtranslations.php +++ b/ajax/viewtranslations.php @@ -32,26 +32,26 @@ * @brief */ -include ('../../../inc/includes.php'); +include('../../../inc/includes.php'); header("Content-Type: text/html; charset=UTF-8"); Html::header_nocache(); Session::checkLoginUser(); if (!isset($_POST['itemtype']) || !isset($_POST['items_id']) || !isset($_POST['id'])) { - exit(); + exit(); } $translation = new PluginFieldsLabelTranslation(); if ($_POST['id'] == -1) { - $canedit = $translation->can(-1, CREATE, $_POST); + $canedit = $translation->can(-1, CREATE, $_POST); } else { - $canedit = $translation->can($_POST['id'], UPDATE); + $canedit = $translation->can($_POST['id'], UPDATE); } if ($canedit) { $translation->showFormForItem($_POST['itemtype'], $_POST['items_id'], $_POST['id']); } else { - echo __('Access denied'); + echo __('Access denied'); } Html::ajaxFooter(); diff --git a/composer.json b/composer.json index f04eeb91..901e5bb6 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,9 @@ "symfony/yaml": "^5.4" }, "require-dev": { - "glpi-project/tools": "^0.5" + "glpi-project/tools": "^0.5", + "php-parallel-lint/php-parallel-lint": "^1.3", + "squizlabs/php_codesniffer": "^3.6" }, "config": { "optimize-autoloader": true, diff --git a/composer.lock b/composer.lock index 565e6671..4f6c2e63 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "14895e82a69534be2d824ea5f8734698", + "content-hash": "0decc662a33ef2874781405ed63fb7ca", "packages": [ { "name": "symfony/deprecation-contracts", @@ -284,6 +284,63 @@ }, "time": "2022-05-03T09:56:09+00:00" }, + { + "name": "php-parallel-lint/php-parallel-lint", + "version": "v1.3.2", + "source": { + "type": "git", + "url": "https://github.com/php-parallel-lint/PHP-Parallel-Lint.git", + "reference": "6483c9832e71973ed29cf71bd6b3f4fde438a9de" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-parallel-lint/PHP-Parallel-Lint/zipball/6483c9832e71973ed29cf71bd6b3f4fde438a9de", + "reference": "6483c9832e71973ed29cf71bd6b3f4fde438a9de", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=5.3.0" + }, + "replace": { + "grogy/php-parallel-lint": "*", + "jakub-onderka/php-parallel-lint": "*" + }, + "require-dev": { + "nette/tester": "^1.3 || ^2.0", + "php-parallel-lint/php-console-highlighter": "0.* || ^1.0", + "squizlabs/php_codesniffer": "^3.6" + }, + "suggest": { + "php-parallel-lint/php-console-highlighter": "Highlight syntax in code snippet" + }, + "bin": [ + "parallel-lint" + ], + "type": "library", + "autoload": { + "classmap": [ + "./src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Jakub Onderka", + "email": "ahoj@jakubonderka.cz" + } + ], + "description": "This tool check syntax of PHP files about 20x faster than serial check.", + "homepage": "https://github.com/php-parallel-lint/PHP-Parallel-Lint", + "support": { + "issues": "https://github.com/php-parallel-lint/PHP-Parallel-Lint/issues", + "source": "https://github.com/php-parallel-lint/PHP-Parallel-Lint/tree/v1.3.2" + }, + "time": "2022-02-21T12:50:22+00:00" + }, { "name": "psr/container", "version": "1.1.2", @@ -332,6 +389,62 @@ }, "time": "2021-11-05T16:50:12+00:00" }, + { + "name": "squizlabs/php_codesniffer", + "version": "3.6.2", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "5e4e71592f69da17871dba6e80dd51bce74a351a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/5e4e71592f69da17871dba6e80dd51bce74a351a", + "reference": "5e4e71592f69da17871dba6e80dd51bce74a351a", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" + }, + "bin": [ + "bin/phpcs", + "bin/phpcbf" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", + "keywords": [ + "phpcs", + "standards" + ], + "support": { + "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", + "source": "https://github.com/squizlabs/PHP_CodeSniffer", + "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" + }, + "time": "2021-12-12T21:44:58+00:00" + }, { "name": "symfony/console", "version": "v5.4.8", diff --git a/front/commondropdown.form.php b/front/commondropdown.form.php index 89484a9d..8276493f 100644 --- a/front/commondropdown.form.php +++ b/front/commondropdown.form.php @@ -30,7 +30,7 @@ include "../../../inc/includes.php"; if (preg_match('/[a-z]/i', $_REQUEST['ddtype']) !== 1) { - throw new \RuntimeException(sprintf('Invalid itemtype "%"', $_REQUEST['ddtype'])); + throw new \RuntimeException(sprintf('Invalid itemtype "%"', $_REQUEST['ddtype'])); } $path = PLUGINFIELDS_FRONT_PATH . '/' . $_REQUEST['ddtype'] . '.form.php'; require_once $path; diff --git a/front/commondropdown.php b/front/commondropdown.php index 18578bef..1ee85120 100644 --- a/front/commondropdown.php +++ b/front/commondropdown.php @@ -30,7 +30,7 @@ include "../../../inc/includes.php"; if (preg_match('/[a-z]/i', $_REQUEST['ddtype']) !== 1) { - throw new \RuntimeException(sprintf('Invalid itemtype "%"', $_REQUEST['ddtype'])); + throw new \RuntimeException(sprintf('Invalid itemtype "%"', $_REQUEST['ddtype'])); } $path = PLUGINFIELDS_FRONT_PATH . '/' . $_REQUEST['ddtype'] . '.php'; require_once $path; diff --git a/front/container.form.php b/front/container.form.php index 08a00e17..a8e701ca 100644 --- a/front/container.form.php +++ b/front/container.form.php @@ -28,41 +28,41 @@ * ------------------------------------------------------------------------- */ -include ("../../../inc/includes.php"); +include("../../../inc/includes.php"); if (empty($_GET["id"])) { - $_GET["id"] = ""; + $_GET["id"] = ""; } -$container = new PluginFieldsContainer; +$container = new PluginFieldsContainer(); if (isset($_POST["add"])) { - $container->check(-1, CREATE, $_POST); - $newID = $container->add($_POST); - Html::redirect(PLUGINFIELDS_WEB_DIR."/front/container.form.php?id=$newID"); - + $container->check(-1, CREATE, $_POST); + $newID = $container->add($_POST); + Html::redirect(PLUGINFIELDS_WEB_DIR . "/front/container.form.php?id=$newID"); } else if (isset($_POST["delete"])) { - $container->check($_POST['id'], DELETE); - $ok = $container->delete($_POST); - Html::redirect(PLUGINFIELDS_WEB_DIR."/front/container.php"); - + $container->check($_POST['id'], DELETE); + $ok = $container->delete($_POST); + Html::redirect(PLUGINFIELDS_WEB_DIR . "/front/container.php"); } else if (isset($_REQUEST["purge"])) { - $container->check($_REQUEST['id'], PURGE); - $container->delete($_REQUEST, 1); - Html::redirect(PLUGINFIELDS_WEB_DIR."/front/container.php"); - + $container->check($_REQUEST['id'], PURGE); + $container->delete($_REQUEST, 1); + Html::redirect(PLUGINFIELDS_WEB_DIR . "/front/container.php"); } else if (isset($_POST["update"])) { - $container->check($_POST['id'], UPDATE); - $container->update($_POST); - Html::back(); - + $container->check($_POST['id'], UPDATE); + $container->update($_POST); + Html::back(); } else if (isset($_POST["update_fields_values"])) { - $container->updateFieldsValues($_REQUEST, $_REQUEST['itemtype'], false); - Html::back(); - + $container->updateFieldsValues($_REQUEST, $_REQUEST['itemtype'], false); + Html::back(); } else { - Html::header(__("Additionnal fields", "fields"), $_SERVER['PHP_SELF'], - "config", "pluginfieldsmenu", "fieldscontainer"); - $container->display(['id' => $_GET["id"]]); - Html::footer(); + Html::header( + __("Additionnal fields", "fields"), + $_SERVER['PHP_SELF'], + "config", + "pluginfieldsmenu", + "fieldscontainer" + ); + $container->display(['id' => $_GET["id"]]); + Html::footer(); } diff --git a/front/container.php b/front/container.php index 0be774ba..6de72f85 100644 --- a/front/container.php +++ b/front/container.php @@ -28,10 +28,15 @@ * ------------------------------------------------------------------------- */ -include ("../../../inc/includes.php"); +include("../../../inc/includes.php"); -Html::header(__("Additionnal fields", "fields"), $_SERVER['PHP_SELF'], - "config", "pluginfieldsmenu", "fieldscontainer"); +Html::header( + __("Additionnal fields", "fields"), + $_SERVER['PHP_SELF'], + "config", + "pluginfieldsmenu", + "fieldscontainer" +); Session::checkRight('entity', READ); diff --git a/front/containerdisplaycondition.form.php b/front/containerdisplaycondition.form.php index 9c07c52e..e3cddf23 100644 --- a/front/containerdisplaycondition.form.php +++ b/front/containerdisplaycondition.form.php @@ -28,7 +28,7 @@ * ------------------------------------------------------------------------- */ -include ("../../../inc/includes.php"); +include("../../../inc/includes.php"); $status_override = new PluginFieldsContainerDisplayCondition(); if (isset($_POST["add"])) { diff --git a/front/export_to_yaml.php b/front/export_to_yaml.php index 407c8fc4..757880ca 100644 --- a/front/export_to_yaml.php +++ b/front/export_to_yaml.php @@ -28,22 +28,21 @@ * ------------------------------------------------------------------------- */ -include ("../../../inc/includes.php"); -include ("../hook.php"); +include("../../../inc/includes.php"); +include("../hook.php"); Session::checkRight('entity', READ); $ID = null; if (isset($_GET['id'])) { - $ID = $_GET['id']; + $ID = $_GET['id']; } if (plugin_fields_exportBlockAsYaml($ID)) { - $filename = "fields_conf.yaml"; - $path = GLPI_TMP_DIR."/fields_conf.yaml"; - Toolbox::sendFile($path, $filename, 'text/yaml'); + $filename = "fields_conf.yaml"; + $path = GLPI_TMP_DIR . "/fields_conf.yaml"; + Toolbox::sendFile($path, $filename, 'text/yaml'); } else { - Session::addMessageAfterRedirect("No data to export", false, INFO); - Html::back(); + Session::addMessageAfterRedirect("No data to export", false, INFO); + Html::back(); } - diff --git a/front/field.form.php b/front/field.form.php index de3c67d3..07986af6 100644 --- a/front/field.form.php +++ b/front/field.form.php @@ -28,40 +28,41 @@ * ------------------------------------------------------------------------- */ -include ("../../../inc/includes.php"); +include("../../../inc/includes.php"); if (empty($_GET["id"])) { - $_GET["id"] = ""; + $_GET["id"] = ""; } Session::checkRight('entity', READ); -$field = new PluginFieldsField; +$field = new PluginFieldsField(); if (isset($_POST["add"])) { - $field->check(-1, CREATE, $_POST); - $field->add($_POST); - Html::back(); + $field->check(-1, CREATE, $_POST); + $field->add($_POST); + Html::back(); } else if (isset($_POST["delete"])) { - $field->check($_POST['id'], DELETE); - $field->delete($_POST); - Html::back(); + $field->check($_POST['id'], DELETE); + $field->delete($_POST); + Html::back(); } else if (isset($_REQUEST["purge"])) { - $field->check($_REQUEST['id'], PURGE); - $field->delete($_REQUEST, 1); - $field->redirectToList(); + $field->check($_REQUEST['id'], PURGE); + $field->delete($_REQUEST, 1); + $field->redirectToList(); } else if (isset($_POST["update"])) { - $field->check($_POST['id'], UPDATE); - $field->update($_POST); - Html::back(); + $field->check($_POST['id'], UPDATE); + $field->update($_POST); + Html::back(); } else if (isset($_GET["id"])) { - $field->check($_GET['id'], READ); + $field->check($_GET['id'], READ); - Html::header(PluginFieldsField::getTypeName(1), $_SERVER['PHP_SELF']); + Html::header(PluginFieldsField::getTypeName(1), $_SERVER['PHP_SELF']); - $field->getFromDB($_GET['id']); - $field->display(['id' => $_GET['id'], - 'parent_id' => $field->fields['plugin_fields_containers_id']]); + $field->getFromDB($_GET['id']); + $field->display(['id' => $_GET['id'], + 'parent_id' => $field->fields['plugin_fields_containers_id'] + ]); - Html::footer(); + Html::footer(); } diff --git a/front/labeltranslation.form.php b/front/labeltranslation.form.php index 1cc1c324..77afa751 100644 --- a/front/labeltranslation.form.php +++ b/front/labeltranslation.form.php @@ -28,16 +28,14 @@ * ------------------------------------------------------------------------- */ -include ('../../../inc/includes.php'); +include('../../../inc/includes.php'); $translation = new PluginFieldsLabelTranslation(); if (isset($_POST['add'])) { - $translation->add($_POST); - + $translation->add($_POST); } else if (isset($_POST['update'])) { - $translation->update($_POST); - + $translation->update($_POST); } else if (isset($_POST['purge'])) { - $translation->delete($_POST, true); + $translation->delete($_POST, true); } Html::back(); diff --git a/front/profile.form.php b/front/profile.form.php index f68138ef..ca9ba96f 100644 --- a/front/profile.form.php +++ b/front/profile.form.php @@ -28,10 +28,9 @@ * ------------------------------------------------------------------------- */ -include ("../../../inc/includes.php"); - +include("../../../inc/includes.php"); if (isset($_POST["update"])) { - PluginFieldsProfile::updateProfile($_POST); + PluginFieldsProfile::updateProfile($_POST); } Html::back(); diff --git a/front/regenerate_files.php b/front/regenerate_files.php index c1d37b4c..89467338 100644 --- a/front/regenerate_files.php +++ b/front/regenerate_files.php @@ -28,11 +28,11 @@ * ------------------------------------------------------------------------- */ -include ("../../../inc/includes.php"); -include ("../hook.php"); +include("../../../inc/includes.php"); +include("../hook.php"); Session::checkRight('entity', READ); plugin_fields_checkFiles(); -Html::back(); \ No newline at end of file +Html::back(); diff --git a/front/statusoverride.form.php b/front/statusoverride.form.php index c5a236e7..ba26eb7f 100644 --- a/front/statusoverride.form.php +++ b/front/statusoverride.form.php @@ -28,7 +28,7 @@ * ------------------------------------------------------------------------- */ -include ("../../../inc/includes.php"); +include("../../../inc/includes.php"); $status_override = new PluginFieldsStatusOverride(); if (isset($_POST["add"])) { diff --git a/hook.php b/hook.php index cd55c567..eb7f0ed3 100644 --- a/hook.php +++ b/hook.php @@ -33,71 +33,71 @@ * * @return boolean */ -function plugin_fields_install() { - - // Regenerating tables/files can consume lot of memory/time - $memory_limit = (int)Toolbox::getMemoryLimit(); - $max_execution_time = ini_get('max_execution_time'); - if ($memory_limit > 0 && $memory_limit < (512 * 1024 * 1024)) { - ini_set('memory_limit', '512M'); - } - if ($max_execution_time > 0 && $max_execution_time < 300) { - ini_set('max_execution_time', '300'); - } - - $plugin_fields = new Plugin; - $plugin_fields->getFromDBbyDir('fields'); - $version = $plugin_fields->fields['version']; - - $classesToInstall = [ - 'PluginFieldsField', - 'PluginFieldsDropdown', - 'PluginFieldsLabelTranslation', - 'PluginFieldsContainer', - 'PluginFieldsProfile', - 'PluginFieldsStatusOverride', - 'PluginFieldsContainerDisplayCondition', - ]; - - $migration = new Migration($version); - echo "
"; - echo ""; - echo ""; - - echo ""; - echo ""; + echo ""; + echo "
".__("MySQL tables installation", "fields")."
"; - - //load all classes - $dir = PLUGINFIELDS_DIR . "/inc/"; - include_once ("{$dir}toolbox.class.php"); - foreach ($classesToInstall as $class) { - if ($plug = isPluginItemType($class)) { - $item = strtolower($plug['class']); - if (file_exists("$dir$item.class.php")) { - include_once ("$dir$item.class.php"); - } - } - } - - //install - foreach ($classesToInstall as $class) { - if ($plug = isPluginItemType($class)) { - $item =strtolower($plug['class']); - if (file_exists("$dir$item.class.php")) { - if (!call_user_func([$class,'install'], $migration, $version)) { - return false; +function plugin_fields_install() +{ + // Regenerating tables/files can consume lot of memory/time + $memory_limit = (int)Toolbox::getMemoryLimit(); + $max_execution_time = ini_get('max_execution_time'); + if ($memory_limit > 0 && $memory_limit < (512 * 1024 * 1024)) { + ini_set('memory_limit', '512M'); + } + if ($max_execution_time > 0 && $max_execution_time < 300) { + ini_set('max_execution_time', '300'); + } + + $plugin_fields = new Plugin(); + $plugin_fields->getFromDBbyDir('fields'); + $version = $plugin_fields->fields['version']; + + $classesToInstall = [ + 'PluginFieldsField', + 'PluginFieldsDropdown', + 'PluginFieldsLabelTranslation', + 'PluginFieldsContainer', + 'PluginFieldsProfile', + 'PluginFieldsStatusOverride', + 'PluginFieldsContainerDisplayCondition', + ]; + + $migration = new Migration($version); + echo "
"; + echo ""; + echo ""; + + echo ""; + echo ""; - echo ""; - echo "
" . __("MySQL tables installation", "fields") . "
"; + + //load all classes + $dir = PLUGINFIELDS_DIR . "/inc/"; + include_once("{$dir}toolbox.class.php"); + foreach ($classesToInstall as $class) { + if ($plug = isPluginItemType($class)) { + $item = strtolower($plug['class']); + if (file_exists("$dir$item.class.php")) { + include_once("$dir$item.class.php"); } - } - } - } + } + } + + //install + foreach ($classesToInstall as $class) { + if ($plug = isPluginItemType($class)) { + $item = strtolower($plug['class']); + if (file_exists("$dir$item.class.php")) { + if (!call_user_func([$class,'install'], $migration, $version)) { + return false; + } + } + } + } - $migration->executeMigration(); + $migration->executeMigration(); - echo "
"; + echo "
"; - return true; + return true; } /** @@ -105,107 +105,115 @@ function plugin_fields_install() { * * @return boolean */ -function plugin_fields_uninstall() { - - if (!class_exists('PluginFieldsProfile')) { - Session::addMessageAfterRedirect(__("The plugin can't be uninstalled when the plugin is disabled", 'fields'), - true, WARNING, true); - return false; - } - - $_SESSION['uninstall_fields'] = true; - - echo "
"; - echo ""; - echo ""; - - echo ""; - echo ""; + echo ""; + echo "
".__("MySQL tables uninstallation", "fields")."
"; - - $classesToUninstall = [ - 'PluginFieldsDropdown', - 'PluginFieldsContainer', - 'PluginFieldsLabelTranslation', - 'PluginFieldsField', - 'PluginFieldsProfile', - 'PluginFieldsStatusOverride', - 'PluginFieldsContainerDisplayCondition' - ]; - - foreach ($classesToUninstall as $class) { - if ($plug = isPluginItemType($class)) { - - $dir = PLUGINFIELDS_DIR . "/inc/"; - $item = strtolower($plug['class']); - - if (file_exists("$dir$item.class.php")) { - include_once ("$dir$item.class.php"); - if (!call_user_func([$class,'uninstall'])) { - return false; +function plugin_fields_uninstall() +{ + + if (!class_exists('PluginFieldsProfile')) { + Session::addMessageAfterRedirect( + __("The plugin can't be uninstalled when the plugin is disabled", 'fields'), + true, + WARNING, + true + ); + return false; + } + + $_SESSION['uninstall_fields'] = true; + + echo "
"; + echo ""; + echo ""; + + echo ""; + echo ""; - echo ""; - echo "
" . __("MySQL tables uninstallation", "fields") . "
"; + + $classesToUninstall = [ + 'PluginFieldsDropdown', + 'PluginFieldsContainer', + 'PluginFieldsLabelTranslation', + 'PluginFieldsField', + 'PluginFieldsProfile', + 'PluginFieldsStatusOverride', + 'PluginFieldsContainerDisplayCondition' + ]; + + foreach ($classesToUninstall as $class) { + if ($plug = isPluginItemType($class)) { + $dir = PLUGINFIELDS_DIR . "/inc/"; + $item = strtolower($plug['class']); + + if (file_exists("$dir$item.class.php")) { + include_once("$dir$item.class.php"); + if (!call_user_func([$class,'uninstall'])) { + return false; + } } - } - } - } + } + } - echo "
"; + echo "
"; - unset($_SESSION['uninstall_fields']); + unset($_SESSION['uninstall_fields']); - // clean display preferences - $pref = new DisplayPreference; - $pref->deleteByCriteria([ - 'itemtype' => ['LIKE' , 'PluginFields%'] - ]); + // clean display preferences + $pref = new DisplayPreference(); + $pref->deleteByCriteria([ + 'itemtype' => ['LIKE' , 'PluginFields%'] + ]); - return true; + return true; } -function plugin_fields_getAddSearchOptions($itemtype) { - if (isset($_SESSION['glpiactiveentities']) - && is_array($_SESSION['glpiactiveentities']) - && count($_SESSION['glpiactiveentities']) > 0) { - - $itemtypes = PluginFieldsContainer::getEntries('all'); - if ($itemtypes !== false && in_array($itemtype, $itemtypes)) { - return PluginFieldsContainer::getAddSearchOptions($itemtype); - } - } - - return null; +function plugin_fields_getAddSearchOptions($itemtype) +{ + if ( + isset($_SESSION['glpiactiveentities']) + && is_array($_SESSION['glpiactiveentities']) + && count($_SESSION['glpiactiveentities']) > 0 + ) { + $itemtypes = PluginFieldsContainer::getEntries('all'); + if ($itemtypes !== false && in_array($itemtype, $itemtypes)) { + return PluginFieldsContainer::getAddSearchOptions($itemtype); + } + } + + return null; } // Define Dropdown tables to be manage in GLPI : -function plugin_fields_getDropdown() { - $dropdowns = []; - - $field_obj = new PluginFieldsField; - $fields = $field_obj->find(['type' => 'dropdown']); - foreach ($fields as $field) { - $field['itemtype'] = PluginFieldsField::getType(); - $label = PluginFieldsLabelTranslation::getLabelFor($field); - $dropdowns["PluginFields".ucfirst($field['name'])."Dropdown"] = $label; - } - - asort($dropdowns); - return $dropdowns; +function plugin_fields_getDropdown() +{ + $dropdowns = []; + + $field_obj = new PluginFieldsField(); + $fields = $field_obj->find(['type' => 'dropdown']); + foreach ($fields as $field) { + $field['itemtype'] = PluginFieldsField::getType(); + $label = PluginFieldsLabelTranslation::getLabelFor($field); + $dropdowns["PluginFields" . ucfirst($field['name']) . "Dropdown"] = $label; + } + + asort($dropdowns); + return $dropdowns; } /**** MASSIVE ACTIONS ****/ // Display specific massive actions for plugin fields -function plugin_fields_MassiveActionsFieldsDisplay($options = []) { - $itemtypes = PluginFieldsContainer::getEntries('all'); +function plugin_fields_MassiveActionsFieldsDisplay($options = []) +{ + $itemtypes = PluginFieldsContainer::getEntries('all'); - if (in_array($options['itemtype'], $itemtypes)) { - PluginFieldsField::showSingle($options['itemtype'], $options['options'], true); - return true; - } + if (in_array($options['itemtype'], $itemtypes)) { + PluginFieldsField::showSingle($options['itemtype'], $options['options'], true); + return true; + } - // Need to return false on non display item - return false; + // Need to return false on non display item + return false; } @@ -218,99 +226,104 @@ function plugin_fields_MassiveActionsFieldsDisplay($options = []) { * @param array $params input data * @return array an array of actions */ -function plugin_fields_getRuleActions($params = []) { - $actions = []; - - switch ($params['rule_itemtype']) { - case "PluginFusioninventoryTaskpostactionRule": - $options = PluginFieldsContainer::getAddSearchOptions("Computer"); - foreach ($options as $option) { - $actions[$option['linkfield']]['name'] = $option['name']; - $actions[$option['linkfield']]['type'] = $option['pfields_type']; - if ($option['pfields_type'] == 'dropdown') { - $actions[$option['linkfield']]['table'] = $option['table']; +function plugin_fields_getRuleActions($params = []) +{ + $actions = []; + + switch ($params['rule_itemtype']) { + case "PluginFusioninventoryTaskpostactionRule": + $options = PluginFieldsContainer::getAddSearchOptions("Computer"); + foreach ($options as $option) { + $actions[$option['linkfield']]['name'] = $option['name']; + $actions[$option['linkfield']]['type'] = $option['pfields_type']; + if ($option['pfields_type'] == 'dropdown') { + $actions[$option['linkfield']]['table'] = $option['table']; + } } - } - break; - } + break; + } - return $actions; + return $actions; } -function plugin_fields_rule_matched($params = []) { - global $DB; - - $container = new PluginFieldsContainer; +function plugin_fields_rule_matched($params = []) +{ + global $DB; - switch ($params['sub_type']) { - case "PluginFusioninventoryTaskpostactionRule": - $agent = new PluginFusioninventoryAgent; + $container = new PluginFieldsContainer(); - if (isset($params['input']['plugin_fusioninventory_agents_id'])) { - foreach ($params['output'] as $field => $value) { + switch ($params['sub_type']) { + case "PluginFusioninventoryTaskpostactionRule": + $agent = new PluginFusioninventoryAgent(); - // check if current field is in a tab container - $query = "SELECT c.id + if (isset($params['input']['plugin_fusioninventory_agents_id'])) { + foreach ($params['output'] as $field => $value) { + // check if current field is in a tab container + $query = "SELECT c.id FROM glpi_plugin_fields_fields f LEFT JOIN glpi_plugin_fields_containers c ON c.id = f.plugin_fields_containers_id WHERE f.name = '$field'"; - $res = $DB->query($query); - if ($DB->numrows($res) > 0) { - $data = $DB->fetchAssoc($res); - - //retrieve computer - $agents_id = $params['input']['plugin_fusioninventory_agents_id']; - $agent->getFromDB($agents_id); - - // update current field - $container->updateFieldsValues( - [ - 'plugin_fields_containers_id' => $data['id'], - $field => $value, - 'items_id' => $agent->fields['computers_id'] - ], - Computer::getType() - ); - } + $res = $DB->query($query); + if ($DB->numrows($res) > 0) { + $data = $DB->fetchAssoc($res); + + //retrieve computer + $agents_id = $params['input']['plugin_fusioninventory_agents_id']; + $agent->getFromDB($agents_id); + + // update current field + $container->updateFieldsValues( + [ + 'plugin_fields_containers_id' => $data['id'], + $field => $value, + 'items_id' => $agent->fields['computers_id'] + ], + Computer::getType() + ); + } + } } - } - break; - } + break; + } } -function plugin_fields_giveItem($itemtype, $ID, $data, $num) { - $searchopt = &Search::getOptions($itemtype); - $table = $searchopt[$ID]["table"]; - - //fix glpi default Search::giveItem who for empty date display "--" - if (strpos($table, "glpi_plugin_fields") !== false - && isset($searchopt[$ID]["datatype"]) - && strpos($searchopt[$ID]["datatype"], "date") !== false - && empty($data['raw']["ITEM_$num"])) { - return " "; - } - - return false; +function plugin_fields_giveItem($itemtype, $ID, $data, $num) +{ + $searchopt = &Search::getOptions($itemtype); + $table = $searchopt[$ID]["table"]; + + //fix glpi default Search::giveItem who for empty date display "--" + if ( + strpos($table, "glpi_plugin_fields") !== false + && isset($searchopt[$ID]["datatype"]) + && strpos($searchopt[$ID]["datatype"], "date") !== false + && empty($data['raw']["ITEM_$num"]) + ) { + return " "; + } + + return false; } /** * Load Fields classes in datainjection. * Called by Setup.php:44 if Datainjection is installed and active -**/ -function plugin_datainjection_populate_fields() { - global $INJECTABLE_TYPES; - - $container = new PluginFieldsContainer(); - $found = $container->find(['is_active' => 1]); - foreach ($found as $values) { - $types = json_decode($values['itemtypes']); - - foreach ($types as $type) { - $classname = PluginFieldsContainer::getClassname($type, $values['name'], 'Injection'); - $INJECTABLE_TYPES[$classname] = 'fields'; - } - } + */ +function plugin_datainjection_populate_fields() +{ + global $INJECTABLE_TYPES; + + $container = new PluginFieldsContainer(); + $found = $container->find(['is_active' => 1]); + foreach ($found as $values) { + $types = json_decode($values['itemtypes']); + + foreach ($types as $type) { + $classname = PluginFieldsContainer::getClassname($type, $values['name'], 'Injection'); + $INJECTABLE_TYPES[$classname] = 'fields'; + } + } } diff --git a/inc/autoload.php b/inc/autoload.php index 001bcefd..02291b43 100644 --- a/inc/autoload.php +++ b/inc/autoload.php @@ -30,68 +30,71 @@ class PluginFieldsAutoloader { - protected $paths = []; + protected $paths = []; - public function __construct($options = null) { - if (null !== $options) { - $this->setOptions($options); - } - } + public function __construct($options = null) + { + if (null !== $options) { + $this->setOptions($options); + } + } - public function setOptions($options) { - if (!is_array($options) && !($options instanceof \Traversable)) { - throw new \InvalidArgumentException(); - } + public function setOptions($options) + { + if (!is_array($options) && !($options instanceof \Traversable)) { + throw new \InvalidArgumentException(); + } - foreach ($options as $path) { - if (!in_array($path, $this->paths)) { - $this->paths[] = $path; - } - } - return $this; - } - - public function processClassname($classname) { - $matches = []; - preg_match("/Plugin([A-Z][a-z0-9]+)([A-Z]\w+)/", $classname, $matches); + foreach ($options as $path) { + if (!in_array($path, $this->paths)) { + $this->paths[] = $path; + } + } + return $this; + } - if (count($matches) < 3) { - return false; - } else { - return $matches; - } + public function processClassname($classname) + { + $matches = []; + preg_match("/Plugin([A-Z][a-z0-9]+)([A-Z]\w+)/", $classname, $matches); - } + if (count($matches) < 3) { + return false; + } else { + return $matches; + } + } - public function autoload($classname) { - $matches = $this->processClassname($classname); + public function autoload($classname) + { + $matches = $this->processClassname($classname); - if ($matches !== false) { - $plugin_name = strtolower($matches[1]); - $class_name = strtolower($matches[2]); + if ($matches !== false) { + $plugin_name = strtolower($matches[1]); + $class_name = strtolower($matches[2]); - if ($plugin_name !== "fields") { - return false; - } + if ($plugin_name !== "fields") { + return false; + } - $filename = implode(".", [ - $class_name, - "class", - "php" - ]); + $filename = implode(".", [ + $class_name, + "class", + "php" + ]); - foreach ($this->paths as $path) { - $test = $path . DIRECTORY_SEPARATOR . $filename; - if (file_exists($test)) { - return include_once($test); + foreach ($this->paths as $path) { + $test = $path . DIRECTORY_SEPARATOR . $filename; + if (file_exists($test)) { + return include_once($test); + } } - } - } - return false; - } + } + return false; + } - public function register() { - spl_autoload_register([$this, 'autoload']); - } + public function register() + { + spl_autoload_register([$this, 'autoload']); + } } - diff --git a/inc/container.class.php b/inc/container.class.php index e35d3b75..3229c2f1 100644 --- a/inc/container.class.php +++ b/inc/container.class.php @@ -30,47 +30,51 @@ use Glpi\Toolbox\Sanitizer; -class PluginFieldsContainer extends CommonDBTM { - use Glpi\Features\Clonable; - - static $rightname = 'config'; - - static function canCreate() { - return self::canUpdate(); - } - - static function canPurge() { - return self::canUpdate(); - } - - static function titleList() { - echo "
 ". - __("Regenerate container files", "fields")."   ". - __("Export to YAML", "fields")."

"; - - } - - /** - * Install or update containers - * - * @param Migration $migration Migration instance - * @param string $version Plugin current version - * - * @return boolean - */ - static function install(Migration $migration, $version) { - global $DB; - - $default_charset = DBConnection::getDefaultCharset(); - $default_collation = DBConnection::getDefaultCollation(); - $default_key_sign = DBConnection::getDefaultPrimaryKeySignOption(); - - $table = self::getTable(); - - if (!$DB->tableExists($table)) { - $migration->displayMessage(sprintf(__("Installing %s"), $table)); - - $query = "CREATE TABLE IF NOT EXISTS `$table` ( +class PluginFieldsContainer extends CommonDBTM +{ + use Glpi\Features\Clonable; + + public static $rightname = 'config'; + + public static function canCreate() + { + return self::canUpdate(); + } + + public static function canPurge() + { + return self::canUpdate(); + } + + public static function titleList() + { + echo "
 " . + __("Regenerate container files", "fields") . "   " . + __("Export to YAML", "fields") . "

"; + } + + /** + * Install or update containers + * + * @param Migration $migration Migration instance + * @param string $version Plugin current version + * + * @return boolean + */ + public static function install(Migration $migration, $version) + { + global $DB; + + $default_charset = DBConnection::getDefaultCharset(); + $default_collation = DBConnection::getDefaultCollation(); + $default_key_sign = DBConnection::getDefaultPrimaryKeySignOption(); + + $table = self::getTable(); + + if (!$DB->tableExists($table)) { + $migration->displayMessage(sprintf(__("Installing %s"), $table)); + + $query = "CREATE TABLE IF NOT EXISTS `$table` ( `id` INT {$default_key_sign} NOT NULL auto_increment, `name` VARCHAR(255) DEFAULT NULL, `label` VARCHAR(255) DEFAULT NULL, @@ -83,1653 +87,1730 @@ static function install(Migration $migration, $version) { PRIMARY KEY (`id`), KEY `entities_id` (`entities_id`) ) ENGINE=InnoDB DEFAULT CHARSET={$default_charset} COLLATE={$default_collation} ROW_FORMAT=DYNAMIC;"; - $DB->query($query) or die ($DB->error()); - } - - // multiple itemtype for one container - if (!$DB->fieldExists($table, "itemtypes")) { - $migration->changeField($table, 'itemtype', 'itemtypes', 'longtext'); - $migration->migrationOneTable($table); - - $query = "UPDATE `$table` SET `itemtypes` = CONCAT('[\"', `itemtypes`, '\"]')"; - $DB->query($query) or die ($DB->error()); - } - - //add display preferences for this class - $d_pref = new DisplayPreference; - $found = $d_pref->find(['itemtype' => __CLASS__]); - if (count($found) == 0) { - for ($i = 2; $i <= 5; $i++) { - $DB->query("REPLACE INTO glpi_displaypreferences VALUES - (NULL, '".__CLASS__."', $i, ".($i-1).", 0)"); - } - } - - if (!$DB->fieldExists($table, "subtype")) { - $migration->addField($table, 'subtype', 'VARCHAR(255) DEFAULT NULL', ['after' => 'type']); - $migration->migrationOneTable($table); - } - - // Fix containers names that were generated prior to Fields 1.9.2. - $bad_named_containers = $DB->request( - [ - 'FROM' => self::getTable(), - 'WHERE' => [ - 'name' => [ - 'REGEXP', - $DB->escape('\d+') - ], - ], - ] - ); + $DB->query($query) or die($DB->error()); + } + + // multiple itemtype for one container + if (!$DB->fieldExists($table, "itemtypes")) { + $migration->changeField($table, 'itemtype', 'itemtypes', 'longtext'); + $migration->migrationOneTable($table); + + $query = "UPDATE `$table` SET `itemtypes` = CONCAT('[\"', `itemtypes`, '\"]')"; + $DB->query($query) or die($DB->error()); + } + + //add display preferences for this class + $d_pref = new DisplayPreference(); + $found = $d_pref->find(['itemtype' => __CLASS__]); + if (count($found) == 0) { + for ($i = 2; $i <= 5; $i++) { + $DB->query("REPLACE INTO glpi_displaypreferences VALUES + (NULL, '" . __CLASS__ . "', $i, " . ($i - 1) . ", 0)"); + } + } + + if (!$DB->fieldExists($table, "subtype")) { + $migration->addField($table, 'subtype', 'VARCHAR(255) DEFAULT NULL', ['after' => 'type']); + $migration->migrationOneTable($table); + } + + // Fix containers names that were generated prior to Fields 1.9.2. + $bad_named_containers = $DB->request( + [ + 'FROM' => self::getTable(), + 'WHERE' => [ + 'name' => [ + 'REGEXP', + $DB->escape('\d+') + ], + ], + ] + ); + + if ($bad_named_containers->count() > 0) { + $migration->displayMessage(__("Fix container names", "fields")); + + $toolbox = new PluginFieldsToolbox(); + + foreach ($bad_named_containers as $container) { + $old_name = $container['name']; + + // Update container name + $new_name = $toolbox->getSystemNameFromLabel($container['label']); + foreach (json_decode($container['itemtypes']) as $itemtype) { + while (strlen(getTableForItemType(self::getClassname($itemtype, $new_name))) > 64) { + // limit tables names to 64 chars (MySQL limit) + $new_name = substr($new_name, 0, -1); + } + } + $container['name'] = $new_name; + $container_obj = new PluginFieldsContainer(); + $container_obj->update( + $container, + false + ); + + // Rename container tables and itemtype if needed + foreach (json_decode($container['itemtypes']) as $itemtype) { + $migration->renameItemtype( + self::getClassname($itemtype, $old_name), + self::getClassname($itemtype, $new_name) + ); + } + } + } + + //Computer OS tab is no longer part of computer object. Moving to main + $ostab = self::findContainer(Computer::getType(), 'domtab', Computer::getType() . '$1'); + if ($ostab) { + //check if we already have a container on Computer main tab + $comptab = self::findContainer(Computer::getType(), 'dom'); + if ($comptab) { + $oscontainer = new PluginFieldsContainer(); + $oscontainer->getFromDB($ostab); + + $compcontainer = new PluginFieldsContainer(); + $compcontainer->getFromDB($comptab); + + $fields = new PluginFieldsField(); + $fields = $fields->find(['plugin_fields_containers_id' => $ostab]); + + $classname = self::getClassname(Computer::getType(), $oscontainer->fields['name']); + $osdata = new $classname(); + $classname = self::getClassname(Computer::getType(), $compcontainer->fields['name']); + $compdata = new $classname(); + + $fieldnames = []; + //add fields to compcontainer + foreach ($fields as $field) { + $newname = $field['name']; + $compfields = $fields->find(['plugin_fields_containers_id' => $comptab, 'name' => $newname]); + if ($compfields) { + $newname = $newname . '_os'; + $DB->query("UPDATE glpi_plugin_fields_fields SET name='$newname' WHERE name='{$field['name']}' AND plugin_fields_containers_id='$ostab'"); + } + $compdata::addField($newname, $field['type']); + $fieldnames[$field['name']] = $newname; + } + + $sql = "UPDATE glpi_plugin_fields_fields SET plugin_fields_containers_id='$comptab' WHERE plugin_fields_containers_id='$ostab'"; + $DB->query($sql); + $DB->query("DELETE FROM glpi_plugin_fields_containers WHERE id='$ostab'"); + + //migrate existing data + $existings = $osdata->find(); + foreach ($existings as $existing) { + $data = []; + foreach ($fieldnames as $oldname => $newname) { + $data[$newname] = $existing[$oldname]; + } + $compdata->add($data); + } + + //drop old table + $DB->query("DROP TABLE " . $osdata::getTable()); + } else { + $sql = "UPDATE glpi_plugin_fields_containers SET type='dom', subtype=NULL WHERE id='$ostab'"; + $comptab = $ostab; + $DB->query($sql); + } + } + + $migration->displayMessage(__("Updating generated containers files", "fields")); + $obj = new self(); + $containers = $obj->find(); + + // -> 0.90-1.3: generated class moved + // OLD path: GLPI_ROOT."/plugins/fields/inc/$class_filename" + // NEW path: PLUGINFIELDS_CLASS_PATH . "/$class_filename" + foreach ($containers as $container) { + //First, drop old fields from plugin directories + $itemtypes = !empty($container['itemtypes']) + ? json_decode($container['itemtypes'], true) + : []; + + foreach ($itemtypes as $itemtype) { + $sysname = self::getSystemName($itemtype, $container['name']); + $class_filename = $sysname . ".class.php"; + if (file_exists(PLUGINFIELDS_DIR . "/inc/$class_filename")) { + unlink(PLUGINFIELDS_DIR . "/inc/$class_filename"); + } + + $injclass_filename = $sysname . "injection.class.php"; + if (file_exists(PLUGINFIELDS_DIR . "/inc/$injclass_filename")) { + unlink(PLUGINFIELDS_DIR . "/inc/$injclass_filename"); + } + } + } + + // Regenerate files and install missing tables + foreach ($containers as $container) { + self::create($container); + } + + return true; + } + + public static function uninstall() + { + global $DB; + + //uninstall container table and class + $obj = new self(); + $containers = $obj->find(); + foreach ($containers as $container) { + $obj->delete(['id' => $container['id']]); + } + + //drop global container table + $DB->query("DROP TABLE IF EXISTS `" . self::getTable() . "`"); + + //delete display preferences for this item + $pref = new DisplayPreference(); + $pref->deleteByCriteria([ + 'itemtype' => __CLASS__ + ]); + + return true; + } + + // phpcs:ignore PSR1.Methods.CamelCapsMethodName + public function post_getEmpty() + { + $this->fields['is_active'] = 1; + $this->fields['is_recursive'] = 1; + } + + public function rawSearchOptions() + { + $tab = []; + + $tab[] = [ + 'id' => 1, + 'table' => self::getTable(), + 'field' => 'name', + 'name' => __("Name"), + 'datatype' => 'itemlink', + 'itemlink_type' => self::getType(), + 'massiveaction' => false, + ]; + + $tab[] = [ + 'id' => 2, + 'table' => self::getTable(), + 'field' => 'label', + 'name' => __("Label"), + 'massiveaction' => false, + 'autocomplete' => true, + ]; + + $tab[] = [ + 'id' => 3, + 'table' => self::getTable(), + 'field' => 'itemtypes', + 'name' => __("Associated item type"), + 'datatype' => 'specific', + 'massiveaction' => false, + 'nosearch' => true, + ]; + + $tab[] = [ + 'id' => 4, + 'table' => self::getTable(), + 'field' => 'type', + 'name' => __("Type"), + 'searchtype' => ['equals', 'notequals'], + 'massiveaction' => false, + ]; + + $tab[] = [ + 'id' => 5, + 'table' => self::getTable(), + 'field' => 'is_active', + 'name' => __("Active"), + 'datatype' => 'bool', + 'searchtype' => ['equals', 'notequals'], + ]; + + $tab[] = [ + 'id' => 6, + 'table' => 'glpi_entities', + 'field' => 'completename', + 'name' => __("Entity"), + 'massiveaction' => false, + 'datatype' => 'dropdown', + ]; + + $tab[] = [ + 'id' => 7, + 'table' => self::getTable(), + 'field' => 'is_recursive', + 'name' => __("Child entities"), + 'massiveaction' => false, + 'datatype' => 'bool', + ]; + + $tab[] = [ + 'id' => 8, + 'table' => self::getTable(), + 'field' => 'id', + 'name' => __("ID"), + 'datatype' => 'number', + 'massiveaction' => false, + ]; + + return $tab; + } + + public static function getSpecificValueToDisplay($field, $values, array $options = []) + { + if (!is_array($values)) { + $values = [$field => $values]; + } + switch ($field) { + case 'type': + $types = self::getTypes(); + return $types[$values[$field]]; + case 'itemtypes': + $types = json_decode($values[$field]); + $obj = ''; + $count = count($types); + $i = 1; + foreach ($types as $type) { + // prevent usage of plugin class if not loaded + if (!class_exists($type)) { + continue; + } + $name_type = getItemForItemtype($type); + $obj .= $name_type->getTypeName(2); + if ($count > $i) { + $obj .= ", "; + } + $i++; + } + return $obj; + } + } + + + public function getValueToSelect($field_id_or_search_options, $name = '', $values = '', $options = []) + { + + switch ($field_id_or_search_options['table'] . '.' . $field_id_or_search_options['field']) { + // For searchoption "Type" + case $this->getTable() . '.type': + $options['display'] = false; + return Dropdown::showFromArray($name, self::getTypes(), $options); + case $this->getTable() . '.itemtypes': + $options['display'] = false; + return Dropdown::showFromArray($name, self::getItemtypes(), $options); + } + + return parent::getValueToSelect($field_id_or_search_options, $name, $values, $options); + } + + public function defineTabs($options = []) + { + $ong = []; + $this->addDefaultFormTab($ong); + $this->addStandardTab('PluginFieldsField', $ong, $options); + $this->addStandardTab('PluginFieldsStatusOverride', $ong, $options); + $this->addStandardTab('PluginFieldsProfile', $ong, $options); + $this->addStandardTab('PluginFieldsContainerDisplayCondition', $ong, $options); + $this->addStandardTab('PluginFieldsLabelTranslation', $ong, $options); + + return $ong; + } + + public function prepareInputForAdd($input) + { + if (!isset($input['itemtypes'])) { + Session::AddMessageAfterRedirect( + __( + "You cannot add block without associated element type", + "fields" + ), + false, + ERROR + ); + return false; + } + + if (!is_array($input['itemtypes'])) { + $input['itemtypes'] = [$input['itemtypes']]; + } + + if ($input['type'] === "dom") { + //check for already exist dom container with this itemtype + $found = $this->find(['type' => 'dom']); + if (count($found) > 0) { + foreach (array_column($found, 'itemtypes') as $founditemtypes) { + foreach (json_decode($founditemtypes) as $founditemtype) { + if (in_array($founditemtype, $input['itemtypes'])) { + Session::AddMessageAfterRedirect(__("You cannot add several blocks with type 'Insertion in the form' on same object", "fields"), false, ERROR); + return false; + } + } + } + } + } + + if ($input['type'] === "domtab") { + //check for already exist domtab container with this itemtype on this tab + $found = $this->find(['type' => 'domtab', 'subtype' => $input['subtype']]); + if (count($found) > 0) { + foreach (array_column($found, 'itemtypes') as $founditemtypes) { + foreach (json_decode($founditemtypes) as $founditemtype) { + if (in_array($founditemtype, $input['itemtypes'])) { + Session::AddMessageAfterRedirect(__("You cannot add several blocks with type 'Insertion in the form of a specific tab' on same object tab", "fields"), false, ERROR); + return false; + } + } + } + } + } + + $toolbox = new PluginFieldsToolbox(); + $input['name'] = $toolbox->getSystemNameFromLabel($input['label']); + + //reject adding when container name is too long for mysql table name + foreach ($input['itemtypes'] as $itemtype) { + $tmp = getTableForItemType(self::getClassname($itemtype, $input['name'])); + if (strlen($tmp) > 64) { + Session::AddMessageAfterRedirect( + __("Container name is too long for database (digits in name are replaced by characters, try to remove them)", 'fields'), + false, + ERROR + ); + return false; + } + } - if ($bad_named_containers->count() > 0) { - $migration->displayMessage(__("Fix container names", "fields")); + //check for already existing container with same name + $found = $this->find(['name' => $input['name']]); + if (count($found) > 0) { + foreach (array_column($found, 'itemtypes') as $founditemtypes) { + foreach (json_decode($founditemtypes) as $founditemtype) { + if (in_array($founditemtype, $input['itemtypes'])) { + Session::AddMessageAfterRedirect(__("You cannot add several blocs with identical name on same object", "fields"), false, ERROR); + return false; + } + } + } + } - $toolbox = new PluginFieldsToolbox(); + $input['itemtypes'] = isset($input['itemtypes']) + ? Sanitizer::dbEscape(json_encode($input['itemtypes'])) + : null; - foreach ($bad_named_containers as $container) { - $old_name = $container['name']; + return $input; + } - // Update container name - $new_name = $toolbox->getSystemNameFromLabel($container['label']); - foreach (json_decode($container['itemtypes']) as $itemtype) { - while (strlen(getTableForItemType(self::getClassname($itemtype, $new_name))) > 64) { - // limit tables names to 64 chars (MySQL limit) - $new_name = substr($new_name, 0, -1); - } - } - $container['name'] = $new_name; - $container_obj = new PluginFieldsContainer(); - $container_obj->update( - $container, - false - ); + // phpcs:ignore PSR1.Methods.CamelCapsMethodName + public function post_addItem() + { - // Rename container tables and itemtype if needed - foreach (json_decode($container['itemtypes']) as $itemtype) { - $migration->renameItemtype( - self::getClassname($itemtype, $old_name), - self::getClassname($itemtype, $new_name) - ); + if (!isset($this->input['clone']) || !$this->input['clone']) { + //create profiles associated to this container + PluginFieldsProfile::createForContainer($this); + //Create label translation + PluginFieldsLabelTranslation::createForItem($this); + } + + self::create($this->fields); + } + + public static function create($fields) + { + //create class file + if (!self::generateTemplate($fields)) { + return false; + } + + foreach (json_decode($fields['itemtypes']) as $itemtype) { + //install table for receive field + $classname = self::getClassname($itemtype, $fields['name']); + $classname::install(); + } + } + + public static function generateTemplate($fields) + { + $itemtypes = strlen($fields['itemtypes']) > 0 + ? json_decode($fields['itemtypes'], true) + : []; + foreach ($itemtypes as $itemtype) { + // prevent usage of plugin class if not loaded + if (!class_exists($itemtype)) { + continue; } - } - } - - //Computer OS tab is no longer part of computer object. Moving to main - $ostab = self::findContainer(Computer::getType(), 'domtab', Computer::getType() . '$1'); - if ($ostab) { - //check if we already have a container on Computer main tab - $comptab = self::findContainer(Computer::getType(), 'dom'); - if ($comptab) { - $oscontainer = new PluginFieldsContainer(); - $oscontainer->getFromDB($ostab); - - $compcontainer = new PluginFieldsContainer(); - $compcontainer->getFromDB($comptab); - - $fields = new PluginFieldsField(); - $fields = $fields->find(['plugin_fields_containers_id' => $ostab]); - - $classname = self::getClassname(Computer::getType(), $oscontainer->fields['name']); - $osdata = new $classname; - $classname = self::getClassname(Computer::getType(), $compcontainer->fields['name']); - $compdata = new $classname; - - $fieldnames = []; - //add fields to compcontainer - foreach ($fields as $field) { - $newname = $field['name']; - $compfields = $fields->find(['plugin_fields_containers_id' => $comptab, 'name' => $newname]); - if ($compfields) { - $newname = $newname . '_os'; - $DB->query("UPDATE glpi_plugin_fields_fields SET name='$newname' WHERE name='{$field['name']}' AND plugin_fields_containers_id='$ostab'"); - } - $compdata::addField($newname, $field['type']); - $fieldnames[$field['name']] = $newname; + + $sysname = self::getSystemName($itemtype, $fields['name']); + $classname = self::getClassname($itemtype, $fields['name']); + + $template_class = file_get_contents(PLUGINFIELDS_DIR . "/templates/container.class.tpl"); + $template_class = str_replace("%%CLASSNAME%%", $classname, $template_class); + $template_class = str_replace("%%ITEMTYPE%%", $itemtype, $template_class); + $template_class = str_replace("%%CONTAINER%%", $fields['id'], $template_class); + $template_class = str_replace("%%ITEMTYPE_RIGHT%%", $itemtype::$rightname, $template_class); + $class_filename = $sysname . ".class.php"; + if (file_put_contents(PLUGINFIELDS_CLASS_PATH . "/$class_filename", $template_class) === false) { + Toolbox::logDebug("Error : class file creation - $class_filename"); + return false; } - $sql = "UPDATE glpi_plugin_fields_fields SET plugin_fields_containers_id='$comptab' WHERE plugin_fields_containers_id='$ostab'"; - $DB->query($sql); - $DB->query("DELETE FROM glpi_plugin_fields_containers WHERE id='$ostab'"); - - //migrate existing data - $existings = $osdata->find(); - foreach ($existings as $existing) { - $data = []; - foreach ($fieldnames as $oldname => $newname) { - $data[$newname] = $existing[$oldname]; - } - $compdata->add($data); + // Generate Datainjection files + $template_class = file_get_contents(PLUGINFIELDS_DIR . "/templates/injection.class.tpl"); + $template_class = str_replace("%%CLASSNAME%%", $classname, $template_class); + $template_class = str_replace("%%ITEMTYPE%%", $itemtype, $template_class); + $template_class = str_replace("%%CONTAINER_ID%%", $fields['id'], $template_class); + $template_class = str_replace("%%CONTAINER_NAME%%", $fields['label'], $template_class); + $class_filename = $sysname . "injection.class.php"; + if (file_put_contents(PLUGINFIELDS_CLASS_PATH . "/$class_filename", $template_class) === false) { + Toolbox::logDebug("Error : datainjection class file creation - $class_filename"); + return false; + } + } + return true; + } + + // phpcs:ignore PSR1.Methods.CamelCapsMethodName + public function pre_deleteItem() + { + global $DB; + + $_SESSION['delete_container'] = true; + + foreach (json_decode($this->fields['itemtypes']) as $itemtype) { + $classname = self::getClassname($itemtype, $this->fields['name']); + $sysname = self::getSystemName($itemtype, $this->fields['name']); + $class_filename = $sysname . ".class.php"; + $injection_filename = $sysname . "injection.class.php"; + + //delete fields + $field_obj = new PluginFieldsField(); + $field_obj->deleteByCriteria([ + 'plugin_fields_containers_id' => $this->fields['id'] + ]); + + //delete display condition + $field_obj = new PluginFieldsContainerDisplayCondition(); + $field_obj->deleteByCriteria([ + 'plugin_fields_containers_id' => $this->fields['id'] + ]); + + //delete profiles + $profile_obj = new PluginFieldsProfile(); + $profile_obj->deleteByCriteria([ + 'plugin_fields_containers_id' => $this->fields['id'] + ]); + + //delete label translations + $translation_obj = new PluginFieldsLabelTranslation(); + $translation_obj->deleteByCriteria([ + 'itemtype' => self::getType(), + 'items_id' => $this->fields['id'] + ]); + + //delete table + if (class_exists($classname)) { + $classname::uninstall(); + } else { + //class does not exists; try to remove any existing table + $tablename = getTableForItemType($classname); + $DB->query("DROP TABLE IF EXISTS `$tablename`"); } - //drop old table - $DB->query("DROP TABLE " . $osdata::getTable()); - } else { - $sql = "UPDATE glpi_plugin_fields_containers SET type='dom', subtype=NULL WHERE id='$ostab'"; - $comptab = $ostab; - $DB->query($sql); - } - } - - $migration->displayMessage(__("Updating generated containers files", "fields")); - $obj = new self; - $containers = $obj->find(); - - // -> 0.90-1.3: generated class moved - // OLD path: GLPI_ROOT."/plugins/fields/inc/$class_filename" - // NEW path: PLUGINFIELDS_CLASS_PATH . "/$class_filename" - foreach ($containers as $container) { - //First, drop old fields from plugin directories - $itemtypes = !empty($container['itemtypes']) - ? json_decode($container['itemtypes'], true) - : []; + //clean session + unset($_SESSION['delete_container']); - foreach ($itemtypes as $itemtype) { - $sysname = self::getSystemName($itemtype, $container['name']); - $class_filename = $sysname.".class.php"; - if (file_exists(PLUGINFIELDS_DIR."/inc/$class_filename")) { - unlink(PLUGINFIELDS_DIR."/inc/$class_filename"); + //remove file + if (file_exists(PLUGINFIELDS_CLASS_PATH . "/$class_filename")) { + unlink(PLUGINFIELDS_CLASS_PATH . "/$class_filename"); } - $injclass_filename = $sysname."injection.class.php"; - if (file_exists(PLUGINFIELDS_DIR."/inc/$injclass_filename")) { - unlink(PLUGINFIELDS_DIR."/inc/$injclass_filename"); + if (file_exists(PLUGINFIELDS_CLASS_PATH . "/$injection_filename")) { + unlink(PLUGINFIELDS_CLASS_PATH . "/$injection_filename"); } - } - } - - // Regenerate files and install missing tables - foreach ($containers as $container) { - self::create($container); - } - - return true; - } - - static function uninstall() { - global $DB; - - //uninstall container table and class - $obj = new self; - $containers = $obj->find(); - foreach ($containers as $container) { - $obj->delete(['id' => $container['id']]); - } - - //drop global container table - $DB->query("DROP TABLE IF EXISTS `".self::getTable()."`"); - - //delete display preferences for this item - $pref = new DisplayPreference; - $pref->deleteByCriteria([ - 'itemtype' => __CLASS__ - ]); - - return true; - } - - function post_getEmpty() { - $this->fields['is_active'] = 1; - $this->fields['is_recursive'] = 1; - } - - function rawSearchOptions() { - $tab = []; - - $tab[] = [ - 'id' => 1, - 'table' => self::getTable(), - 'field' => 'name', - 'name' => __("Name"), - 'datatype' => 'itemlink', - 'itemlink_type' => self::getType(), - 'massiveaction' => false, - ]; - - $tab[] = [ - 'id' => 2, - 'table' => self::getTable(), - 'field' => 'label', - 'name' => __("Label"), - 'massiveaction' => false, - 'autocomplete' => true, - ]; - - $tab[] = [ - 'id' => 3, - 'table' => self::getTable(), - 'field' => 'itemtypes', - 'name' => __("Associated item type"), - 'datatype' => 'specific', - 'massiveaction' => false, - 'nosearch' => true, - ]; - - $tab[] = [ - 'id' => 4, - 'table' => self::getTable(), - 'field' => 'type', - 'name' => __("Type"), - 'searchtype' => ['equals', 'notequals'], - 'massiveaction' => false, - ]; - - $tab[] = [ - 'id' => 5, - 'table' => self::getTable(), - 'field' => 'is_active', - 'name' => __("Active"), - 'datatype' => 'bool', - 'searchtype' => ['equals', 'notequals'], - ]; - - $tab[] = [ - 'id' => 6, - 'table' => 'glpi_entities', - 'field' => 'completename', - 'name' => __("Entity"), - 'massiveaction' => false, - 'datatype' => 'dropdown', - ]; - - $tab[] = [ - 'id' => 7, - 'table' => self::getTable(), - 'field' => 'is_recursive', - 'name' => __("Child entities"), - 'massiveaction' => false, - 'datatype' => 'bool', - ]; - - $tab[] = [ - 'id' => 8, - 'table' => self::getTable(), - 'field' => 'id', - 'name' => __("ID"), - 'datatype' => 'number', - 'massiveaction' => false, - ]; - - return $tab; - } - - static function getSpecificValueToDisplay($field, $values, array $options = []) { - if (!is_array($values)) { - $values = [$field => $values]; - } - switch ($field) { - case 'type': + } + + return true; + } + + public static function preItemPurge($item) + { + $itemtype = get_class($item); + $containers = new self(); + $founded_containers = $containers->find(); + foreach ($founded_containers as $container) { + $itemtypes = json_decode($container['itemtypes']); + if (in_array($itemtype, $itemtypes)) { + $classname = 'PluginFields' . $itemtype . getSingular($container['name']); + $fields = new $classname(); + $fields->deleteByCriteria(['items_id' => $item->fields['id']], true); + } + } + return true; + } + + public static function getTypeName($nb = 0) + { + return __("Block", "fields"); + } + + public function showForm($ID, $options = []) + { + + $this->initForm($ID, $options); + + if (!$this->isNewID($ID)) { + $btn_url = Plugin::getWebDir('fields') . '/front/export_to_yaml.php?id=' . $ID; + $btn_label = __("Export to YAML", "fields"); + $export_btn = << + + +HTML; + $options['header_toolbar'] = [$export_btn]; + } + + $this->showFormHeader($options); + $rand = mt_rand(); + + echo ""; + echo "" . __("Label") . " : "; + echo ""; + echo Html::input( + 'label', + [ + 'value' => $this->fields['label'], + ] + ); + echo ""; + echo " "; + echo " "; + echo ""; + + echo ""; + echo "" . __("Type") . " : "; + echo ""; + if ($ID > 0) { $types = self::getTypes(); - return $types[$values[$field]]; - case 'itemtypes' : - $types = json_decode($values[$field]); - $obj = ''; + echo $types[$this->fields["type"]]; + } else { + Dropdown::showFromArray( + 'type', + self::getTypes(), + [ + 'value' => $this->fields["type"], + 'rand' => $rand + ] + ); + Ajax::updateItemOnSelectEvent( + "dropdown_type$rand", + "itemtypes_$rand", + "../ajax/container_itemtypes_dropdown.php", + [ + 'type' => '__VALUE__', + 'itemtype' => $this->fields["itemtypes"], + 'subtype' => $this->fields['subtype'], + 'rand' => $rand + ] + ); + } + echo ""; + echo "" . __("Associated item type") . " : "; + echo ""; + if ($ID > 0) { + $types = json_decode($this->fields['itemtypes']); + $obj = ''; $count = count($types); - $i = 1; + $i = 1; foreach ($types as $type) { - // prevent usage of plugin class if not loaded - if (!class_exists($type)) { - continue; - } - $name_type = getItemForItemtype($type); - $obj .= $name_type->getTypeName(2); - if ($count > $i) { - $obj .= ", "; - } - $i++; + // prevent usage of plugin class if not loaded + if (!class_exists($type)) { + continue; + } + + $name_type = getItemForItemtype($type); + $obj .= $name_type->getTypeName(2); + if ($count > $i) { + $obj .= ", "; + } + $i++; } - return $obj; - } - } - - - function getValueToSelect($field_id_or_search_options, $name = '', $values = '', $options = []) { - - switch ($field_id_or_search_options['table'].'.'.$field_id_or_search_options['field']) { - // For searchoption "Type" - case $this->getTable().'.type': - $options['display'] = false; - return Dropdown::showFromArray($name, self::getTypes(), $options); - case $this->getTable().'.itemtypes': - $options['display'] = false; - return Dropdown::showFromArray($name, self::getItemtypes(), $options); - } - - return parent::getValueToSelect($field_id_or_search_options, $name, $values, $options); - } - - function defineTabs($options = []) { - $ong = []; - $this->addDefaultFormTab($ong); - $this->addStandardTab('PluginFieldsField', $ong, $options); - $this->addStandardTab('PluginFieldsStatusOverride', $ong, $options); - $this->addStandardTab('PluginFieldsProfile', $ong, $options); - $this->addStandardTab('PluginFieldsContainerDisplayCondition', $ong, $options); - $this->addStandardTab('PluginFieldsLabelTranslation', $ong, $options); - - return $ong; - } - - function prepareInputForAdd($input) { - if (!isset($input['itemtypes'])) { - Session::AddMessageAfterRedirect(__("You cannot add block without associated element type", - "fields"), - false, ERROR); - return false; - } - - if (!is_array($input['itemtypes'])) { - $input['itemtypes'] = [$input['itemtypes']]; - } - - if ($input['type'] === "dom") { - //check for already exist dom container with this itemtype - $found = $this->find(['type' => 'dom']); - if (count($found) > 0) { - foreach (array_column($found, 'itemtypes') as $founditemtypes) { - foreach (json_decode($founditemtypes) as $founditemtype) { - if (in_array( $founditemtype, $input['itemtypes'])) { - Session::AddMessageAfterRedirect(__("You cannot add several blocks with type 'Insertion in the form' on same object", "fields"), false, ERROR); - return false; - } - } + echo $obj; + } else { + echo " "; + self::showFormItemtype([ + 'rand' => $rand, + 'subtype' => $this->fields['subtype'] + ]); + echo ""; + } + echo ""; + echo ""; + + $display = "style='display:none'"; + if (!empty($this->fields["subtype"])) { + $display = ""; + } + echo ""; + echo ""; + echo "" . __("Tab", "fields") . " : "; + echo ""; + echo " "; + if ($ID > 0 && !empty($this->fields["subtype"])) { + $itemtypes = json_decode($this->fields["itemtypes"], true); + $itemtype = array_shift($itemtypes); + $item = new $itemtype(); + $item->getEmpty(); + $tabs = self::getSubtypes($item); + echo $tabs[$this->fields["subtype"]]; + } + echo ""; + echo ""; + + echo ""; + echo "" . __("Active") . " : "; + echo ""; + Dropdown::showYesNo("is_active", $this->fields["is_active"]); + echo ""; + echo ""; + + $this->showFormButtons($options); + + return true; + } + + public static function showFormItemtype($params = []) + { + $is_domtab = isset($params['type']) && $params['type'] == 'domtab'; + + $rand = $params['rand']; + Dropdown::showFromArray( + "itemtypes", + self::getItemtypes($is_domtab), + [ + 'rand' => $rand, + 'multiple' => !$is_domtab, + 'width' => 200, + 'display_emptychoice' => $is_domtab + ] + ); + + if ($is_domtab) { + Ajax::updateItemOnSelectEvent( + ["dropdown_type$rand", "dropdown_itemtypes$rand"], + "subtype_$rand", + "../ajax/container_subtype_dropdown.php", + [ + 'type' => '__VALUE0__', + 'itemtype' => '__VALUE1__', + 'subtype' => $params["subtype"], + 'rand' => $rand + ] + ); + } + } + + /** + * Show subtype selection form + * + * @param array $params Parameters + * @param boolean $display Whether to display or not; defaults to false + * + * @return string|void + */ + public static function showFormSubtype($params, $display = false) + { + $out = ""; + if (isset($params['type']) && $params['type'] == "domtab") { + if (class_exists($params['itemtype'])) { + $item = new $params['itemtype'](); + $item->getEmpty(); + + $tabs = self::getSubtypes($item); + + if (count($tabs)) { + // delete Log of array (don't work with this tab) + $tabs_to_remove = ['Log$1', 'Document_Item$1']; + foreach ($tabs_to_remove as $tab_to_remove) { + if (isset($tabs[$tab_to_remove])) { + unset($tabs[$tab_to_remove]); + } + } + + // For delete number : + foreach ($tabs as &$value) { + $results = []; + if (preg_match_all('#(.+)#', $value, $results)) { + $value = str_replace($results[0][0], "", $value); + } + } + + if (!isset($params['subtype'])) { + $params['subtype'] = null; + } + + $out .= Dropdown::showFromArray( + 'subtype', + $tabs, + ['value' => $params['subtype'], + 'width' => '100%', + 'display' => false + ] + ); + $out .= ""; + } } - } - } - - if ($input['type'] === "domtab") { - //check for already exist domtab container with this itemtype on this tab - $found = $this->find(['type' => 'domtab', 'subtype' => $input['subtype']]); - if (count($found) > 0) { - foreach (array_column( $found, 'itemtypes' ) as $founditemtypes) { - foreach (json_decode( $founditemtypes ) as $founditemtype) { - if (in_array( $founditemtype, $input['itemtypes'])) { - Session::AddMessageAfterRedirect(__("You cannot add several blocks with type 'Insertion in the form of a specific tab' on same object tab", "fields"), false, ERROR); - return false; - } - } + } + if ($display === false) { + return $out; + } else { + echo $out; + } + } + + /** + * Get supported item types + * + * @param boolean $is_domtab Domtab or not + * + * @return array + */ + public static function getItemtypes($is_domtab) + { + $all_itemtypes = PluginFieldsToolbox::getGlpiItemtypes(); + + if ($is_domtab) { + // Filter items that do not have tab handled + foreach ($all_itemtypes as $section => $itemtypes) { + $all_itemtypes[$section] = array_filter( + $itemtypes, + function ($itemtype) { + return count(self::getSubtypes($itemtype)) > 0; + }, + ARRAY_FILTER_USE_KEY + ); } - } - } - - $toolbox = new PluginFieldsToolbox(); - $input['name'] = $toolbox->getSystemNameFromLabel($input['label']); - //reject adding when container name is too long for mysql table name - foreach ($input['itemtypes'] as $itemtype) { - $tmp = getTableForItemType(self::getClassname($itemtype, $input['name'])); - if (strlen($tmp) > 64) { - Session::AddMessageAfterRedirect( - __("Container name is too long for database (digits in name are replaced by characters, try to remove them)", 'fields'), - false, - ERROR - ); - return false; - } - } - - //check for already existing container with same name - $found = $this->find(['name' => $input['name']]); - if (count($found) > 0) { - foreach (array_column($found, 'itemtypes') as $founditemtypes) { - foreach (json_decode($founditemtypes) as $founditemtype) { - if (in_array($founditemtype, $input['itemtypes'])) { - Session::AddMessageAfterRedirect(__("You cannot add several blocs with identical name on same object", "fields"), false, ERROR); - return false; - } - } - } - } - - $input['itemtypes'] = isset($input['itemtypes']) - ? Sanitizer::dbEscape(json_encode($input['itemtypes'])) - : null; - - return $input; - } - - function post_addItem() { - - if (!isset($this->input['clone']) || !$this->input['clone']) { - //create profiles associated to this container - PluginFieldsProfile::createForContainer($this); - //Create label translation - PluginFieldsLabelTranslation::createForItem($this); - } - - self::create($this->fields); - } - - public static function create($fields) { - //create class file - if (!self::generateTemplate($fields)) { - return false; - } - - foreach (json_decode($fields['itemtypes']) as $itemtype) { - //install table for receive field - $classname = self::getClassname($itemtype, $fields['name']); - $classname::install(); - } - } - - public static function generateTemplate($fields) { - $itemtypes = strlen($fields['itemtypes']) > 0 - ? json_decode($fields['itemtypes'], true) - : []; - foreach ($itemtypes as $itemtype) { - // prevent usage of plugin class if not loaded - if (!class_exists($itemtype)) { - continue; - } - - $sysname = self::getSystemName($itemtype, $fields['name']); - $classname = self::getClassname($itemtype, $fields['name']); - - $template_class = file_get_contents(PLUGINFIELDS_DIR."/templates/container.class.tpl"); - $template_class = str_replace("%%CLASSNAME%%", $classname, $template_class); - $template_class = str_replace("%%ITEMTYPE%%", $itemtype, $template_class); - $template_class = str_replace("%%CONTAINER%%", $fields['id'], $template_class); - $template_class = str_replace("%%ITEMTYPE_RIGHT%%", $itemtype::$rightname, $template_class); - $class_filename = $sysname.".class.php"; - if (file_put_contents(PLUGINFIELDS_CLASS_PATH . "/$class_filename", $template_class) === false) { - Toolbox::logDebug("Error : class file creation - $class_filename"); - return false; - } - - // Generate Datainjection files - $template_class = file_get_contents(PLUGINFIELDS_DIR."/templates/injection.class.tpl"); - $template_class = str_replace("%%CLASSNAME%%", $classname, $template_class); - $template_class = str_replace("%%ITEMTYPE%%", $itemtype, $template_class); - $template_class = str_replace("%%CONTAINER_ID%%", $fields['id'], $template_class); - $template_class = str_replace("%%CONTAINER_NAME%%", $fields['label'], $template_class); - $class_filename = $sysname."injection.class.php"; - if (file_put_contents(PLUGINFIELDS_CLASS_PATH . "/$class_filename", $template_class) === false) { - Toolbox::logDebug("Error : datainjection class file creation - $class_filename"); + // Filter groupts that do not have items handled + $all_itemtypes = array_filter($all_itemtypes); + } + + return $all_itemtypes; + } + + public static function getTypes() + { + return [ + 'tab' => __("Add tab", "fields"), + 'dom' => __("Insertion in the form (before save button)", "fields"), + 'domtab' => __("Insertion in the form of a specific tab (before save button)", "fields") + ]; + } + + public static function getEntries($type = 'tab', $full = false) + { + global $DB; + + $condition = [ + 'is_active' => 1, + ]; + if ($type !== "all") { + $condition[] = ['type' => $type]; + } + + if (!$DB->tableExists(self::getTable())) { return false; - } - } - return true; - } - - function pre_deleteItem() { - global $DB; - - $_SESSION['delete_container'] = true; - - foreach (json_decode($this->fields['itemtypes']) as $itemtype) { - $classname = self::getClassname($itemtype, $this->fields['name']); - $sysname = self::getSystemName($itemtype, $this->fields['name']); - $class_filename = $sysname.".class.php"; - $injection_filename = $sysname."injection.class.php"; - - //delete fields - $field_obj = new PluginFieldsField; - $field_obj->deleteByCriteria([ - 'plugin_fields_containers_id' => $this->fields['id'] - ]); - - //delete display condition - $field_obj = new PluginFieldsContainerDisplayCondition(); - $field_obj->deleteByCriteria([ - 'plugin_fields_containers_id' => $this->fields['id'] - ]); - - //delete profiles - $profile_obj = new PluginFieldsProfile; - $profile_obj->deleteByCriteria([ - 'plugin_fields_containers_id' => $this->fields['id'] - ]); - - //delete label translations - $translation_obj = new PluginFieldsLabelTranslation(); - $translation_obj->deleteByCriteria([ - 'itemtype' => self::getType(), - 'items_id' => $this->fields['id'] - ]); - - //delete table - if (class_exists($classname)) { - $classname::uninstall(); - } else { - //class does not exists; try to remove any existing table - $tablename = getTableForItemType($classname); - $DB->query("DROP TABLE IF EXISTS `$tablename`"); - } - - //clean session - unset($_SESSION['delete_container']); - - //remove file - if (file_exists(PLUGINFIELDS_CLASS_PATH . "/$class_filename")) { - unlink(PLUGINFIELDS_CLASS_PATH . "/$class_filename"); - } - - if (file_exists(PLUGINFIELDS_CLASS_PATH . "/$injection_filename")) { - unlink(PLUGINFIELDS_CLASS_PATH . "/$injection_filename"); - } - } - - return true; - } - - static function preItemPurge($item) { - $itemtype = get_class($item); - $containers = new self(); - $founded_containers = $containers->find(); - foreach ($founded_containers as $container) { - $itemtypes = json_decode($container['itemtypes']); - if (in_array($itemtype, $itemtypes)) { - $classname = 'PluginFields' . $itemtype . getSingular($container['name']); - $fields = new $classname(); - $fields->deleteByCriteria(['items_id' => $item->fields['id']], true); - } - } - return true; - } - - static function getTypeName($nb = 0) { - return __("Block", "fields"); - } - - public function showForm($ID, $options = []) { - - $this->initForm($ID, $options); - - if (!$this->isNewID($ID)) { - $btn_url = Plugin::getWebDir('fields') . '/front/export_to_yaml.php?id=' . $ID; - $btn_label = __("Export to YAML", "fields"); - $export_btn = << - - -HTML; - $options['header_toolbar'] = [$export_btn]; - } - - $this->showFormHeader($options); - $rand = mt_rand(); - - echo ""; - echo "".__("Label")." : "; - echo ""; - echo Html::input( - 'label', - [ - 'value' => $this->fields['label'], - ] - ); - echo ""; - echo " "; - echo " "; - echo ""; - - echo ""; - echo "".__("Type")." : "; - echo ""; - if ($ID > 0) { - $types = self::getTypes(); - echo $types[$this->fields["type"]]; - } else { - Dropdown::showFromArray('type', - self::getTypes(), - ['value' => $this->fields["type"], - 'rand' => $rand]); - Ajax::updateItemOnSelectEvent("dropdown_type$rand", - "itemtypes_$rand", - "../ajax/container_itemtypes_dropdown.php", - ['type' => '__VALUE__', - 'itemtype' => $this->fields["itemtypes"], - 'subtype' => $this->fields['subtype'], - 'rand' => $rand]); - } - echo ""; - echo "".__("Associated item type")." : "; - echo ""; - if ($ID > 0) { - $types = json_decode($this->fields['itemtypes']); - $obj = ''; - $count = count($types); - $i = 1; - foreach ($types as $type) { - // prevent usage of plugin class if not loaded - if (!class_exists($type)) { - continue; + } + + $itemtypes = []; + $container = new self(); + $profile = new PluginFieldsProfile(); + $found = $container->find($condition, 'label'); + foreach ($found as $item) { + //entities restriction + if (!in_array($item['entities_id'], $_SESSION['glpiactiveentities'])) { + if ($item['is_recursive'] == 1) { + $entities = getSonsOf("glpi_entities", $item['entities_id']); + if (count(array_intersect($entities, $_SESSION['glpiactiveentities'])) == 0) { + continue; + } + } else { + continue; + } } - $name_type = getItemForItemtype($type); - $obj .= $name_type->getTypeName(2); - if ($count > $i) { - $obj .= ", "; + if (Session::isCron() || !isset($_SESSION['glpiactiveprofile']['id'])) { + continue; } - $i++; - } - echo $obj; - - } else { - echo " "; - self::showFormItemtype(['rand' => $rand, - 'subtype' => $this->fields['subtype']]); - echo ""; - } - echo ""; - echo ""; - - $display = "style='display:none'"; - if (!empty($this->fields["subtype"])) { - $display = ""; - } - echo ""; - echo ""; - echo "".__("Tab", "fields")." : "; - echo ""; - echo " "; - if ($ID > 0 && !empty($this->fields["subtype"])) { - $itemtypes = json_decode($this->fields["itemtypes"], true); - $itemtype = array_shift($itemtypes); - $item = new $itemtype; - $item->getEmpty(); - $tabs = self::getSubtypes($item); - echo $tabs[$this->fields["subtype"]]; - } - echo ""; - echo ""; - - echo ""; - echo "".__("Active")." : "; - echo ""; - Dropdown::showYesNo("is_active", $this->fields["is_active"]); - echo ""; - echo ""; - - $this->showFormButtons($options); - - return true; - } - - static function showFormItemtype($params = []) { - $is_domtab = isset($params['type']) && $params['type'] == 'domtab'; - - $rand = $params['rand']; - Dropdown::showFromArray("itemtypes", self::getItemtypes($is_domtab), - ['rand' => $rand, - 'multiple' => !$is_domtab, - 'width' => 200, - 'display_emptychoice' => $is_domtab]); - - if ($is_domtab) { - Ajax::updateItemOnSelectEvent(["dropdown_type$rand", "dropdown_itemtypes$rand"], - "subtype_$rand", - "../ajax/container_subtype_dropdown.php", - ['type' => '__VALUE0__', - 'itemtype' => '__VALUE1__', - 'subtype' => $params["subtype"], - 'rand' => $rand]); - } - } - - /** - * Show subtype selection form - * - * @param array $params Parameters - * @param boolean $display Whether to display or not; defaults to false - * - * @return string|void - */ - static function showFormSubtype($params, $display = false) { - $out = ""; - if (isset($params['type']) && $params['type'] == "domtab") { - if (class_exists($params['itemtype'])) { - $item = new $params['itemtype']; - $item->getEmpty(); - - $tabs = self::getSubtypes($item); - - if (count($tabs)) { - // delete Log of array (don't work with this tab) - $tabs_to_remove = ['Log$1', 'Document_Item$1']; - foreach ($tabs_to_remove as $tab_to_remove) { - if (isset($tabs[$tab_to_remove])) { - unset($tabs[$tab_to_remove]); - } - } - - // For delete number : - foreach ($tabs as &$value) { - $results = []; - if (preg_match_all('#(.+)#', $value, $results)) { - $value = str_replace($results[0][0], "", $value); - } - } - - if (!isset($params['subtype'])) { - $params['subtype'] = null; - } - - $out .= Dropdown::showFromArray('subtype', $tabs, - ['value' => $params['subtype'], - 'width' => '100%', - 'display' => false]); - $out .= ""; + //profiles restriction + $found = $profile->find(['profiles_id' => $_SESSION['glpiactiveprofile']['id'], + 'plugin_fields_containers_id' => $item['id'], + 'right' => ['>=', READ] + ]); + $first_found = array_shift($found); + if (!$first_found || $first_found['right'] == null || $first_found['right'] == 0) { + continue; } - } - } - if ($display === false) { - return $out; - } else { - echo $out; - } - } - - /** - * Get supported item types - * - * @param boolean $is_domtab Domtab or not - * - * @return array - */ - static function getItemtypes($is_domtab) { - - $all_itemtypes = PluginFieldsToolbox::getGlpiItemtypes(); - - if ($is_domtab) { - // Filter items that do not have tab handled - foreach ($all_itemtypes as $section => $itemtypes) { - $all_itemtypes[$section] = array_filter( - $itemtypes, - function ($itemtype) { - return count(self::getSubtypes($itemtype)) > 0; - }, - ARRAY_FILTER_USE_KEY - ); - } - - // Filter groupts that do not have items handled - $all_itemtypes = array_filter($all_itemtypes); - } - - return $all_itemtypes; - } - - static function getTypes() { - return [ - 'tab' => __("Add tab", "fields"), - 'dom' => __("Insertion in the form (before save button)", "fields"), - 'domtab' => __("Insertion in the form of a specific tab (before save button)", "fields") - ]; - } - - static function getEntries($type = 'tab', $full = false) { - global $DB; - - $condition = [ - 'is_active' => 1, - ]; - if ($type !== "all") { - $condition[] = ['type' => $type]; - } - - if (!$DB->tableExists(self::getTable())) { - return false; - } - - $itemtypes = []; - $container = new self; - $profile = new PluginFieldsProfile; - $found = $container->find($condition, 'label'); - foreach ($found as $item) { - //entities restriction - if (!in_array($item['entities_id'], $_SESSION['glpiactiveentities'])) { - if ($item['is_recursive'] == 1) { - $entities = getSonsOf("glpi_entities", $item['entities_id']); - if (count(array_intersect($entities, $_SESSION['glpiactiveentities'])) == 0) { - continue; - } - } else { - continue; + + $jsonitemtypes = json_decode($item['itemtypes']); + //show more info or not + foreach ($jsonitemtypes as $v) { + if ($full) { + //check for translation + $item['itemtype'] = self::getType(); + $label = PluginFieldsLabelTranslation::getLabelFor($item); + $itemtypes[$v][$item['name']] = $label; + } else { + $itemtypes[] = $v; + } } - } - - if (Session::isCron() || !isset($_SESSION['glpiactiveprofile']['id'])) { - continue; - } - //profiles restriction - $found = $profile->find(['profiles_id' => $_SESSION['glpiactiveprofile']['id'], - 'plugin_fields_containers_id' => $item['id'], - 'right' => ['>=', READ]]); - $first_found = array_shift($found); - if (!$first_found || $first_found['right'] == null || $first_found['right'] == 0) { - continue; - } - - $jsonitemtypes = json_decode($item['itemtypes']); - //show more info or not - foreach ($jsonitemtypes as $v) { - if ($full) { - //check for translation - $item['itemtype'] = self::getType(); - $label = PluginFieldsLabelTranslation::getLabelFor($item); - $itemtypes[$v][$item['name']] = $label; - } else { - $itemtypes[] = $v; + } + return $itemtypes; + } + + public static function getUsedItemtypes($type = 'all', $must_be_active = false) + { + global $DB; + $itemtypes = []; + $where = $type == 'all' ? '1=1' : ('type = "' . $type . '"'); + if ($must_be_active) { + $where .= ' AND is_active = 1'; + } + + $query = 'SELECT DISTINCT `itemtypes` FROM `glpi_plugin_fields_containers` WHERE ' . $where; + $result = $DB->query($query); + while (list($data) = $DB->fetchArray($result)) { + $jsonitemtype = json_decode($data); + $itemtypes = array_merge($itemtypes, $jsonitemtype); + } + + return $itemtypes; + } + + public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) + { + $itemtypes = self::getEntries('tab', true); + if (isset($itemtypes[$item->getType()])) { + $tabs_entries = []; + $container = new self(); + foreach ($itemtypes[$item->getType()] as $tab_name => $tab_label) { + // needs to check if entity of item is in hierachy of $tab_name + foreach ($container->find(['is_active' => 1, 'name' => $tab_name]) as $data) { + $dataitemtypes = json_decode($data['itemtypes']); + if (in_array(get_class($item), $dataitemtypes) != false) { + $entities = [$data['entities_id']]; + if ($data['is_recursive']) { + $entities = getSonsOf(getTableForItemType('Entity'), $data['entities_id']); + } + + if (!$item->isEntityAssign() || in_array($item->fields['entities_id'], $entities)) { + $display_condition = new PluginFieldsContainerDisplayCondition(); + if ($display_condition->computeDisplayContainer($item, $data['id'])) { + $tabs_entries[$tab_name] = $tab_label; + } + } + } + } } - } - } - return $itemtypes; - } - - static function getUsedItemtypes($type = 'all', $must_be_active = false) { - global $DB; - $itemtypes = []; - $where = $type == 'all' - ? '1=1' - : 'type = "'.$type.'"'; - if ($must_be_active) { - $where .= ' AND is_active = 1'; - } - - $query = 'SELECT DISTINCT `itemtypes` - FROM `glpi_plugin_fields_containers` - WHERE '.$where; - $result = $DB->query($query); - while (list($data) = $DB->fetchArray($result)) { - $jsonitemtype = json_decode($data); - $itemtypes = array_merge($itemtypes, $jsonitemtype); - } - - return $itemtypes; - } - - function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { - $itemtypes = self::getEntries('tab', true); - if (isset($itemtypes[$item->getType()])) { - $tabs_entries = []; - $container = new self; - foreach ($itemtypes[$item->getType()] as $tab_name => $tab_label) { - // needs to check if entity of item is in hierachy of $tab_name - foreach ($container->find(['is_active' => 1, 'name' => $tab_name]) as $data) { - $dataitemtypes = json_decode($data['itemtypes']); - if (in_array(get_class($item), $dataitemtypes) != false) { - $entities = [$data['entities_id']]; - if ($data['is_recursive']) { - $entities = getSonsOf(getTableForItemType('Entity'), $data['entities_id']); - } - - if (!$item->isEntityAssign() || in_array($item->fields['entities_id'], $entities)) { - - $display_condition = new PluginFieldsContainerDisplayCondition(); - if($display_condition->computeDisplayContainer($item, $data['id'])) { - $tabs_entries[$tab_name] = $tab_label; - } - } - } + return $tabs_entries; + } + } + + + public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) + { + //retrieve container for current tab + $container = new self(); + $found_c = $container->find(['type' => 'tab', 'name' => $tabnum, 'is_active' => 1]); + foreach ($found_c as $data) { + $dataitemtypes = json_decode($data['itemtypes']); + if (in_array(get_class($item), $dataitemtypes) != false) { + return PluginFieldsField::showForTabContainer($data['id'], $item->fields['id'], get_class($item)); } - } - return $tabs_entries; - } - } - - - static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { - //retrieve container for current tab - $container = new self; - $found_c = $container->find(['type' => 'tab', 'name' => $tabnum, 'is_active' => 1]); - foreach ($found_c as $data) { - $dataitemtypes = json_decode($data['itemtypes']); - if (in_array(get_class($item), $dataitemtypes) != false) { - return PluginFieldsField::showForTabContainer($data['id'], $item->fields['id'], get_class($item)); - } - } - } - - /** - * Insert values submited by fields container - * - * @param array $data data posted - * @param string $itemtype Item type - * @param boolean $massiveaction Is a massive action - * - * @return boolean - */ - function updateFieldsValues($data, $itemtype, $massiveaction = false) { - if (self::validateValues($data, $itemtype, $massiveaction) === false) { - return false; - } - - $container_obj = new PluginFieldsContainer; - $container_obj->getFromDB($data['plugin_fields_containers_id']); - - $items_id = $data['items_id']; - $classname = self::getClassname($itemtype, $container_obj->fields['name']); - - //check if data already inserted - $obj = new $classname; - $found = $obj->find(['items_id' => $items_id]); - if (empty($found)) { - // add fields data - $obj->add($data); - - //construct history on itemtype object (Historical tab) - self::constructHistory($data['plugin_fields_containers_id'], $items_id, - $itemtype, $data); - - } else { - $first_found = array_pop($found); - $data['id'] = $first_found['id']; - $obj->update($data); - - //construct history on itemtype object (Historical tab) - self::constructHistory($data['plugin_fields_containers_id'], $items_id, - $itemtype, $data, $first_found); - } - - return true; - } - - /** - * Add log in "itemtype" object on fields values update - * @param int $containers_id container id - * @param int $items_id item id - * @param string $itemtype item type - * @param array $data values send by update form - * @param array $old_values old values, if empty -> values add - * @return void - */ - static function constructHistory($containers_id, $items_id, $itemtype, $data, - $old_values = []) { - // Don't log few itemtypes - $obj = new $itemtype(); - if ($obj->dohistory == false) { - return; - } - - //get searchoptions - $searchoptions = self::getAddSearchOptions($itemtype, $containers_id); - - //define non-data keys - $blacklist_k = [ - 'plugin_fields_containers_id' => 0, - 'items_id' => 0, - 'itemtype' => $itemtype, - 'update_fields_values' => 0, - '_glpi_csrf_token' => 0 - ]; - - //remove non-data keys - $data = array_diff_key($data, $blacklist_k); - - //add/update values condition - if (empty($old_values)) { - // -- add new item -- - - foreach ($data as $key => $value) { - //log only not empty values - if (!empty($value)) { - //prepare log - $changes = [0, "N/A", $value]; - - //find searchoption - foreach ($searchoptions as $id_search_option => $searchoption) { - if ($searchoption['linkfield'] == $key) { - $changes[0] = $id_search_option; - - //manage dropdown values - if ($searchoption['datatype'] === 'dropdown') { - $changes = [$id_search_option, + } + } + + /** + * Insert values submited by fields container + * + * @param array $data data posted + * @param string $itemtype Item type + * @param boolean $massiveaction Is a massive action + * + * @return boolean + */ + public function updateFieldsValues($data, $itemtype, $massiveaction = false) + { + if (self::validateValues($data, $itemtype, $massiveaction) === false) { + return false; + } + + $container_obj = new PluginFieldsContainer(); + $container_obj->getFromDB($data['plugin_fields_containers_id']); + + $items_id = $data['items_id']; + $classname = self::getClassname($itemtype, $container_obj->fields['name']); + + //check if data already inserted + $obj = new $classname(); + $found = $obj->find(['items_id' => $items_id]); + if (empty($found)) { + // add fields data + $obj->add($data); + + //construct history on itemtype object (Historical tab) + self::constructHistory( + $data['plugin_fields_containers_id'], + $items_id, + $itemtype, + $data + ); + } else { + $first_found = array_pop($found); + $data['id'] = $first_found['id']; + $obj->update($data); + + //construct history on itemtype object (Historical tab) + self::constructHistory( + $data['plugin_fields_containers_id'], + $items_id, + $itemtype, + $data, + $first_found + ); + } + + return true; + } + + /** + * Add log in "itemtype" object on fields values update + * @param int $containers_id container id + * @param int $items_id item id + * @param string $itemtype item type + * @param array $data values send by update form + * @param array $old_values old values, if empty -> values add + * @return void + */ + public static function constructHistory( + $containers_id, + $items_id, + $itemtype, + $data, + $old_values = [] + ) { + // Don't log few itemtypes + $obj = new $itemtype(); + if ($obj->dohistory == false) { + return; + } + + //get searchoptions + $searchoptions = self::getAddSearchOptions($itemtype, $containers_id); + + //define non-data keys + $blacklist_k = [ + 'plugin_fields_containers_id' => 0, + 'items_id' => 0, + 'itemtype' => $itemtype, + 'update_fields_values' => 0, + '_glpi_csrf_token' => 0 + ]; + + //remove non-data keys + $data = array_diff_key($data, $blacklist_k); + + //add/update values condition + if (empty($old_values)) { + // -- add new item -- + + foreach ($data as $key => $value) { + //log only not empty values + if (!empty($value)) { + //prepare log + $changes = [0, "N/A", $value]; + + //find searchoption + foreach ($searchoptions as $id_search_option => $searchoption) { + if ($searchoption['linkfield'] == $key) { + $changes[0] = $id_search_option; + + //manage dropdown values + if ($searchoption['datatype'] === 'dropdown') { + $changes = [$id_search_option, "", - Dropdown::getDropdownName($searchoption['table'], $value)]; - } - - //manage bool dropdown values - if ($searchoption['datatype'] === 'bool') { - $changes = [$id_search_option, "", Dropdown::getYesNo($value)]; - } - } - } - - //add log - Log::history($items_id, $itemtype, $changes); + Dropdown::getDropdownName($searchoption['table'], $value) + ]; + } + + //manage bool dropdown values + if ($searchoption['datatype'] === 'bool') { + $changes = [$id_search_option, "", Dropdown::getYesNo($value)]; + } + } + } + + //add log + Log::history($items_id, $itemtype, $changes); + } } - } - } else { - // -- update existing item -- - - //find changes - $updates = []; - foreach ($old_values as $key => $old_value) { - if (!isset($data[$key]) - || empty($old_value) && empty($data[$key]) - || $old_value !== '' && $data[$key] == 'NULL' + } else { + // -- update existing item -- + + //find changes + $updates = []; + foreach ($old_values as $key => $old_value) { + if ( + !isset($data[$key]) + || empty($old_value) && empty($data[$key]) + || $old_value !== '' && $data[$key] == 'NULL' ) { - continue; + continue; + } + + if ($data[$key] !== $old_value) { + $updates[$key] = [0, $old_value ?? '', $data[$key]]; + } } - if ($data[$key] !== $old_value) { - $updates[$key] = [0, $old_value ?? '', $data[$key]]; + //for all change find searchoption + foreach ($updates as $key => $changes) { + foreach ($searchoptions as $id_search_option => $searchoption) { + if ($searchoption['linkfield'] == $key) { + $changes[0] = $id_search_option; + + //manage dropdown values + if ($searchoption['datatype'] === 'dropdown') { + $changes[1] = Dropdown::getDropdownName($searchoption['table'], $changes[1]); + $changes[2] = Dropdown::getDropdownName($searchoption['table'], $changes[2]); + } + if ($searchoption['datatype'] === 'bool') { + $changes[1] = Dropdown::getYesNo($changes[1]); + $changes[2] = Dropdown::getYesNo($changes[2]); + } + } + } + + //add log + Log::history($items_id, $itemtype, $changes); } - } - - //for all change find searchoption - foreach ($updates as $key => $changes) { - foreach ($searchoptions as $id_search_option => $searchoption) { - if ($searchoption['linkfield'] == $key) { - $changes[0] = $id_search_option; - - //manage dropdown values - if ($searchoption['datatype'] === 'dropdown') { - $changes[1] = Dropdown::getDropdownName($searchoption['table'], $changes[1]); - $changes[2] = Dropdown::getDropdownName($searchoption['table'], $changes[2]); - } - if ($searchoption['datatype'] === 'bool') { - $changes[1] = Dropdown::getYesNo($changes[1]); - $changes[2] = Dropdown::getYesNo($changes[2]); - } - } + } + } + + /** + * check data inserted + * display a message when not ok + * + * @param array $data Data send by form + * @param string $itemtype Item type + * @param boolean $massiveaction ? + * + * @return boolean + */ + public static function validateValues($data, $itemtype, $massiveaction) + { + global $DB; + + $valid = true; + $empty_errors = []; + $number_errors = []; + + $container = new self(); + $container->getFromDB($data['plugin_fields_containers_id']); + + $field_obj = new PluginFieldsField(); + $fields = $field_obj->find([ + 'plugin_fields_containers_id' => $data['plugin_fields_containers_id'] + ]); + + foreach ($fields as $field) { + if (!$field['is_active']) { + continue; } - //add log - Log::history($items_id, $itemtype, $changes); - } - } - } - - /** - * check data inserted - * display a message when not ok - * - * @param array $data Data send by form - * @param string $itemtype Item type - * @param boolean $massiveaction ? - * - * @return boolean - */ - static function validateValues($data, $itemtype, $massiveaction) { - global $DB; - - $valid = true; - $empty_errors = []; - $number_errors = []; - - $container = new self(); - $container->getFromDB($data['plugin_fields_containers_id']); - - $field_obj = new PluginFieldsField(); - $fields = $field_obj->find([ - 'plugin_fields_containers_id' => $data['plugin_fields_containers_id'] - ]); - - foreach ($fields as $field) { - if (!$field['is_active']) { - continue; - } - - if ($field['type'] == "yesno" || $field['type'] == "header") { - continue; - } - - $name = $field['name']; - $value = null; - - if ($field['type'] == "glpi_item") { - $itemtype_key = sprintf('itemtype_%s', $name); - $items_id_key = sprintf('items_id_%s', $name); - - if ( - isset($data[$itemtype_key], $data[$items_id_key]) - && is_a($data[$itemtype_key], CommonDBTM::class, true) - && $data[$items_id_key] > 0 - ) { - $glpi_item = new $data[$itemtype_key](); - $value = $glpi_item->getFromDB($data[$items_id_key]) ? $data[$items_id_key] : null; - } - } elseif (isset($data[$name])) { - $value = $data[$name]; - } else if (isset($data['plugin_fields_'.$name.'dropdowns_id'])) { - $value = $data['plugin_fields_'.$name.'dropdowns_id']; - } else if ($field['mandatory'] == 1) { - $tablename = getTableForItemType(self::getClassname($itemtype, $container->fields['name'])); - - $query = "SELECT * FROM `$tablename` WHERE - `itemtype`='$itemtype' - AND `items_id`='{$data['items_id']}' - AND `plugin_fields_containers_id`='{$data['plugin_fields_containers_id']}'"; - - $db_result = []; - if ($result = $DB->query($query)) { - $db_result = $DB->fetchAssoc($result); - if (isset($db_result[$name])) { - $value = $db_result[$name]; - } + if ($field['type'] == "yesno" || $field['type'] == "header") { + continue; } - } else { - if ($massiveaction) { - continue; + $name = $field['name']; + $value = null; + + if ($field['type'] == "glpi_item") { + $itemtype_key = sprintf('itemtype_%s', $name); + $items_id_key = sprintf('items_id_%s', $name); + + if ( + isset($data[$itemtype_key], $data[$items_id_key]) + && is_a($data[$itemtype_key], CommonDBTM::class, true) + && $data[$items_id_key] > 0 + ) { + $glpi_item = new $data[$itemtype_key](); + $value = $glpi_item->getFromDB($data[$items_id_key]) ? $data[$items_id_key] : null; + } + } elseif (isset($data[$name])) { + $value = $data[$name]; + } else if (isset($data['plugin_fields_' . $name . 'dropdowns_id'])) { + $value = $data['plugin_fields_' . $name . 'dropdowns_id']; + } else if ($field['mandatory'] == 1) { + $tablename = getTableForItemType(self::getClassname($itemtype, $container->fields['name'])); + + $query = "SELECT * FROM `$tablename` WHERE + `itemtype`='$itemtype' + AND `items_id`='{$data['items_id']}' + AND `plugin_fields_containers_id`='{$data['plugin_fields_containers_id']}'"; + + $db_result = []; + if ($result = $DB->query($query)) { + $db_result = $DB->fetchAssoc($result); + if (isset($db_result[$name])) { + $value = $db_result[$name]; + } + } + } else { + if ($massiveaction) { + continue; + } } - } - - //translate label - $field['itemtype'] = PluginFieldsField::getType(); - $field['label'] = PluginFieldsLabelTranslation::getLabelFor($field); - - // Check mandatory fields - if ( - $field['mandatory'] == 1 - && ( - $value === null - || $value === '' - || (($field['type'] === 'dropdown' || preg_match('/^dropdown-.+/i', $field['type'])) && $value == 0) - || ($field['type'] === 'glpi_item' && $value === null) - || (in_array($field['type'], ['date', 'datetime']) && $value == 'NULL') - ) - ) { - $empty_errors[] = $field['label']; - $valid = false; - } else if ($field['type'] == 'number' && !empty($value) && !is_numeric($value)) { - // Check number fields - $number_errors[] = $field['label']; - $valid = false; - } else if ($field['type'] == 'url' && !empty($value)) { - if (filter_var($value, FILTER_VALIDATE_URL) === false) { - $url_errors[] = $field['label']; - $valid = false; + + //translate label + $field['itemtype'] = PluginFieldsField::getType(); + $field['label'] = PluginFieldsLabelTranslation::getLabelFor($field); + + // Check mandatory fields + if ( + $field['mandatory'] == 1 + && ( + $value === null + || $value === '' + || (($field['type'] === 'dropdown' || preg_match('/^dropdown-.+/i', $field['type'])) && $value == 0) + || ($field['type'] === 'glpi_item' && $value === null) + || (in_array($field['type'], ['date', 'datetime']) && $value == 'NULL') + ) + ) { + $empty_errors[] = $field['label']; + $valid = false; + } else if ($field['type'] == 'number' && !empty($value) && !is_numeric($value)) { + // Check number fields + $number_errors[] = $field['label']; + $valid = false; + } else if ($field['type'] == 'url' && !empty($value)) { + if (filter_var($value, FILTER_VALIDATE_URL) === false) { + $url_errors[] = $field['label']; + $valid = false; + } } - } - } + } - if (!empty($empty_errors)) { - Session::AddMessageAfterRedirect(__("Some mandatory fields are empty", "fields"). - " : ".implode(', ', $empty_errors), false, ERROR); - } + if (!empty($empty_errors)) { + Session::AddMessageAfterRedirect(__("Some mandatory fields are empty", "fields") . + " : " . implode(', ', $empty_errors), false, ERROR); + } - if (!empty($number_errors)) { - Session::AddMessageAfterRedirect(__("Some numeric fields contains non numeric values", "fields"). - " : ".implode(', ', $number_errors), false, ERROR); - } + if (!empty($number_errors)) { + Session::AddMessageAfterRedirect(__("Some numeric fields contains non numeric values", "fields") . + " : " . implode(', ', $number_errors), false, ERROR); + } - if (!empty($url_errors)) { - Session::AddMessageAfterRedirect(__("Some URL fields contains invalid links", "fields"). - " : ".implode(', ', $url_errors), false, ERROR); - } + if (!empty($url_errors)) { + Session::AddMessageAfterRedirect(__("Some URL fields contains invalid links", "fields") . + " : " . implode(', ', $url_errors), false, ERROR); + } - return $valid; - } + return $valid; + } - static function findContainer($itemtype, $type = 'tab', $subtype = '') { + public static function findContainer($itemtype, $type = 'tab', $subtype = '') + { - $condition = [ - 'is_active' => 1, - ['type' => $type], - ]; + $condition = [ + 'is_active' => 1, + ['type' => $type], + ]; - $entity = isset($_SESSION['glpiactiveentities']) + $entity = isset($_SESSION['glpiactiveentities']) ? $_SESSION['glpiactiveentities'] : 0; - $condition += getEntitiesRestrictCriteria("", "", $entity, true, true); - - if ($subtype != '') { - if ($subtype == $itemtype.'$main') { - $condition[] = ['type' => 'dom']; - } else { - $condition[] = ['type' => ['!=', 'dom']]; - $condition['subtype'] = $subtype; - } - } - - $container = new PluginFieldsContainer(); - $itemtypes = $container->find($condition); - $id = 0; - if (count($itemtypes) < 1) { - return false; - } - - foreach ($itemtypes as $data) { - $dataitemtypes = json_decode($data['itemtypes']); - if (in_array($itemtype, $dataitemtypes) != false) { - $id = $data['id']; - } - } - - //profiles restriction - if (isset($_SESSION['glpiactiveprofile']['id'])) { - $profile = new PluginFieldsProfile(); - if (isset($id)) { - $found = $profile->find(['profiles_id' => $_SESSION['glpiactiveprofile']['id'], - 'plugin_fields_containers_id' => $id]); - $first_found = array_shift($found); - if ($first_found === null || $first_found['right'] == null || $first_found['right'] == 0) { - return false; + $condition += getEntitiesRestrictCriteria("", "", $entity, true, true); + + if ($subtype != '') { + if ($subtype == $itemtype . '$main') { + $condition[] = ['type' => 'dom']; + } else { + $condition[] = ['type' => ['!=', 'dom']]; + $condition['subtype'] = $subtype; + } + } + + $container = new PluginFieldsContainer(); + $itemtypes = $container->find($condition); + $id = 0; + if (count($itemtypes) < 1) { + return false; + } + + foreach ($itemtypes as $data) { + $dataitemtypes = json_decode($data['itemtypes']); + if (in_array($itemtype, $dataitemtypes) != false) { + $id = $data['id']; + } + } + + //profiles restriction + if (isset($_SESSION['glpiactiveprofile']['id'])) { + $profile = new PluginFieldsProfile(); + if (isset($id)) { + $found = $profile->find(['profiles_id' => $_SESSION['glpiactiveprofile']['id'], + 'plugin_fields_containers_id' => $id + ]); + $first_found = array_shift($found); + if ($first_found === null || $first_found['right'] == null || $first_found['right'] == 0) { + return false; + } + } + } + + return $id; + } + + /** + * Post item hook for add + * Do store data in db + * + * @param CommonDBTM $item Item instance + * + * @return CommonDBTM|true + */ + public static function postItemAdd(CommonDBTM $item) + { + if (property_exists($item, 'plugin_fields_data')) { + $data = $item->plugin_fields_data; + $data['items_id'] = $item->getID(); + //update data + $container = new self(); + if ($container->updateFieldsValues($data, $item->getType(), isset($_REQUEST['massiveaction']))) { + return true; } - } - } - - return $id; - } - - /** - * Post item hook for add - * Do store data in db - * - * @param CommonDBTM $item Item instance - * - * @return CommonDBTM|true - */ - static function postItemAdd(CommonDBTM $item) { - if (property_exists($item, 'plugin_fields_data')) { - $data = $item->plugin_fields_data; - $data['items_id'] = $item->getID(); - //update data - $container = new self(); - if ($container->updateFieldsValues($data, $item->getType(), isset($_REQUEST['massiveaction']))) { - return true; - } - return $item->input = []; - } - } - - /** - * Pre item hook for update - * Do store data in db - * - * @param CommonDBTM $item Item instance - * - * @return boolean - */ - static function preItemUpdate(CommonDBTM $item) { - self::preItem($item); - if (property_exists($item, 'plugin_fields_data')) { - $data = $item->plugin_fields_data; - //update data - $container = new self(); - if (count($data) == 0 - || $container->updateFieldsValues($data, $item->getType(), isset($_REQUEST['massiveaction']))) { - return true; - } - return $item->input = []; - } - } - - - /** - * Pre item hook for add and update - * Validates and store plugin data in item object - * - * @param CommonDBTM $item Item instance - * - * @return boolean - */ - static function preItem(CommonDBTM $item) { - //find container (if not exist, do nothing) - if (isset($_REQUEST['c_id'])) { - $c_id = $_REQUEST['c_id']; - } else { - $type = 'dom'; - if (isset($_REQUEST['_plugin_fields_type'])) { - $type = $_REQUEST['_plugin_fields_type']; - } - $subtype = ''; - if ($type == 'domtab') { - $subtype = $_REQUEST['_plugin_fields_subtype']; - } - if (false === ($c_id = self::findContainer(get_Class($item), $type, $subtype))) { - // tries for 'tab' - if (false === ($c_id = self::findContainer(get_Class($item)))) { - return false; + return $item->input = []; + } + } + + /** + * Pre item hook for update + * Do store data in db + * + * @param CommonDBTM $item Item instance + * + * @return boolean + */ + public static function preItemUpdate(CommonDBTM $item) + { + self::preItem($item); + if (property_exists($item, 'plugin_fields_data')) { + $data = $item->plugin_fields_data; + //update data + $container = new self(); + if ( + count($data) == 0 + || $container->updateFieldsValues($data, $item->getType(), isset($_REQUEST['massiveaction'])) + ) { + return true; } - } - } - - //need to check if container is usable on this object entity - $loc_c = new PluginFieldsContainer; - $loc_c->getFromDB($c_id); - $entities = [$loc_c->fields['entities_id']]; - if ($loc_c->fields['is_recursive']) { - $entities = getSonsOf(getTableForItemType('Entity'), $loc_c->fields['entities_id']); - } - - //workaround: when a ticket is created from readdonly profile, - //it is not initialized; see https://github.com/glpi-project/glpi/issues/1438 - if (!isset($item->fields) || count($item->fields) == 0) { - $item->fields = $item->input; - } - - $current_entity = $item::getType() == Entity::getType() - ? $item->getID() - : $item->fields['entities_id']; - if ($item->isEntityAssign() && !in_array($current_entity, $entities)) { - return false; - } - - if (false !== ($data = self::populateData($c_id, $item))) { - if (self::validateValues($data, $item::getType(), isset($_REQUEST['massiveaction'])) === false) { return $item->input = []; - } - return $item->plugin_fields_data = $data; - } - - return; - } - - /** - * Populates fields data from item - * - * @param integer $c_id Container ID - * @param CommonDBTM $item Item instance - * - * @return array|false - */ - static private function populateData($c_id, CommonDBTM $item) { - //find fields associated to found container - $field_obj = new PluginFieldsField(); - $fields = $field_obj->find( - [ - 'plugin_fields_containers_id' => $c_id, - 'type' => ['!=', 'header'] - ], - "ranking" - ); - - //prepare data to update - $data = ['plugin_fields_containers_id' => $c_id]; - if (!$item->isNewItem()) { - //no ID yet while creating - $data['items_id'] = $item->getID(); - } - - $has_fields = false; - foreach ($fields as $field) { - if ($field['type'] == 'glpi_item') { - $itemtype_key = sprintf('itemtype_%s', $field['name']); - $items_id_key = sprintf('items_id_%s', $field['name']); - - if (!isset($item->input[$itemtype_key], $item->input[$items_id_key])) { - continue; // not a valid input + } + } + + + /** + * Pre item hook for add and update + * Validates and store plugin data in item object + * + * @param CommonDBTM $item Item instance + * + * @return boolean + */ + public static function preItem(CommonDBTM $item) + { + //find container (if not exist, do nothing) + if (isset($_REQUEST['c_id'])) { + $c_id = $_REQUEST['c_id']; + } else { + $type = 'dom'; + if (isset($_REQUEST['_plugin_fields_type'])) { + $type = $_REQUEST['_plugin_fields_type']; + } + $subtype = ''; + if ($type == 'domtab') { + $subtype = $_REQUEST['_plugin_fields_subtype']; } + if (false === ($c_id = self::findContainer(get_Class($item), $type, $subtype))) { + // tries for 'tab' + if (false === ($c_id = self::findContainer(get_Class($item)))) { + return false; + } + } + } + + //need to check if container is usable on this object entity + $loc_c = new PluginFieldsContainer(); + $loc_c->getFromDB($c_id); + $entities = [$loc_c->fields['entities_id']]; + if ($loc_c->fields['is_recursive']) { + $entities = getSonsOf(getTableForItemType('Entity'), $loc_c->fields['entities_id']); + } + + //workaround: when a ticket is created from readdonly profile, + //it is not initialized; see https://github.com/glpi-project/glpi/issues/1438 + if (!isset($item->fields) || count($item->fields) == 0) { + $item->fields = $item->input; + } + + $current_entity = $item::getType() == Entity::getType() + ? $item->getID() + : $item->fields['entities_id']; + if ($item->isEntityAssign() && !in_array($current_entity, $entities)) { + return false; + } - $has_fields = true; - $data[$itemtype_key] = $item->input[$itemtype_key]; - $data[$items_id_key] = $item->input[$items_id_key]; - - continue; // bypass unique field handling - } - - if (isset($item->input[$field['name']])) { - //standard field - $input = $field['name']; - } else { - //dropdown field - $input = "plugin_fields_".$field['name']."dropdowns_id"; - } - if (isset($item->input[$input])) { - $has_fields = true; - // Before is_number check, help user to have a number correct, during a massive action of a number field - if ($field['type'] == 'number') { - $item->input[$input] = str_replace(",", ".", $item->input[$input]); + if (false !== ($data = self::populateData($c_id, $item))) { + if (self::validateValues($data, $item::getType(), isset($_REQUEST['massiveaction'])) === false) { + return $item->input = []; + } + return $item->plugin_fields_data = $data; + } + + return; + } + + /** + * Populates fields data from item + * + * @param integer $c_id Container ID + * @param CommonDBTM $item Item instance + * + * @return array|false + */ + private static function populateData($c_id, CommonDBTM $item) + { + //find fields associated to found container + $field_obj = new PluginFieldsField(); + $fields = $field_obj->find( + [ + 'plugin_fields_containers_id' => $c_id, + 'type' => ['!=', 'header'] + ], + "ranking" + ); + + //prepare data to update + $data = ['plugin_fields_containers_id' => $c_id]; + if (!$item->isNewItem()) { + //no ID yet while creating + $data['items_id'] = $item->getID(); + } + + $has_fields = false; + foreach ($fields as $field) { + if ($field['type'] == 'glpi_item') { + $itemtype_key = sprintf('itemtype_%s', $field['name']); + $items_id_key = sprintf('items_id_%s', $field['name']); + + if (!isset($item->input[$itemtype_key], $item->input[$items_id_key])) { + continue; // not a valid input + } + + $has_fields = true; + $data[$itemtype_key] = $item->input[$itemtype_key]; + $data[$items_id_key] = $item->input[$items_id_key]; + + continue; // bypass unique field handling } - $data[$input] = $item->input[$input]; - } - } - if ($has_fields === true) { - return $data; - } else { - return false; - } - } + if (isset($item->input[$field['name']])) { + //standard field + $input = $field['name']; + } else { + //dropdown field + $input = "plugin_fields_" . $field['name'] . "dropdowns_id"; + } + if (isset($item->input[$input])) { + $has_fields = true; + // Before is_number check, help user to have a number correct, during a massive action of a number field + if ($field['type'] == 'number') { + $item->input[$input] = str_replace(",", ".", $item->input[$input]); + } + $data[$input] = $item->input[$input]; + } + } - static function getAddSearchOptions($itemtype, $containers_id = false) { - global $DB; + if ($has_fields === true) { + return $data; + } else { + return false; + } + } + + public static function getAddSearchOptions($itemtype, $containers_id = false) + { + global $DB; - $opt = []; + $opt = []; - $i = 76665; + $i = 76665; - $search_string = json_encode($itemtype); - // Backslashes must be doubled in LIKE clause, according to MySQL documentation: - // > To search for \, specify it as \\\\; this is because the backslashes are stripped - // > once by the parser and again when the pattern match is made, - // > leaving a single backslash to be matched against. - $search_string = str_replace('\\', '\\\\', $search_string); + $search_string = json_encode($itemtype); + // Backslashes must be doubled in LIKE clause, according to MySQL documentation: + // > To search for \, specify it as \\\\; this is because the backslashes are stripped + // > once by the parser and again when the pattern match is made, + // > leaving a single backslash to be matched against. + $search_string = str_replace('\\', '\\\\', $search_string); - $query = "SELECT DISTINCT fields.id, fields.name, fields.label, fields.type, fields.is_readonly, fields.allowed_values, + $query = "SELECT DISTINCT fields.id, fields.name, fields.label, fields.type, fields.is_readonly, fields.allowed_values, containers.name as container_name, containers.label as container_label, containers.itemtypes, containers.id as container_id, fields.id as field_id FROM glpi_plugin_fields_containers containers INNER JOIN glpi_plugin_fields_profiles profiles ON containers.id = profiles.plugin_fields_containers_id AND profiles.right > 0 - AND profiles.profiles_id = ".(int) $_SESSION['glpiactiveprofile']['id']." + AND profiles.profiles_id = " . (int) $_SESSION['glpiactiveprofile']['id'] . " INNER JOIN glpi_plugin_fields_fields fields ON containers.id = fields.plugin_fields_containers_id AND containers.is_active = 1 WHERE containers.itemtypes LIKE '%" . $DB->escape($search_string) . "%' AND fields.type != 'header' ORDER BY fields.id ASC"; - $res = $DB->query($query); - while ($data = $DB->fetchAssoc($res)) { - - if ($containers_id !== false) { - // Filter by container (don't filter by SQL for have $i value with few containers for a itemtype) - if ($data['container_id'] != $containers_id) { - $i++; - continue; + $res = $DB->query($query); + while ($data = $DB->fetchAssoc($res)) { + if ($containers_id !== false) { + // Filter by container (don't filter by SQL for have $i value with few containers for a itemtype) + if ($data['container_id'] != $containers_id) { + $i++; + continue; + } } - } - $tablename = getTableForItemType(self::getClassname($itemtype, $data['container_name'])); - - //get translations - $container = [ - 'itemtype' => PluginFieldsContainer::getType(), - 'id' => $data['container_id'], - 'label' => $data['container_label'] - ]; - $data['container_label'] = PluginFieldsLabelTranslation::getLabelFor($container); - - $field = [ - 'itemtype' => PluginFieldsField::getType(), - 'id' => $data['field_id'], - 'label' => $data['label'] - ]; - $data['label'] = PluginFieldsLabelTranslation::getLabelFor($field); - - // Default SO params - $opt[$i]['table'] = $tablename; - $opt[$i]['field'] = $data['name']; - $opt[$i]['name'] = $data['container_label']." - ".$data['label']; - $opt[$i]['linkfield'] = $data['name']; - $opt[$i]['joinparams']['jointype'] = "itemtype_item"; - $opt[$i]['pfields_type'] = $data['type']; - if ($data['is_readonly']) { - $opt[$i]['massiveaction'] = false; - } - switch ($data['type']) { - case 'yesno': - $opt[$i]['datatype'] = "bool"; - break; - case 'textarea': - $opt[$i]['datatype'] = "text"; - break; - case 'number': - $opt[$i]['datatype'] = "decimal"; - break; - case 'date': - case 'datetime': - $opt[$i]['datatype'] = $data['type']; - break; - case 'url': - $opt[$i]['datatype'] = 'weblink'; - break; - default: - $opt[$i]['datatype'] = "string"; - } - - $dropdown_matches = []; - if ($data['type'] === "dropdown") { - $opt[$i]['table'] = 'glpi_plugin_fields_'.$data['name'].'dropdowns'; - $opt[$i]['field'] = 'completename'; - $opt[$i]['linkfield'] = "plugin_fields_".$data['name']."dropdowns_id"; - $opt[$i]['datatype'] = "dropdown"; - - $opt[$i]['forcegroupby'] = true; - - $opt[$i]['joinparams']['jointype'] = ""; - $opt[$i]['joinparams']['beforejoin']['table'] = $tablename; - $opt[$i]['joinparams']['beforejoin']['joinparams']['jointype'] = "itemtype_item"; - } elseif ( - preg_match('/^dropdown-(?.+)$/i', $data['type'], $dropdown_matches) - && class_exists($dropdown_matches['class']) - ) { - $opt[$i]['table'] = CommonDBTM::getTable($dropdown_matches['class']); - $opt[$i]['field'] = 'name'; - $opt[$i]['linkfield'] = $data['name']; - $opt[$i]['right'] = 'all'; - $opt[$i]['datatype'] = "dropdown"; - - $opt[$i]['forcegroupby'] = true; - - $opt[$i]['joinparams']['jointype'] = ""; - $opt[$i]['joinparams']['beforejoin']['table'] = $tablename; - $opt[$i]['joinparams']['beforejoin']['joinparams']['jointype'] = "itemtype_item"; - } elseif ($data['type'] === "glpi_item") { - $itemtype_field = sprintf('itemtype_%s', $data['name']); - $items_id_field = sprintf('items_id_%s', $data['name']); - - $opt[$i]['table'] = $tablename; - $opt[$i]['field'] = $itemtype_field; - $opt[$i]['linkfield'] = $itemtype_field; - $opt[$i]['name'] = $data['container_label']." - ".$data['label'].' - '._n('Associated item type', 'Associated item types', Session::getPluralNumber()); - $opt[$i]['datatype'] = 'itemtypename'; - $opt[$i]['types'] = !empty($data['allowed_values']) ? json_decode($data['allowed_values']) : []; - $opt[$i]['additionalfields'] = ['itemtype']; - $opt[$i]['joinparams']['jointype'] = 'itemtype_item'; - $opt[$i]['forcegroupby'] = true; - $opt[$i]['massiveaction'] = false; - $i++; + $tablename = getTableForItemType(self::getClassname($itemtype, $data['container_name'])); - $opt[$i]['table'] = $tablename; - $opt[$i]['field'] = $items_id_field; - $opt[$i]['linkfield'] = $items_id_field; - $opt[$i]['name'] = $data['container_label']." - ".$data['label'].' - '.__('Associated item ID'); - $opt[$i]['massiveaction'] = false; - $opt[$i]['joinparams']['jointype'] = 'itemtype_item'; - $opt[$i]['datatype'] = 'text'; - $opt[$i]['additionalfields'] = ['itemtype']; - } - - $i++; - } - - return $opt; - } - - /** - * Get subtypes for specified itemtype. - * Was previously retrieved using $item::defineTabs() but - * this is not relevant with actual core. - * - * @param CommonDBTM $item Item instance - * - * @return array - */ - private static function getSubtypes($item) { - $tabs = []; - switch ($item::getType()) { - case Ticket::getType(): - case Problem::getType(): - $tabs = [ - $item::getType() . '$2' => __('Solution') + //get translations + $container = [ + 'itemtype' => PluginFieldsContainer::getType(), + 'id' => $data['container_id'], + 'label' => $data['container_label'] ]; - break; - case Change::getType(): - $tabs = [ - 'Change$1' => __('Analysis'), - 'Change$2' => __('Solution'), - 'Change$3' => __('Plans') - ]; - break; - case Entity::getType(): - $tabs = [ - 'Entity$2' => __('Address'), - 'Entity$3' => __('Advanced information'), - 'Entity$4' => __('Notifications'), - 'Entity$5' => __('Assistance'), - 'Entity$6' => __('Assets') + $data['container_label'] = PluginFieldsLabelTranslation::getLabelFor($container); + + $field = [ + 'itemtype' => PluginFieldsField::getType(), + 'id' => $data['field_id'], + 'label' => $data['label'] ]; - break; - default: - //Toolbox::logDebug('Item type ' . $item::getType() . ' does not have any preconfigured subtypes!'); - /* For debug purposes - $tabs = $item->defineTabs(); - list($id, ) = each($tabs); - // delete first element of array ($main) - unset($tabs[$id]);*/ - break; - } - - return $tabs; - } - - /** - * Retrieve the class name corresponding to an itemtype for given container. - * - * @param string $itemtype Name of associated itemtype - * @param string $container_name Name of container - * @param string $suffix Suffix to add - * - * @return string - */ - public static function getClassname(string $itemtype, string $container_name, string $suffix = ''): string { - return sprintf( - 'PluginFields%s%s', - ucfirst(self::getSystemName($itemtype, $container_name)), - $suffix - ); - } - - /** - * Retrieve the system name corresponding to an itemtype for given container. - * - * @param string $itemtype Name of associated itemtype - * @param string $container_name Name of container - * - * @return string - */ - protected static function getSystemName(string $itemtype, string $container_name): string { - return strtolower(str_replace('\\', '', $itemtype) . preg_replace('/s$/', '', $container_name)); - } - - - static function getIcon() { - return "fas fa-tasks"; - } - - static function getNameField() { - return 'label'; - } - - function prepareInputForClone($input) { - if (array_key_exists('itemtypes', $input) && !empty($input['itemtypes'])) { - // $input has been transformed with `Toolbox::addslashes_deep()`, and `self::prepareInputForAdd()` - // is expecting an array, so it have to be unslashed then json decoded. - $input['itemtypes'] = json_decode(Sanitizer::dbUnescape($input['itemtypes'])); - } else { - unset($input['itemtypes']); - } - - return $input; - } - - public function getCloneRelations(): array - { - return [ - PluginFieldsContainerDisplayCondition::class, - PluginFieldsField::class, - PluginFieldsLabelTranslation::class, - PluginFieldsProfile::class, - ]; - } + $data['label'] = PluginFieldsLabelTranslation::getLabelFor($field); + + // Default SO params + $opt[$i]['table'] = $tablename; + $opt[$i]['field'] = $data['name']; + $opt[$i]['name'] = $data['container_label'] . " - " . $data['label']; + $opt[$i]['linkfield'] = $data['name']; + $opt[$i]['joinparams']['jointype'] = "itemtype_item"; + $opt[$i]['pfields_type'] = $data['type']; + if ($data['is_readonly']) { + $opt[$i]['massiveaction'] = false; + } + switch ($data['type']) { + case 'yesno': + $opt[$i]['datatype'] = "bool"; + break; + case 'textarea': + $opt[$i]['datatype'] = "text"; + break; + case 'number': + $opt[$i]['datatype'] = "decimal"; + break; + case 'date': + case 'datetime': + $opt[$i]['datatype'] = $data['type']; + break; + case 'url': + $opt[$i]['datatype'] = 'weblink'; + break; + default: + $opt[$i]['datatype'] = "string"; + } + + $dropdown_matches = []; + if ($data['type'] === "dropdown") { + $opt[$i]['table'] = 'glpi_plugin_fields_' . $data['name'] . 'dropdowns'; + $opt[$i]['field'] = 'completename'; + $opt[$i]['linkfield'] = "plugin_fields_" . $data['name'] . "dropdowns_id"; + $opt[$i]['datatype'] = "dropdown"; + + $opt[$i]['forcegroupby'] = true; + + $opt[$i]['joinparams']['jointype'] = ""; + $opt[$i]['joinparams']['beforejoin']['table'] = $tablename; + $opt[$i]['joinparams']['beforejoin']['joinparams']['jointype'] = "itemtype_item"; + } elseif ( + preg_match('/^dropdown-(?.+)$/i', $data['type'], $dropdown_matches) + && class_exists($dropdown_matches['class']) + ) { + $opt[$i]['table'] = CommonDBTM::getTable($dropdown_matches['class']); + $opt[$i]['field'] = 'name'; + $opt[$i]['linkfield'] = $data['name']; + $opt[$i]['right'] = 'all'; + $opt[$i]['datatype'] = "dropdown"; + + $opt[$i]['forcegroupby'] = true; + + $opt[$i]['joinparams']['jointype'] = ""; + $opt[$i]['joinparams']['beforejoin']['table'] = $tablename; + $opt[$i]['joinparams']['beforejoin']['joinparams']['jointype'] = "itemtype_item"; + } elseif ($data['type'] === "glpi_item") { + $itemtype_field = sprintf('itemtype_%s', $data['name']); + $items_id_field = sprintf('items_id_%s', $data['name']); + + $opt[$i]['table'] = $tablename; + $opt[$i]['field'] = $itemtype_field; + $opt[$i]['linkfield'] = $itemtype_field; + $opt[$i]['name'] = $data['container_label'] . " - " . $data['label'] . ' - ' . _n('Associated item type', 'Associated item types', Session::getPluralNumber()); + $opt[$i]['datatype'] = 'itemtypename'; + $opt[$i]['types'] = !empty($data['allowed_values']) ? json_decode($data['allowed_values']) : []; + $opt[$i]['additionalfields'] = ['itemtype']; + $opt[$i]['joinparams']['jointype'] = 'itemtype_item'; + $opt[$i]['forcegroupby'] = true; + $opt[$i]['massiveaction'] = false; + $i++; + + $opt[$i]['table'] = $tablename; + $opt[$i]['field'] = $items_id_field; + $opt[$i]['linkfield'] = $items_id_field; + $opt[$i]['name'] = $data['container_label'] . " - " . $data['label'] . ' - ' . __('Associated item ID'); + $opt[$i]['massiveaction'] = false; + $opt[$i]['joinparams']['jointype'] = 'itemtype_item'; + $opt[$i]['datatype'] = 'text'; + $opt[$i]['additionalfields'] = ['itemtype']; + } + + $i++; + } + + return $opt; + } + + /** + * Get subtypes for specified itemtype. + * Was previously retrieved using $item::defineTabs() but + * this is not relevant with actual core. + * + * @param CommonDBTM $item Item instance + * + * @return array + */ + private static function getSubtypes($item) + { + $tabs = []; + switch ($item::getType()) { + case Ticket::getType(): + case Problem::getType(): + $tabs = [ + $item::getType() . '$2' => __('Solution') + ]; + break; + case Change::getType(): + $tabs = [ + 'Change$1' => __('Analysis'), + 'Change$2' => __('Solution'), + 'Change$3' => __('Plans') + ]; + break; + case Entity::getType(): + $tabs = [ + 'Entity$2' => __('Address'), + 'Entity$3' => __('Advanced information'), + 'Entity$4' => __('Notifications'), + 'Entity$5' => __('Assistance'), + 'Entity$6' => __('Assets') + ]; + break; + default: + //Toolbox::logDebug('Item type ' . $item::getType() . ' does not have any preconfigured subtypes!'); + /* For debug purposes + $tabs = $item->defineTabs(); + list($id, ) = each($tabs); + // delete first element of array ($main) + unset($tabs[$id]);*/ + break; + } + + return $tabs; + } + + /** + * Retrieve the class name corresponding to an itemtype for given container. + * + * @param string $itemtype Name of associated itemtype + * @param string $container_name Name of container + * @param string $suffix Suffix to add + * + * @return string + */ + public static function getClassname(string $itemtype, string $container_name, string $suffix = ''): string + { + return sprintf( + 'PluginFields%s%s', + ucfirst(self::getSystemName($itemtype, $container_name)), + $suffix + ); + } + + /** + * Retrieve the system name corresponding to an itemtype for given container. + * + * @param string $itemtype Name of associated itemtype + * @param string $container_name Name of container + * + * @return string + */ + protected static function getSystemName(string $itemtype, string $container_name): string + { + return strtolower(str_replace('\\', '', $itemtype) . preg_replace('/s$/', '', $container_name)); + } + + + public static function getIcon() + { + return "fas fa-tasks"; + } + + public static function getNameField() + { + return 'label'; + } + + public function prepareInputForClone($input) + { + if (array_key_exists('itemtypes', $input) && !empty($input['itemtypes'])) { + // $input has been transformed with `Toolbox::addslashes_deep()`, and `self::prepareInputForAdd()` + // is expecting an array, so it have to be unslashed then json decoded. + $input['itemtypes'] = json_decode(Sanitizer::dbUnescape($input['itemtypes'])); + } else { + unset($input['itemtypes']); + } + + return $input; + } + + public function getCloneRelations(): array + { + return [ + PluginFieldsContainerDisplayCondition::class, + PluginFieldsField::class, + PluginFieldsLabelTranslation::class, + PluginFieldsProfile::class, + ]; + } } diff --git a/inc/containerdisplaycondition.class.php b/inc/containerdisplaycondition.class.php index 997d721c..dc79c888 100644 --- a/inc/containerdisplaycondition.class.php +++ b/inc/containerdisplaycondition.class.php @@ -31,7 +31,8 @@ use Glpi\Application\View\TemplateRenderer; use Glpi\Toolbox\Sanitizer; -class PluginFieldsContainerDisplayCondition extends CommonDBChild { +class PluginFieldsContainerDisplayCondition extends CommonDBChild +{ use Glpi\Features\Clonable; public static $itemtype = PluginFieldsContainer::class; @@ -43,7 +44,8 @@ class PluginFieldsContainerDisplayCondition extends CommonDBChild { const SHOW_CONDITION_GT = 4; const SHOW_CONDITION_REGEX = 5; - static function install(Migration $migration, $version) { + public static function install(Migration $migration, $version) + { global $DB; $default_charset = DBConnection::getDefaultCharset(); $default_collation = DBConnection::getDefaultCollation(); @@ -63,19 +65,20 @@ static function install(Migration $migration, $version) { PRIMARY KEY (`id`), KEY `plugin_fields_containers_id_itemtype` (`plugin_fields_containers_id`, `itemtype`) ) ENGINE=InnoDB DEFAULT CHARSET={$default_charset} COLLATE={$default_collation} ROW_FORMAT=DYNAMIC;"; - $DB->query($query) or die ($DB->error()); + $DB->query($query) or die($DB->error()); } return true; } - public static function getEnumCondition($is_dropdown = false) : array { + public static function getEnumCondition($is_dropdown = false): array + { - if ($is_dropdown){ + if ($is_dropdown) { return [ self::SHOW_CONDITION_EQ => '=', self::SHOW_CONDITION_NE => '≠' - ]; + ]; } else { return [ self::SHOW_CONDITION_EQ => '=', @@ -83,12 +86,12 @@ public static function getEnumCondition($is_dropdown = false) : array { self::SHOW_CONDITION_LT => '<', self::SHOW_CONDITION_GT => '>', self::SHOW_CONDITION_REGEX => __('regular expression matches', 'fields'), - ]; + ]; } - } - public static function getConditionName($condition) { + public static function getConditionName($condition) + { switch ($condition) { case self::SHOW_CONDITION_EQ: echo '='; @@ -101,6 +104,7 @@ public static function getConditionName($condition) { break; case self::SHOW_CONDITION_GT: echo '>'; + break; case self::SHOW_CONDITION_REGEX: echo __('regular expression matches', 'fields'); break; @@ -108,19 +112,22 @@ public static function getConditionName($condition) { } - static function uninstall() { + public static function uninstall() + { global $DB; - $DB->query("DROP TABLE IF EXISTS `".self::getTable()."`"); + $DB->query("DROP TABLE IF EXISTS `" . self::getTable() . "`"); return true; } - static function getTypeName($nb = 0) { + public static function getTypeName($nb = 0) + { return _n('Condition to hide block', 'Conditions to hide block', $nb, 'fields'); } - function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { + public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) + { return self::createTabEntry( self::getTypeName(Session::getPluralNumber()), countElementsInTable(self::getTable(), ['plugin_fields_containers_id' => $item->getID()]) @@ -128,7 +135,8 @@ function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { } - static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { + public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) + { if ($item instanceof PluginFieldsContainer) { self::showForTabContainer($item); return true; @@ -137,11 +145,12 @@ static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtem } - public static function getDisplayConditionForContainer(int $container_id): array { + public static function getDisplayConditionForContainer(int $container_id): array + { global $DB; $iterator = $DB->request([ 'SELECT' => [ - self::getTable().'.*', + self::getTable() . '.*', ], 'FROM' => self::getTable(), 'WHERE' => [ @@ -157,7 +166,8 @@ public static function getDisplayConditionForContainer(int $container_id): array } - private static function getItemtypesForContainer(int $container_id): array { + private static function getItemtypesForContainer(int $container_id): array + { global $DB; $iterator = $DB->request([ @@ -180,16 +190,18 @@ private static function getItemtypesForContainer(int $container_id): array { } - public static function getFieldName($so_id, $itemtype) { + public static function getFieldName($so_id, $itemtype) + { echo Search::getOptions($itemtype)[$so_id]['name']; } - public static function showItemtypeFieldForm($itemtype) { + public static function showItemtypeFieldForm($itemtype) + { $rand = mt_rand(); $out = ""; - $out .= Dropdown::showFromArray("search_option",self::removeBlackListedOption(Search::getOptions($itemtype), $itemtype),["display_emptychoice" => true, "display" => false, 'rand' => $rand]); + $out .= Dropdown::showFromArray("search_option", self::removeBlackListedOption(Search::getOptions($itemtype), $itemtype), ["display_emptychoice" => true, "display" => false, 'rand' => $rand]); $out .= Ajax::updateItemOnSelectEvent( "dropdown_search_option" . $rand, @@ -203,11 +215,11 @@ public static function showItemtypeFieldForm($itemtype) { ); echo $out; - } - public static function showSearchOptionCondition($searchoption_id, $itemtype, ?string $condition = null, ?string $value = null) { + public static function showSearchOptionCondition($searchoption_id, $itemtype, ?string $condition = null, ?string $value = null) + { $so = Search::getOptions($itemtype)[$searchoption_id]; $itemtypetable = $itemtype::getTable(); @@ -256,7 +268,8 @@ public static function showSearchOptionCondition($searchoption_id, $itemtype, ?s } - public static function getRawValue($searchoption_id, $itemtype, $value) { + public static function getRawValue($searchoption_id, $itemtype, $value) + { $so = Search::getOptions($itemtype)[$searchoption_id]; $itemtypetable = $itemtype::getTable(); @@ -289,7 +302,7 @@ public static function getRawValue($searchoption_id, $itemtype, $value) { $raw_value = CommonITILValidation::getStatus($value); break; } - }else{ + } else { $raw_value = $value; } @@ -297,7 +310,8 @@ public static function getRawValue($searchoption_id, $itemtype, $value) { } - public static function removeBlackListedOption($array, $itemtype_class){ + public static function removeBlackListedOption($array, $itemtype_class) + { $itemtype_object = new $itemtype_class(); $allowed_so = []; @@ -310,33 +324,37 @@ public static function removeBlackListedOption($array, $itemtype_class){ //use relation.constant.php to allow some tables (exclude Location which is managed later) foreach (getDbRelations() as $relation) { foreach ($relation as $main_table => $foreignKey) { - if($main_table == getTableForItemType($itemtype_class) + if ( + $main_table == getTableForItemType($itemtype_class) && !is_array($foreignKey) - && getTableNameForForeignKeyField($foreignKey) != getTableForItemType(Location::getType())) { + && getTableNameForForeignKeyField($foreignKey) != getTableForItemType(Location::getType()) + ) { $allowed_table[] = getTableNameForForeignKeyField($foreignKey); } } } - if($itemtype_object->isEntityAssign()){ + if ($itemtype_object->isEntityAssign()) { $allowed_table[] = getTableForItemType(Entity::getType()); } - //allew specific datatype + //allow specific datatype $allowed_datatype = ["email", "weblink", "specific", "itemlink", "string", "text","number", "dropdown", "decimal", "integer", "bool"]; - foreach($array as $subKey => $subArray){ - if(isset($subArray["table"]) && in_array($subArray["table"], $allowed_table) + foreach ($array as $subKey => $subArray) { + if ( + isset($subArray["table"]) && in_array($subArray["table"], $allowed_table) && (isset($subArray["datatype"]) && in_array($subArray["datatype"], $allowed_datatype)) && !isset($subArray["nosearch"]) //Exclude SO with no search && !isset($subArray["usehaving"]) //Exclude count SO ex: Ticket -> Number of sons tickets && !isset($subArray["forcegroupby"]) //Exclude 1-n relation ex: Ticket_User - && !isset($subArray["computation"])){ //Exclude SO with computation Ex : Ticket -> Time to own exceeded + && !isset($subArray["computation"]) //Exclude SO with computation Ex : Ticket -> Time to own exceeded + ) { $allowed_so[$subKey] = $subArray["name"]; } } - if($itemtype_object->maybeLocated()){ + if ($itemtype_object->maybeLocated()) { $allowed_so[80] = Location::getTypeName(0); } @@ -344,31 +362,32 @@ public static function removeBlackListedOption($array, $itemtype_class){ } - public function computeDisplayContainer($item, $container_id){ + public function computeDisplayContainer($item, $container_id) + { //load all condition for itemtype and container $displayCondition = new self(); $found_dc = $displayCondition->find(['itemtype' => get_class($item), 'plugin_fields_containers_id' => $container_id]); - if (count($found_dc)){ + if (count($found_dc)) { $display = true; foreach ($found_dc as $data) { - $displayCondition->getFromDB($data['id']); $result = $displayCondition->checkCondition($item); - if(!$result){ + if (!$result) { return $result; } } return $display; - }else { + } else { //no condition found -> display container return true; } } - public function checkCondition($item){ + public function checkCondition($item) + { $value = $this->fields['value']; $condition = $this->fields['condition']; $searchOption = Search::getOptions(get_class($item))[$this->fields['search_option']]; @@ -376,31 +395,31 @@ public function checkCondition($item){ switch ($condition) { case self::SHOW_CONDITION_EQ: // '=' - if ($value == $item->fields[$searchOption['linkfield']]){ + if ($value == $item->fields[$searchOption['linkfield']]) { return false; } break; case self::SHOW_CONDITION_NE: // '≠' - if ($value != $item->fields[$searchOption['linkfield']]){ + if ($value != $item->fields[$searchOption['linkfield']]) { return false; } break; case self::SHOW_CONDITION_LT: // '<'; - if ($item->fields[$searchOption['linkfield']] > $value){ + if ($item->fields[$searchOption['linkfield']] > $value) { return false; } break; case self::SHOW_CONDITION_GT: //'>'; - if ($item->fields[$searchOption['linkfield']] > $value){ + if ($item->fields[$searchOption['linkfield']] > $value) { return false; } break; case self::SHOW_CONDITION_REGEX: //'regex'; - if(self::checkRegex($value)) { + if (self::checkRegex($value)) { $value = Sanitizer::unsanitize($value); if (preg_match_all($value . "i", $item->fields[$searchOption['linkfield']]) > 0) { return false; @@ -413,7 +432,8 @@ public function checkCondition($item){ } - public static function checkRegex($regex) { + public static function checkRegex($regex) + { // Avoid php notice when validating the regular expression set_error_handler(function ($errno, $errstr, $errfile, $errline) { }); @@ -451,7 +471,8 @@ public function prepareInputForUpdate($input) return parent::prepareInputForUpdate($input); } - public static function showForTabContainer(CommonGLPI $item, $options = []) { + public static function showForTabContainer(CommonGLPI $item, $options = []) + { $displayCondition_id = $options['displaycondition_id'] ?? 0; $display_condition = null; @@ -474,7 +495,8 @@ public static function showForTabContainer(CommonGLPI $item, $options = []) { TemplateRenderer::getInstance()->display('@fields/container_display_conditions.html.twig', $twig_params); } - public function showForm($ID, array $options = []) { + public function showForm($ID, array $options = []) + { $container_id = $options['plugin_fields_containers_id']; $twig_params = [ @@ -488,7 +510,8 @@ public function showForm($ID, array $options = []) { TemplateRenderer::getInstance()->display('@fields/forms/container_display_condition.html.twig', $twig_params); } - public function getCloneRelations(): array { + public function getCloneRelations(): array + { return []; } } diff --git a/inc/dropdown.class.php b/inc/dropdown.class.php index 789653fe..8b76156c 100644 --- a/inc/dropdown.class.php +++ b/inc/dropdown.class.php @@ -28,198 +28,216 @@ * ------------------------------------------------------------------------- */ -class PluginFieldsDropdown { - static $rightname = 'dropdown'; - public $can_be_translated = true; - - /** - * Install or update dropdowns - * - * @param Migration $migration Migration instance - * @param string $version Plugin current version - * - * @return void - */ - static function install(Migration $migration, $version) { - $toolbox = new PluginFieldsToolbox(); - $toolbox->fixFieldsNames($migration, ['type' => 'dropdown']); - - $migration->displayMessage(__("Updating generated dropdown files", "fields")); - - $obj = new PluginFieldsField; - $fields = $obj->find(['type' => 'dropdown']); - - // -> 0.90-1.3: generated class moved - // OLD path: GLPI_ROOT."/plugins/fields/inc/$class_filename" - // NEW path: PLUGINFIELDS_CLASS_PATH . "/$class_filename" - // OLD path: GLPI_ROOT."/plugins/fields/front/$class_filename" - // NEW path: PLUGINFIELDS_FRONT_PATH . "/$class_filename" - foreach ($fields as $field) { - //First, drop old fields from plugin directories - $class_filename = $field['name']."dropdown.class.php"; - if (file_exists(PLUGINFIELDS_DIR."/inc/$class_filename")) { - unlink(PLUGINFIELDS_DIR."/inc/$class_filename"); - } - - $front_filename = $field['name']."dropdown.php"; - if (file_exists(PLUGINFIELDS_DIR."/front/$front_filename")) { - unlink(PLUGINFIELDS_DIR."/front/$front_filename"); - } - - $form_filename = $field['name']."dropdown.form.php"; - if (file_exists(PLUGINFIELDS_DIR."/front/$form_filename")) { - unlink(PLUGINFIELDS_DIR."/front/$form_filename"); - } - } - - // Regenerate files and install missing tables - foreach ($fields as $field) { - self::create($field); - } - - return true; - } - - static function uninstall() { - global $DB; - - //remove dropdown tables and files - if ($DB->tableExists("glpi_plugin_fields_fields")) { - require_once "field.class.php"; - $field = new PluginFieldsField; - $dropdowns = $field->find(['type' => 'dropdown']); - foreach ($dropdowns as $dropdown) { - self::destroy($dropdown['name']); - } - } - return true; - } - - static function create($input) { - //get class template - $template_class = file_get_contents(PLUGINFIELDS_DIR."/templates/dropdown.class.tpl"); - if ($template_class === false) { - return false; - } - - $classname = self::getClassname($input['name']); - - //create dropdown class file - $template_class = str_replace( - "%%CLASSNAME%%", - $classname, - $template_class - ); - $template_class = str_replace( - "%%FIELDNAME%%", - $input['name'], - $template_class - ); - $template_class = str_replace( - "%%FIELDID%%", - $input['id'], - $template_class - ); - $template_class = str_replace( - "%%LABEL%%", - $input['label'], - $template_class - ); - $class_filename = $input['name']."dropdown.class.php"; - if (file_put_contents(PLUGINFIELDS_CLASS_PATH . "/$class_filename", - $template_class) === false) { - Toolbox::logDebug("Error : dropdown class file creation - $class_filename"); - return false; - } - - //get front template - $template_front = file_get_contents(PLUGINFIELDS_DIR."/templates/dropdown.tpl"); - if ($template_front === false) { - Toolbox::logDebug("Error : get dropdown front template error"); - return false; - } - - //create dropdown front file - $template_front = str_replace("%%CLASSNAME%%", $classname, $template_front); - $front_filename = $input['name']."dropdown.php"; - if (file_put_contents(PLUGINFIELDS_FRONT_PATH . "/$front_filename", - $template_front) === false) { - Toolbox::logDebug("Error : dropdown front file creation - $class_filename"); - return false; - } - - //get form template - $template_form = file_get_contents(PLUGINFIELDS_DIR."/templates/dropdown.form.tpl"); - if ($template_form === false) { - return false; - } - - //create dropdown form file - $template_form = str_replace("%%CLASSNAME%%", $classname, $template_form); - $form_filename = $input['name']."dropdown.form.php"; - if (file_put_contents(PLUGINFIELDS_FRONT_PATH . "/$form_filename", - $template_form) === false) { - Toolbox::logDebug("Error : get dropdown form template error"); - return false; - } - - //load class manually on plugin installation - if (!class_exists($classname)) { - require_once $class_filename; - } - - //call install method (create table) - if ($classname::install() === false) { - Toolbox::logDebug("Error : calling dropdown $classname installation"); - return false; - } - - // Destroy menu in session for force to regenerate it - unset($_SESSION['glpimenu']); - - return true; - } - - static function destroy($dropdown_name) { - $classname = self::getClassname($dropdown_name); - $class_filename = PLUGINFIELDS_CLASS_PATH . "/".$dropdown_name."dropdown.class.php"; - - //call uninstall method in dropdown class - if ($classname::uninstall() === false) { - Toolbox::logDebug("Error : calling dropdown $classname uninstallation"); - return false; - } - - //remove class file for this dropdown - if (file_exists($class_filename)) { - if (unlink($class_filename) === false) { - Toolbox::logDebug("Error : dropdown class file creation - ".$dropdown_name."dropdown.class.php"); +class PluginFieldsDropdown +{ + public static $rightname = 'dropdown'; + public $can_be_translated = true; + + /** + * Install or update dropdowns + * + * @param Migration $migration Migration instance + * @param string $version Plugin current version + * + * @return void + */ + public static function install(Migration $migration, $version) + { + $toolbox = new PluginFieldsToolbox(); + $toolbox->fixFieldsNames($migration, ['type' => 'dropdown']); + + $migration->displayMessage(__("Updating generated dropdown files", "fields")); + + $obj = new PluginFieldsField(); + $fields = $obj->find(['type' => 'dropdown']); + + // -> 0.90-1.3: generated class moved + // OLD path: GLPI_ROOT."/plugins/fields/inc/$class_filename" + // NEW path: PLUGINFIELDS_CLASS_PATH . "/$class_filename" + // OLD path: GLPI_ROOT."/plugins/fields/front/$class_filename" + // NEW path: PLUGINFIELDS_FRONT_PATH . "/$class_filename" + foreach ($fields as $field) { + //First, drop old fields from plugin directories + $class_filename = $field['name'] . "dropdown.class.php"; + if (file_exists(PLUGINFIELDS_DIR . "/inc/$class_filename")) { + unlink(PLUGINFIELDS_DIR . "/inc/$class_filename"); + } + + $front_filename = $field['name'] . "dropdown.php"; + if (file_exists(PLUGINFIELDS_DIR . "/front/$front_filename")) { + unlink(PLUGINFIELDS_DIR . "/front/$front_filename"); + } + + $form_filename = $field['name'] . "dropdown.form.php"; + if (file_exists(PLUGINFIELDS_DIR . "/front/$form_filename")) { + unlink(PLUGINFIELDS_DIR . "/front/$form_filename"); + } + } + + // Regenerate files and install missing tables + foreach ($fields as $field) { + self::create($field); + } + + return true; + } + + public static function uninstall() + { + global $DB; + + //remove dropdown tables and files + if ($DB->tableExists("glpi_plugin_fields_fields")) { + require_once "field.class.php"; + $field = new PluginFieldsField(); + $dropdowns = $field->find(['type' => 'dropdown']); + foreach ($dropdowns as $dropdown) { + self::destroy($dropdown['name']); + } + } + return true; + } + + public static function create($input) + { + //get class template + $template_class = file_get_contents(PLUGINFIELDS_DIR . "/templates/dropdown.class.tpl"); + if ($template_class === false) { return false; - } - } - - //remove front file for this dropdown - $front_filename = PLUGINFIELDS_FRONT_PATH . "/".$dropdown_name."dropdown.php"; - if (file_exists($front_filename)) { - if (unlink($front_filename) === false) { - Toolbox::logDebug("Error : dropdown front file removing - ".$dropdown_name."dropdown.php"); + } + + $classname = self::getClassname($input['name']); + + //create dropdown class file + $template_class = str_replace( + "%%CLASSNAME%%", + $classname, + $template_class + ); + $template_class = str_replace( + "%%FIELDNAME%%", + $input['name'], + $template_class + ); + $template_class = str_replace( + "%%FIELDID%%", + $input['id'], + $template_class + ); + $template_class = str_replace( + "%%LABEL%%", + $input['label'], + $template_class + ); + $class_filename = $input['name'] . "dropdown.class.php"; + if ( + file_put_contents( + PLUGINFIELDS_CLASS_PATH . "/$class_filename", + $template_class + ) === false + ) { + Toolbox::logDebug("Error : dropdown class file creation - $class_filename"); return false; - } - } - - //remove front.form file for this dropdown - $form_filename = PLUGINFIELDS_FRONT_PATH . "/".$dropdown_name."dropdown.form.php"; - if (file_exists($form_filename)) { - if (unlink($form_filename) === false) { - Toolbox::logDebug("Error : dropdown form file removing - ".$dropdown_name."dropdown.form.php"); + } + + //get front template + $template_front = file_get_contents(PLUGINFIELDS_DIR . "/templates/dropdown.tpl"); + if ($template_front === false) { + Toolbox::logDebug("Error : get dropdown front template error"); + return false; + } + + //create dropdown front file + $template_front = str_replace("%%CLASSNAME%%", $classname, $template_front); + $front_filename = $input['name'] . "dropdown.php"; + if ( + file_put_contents( + PLUGINFIELDS_FRONT_PATH . "/$front_filename", + $template_front + ) === false + ) { + Toolbox::logDebug("Error : dropdown front file creation - $class_filename"); + return false; + } + + //get form template + $template_form = file_get_contents(PLUGINFIELDS_DIR . "/templates/dropdown.form.tpl"); + if ($template_form === false) { + return false; + } + + //create dropdown form file + $template_form = str_replace("%%CLASSNAME%%", $classname, $template_form); + $form_filename = $input['name'] . "dropdown.form.php"; + if ( + file_put_contents( + PLUGINFIELDS_FRONT_PATH . "/$form_filename", + $template_form + ) === false + ) { + Toolbox::logDebug("Error : get dropdown form template error"); return false; - } - } + } - return true; - } + //load class manually on plugin installation + if (!class_exists($classname)) { + require_once $class_filename; + } - static function getClassname($system_name) { - return "PluginFields".ucfirst($system_name)."Dropdown"; - } + //call install method (create table) + if ($classname::install() === false) { + Toolbox::logDebug("Error : calling dropdown $classname installation"); + return false; + } + + // Destroy menu in session for force to regenerate it + unset($_SESSION['glpimenu']); + + return true; + } + + public static function destroy($dropdown_name) + { + $classname = self::getClassname($dropdown_name); + $class_filename = PLUGINFIELDS_CLASS_PATH . "/" . $dropdown_name . "dropdown.class.php"; + + //call uninstall method in dropdown class + if ($classname::uninstall() === false) { + Toolbox::logDebug("Error : calling dropdown $classname uninstallation"); + return false; + } + + //remove class file for this dropdown + if (file_exists($class_filename)) { + if (unlink($class_filename) === false) { + Toolbox::logDebug("Error : dropdown class file creation - " . $dropdown_name . "dropdown.class.php"); + return false; + } + } + + //remove front file for this dropdown + $front_filename = PLUGINFIELDS_FRONT_PATH . "/" . $dropdown_name . "dropdown.php"; + if (file_exists($front_filename)) { + if (unlink($front_filename) === false) { + Toolbox::logDebug("Error : dropdown front file removing - " . $dropdown_name . "dropdown.php"); + return false; + } + } + + //remove front.form file for this dropdown + $form_filename = PLUGINFIELDS_FRONT_PATH . "/" . $dropdown_name . "dropdown.form.php"; + if (file_exists($form_filename)) { + if (unlink($form_filename) === false) { + Toolbox::logDebug("Error : dropdown form file removing - " . $dropdown_name . "dropdown.form.php"); + return false; + } + } + + return true; + } + + public static function getClassname($system_name) + { + return "PluginFields" . ucfirst($system_name) . "Dropdown"; + } } diff --git a/inc/field.class.php b/inc/field.class.php index db77d709..bfec1c49 100644 --- a/inc/field.class.php +++ b/inc/field.class.php @@ -31,33 +31,35 @@ use Glpi\Application\View\TemplateRenderer; use Glpi\Toolbox\Sanitizer; -class PluginFieldsField extends CommonDBChild { - use Glpi\Features\Clonable; - - public static $itemtype = PluginFieldsContainer::class; - public static $items_id = 'plugin_fields_containers_id'; - - /** - * Install or update fields - * - * @param Migration $migration Migration instance - * @param string $version Plugin current version - * - * @return boolean - */ - static function install(Migration $migration, $version) { - global $DB; - - $default_charset = DBConnection::getDefaultCharset(); - $default_collation = DBConnection::getDefaultCollation(); - $default_key_sign = DBConnection::getDefaultPrimaryKeySignOption(); - - $table = self::getTable(); - - if (!$DB->tableExists($table)) { - $migration->displayMessage(sprintf(__("Installing %s"), $table)); - - $query = "CREATE TABLE IF NOT EXISTS `$table` ( +class PluginFieldsField extends CommonDBChild +{ + use Glpi\Features\Clonable; + + public static $itemtype = PluginFieldsContainer::class; + public static $items_id = 'plugin_fields_containers_id'; + + /** + * Install or update fields + * + * @param Migration $migration Migration instance + * @param string $version Plugin current version + * + * @return boolean + */ + public static function install(Migration $migration, $version) + { + global $DB; + + $default_charset = DBConnection::getDefaultCharset(); + $default_collation = DBConnection::getDefaultCollation(); + $default_key_sign = DBConnection::getDefaultPrimaryKeySignOption(); + + $table = self::getTable(); + + if (!$DB->tableExists($table)) { + $migration->displayMessage(sprintf(__("Installing %s"), $table)); + + $query = "CREATE TABLE IF NOT EXISTS `$table` ( `id` INT {$default_key_sign} NOT NULL auto_increment, `name` VARCHAR(255) DEFAULT NULL, `label` VARCHAR(255) DEFAULT NULL, @@ -74,966 +76,1016 @@ static function install(Migration $migration, $version) { KEY `is_active` (`is_active`), KEY `is_readonly` (`is_readonly`) ) ENGINE=InnoDB DEFAULT CHARSET={$default_charset} COLLATE={$default_collation} ROW_FORMAT=DYNAMIC;"; - $DB->query($query) or die ($DB->error()); - } - - $migration->displayMessage("Updating $table"); - - if (!$DB->fieldExists($table, 'is_active')) { - $migration->addField($table, 'is_active', 'bool', ['value' => 1]); - $migration->addKey($table, 'is_active', 'is_active'); - } - if (!$DB->fieldExists($table, 'is_readonly')) { - $migration->addField( $table, 'is_readonly', 'bool', ['default' => false]); - $migration->addKey($table, 'is_readonly', 'is_readonly'); - } - if (!$DB->fieldExists($table, 'mandatory')) { - $migration->addField($table, 'mandatory', 'bool', ['value' => 0]); - } - - //increase the size of column 'type' (25 to 255) - $migration->changeField($table, 'type', 'type', 'string'); - - if (!$DB->fieldExists($table, 'allowed_values')) { - $migration->addField($table, 'allowed_values', 'text'); - } - - $toolbox = new PluginFieldsToolbox(); - $toolbox->fixFieldsNames($migration, ['NOT' => ['type' => 'dropdown']]); - - //move old types to new format - $migration->addPostQuery( - $DB->buildUpdate( - PluginFieldsField::getTable() , - ['type' => 'dropdown-User'], - ['type' => 'dropdownusers'] - ) - ); - $migration->addPostQuery( - $DB->buildUpdate( - PluginFieldsField::getTable() , - ['type' => 'dropdown-User'], - ['type' => 'dropdownusers'] - ) - ); - - return true; - } - - static function uninstall() { - global $DB; - - $DB->query("DROP TABLE IF EXISTS `".self::getTable()."`"); - - return true; - } - - static function getTypeName($nb = 0) { - return __("Field", "fields"); - } - - - function prepareInputForAdd($input) { - //parse name - $input['name'] = $this->prepareName($input); - - //reject adding when field name is too long for mysql - if (strlen($input['name']) > 64) { - Session::AddMessageAfterRedirect( - __("Field name is too long for database (digits in name are replaced by characters, try to remove them)", 'fields'), - false, - ERROR - ); - return false; - } - - if ($input['type'] === "dropdown") { - //search if dropdown already exist in this container - $found = $this->find( - [ - 'name' => $input['name'], - 'plugin_fields_containers_id' => $input['plugin_fields_containers_id'], - ] - ); + $DB->query($query) or die($DB->error()); + } + + $migration->displayMessage("Updating $table"); + + if (!$DB->fieldExists($table, 'is_active')) { + $migration->addField($table, 'is_active', 'bool', ['value' => 1]); + $migration->addKey($table, 'is_active', 'is_active'); + } + if (!$DB->fieldExists($table, 'is_readonly')) { + $migration->addField($table, 'is_readonly', 'bool', ['default' => false]); + $migration->addKey($table, 'is_readonly', 'is_readonly'); + } + if (!$DB->fieldExists($table, 'mandatory')) { + $migration->addField($table, 'mandatory', 'bool', ['value' => 0]); + } + + //increase the size of column 'type' (25 to 255) + $migration->changeField($table, 'type', 'type', 'string'); + + if (!$DB->fieldExists($table, 'allowed_values')) { + $migration->addField($table, 'allowed_values', 'text'); + } + + $toolbox = new PluginFieldsToolbox(); + $toolbox->fixFieldsNames($migration, ['NOT' => ['type' => 'dropdown']]); + + //move old types to new format + $migration->addPostQuery( + $DB->buildUpdate( + PluginFieldsField::getTable(), + ['type' => 'dropdown-User'], + ['type' => 'dropdownusers'] + ) + ); + $migration->addPostQuery( + $DB->buildUpdate( + PluginFieldsField::getTable(), + ['type' => 'dropdown-User'], + ['type' => 'dropdownusers'] + ) + ); - //reject adding for same dropdown on same bloc - if (!empty($found)) { - Session::AddMessageAfterRedirect(__("You cannot add same field 'dropdown' on same bloc", 'fields', false, ERROR)); - return false; - } + return true; + } + + public static function uninstall() + { + global $DB; + + $DB->query("DROP TABLE IF EXISTS `" . self::getTable() . "`"); + + return true; + } + + public static function getTypeName($nb = 0) + { + return __("Field", "fields"); + } - //reject adding when dropdown name is too long for mysql table name - if (strlen(getTableForItemType(PluginFieldsDropdown::getClassname($input['name']))) > 64) { + + public function prepareInputForAdd($input) + { + //parse name + $input['name'] = $this->prepareName($input); + + //reject adding when field name is too long for mysql + if (strlen($input['name']) > 64) { Session::AddMessageAfterRedirect( - __("Field name is too long for database (digits in name are replaced by characters, try to remove them)", 'fields'), - false, - ERROR + __("Field name is too long for database (digits in name are replaced by characters, try to remove them)", 'fields'), + false, + ERROR ); return false; - } - } - - // Before adding, add the ranking of the new field - if (empty($input["ranking"])) { - $input["ranking"] = $this->getNextRanking(); - } - - //add field to container table - if ($input['type'] !== "header") { - $container_obj = new PluginFieldsContainer; - $container_obj->getFromDB($input['plugin_fields_containers_id']); - foreach (json_decode($container_obj->fields['itemtypes']) as $itemtype) { - $classname = PluginFieldsContainer::getClassname($itemtype, $container_obj->fields['name']); - $classname::addField($input['name'], $input['type']); - } - } - - if (isset($input['allowed_values'])) { - $input['allowed_values'] = Sanitizer::dbEscape(json_encode($input['allowed_values'])); - } - - return $input; - } - - function pre_deleteItem() { - //remove field in container table - if ($this->fields['type'] !== "header" - && !isset($_SESSION['uninstall_fields']) - && !isset($_SESSION['delete_container'])) { - $container_obj = new PluginFieldsContainer; - $container_obj->getFromDB($this->fields['plugin_fields_containers_id']); - foreach (json_decode($container_obj->fields['itemtypes']) as $itemtype) { - $classname = PluginFieldsContainer::getClassname($itemtype, $container_obj->fields['name']); - $classname::removeField($this->fields['name'], $this->fields['type']); - } - } - - //delete label translations - $translation_obj = new PluginFieldsLabelTranslation(); - $translation_obj->deleteByCriteria([ - 'itemtype' => self::getType(), - 'items_id' => $this->fields['id'] - ]); - - if ($this->fields['type'] === "dropdown") { - return PluginFieldsDropdown::destroy($this->fields['name']); - } - return true; - } - - function post_purgeItem() { - global $DB; - - $table = getTableForItemType(__CLASS__); - $old_container = $this->fields['plugin_fields_containers_id']; - $old_ranking = $this->fields['ranking']; - - $query = "UPDATE $table SET + } + + if ($input['type'] === "dropdown") { + //search if dropdown already exist in this container + $found = $this->find( + [ + 'name' => $input['name'], + 'plugin_fields_containers_id' => $input['plugin_fields_containers_id'], + ] + ); + + //reject adding for same dropdown on same bloc + if (!empty($found)) { + Session::AddMessageAfterRedirect(__("You cannot add same field 'dropdown' on same bloc", 'fields', false, ERROR)); + return false; + } + + //reject adding when dropdown name is too long for mysql table name + if (strlen(getTableForItemType(PluginFieldsDropdown::getClassname($input['name']))) > 64) { + Session::AddMessageAfterRedirect( + __("Field name is too long for database (digits in name are replaced by characters, try to remove them)", 'fields'), + false, + ERROR + ); + return false; + } + } + + // Before adding, add the ranking of the new field + if (empty($input["ranking"])) { + $input["ranking"] = $this->getNextRanking(); + } + + //add field to container table + if ($input['type'] !== "header") { + $container_obj = new PluginFieldsContainer(); + $container_obj->getFromDB($input['plugin_fields_containers_id']); + foreach (json_decode($container_obj->fields['itemtypes']) as $itemtype) { + $classname = PluginFieldsContainer::getClassname($itemtype, $container_obj->fields['name']); + $classname::addField($input['name'], $input['type']); + } + } + + if (isset($input['allowed_values'])) { + $input['allowed_values'] = Sanitizer::dbEscape(json_encode($input['allowed_values'])); + } + + return $input; + } + + // phpcs:ignore PSR1.Methods.CamelCapsMethodName + public function pre_deleteItem() + { + //remove field in container table + if ( + $this->fields['type'] !== "header" + && !isset($_SESSION['uninstall_fields']) + && !isset($_SESSION['delete_container']) + ) { + $container_obj = new PluginFieldsContainer(); + $container_obj->getFromDB($this->fields['plugin_fields_containers_id']); + foreach (json_decode($container_obj->fields['itemtypes']) as $itemtype) { + $classname = PluginFieldsContainer::getClassname($itemtype, $container_obj->fields['name']); + $classname::removeField($this->fields['name'], $this->fields['type']); + } + } + + //delete label translations + $translation_obj = new PluginFieldsLabelTranslation(); + $translation_obj->deleteByCriteria([ + 'itemtype' => self::getType(), + 'items_id' => $this->fields['id'] + ]); + + if ($this->fields['type'] === "dropdown") { + return PluginFieldsDropdown::destroy($this->fields['name']); + } + return true; + } + + // phpcs:ignore PSR1.Methods.CamelCapsMethodName + public function post_purgeItem() + { + global $DB; + + $table = getTableForItemType(__CLASS__); + $old_container = $this->fields['plugin_fields_containers_id']; + $old_ranking = $this->fields['ranking']; + + $query = "UPDATE $table SET ranking = ranking-1 WHERE plugin_fields_containers_id = $old_container AND ranking > $old_ranking"; - $DB->query($query); - - return true; - } - - - /** - * parse name for avoid non alphanumeric char in it and conflict with other fields - * @param array $input the field form input - * @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'] = $toolbox->getSystemNameFromLabel($input['label']) . 'field'; - } - - //for dropdown, if already exist, link to it - if (isset($input['type']) && $input['type'] === "dropdown") { - $found = $this->find(['name' => $input['name']]); - if (!empty($found)) { - return $input['name']; - } - } - - //check if field name not already exist and not in conflict with itemtype fields name - $container = new PluginFieldsContainer; - $container->getFromDB($input['plugin_fields_containers_id']); - - $field = new self; - $field_name = $input['name']; - $i = 2; - while (count($field->find(['name' => $field_name])) > 0) { - $field_name = $toolbox->getIncrementedSystemName($input['name'], $i); - $i++; - } - - return $field_name; - } - - /** - * Get the next ranking for a specified field - * - * @return integer - **/ - function getNextRanking() { - global $DB; - - $sql = "SELECT max(`ranking`) AS `rank` - FROM `".self::getTable()."` - WHERE `plugin_fields_containers_id` = '". - $this->fields['plugin_fields_containers_id']."'"; - $result = $DB->query($sql); - - if ($DB->numrows($result) > 0) { - $data = $DB->fetchAssoc($result); - return $data["rank"] + 1; - } - return 0; - } - - function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { - if (!$withtemplate) { - switch ($item->getType()) { - case __CLASS__ : - $ong[1] = $this->getTypeName(1); - return $ong; - } - } - - return self::createTabEntry(__("Fields", "fields"), - countElementsInTable(self::getTable(), - ['plugin_fields_containers_id' => $item->getID()])); - } - - static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { - $fup = new self(); - $fup->showSummary($item); - return true; - } - - function defineTabs($options = []) { - $ong = []; - $this->addDefaultFormTab($ong); - $this->addStandardTab('PluginFieldsLabelTranslation', $ong, $options); - - return $ong; - } - - function showSummary($container) { - global $DB, $CFG_GLPI; - - $cID = $container->fields['id']; - - // Display existing Fields - $query = "SELECT `id`, `label` - FROM `".$this->getTable()."` + $DB->query($query); + + return true; + } + + + /** + * parse name for avoid non alphanumeric char in it and conflict with other fields + * @param array $input the field form input + * @return string the parsed name + */ + public function prepareName($input) + { + $toolbox = new PluginFieldsToolbox(); + + //contruct field name by processing label (remove non alphanumeric char) + if (empty($input['name'])) { + $input['name'] = $toolbox->getSystemNameFromLabel($input['label']) . 'field'; + } + + //for dropdown, if already exist, link to it + if (isset($input['type']) && $input['type'] === "dropdown") { + $found = $this->find(['name' => $input['name']]); + if (!empty($found)) { + return $input['name']; + } + } + + //check if field name not already exist and not in conflict with itemtype fields name + $container = new PluginFieldsContainer(); + $container->getFromDB($input['plugin_fields_containers_id']); + + $field = new self(); + $field_name = $input['name']; + $i = 2; + while (count($field->find(['name' => $field_name])) > 0) { + $field_name = $toolbox->getIncrementedSystemName($input['name'], $i); + $i++; + } + + return $field_name; + } + + /** + * Get the next ranking for a specified field + * + * @return integer + */ + public function getNextRanking() + { + global $DB; + + $sql = "SELECT max(`ranking`) AS `rank` + FROM `" . self::getTable() . "` + WHERE `plugin_fields_containers_id` = '" . + $this->fields['plugin_fields_containers_id'] . "'"; + $result = $DB->query($sql); + + if ($DB->numrows($result) > 0) { + $data = $DB->fetchAssoc($result); + return $data["rank"] + 1; + } + return 0; + } + + public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) + { + if (!$withtemplate) { + switch ($item->getType()) { + case __CLASS__: + $ong[1] = $this->getTypeName(1); + return $ong; + } + } + + return self::createTabEntry( + __("Fields", "fields"), + countElementsInTable( + self::getTable(), + ['plugin_fields_containers_id' => $item->getID()] + ) + ); + } + + public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) + { + $fup = new self(); + $fup->showSummary($item); + return true; + } + + public function defineTabs($options = []) + { + $ong = []; + $this->addDefaultFormTab($ong); + $this->addStandardTab('PluginFieldsLabelTranslation', $ong, $options); + + return $ong; + } + + public function showSummary($container) + { + global $DB, $CFG_GLPI; + + $cID = $container->fields['id']; + + // Display existing Fields + $query = "SELECT `id`, `label` + FROM `" . $this->getTable() . "` WHERE `plugin_fields_containers_id` = '$cID' ORDER BY `ranking` ASC"; - $result = $DB->query($query); - - $rand = mt_rand(); - - echo "
"; - - echo Html::scriptBlock(' - viewAddField' . $cID . $rand . ' = function() { - $("#viewField' . $cID . $rand . '").load( - "' . $CFG_GLPI['root_doc'] . '/ajax/viewsubitem.php", - ' . json_encode([ - 'type' => __CLASS__, - 'parenttype' => PluginFieldsContainer::class, - 'plugin_fields_containers_id' => $cID, - 'id' => -1 - ]) . ' - ); - }; - '); + $result = $DB->query($query); + + $rand = mt_rand(); + + echo "
"; + + $ajax_params = [ + 'type' => __CLASS__, + 'parenttype' => PluginFieldsContainer::class, + 'plugin_fields_containers_id' => $cID, + 'id' => -1 + ]; + echo Html::scriptBlock(' + viewAddField' . $cID . $rand . ' = function() { + $("#viewField' . $cID . $rand . '").load( + "' . $CFG_GLPI['root_doc'] . '/ajax/viewsubitem.php", + ' . json_encode($ajax_params) . ' + ); + }; + '); - echo "
". + echo "
"; - - if ($DB->numrows($result) == 0) { - echo ""; - echo "
".__("No field for this block", "fields")."
"; - } else { - echo '
'; - echo Html::hidden("_plugin_fields_containers_id", ['value' => $cID, - 'id' => 'plugin_fields_containers_id']); - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - - $fields_type = self::getTypes(); - - Session::initNavigateListItems('PluginFieldsField', __('Fields list')); - - while ($data = $DB->fetchArray($result)) { - if ($this->getFromDB($data['id'])) { - echo ""; - - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - - echo ""; - echo ""; - echo ""; - echo ""; + echo ""; + echo ""; + + echo ""; + echo ""; + echo ""; + echo ""; - echo ""; - - $style_default = $this->fields['type'] === 'glpi_item' ? 'style="display:none;"' : ''; - $style_allowed = $this->fields['type'] !== 'glpi_item' ? 'style="display:none;"' : ''; - echo ""; - echo ""; - echo ""; + echo ""; + + $style_default = $this->fields['type'] === 'glpi_item' ? 'style="display:none;"' : ''; + $style_allowed = $this->fields['type'] !== 'glpi_item' ? 'style="display:none;"' : ''; + echo ""; + echo ""; + echo ""; - echo ""; - - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - - echo ""; - echo ""; - echo ""; - echo ""; - - $this->showFormButtons($options); - } - - static function showForTabContainer($c_id, $items_id, $itemtype) { - //profile restriction (for reading profile) - $profile = new PluginFieldsProfile; - $found = $profile->find(['profiles_id' => $_SESSION['glpiactiveprofile']['id'], - 'plugin_fields_containers_id' => $c_id]); - $first_found = array_shift($found); - $canedit = ($first_found['right'] == CREATE); - - //get fields for this container - $field_obj = new self(); - $fields = $field_obj->find(['plugin_fields_containers_id' => $c_id, 'is_active' => 1], "ranking"); - echo ""; - echo Html::hidden('plugin_fields_containers_id', ['value' => $c_id]); - echo Html::hidden('items_id', ['value' => $items_id]); - echo Html::hidden('itemtype', ['value' => $itemtype]); - echo "
".__("Label") ."".__("Type") ."".__("Default values") ."".__("Mandatory field") ."".__("Active") ."".__("Read only", "fields")." 
"; - echo "getID()}'>{$this->fields['label']}"; - echo "".$fields_type[$this->fields['type']]."".$this->fields['default_value']."".Dropdown::getYesNo($this->fields["mandatory"]).""; - echo ($this->isActive()) + echo __("Add a new field", "fields") . "
"; + + if ($DB->numrows($result) == 0) { + echo ""; + echo "
" . __("No field for this block", "fields") . "
"; + } else { + echo '
'; + echo Html::hidden("_plugin_fields_containers_id", ['value' => $cID, + 'id' => 'plugin_fields_containers_id' + ]); + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; + + $fields_type = self::getTypes(); + + Session::initNavigateListItems('PluginFieldsField', __('Fields list')); + + while ($data = $DB->fetchArray($result)) { + if ($this->getFromDB($data['id'])) { + echo ""; + + echo ""; + echo ""; + echo ""; + echo ""; + echo ""; - - echo ""; - - echo ''; - echo ""; + : '' . __('No') . ''; + echo ""; + + echo ""; + + echo ''; + echo ""; + } } - } - } - echo '
" . __("Label") . "" . __("Type") . "" . __("Default values") . "" . __("Mandatory field") . "" . __("Active") . "" . __("Read only", "fields") . " 
"; + echo "getID()}'>{$this->fields['label']}"; + echo "" . $fields_type[$this->fields['type']] . "" . $this->fields['default_value'] . "" . Dropdown::getYesNo($this->fields["mandatory"]) . ""; + echo ($this->isActive()) ? __('Yes') - : ''.__('No').''; - echo ""; - echo Dropdown::getYesNo($this->fields["is_readonly"]); - echo "'; - echo '
'; - echo ''; - echo '
'; - echo '
"; + echo Dropdown::getYesNo($this->fields["is_readonly"]); + echo "'; + echo '
'; + echo ''; + echo '
'; + echo '
'; - echo '
'; - echo Html::scriptBlock('$(document).ready(function() { - redipsInit() - });'); - } - - - function showForm($ID, $options = []) { - global $CFG_GLPI; - - $rand = mt_rand(); - - if (isset($options['parent_id']) && !empty($options['parent_id'])) { - $container = new PluginFieldsContainer; - $container->getFromDB($options['parent_id']); - } else if (isset($options['parent']) - && $options['parent'] instanceof CommonDBTM) { - $container = $options['parent']; - } - - if ($ID > 0) { - $attrs = ['readonly' => 'readonly']; - $edit = true; - } else { - $attrs = []; - // Create item - $edit = false; - $options['plugin_fields_containers_id'] = $container->getField('id'); - } - - $this->initForm($ID, $options); - $this->showFormHeader($ID, $options); - - echo "
".__("Label")." : "; - echo Html::hidden('plugin_fields_containers_id', ['value' => $container->getField('id')]); - echo Html::input( - 'label', - [ - 'value' => $this->fields['label'], - ] + $attrs - ); - echo "
".__("Type")." : "; - if ($edit) { - echo self::getTypes(true)[$this->fields['type']]; - } else { - // if glpi_item selected display dropdown and hide input default_value - echo Html::scriptBlock(<<'; + echo ''; + echo Html::scriptBlock('$(document).ready(function() { + redipsInit() + });'); + } + + + public function showForm($ID, $options = []) + { + global $CFG_GLPI; + + $rand = mt_rand(); + + if (isset($options['parent_id']) && !empty($options['parent_id'])) { + $container = new PluginFieldsContainer(); + $container->getFromDB($options['parent_id']); + } else if ( + isset($options['parent']) + && $options['parent'] instanceof CommonDBTM + ) { + $container = $options['parent']; + } + + if ($ID > 0) { + $attrs = ['readonly' => 'readonly']; + $edit = true; + } else { + $attrs = []; + // Create item + $edit = false; + $options['plugin_fields_containers_id'] = $container->getField('id'); + } + + $this->initForm($ID, $options); + $this->showFormHeader($ID, $options); + + echo "
" . __("Label") . " : "; + echo Html::hidden('plugin_fields_containers_id', ['value' => $container->getField('id')]); + echo Html::input( + 'label', + [ + 'value' => $this->fields['label'], + ] + $attrs + ); + echo "
" . __("Type") . " : "; + if ($edit) { + echo self::getTypes(true)[$this->fields['type']]; + } else { + // if glpi_item selected display dropdown and hide input default_value + echo Html::scriptBlock(<<fields['itemtypes']) - ? array_map( - function ($itemtype) { - return 'dropdown-' . $itemtype; - }, - json_decode($container->fields['itemtypes']) - ) - : []; - Dropdown::showFromArray( - 'type', - self::getTypes(false), - [ - 'value' => $this->fields['type'], - 'on_change' => 'plugin_fields_change_field_type_' . $rand . '(this.value)', - 'used' => array_combine($itemtypes_to_exclude, $itemtypes_to_exclude), - ] - ); - } - echo "
"; - echo '
'; - echo __("Default values")." : "; - echo '
'; - echo '
'; - echo __('Allowed values', 'fields')." : "; - echo '
'; - echo "
"; - echo '
"; + echo '
'; + echo __("Default values") . " : "; + echo '
'; + echo '
'; + echo __('Allowed values', 'fields') . " : "; + echo '
'; + echo "
"; + echo '
'; + echo Html::input( + 'default_value', + [ + 'value' => $this->fields['default_value'], + ] + ); + if ($this->fields["type"] == "dropdown") { + echo ' + ' . __('Configure', 'fields') . ' '; - } - if (in_array($this->fields['type'], ['date', 'datetime'])) { - echo ""; - } - echo '
'; - echo '
'; - if (!$edit) { - Dropdown::showFromArray('allowed_values', PluginFieldsToolbox::getGlpiItemtypes(), [ - 'display_emptychoice' => true, - 'multiple' => true - ]); - } else { - $allowed_itemtypes = !empty($this->fields['allowed_values']) + } + if (in_array($this->fields['type'], ['date', 'datetime'])) { + echo ""; + } + echo '
'; + echo '
'; + if (!$edit) { + Dropdown::showFromArray('allowed_values', PluginFieldsToolbox::getGlpiItemtypes(), [ + 'display_emptychoice' => true, + 'multiple' => true + ]); + } else { + $allowed_itemtypes = !empty($this->fields['allowed_values']) ? json_decode($this->fields['allowed_values']) : []; - echo implode( - ', ', - array_map( - function ($itemtype) { - return is_a($itemtype, CommonDBTM::class, true) + echo implode( + ', ', + array_map( + function ($itemtype) { + return is_a($itemtype, CommonDBTM::class, true) ? $itemtype::getTypeName(Session::getPluralNumber()) : $itemtype; - }, - $allowed_itemtypes - ) - ); - } - echo '
'; - echo "
".__('Active')." :"; - Dropdown::showYesNo('is_active', $this->fields["is_active"]); - echo "".__("Mandatory field")." : "; - Dropdown::showYesNo("mandatory", $this->fields["mandatory"]); - echo "
".__("Read only", "fields")." :"; - Dropdown::showYesNo("is_readonly", $this->fields["is_readonly"]); - echo "
"; - echo self::prepareHtmlFields($fields, $items_id, $itemtype, $canedit); - - if ($canedit) { - echo ""; - } - - echo "
"; - echo ""; - echo "
"; - Html::closeForm(); - - return true; - } - - /** - * Display dom container - * - * @param integer $c_id Container's ID - * @param string $itemtype Item type - * @param integer $items_id Item ID - * @param string $type Type (either 'dom' or 'domtab' - * @param string $subtype Requested subtype (used for domtab only) - * - * @return void - */ - static private function showDomContainer($c_id, $itemtype, $items_id, $type = "dom", $subtype = "") { - - if ($c_id !== false) { - //get fields for this container - $field_obj = new self(); - $fields = $field_obj->find( - [ - 'plugin_fields_containers_id' => $c_id, - 'is_active' => 1, - ], - "ranking" - ); - } else { - $fields = []; - } - - echo Html::hidden('_plugin_fields_type', ['value' => $type]); - echo Html::hidden('_plugin_fields_subtype', ['value' => $subtype]); - echo self::prepareHtmlFields($fields, $items_id, $itemtype); - } - - /** - * Display fields in any existing tab - * - * @param array $params [item, options] - * - * @return void - */ - static function showForTab($params) { - $item = $params['item']; - - $functions = array_column(debug_backtrace(), 'function'); - - $subtype = isset($_SESSION['glpi_tabs'][strtolower($item::getType())]) ? $_SESSION['glpi_tabs'][strtolower($item::getType())] : ""; - $type = substr($subtype, -strlen('$main')) === '$main' - || in_array('showForm', $functions) - || in_array('showPrimaryForm', $functions) - || in_array('showFormHelpdesk', $functions) - ? 'dom' - : 'domtab'; - if ($subtype == -1) { - $type = 'dom'; - } - // if we are in 'dom' or 'tab' type, no need for subtype ('domtab' specific) - if ($type != 'domtab') { - $subtype = ""; - } - //find container (if not exist, do nothing) - if (isset($_REQUEST['c_id'])) { - $c_id = $_REQUEST['c_id']; - } else if (!$c_id = PluginFieldsContainer::findContainer(get_Class($item), $type, $subtype)) { - return false; - } - - //need to check if container is usable on this object entity - $loc_c = new PluginFieldsContainer; - $loc_c->getFromDB($c_id); - $entities = [$loc_c->fields['entities_id']]; - if ($loc_c->fields['is_recursive']) { - $entities = getSonsOf(getTableForItemType('Entity'), $loc_c->fields['entities_id']); - } - - if ($item->isEntityAssign()) { - $current_entity = $item->getEntityID(); - if (!in_array($current_entity, $entities)) { + }, + $allowed_itemtypes + ) + ); + } + echo '
'; + echo ""; + echo ""; + + echo ""; + echo "" . __('Active') . " :"; + echo ""; + Dropdown::showYesNo('is_active', $this->fields["is_active"]); + echo ""; + echo "" . __("Mandatory field") . " : "; + echo ""; + Dropdown::showYesNo("mandatory", $this->fields["mandatory"]); + echo ""; + echo ""; + + echo ""; + echo "" . __("Read only", "fields") . " :"; + echo ""; + Dropdown::showYesNo("is_readonly", $this->fields["is_readonly"]); + echo ""; + echo ""; + + $this->showFormButtons($options); + } + + public static function showForTabContainer($c_id, $items_id, $itemtype) + { + //profile restriction (for reading profile) + $profile = new PluginFieldsProfile(); + $found = $profile->find(['profiles_id' => $_SESSION['glpiactiveprofile']['id'], + 'plugin_fields_containers_id' => $c_id + ]); + $first_found = array_shift($found); + $canedit = ($first_found['right'] == CREATE); + + //get fields for this container + $field_obj = new self(); + $fields = $field_obj->find(['plugin_fields_containers_id' => $c_id, 'is_active' => 1], "ranking"); + echo ""; + echo Html::hidden('plugin_fields_containers_id', ['value' => $c_id]); + echo Html::hidden('items_id', ['value' => $items_id]); + echo Html::hidden('itemtype', ['value' => $itemtype]); + echo ""; + echo self::prepareHtmlFields($fields, $items_id, $itemtype, $canedit); + + if ($canedit) { + echo ""; + } + + echo "
"; + echo ""; + echo "
"; + Html::closeForm(); + + return true; + } + + /** + * Display dom container + * + * @param integer $c_id Container's ID + * @param string $itemtype Item type + * @param integer $items_id Item ID + * @param string $type Type (either 'dom' or 'domtab' + * @param string $subtype Requested subtype (used for domtab only) + * + * @return void + */ + private static function showDomContainer($c_id, $itemtype, $items_id, $type = "dom", $subtype = "") + { + + if ($c_id !== false) { + //get fields for this container + $field_obj = new self(); + $fields = $field_obj->find( + [ + 'plugin_fields_containers_id' => $c_id, + 'is_active' => 1, + ], + "ranking" + ); + } else { + $fields = []; + } + + echo Html::hidden('_plugin_fields_type', ['value' => $type]); + echo Html::hidden('_plugin_fields_subtype', ['value' => $subtype]); + echo self::prepareHtmlFields($fields, $items_id, $itemtype); + } + + /** + * Display fields in any existing tab + * + * @param array $params [item, options] + * + * @return void + */ + public static function showForTab($params) + { + $item = $params['item']; + + $functions = array_column(debug_backtrace(), 'function'); + + $subtype = isset($_SESSION['glpi_tabs'][strtolower($item::getType())]) ? $_SESSION['glpi_tabs'][strtolower($item::getType())] : ""; + $type = substr($subtype, -strlen('$main')) === '$main' + || in_array('showForm', $functions) + || in_array('showPrimaryForm', $functions) + || in_array('showFormHelpdesk', $functions) + ? 'dom' + : 'domtab'; + if ($subtype == -1) { + $type = 'dom'; + } + // if we are in 'dom' or 'tab' type, no need for subtype ('domtab' specific) + if ($type != 'domtab') { + $subtype = ""; + } + //find container (if not exist, do nothing) + if (isset($_REQUEST['c_id'])) { + $c_id = $_REQUEST['c_id']; + } else if (!$c_id = PluginFieldsContainer::findContainer(get_Class($item), $type, $subtype)) { return false; - } - } - - //parse REQUEST_URI - if (!isset($_SERVER['REQUEST_URI'])) { - return false; - } - $current_url = $_SERVER['REQUEST_URI']; - if (strpos($current_url, ".form.php") === false - && strpos($current_url, ".injector.php") === false - && strpos($current_url, ".public.php") === false) { - return false; - } - - //Retrieve dom container - $itemtypes = PluginFieldsContainer::getUsedItemtypes($type, true); - - //if no dom containers defined for this itemtype, do nothing (in_array case insensitive) - if (!in_array(strtolower($item::getType()), array_map('strtolower', $itemtypes))) { - return false; - } - - $display_condition = new PluginFieldsContainerDisplayCondition(); - if($display_condition->computeDisplayContainer($item, $c_id)) { - self::showDomContainer( - $c_id, - $item::getType(), - $item->getID(), - $type, - $subtype - ); - } - - - } - - static function prepareHtmlFields($fields, $items_id, $itemtype, $canedit = true, - $show_table = true, $massiveaction = false) { - - if (empty($fields)) { - return false; - } - - //get object associated with this fields - $tmp = $fields; - $first_field = array_shift($tmp); - $container_obj = new PluginFieldsContainer; - $container_obj->getFromDB($first_field['plugin_fields_containers_id']); - - // Fill status overrides if needed - $item = new $itemtype(); - if (in_array($itemtype, PluginFieldsStatusOverride::getStatusItemtypes()) && $item->getFromDB($items_id)) { - $status_overrides = PluginFieldsStatusOverride::getOverridesForItem($container_obj->getID(), $item); - foreach ($status_overrides as $status_override) { - if (isset($fields[$status_override['plugin_fields_fields_id']])) { - $fields[$status_override['plugin_fields_fields_id']]['is_readonly'] = $status_override['is_readonly']; - $fields[$status_override['plugin_fields_fields_id']]['mandatory'] = $status_override['mandatory']; - } - } - } - - $classname = PluginFieldsContainer::getClassname($itemtype, $container_obj->fields['name']); - $obj = new $classname; - - //find row for this object with the items_id - $found_values = $obj->find( - [ - 'plugin_fields_containers_id' => $first_field['plugin_fields_containers_id'], - 'items_id' => $items_id, - ] - ); - $found_v = array_shift($found_values); - - // find profiles (to check if current profile can edit fields) - $fprofile = new PluginFieldsProfile; - $found_p = $fprofile->find( - [ - 'profiles_id' => $_SESSION['glpiactiveprofile']['id'], - 'plugin_fields_containers_id' => $first_field['plugin_fields_containers_id'], - ] - ); - $first_found_p = array_shift($found_p); - - // test status for "CommonITILObject" objects - if (is_subclass_of($itemtype, "CommonITILObject")) { - $items_obj = new $itemtype(); - if ($items_id > 0) { - $items_obj->getFromDB($items_id); - } else { - $items_obj->getEmpty(); - } - - if (in_array($items_obj->fields['status'], $items_obj->getClosedStatusArray()) - || $first_found_p['right'] != CREATE) { - $canedit = false; - } - } else { - if ($first_found_p['right'] != CREATE) { - $canedit = false; - } - } - - //show all fields - foreach ($fields as &$field) { - - $field['itemtype'] = self::getType(); - $field['label'] = PluginFieldsLabelTranslation::getLabelFor($field); - - $field['allowed_values'] = !empty($field['allowed_values']) ? json_decode($field['allowed_values']) : []; - if ($field['type'] === 'glpi_item') { - // Convert allowed values to [$itemtype_class => $itemtype_name] format - $allowed_itemtypes = []; - foreach ($field['allowed_values'] as $allowed_itemtype) { - if (is_a($allowed_itemtype, CommonDBTM::class, true)) { - $allowed_itemtypes[$allowed_itemtype] = $allowed_itemtype::getTypeName(Session::getPluralNumber()); - } + } + + //need to check if container is usable on this object entity + $loc_c = new PluginFieldsContainer(); + $loc_c->getFromDB($c_id); + $entities = [$loc_c->fields['entities_id']]; + if ($loc_c->fields['is_recursive']) { + $entities = getSonsOf(getTableForItemType('Entity'), $loc_c->fields['entities_id']); + } + + if ($item->isEntityAssign()) { + $current_entity = $item->getEntityID(); + if (!in_array($current_entity, $entities)) { + return false; } - $field['allowed_values'] = $allowed_itemtypes; - } - - //compute classname for 'dropdown-XXXXXX' field - $dropdown_matches = []; - if ( - preg_match('/^dropdown-(?.+)$/i', $field['type'], $dropdown_matches) - && class_exists($dropdown_matches['class']) - ) { - $dropdown_class = $dropdown_matches['class']; - - $field['dropdown_class'] = $dropdown_class; - $field['dropdown_condition'] = []; - - $object = new $dropdown_class(); - if ($object->maybeDeleted()){ - $field['dropdown_condition']['is_deleted'] = false; - } - if ($object->maybeActive()){ - $field['dropdown_condition']['is_active'] = true; + } + + //parse REQUEST_URI + if (!isset($_SERVER['REQUEST_URI'])) { + return false; + } + $current_url = $_SERVER['REQUEST_URI']; + if ( + strpos($current_url, ".form.php") === false + && strpos($current_url, ".injector.php") === false + && strpos($current_url, ".public.php") === false + ) { + return false; + } + + //Retrieve dom container + $itemtypes = PluginFieldsContainer::getUsedItemtypes($type, true); + + //if no dom containers defined for this itemtype, do nothing (in_array case insensitive) + if (!in_array(strtolower($item::getType()), array_map('strtolower', $itemtypes))) { + return false; + } + + $display_condition = new PluginFieldsContainerDisplayCondition(); + if ($display_condition->computeDisplayContainer($item, $c_id)) { + self::showDomContainer( + $c_id, + $item::getType(), + $item->getID(), + $type, + $subtype + ); + } + } + + public static function prepareHtmlFields( + $fields, + $items_id, + $itemtype, + $canedit = true, + $show_table = true, + $massiveaction = false + ) { + + if (empty($fields)) { + return false; + } + + //get object associated with this fields + $tmp = $fields; + $first_field = array_shift($tmp); + $container_obj = new PluginFieldsContainer(); + $container_obj->getFromDB($first_field['plugin_fields_containers_id']); + + // Fill status overrides if needed + $item = new $itemtype(); + if (in_array($itemtype, PluginFieldsStatusOverride::getStatusItemtypes()) && $item->getFromDB($items_id)) { + $status_overrides = PluginFieldsStatusOverride::getOverridesForItem($container_obj->getID(), $item); + foreach ($status_overrides as $status_override) { + if (isset($fields[$status_override['plugin_fields_fields_id']])) { + $fields[$status_override['plugin_fields_fields_id']]['is_readonly'] = $status_override['is_readonly']; + $fields[$status_override['plugin_fields_fields_id']]['mandatory'] = $status_override['mandatory']; + } } - } - - //get value - $value = null; - if (is_array($found_v)) { - if ($field['type'] == "dropdown") { - $value = $found_v["plugin_fields_".$field['name']."dropdowns_id"]; - } else if ($field['type'] == "glpi_item") { - $itemtype_key = sprintf('itemtype_%s', $field['name']); - $items_id_key = sprintf('items_id_%s', $field['name']); - $value = [ - 'itemtype' => $found_v[$itemtype_key], - 'items_id' => $found_v[$items_id_key], - ]; + } + + $classname = PluginFieldsContainer::getClassname($itemtype, $container_obj->fields['name']); + $obj = new $classname(); + + //find row for this object with the items_id + $found_values = $obj->find( + [ + 'plugin_fields_containers_id' => $first_field['plugin_fields_containers_id'], + 'items_id' => $items_id, + ] + ); + $found_v = array_shift($found_values); + + // find profiles (to check if current profile can edit fields) + $fprofile = new PluginFieldsProfile(); + $found_p = $fprofile->find( + [ + 'profiles_id' => $_SESSION['glpiactiveprofile']['id'], + 'plugin_fields_containers_id' => $first_field['plugin_fields_containers_id'], + ] + ); + $first_found_p = array_shift($found_p); + + // test status for "CommonITILObject" objects + if (is_subclass_of($itemtype, "CommonITILObject")) { + $items_obj = new $itemtype(); + if ($items_id > 0) { + $items_obj->getFromDB($items_id); } else { - $value = $found_v[$field['name']] ?? ""; + $items_obj->getEmpty(); } - } - - if (!$field['is_readonly']) { - if ($field['type'] == "dropdown") { - if (isset($_SESSION['plugin']['fields']['values_sent']["plugin_fields_". - $field['name']. - "dropdowns_id"])) { - $value = $_SESSION['plugin']['fields']['values_sent']["plugin_fields_". - $field['name']. - "dropdowns_id"]; - } - } else if (isset($_SESSION['plugin']['fields']['values_sent'][$field['name']])) { - $value = $_SESSION['plugin']['fields']['values_sent'][$field['name']]; + + if ( + in_array($items_obj->fields['status'], $items_obj->getClosedStatusArray()) + || $first_found_p['right'] != CREATE + ) { + $canedit = false; } - } - - //get default value - if ($value === null) { - if ($field['type'] === 'dropdown' && $field['default_value'] === '') { - $value = 0; - } else if ($field['default_value'] !== "") { - $value = $field['default_value']; - - // shortcut for date/datetime - if (in_array($field['type'], ['date', 'datetime']) - && $value == 'now') { - $value = $_SESSION["glpi_currenttime"]; + } else { + if ($first_found_p['right'] != CREATE) { + $canedit = false; + } + } + + //show all fields + foreach ($fields as &$field) { + $field['itemtype'] = self::getType(); + $field['label'] = PluginFieldsLabelTranslation::getLabelFor($field); + + $field['allowed_values'] = !empty($field['allowed_values']) ? json_decode($field['allowed_values']) : []; + if ($field['type'] === 'glpi_item') { + // Convert allowed values to [$itemtype_class => $itemtype_name] format + $allowed_itemtypes = []; + foreach ($field['allowed_values'] as $allowed_itemtype) { + if (is_a($allowed_itemtype, CommonDBTM::class, true)) { + $allowed_itemtypes[$allowed_itemtype] = $allowed_itemtype::getTypeName(Session::getPluralNumber()); + } } + $field['allowed_values'] = $allowed_itemtypes; } - } - $field['value'] = $value; - } + //compute classname for 'dropdown-XXXXXX' field + $dropdown_matches = []; + if ( + preg_match('/^dropdown-(?.+)$/i', $field['type'], $dropdown_matches) + && class_exists($dropdown_matches['class']) + ) { + $dropdown_class = $dropdown_matches['class']; - $item = new $itemtype; - $item->getFromDB($items_id); - $html = TemplateRenderer::getInstance()->render('@fields/fields.html.twig', [ - 'item' => $item, - 'fields' => $fields, - 'canedit' => $canedit, - 'massiveaction' => $massiveaction, - 'container' => $container_obj, - ]); + $field['dropdown_class'] = $dropdown_class; + $field['dropdown_condition'] = []; - unset($_SESSION['plugin']['fields']['values_sent']); + $object = new $dropdown_class(); + if ($object->maybeDeleted()) { + $field['dropdown_condition']['is_deleted'] = false; + } + if ($object->maybeActive()) { + $field['dropdown_condition']['is_active'] = true; + } + } - return $html; - } + //get value + $value = null; + if (is_array($found_v)) { + if ($field['type'] == "dropdown") { + $value = $found_v["plugin_fields_" . $field['name'] . "dropdowns_id"]; + } else if ($field['type'] == "glpi_item") { + $itemtype_key = sprintf('itemtype_%s', $field['name']); + $items_id_key = sprintf('items_id_%s', $field['name']); + $value = [ + 'itemtype' => $found_v[$itemtype_key], + 'items_id' => $found_v[$items_id_key], + ]; + } else { + $value = $found_v[$field['name']] ?? ""; + } + } - static function showSingle($itemtype, $searchOption, $massiveaction = false) { - global $DB; + if (!$field['is_readonly']) { + if ($field['type'] == "dropdown") { + if ( + isset($_SESSION['plugin']['fields']['values_sent']["plugin_fields_" . + $field['name'] . + "dropdowns_id"]) + ) { + $value = $_SESSION['plugin']['fields']['values_sent']["plugin_fields_" . + $field['name'] . + "dropdowns_id"]; + } + } else if (isset($_SESSION['plugin']['fields']['values_sent'][$field['name']])) { + $value = $_SESSION['plugin']['fields']['values_sent'][$field['name']]; + } + } - //clean dropdown [pre/su]fix if exists - $cleaned_linkfield = preg_replace("/plugin_fields_(.*)dropdowns_id/", "$1", - $searchOption['linkfield']); + //get default value + if ($value === null) { + if ($field['type'] === 'dropdown' && $field['default_value'] === '') { + $value = 0; + } else if ($field['default_value'] !== "") { + $value = $field['default_value']; + + // shortcut for date/datetime + if ( + in_array($field['type'], ['date', 'datetime']) + && $value == 'now' + ) { + $value = $_SESSION["glpi_currenttime"]; + } + } + } - //find field - $query = "SELECT fields.plugin_fields_containers_id, fields.is_readonly, fields.default_value + $field['value'] = $value; + } + + $item = new $itemtype(); + $item->getFromDB($items_id); + $html = TemplateRenderer::getInstance()->render('@fields/fields.html.twig', [ + 'item' => $item, + 'fields' => $fields, + 'canedit' => $canedit, + 'massiveaction' => $massiveaction, + 'container' => $container_obj, + ]); + + unset($_SESSION['plugin']['fields']['values_sent']); + + return $html; + } + + public static function showSingle($itemtype, $searchOption, $massiveaction = false) + { + global $DB; + + //clean dropdown [pre/su]fix if exists + $cleaned_linkfield = preg_replace( + "/plugin_fields_(.*)dropdowns_id/", + "$1", + $searchOption['linkfield'] + ); + + //find field + $query = "SELECT fields.plugin_fields_containers_id, fields.is_readonly, fields.default_value FROM glpi_plugin_fields_fields fields LEFT JOIN glpi_plugin_fields_containers containers ON containers.id = fields.plugin_fields_containers_id AND containers.itemtypes LIKE '%$itemtype%' WHERE fields.name = '$cleaned_linkfield'"; - $res = $DB->query($query); - if ($DB->numrows($res) == 0) { - return false; - } - - $data = $DB->fetchAssoc($res); - - //display an hidden post field to store container id - echo Html::hidden('c_id', ['value' => $data['plugin_fields_containers_id']]); - - //prepare array for function prepareHtmlFields - $fields = [[ - 'id' => 0, - 'type' => $searchOption['pfields_type'], - 'plugin_fields_containers_id' => $data['plugin_fields_containers_id'], - 'name' => $cleaned_linkfield, - 'is_readonly' => $data['is_readonly'], - 'default_value' => $data['default_value'] - ]]; - - //show field - echo self::prepareHtmlFields($fields, 0, $itemtype, true, false, $massiveaction); - - return true; - } - - function post_getEmpty() { - $this->fields['is_active'] = 1; - $this->fields['type'] = 'text'; - } - - static function getTypes(bool $flat_list = true) { - - $common_types = [ - 'header' => __("Header", "fields"), - 'text' => __("Text (single line)", "fields"), - 'textarea' => __("Text (multiples lines)", "fields"), - 'number' => __("Number", "fields"), - 'url' => __("URL", "fields"), - 'dropdown' => __("Dropdown", "fields"), - 'yesno' => __("Yes/No", "fields"), - 'date' => __("Date", "fields"), - 'datetime' => __("Date & time", "fields"), - 'glpi_item' => __("GLPI item", "fields"), - ]; - - $all_types = [ - __('Common') => $common_types, - ]; - - foreach (PluginFieldsToolbox::getGlpiItemtypes() as $section => $itemtypes) { - $all_types[$section] = []; - foreach ($itemtypes as $itemtype => $itemtype_name) { - $all_types[$section]['dropdown-' . $itemtype] = $itemtype_name; - } - } - - return $flat_list ? array_merge([], ...array_values($all_types)) : $all_types; - } - - function post_addItem() { - $input = $this->fields; - - //dropdowns : create files - if ($input['type'] === "dropdown") { - //search if dropdown already exist in other container - $found = $this->find(['id' => ['!=', $input['id']], 'name' => $input['name']]); - //for dropdown, if already exist, don't create files - if (empty($found)) { - PluginFieldsDropdown::create($input); - } - } - - //Create label translation - if (!isset($this->input['clone']) || !$this->input['clone']) { - PluginFieldsLabelTranslation::createForItem($this); - } - } - - function rawSearchOptions() { - $tab = []; - - $tab[] = [ - 'id' => 2, - 'table' => self::getTable(), - 'field' => 'label', - 'name' => __('Label'), - 'massiveaction' => false, - 'autocomplete' => true, - ]; - - $tab[] = [ - 'id' => 3, - 'table' => self::getTable(), - 'field' => 'default_value', - 'name' => __('Default values'), - 'massiveaction' => false, - 'autocomplete' => true, - ]; - - return $tab; - } - - function prepareInputForClone($input) { - if (array_key_exists('allowed_values', $input) && !empty($input['allowed_values'])) { - // $input has been transformed with `Toolbox::addslashes_deep()`, and `self::prepareInputForAdd()` - // is expecting an array, so it have to be unslashed then json decoded. - $input['allowed_values'] = json_decode(Sanitizer::dbUnescape($input['allowed_values'])); - } else { - unset($input['allowed_values']); - } - - return $input; - } - - public function getCloneRelations(): array - { - return [ - PluginFieldsStatusOverride::class, - PluginFieldsLabelTranslation::class, - ]; - } + $res = $DB->query($query); + if ($DB->numrows($res) == 0) { + return false; + } + + $data = $DB->fetchAssoc($res); + + //display an hidden post field to store container id + echo Html::hidden('c_id', ['value' => $data['plugin_fields_containers_id']]); + + //prepare array for function prepareHtmlFields + $fields = [[ + 'id' => 0, + 'type' => $searchOption['pfields_type'], + 'plugin_fields_containers_id' => $data['plugin_fields_containers_id'], + 'name' => $cleaned_linkfield, + 'is_readonly' => $data['is_readonly'], + 'default_value' => $data['default_value'] + ] + ]; + + //show field + echo self::prepareHtmlFields($fields, 0, $itemtype, true, false, $massiveaction); + + return true; + } + + // phpcs:ignore PSR1.Methods.CamelCapsMethodName + public function post_getEmpty() + { + $this->fields['is_active'] = 1; + $this->fields['type'] = 'text'; + } + + public static function getTypes(bool $flat_list = true) + { + $common_types = [ + 'header' => __("Header", "fields"), + 'text' => __("Text (single line)", "fields"), + 'textarea' => __("Text (multiples lines)", "fields"), + 'number' => __("Number", "fields"), + 'url' => __("URL", "fields"), + 'dropdown' => __("Dropdown", "fields"), + 'yesno' => __("Yes/No", "fields"), + 'date' => __("Date", "fields"), + 'datetime' => __("Date & time", "fields"), + 'glpi_item' => __("GLPI item", "fields"), + ]; + + $all_types = [ + __('Common') => $common_types, + ]; + + foreach (PluginFieldsToolbox::getGlpiItemtypes() as $section => $itemtypes) { + $all_types[$section] = []; + foreach ($itemtypes as $itemtype => $itemtype_name) { + $all_types[$section]['dropdown-' . $itemtype] = $itemtype_name; + } + } + + return $flat_list ? array_merge([], ...array_values($all_types)) : $all_types; + } + + // phpcs:ignore PSR1.Methods.CamelCapsMethodName + public function post_addItem() + { + $input = $this->fields; + + //dropdowns : create files + if ($input['type'] === "dropdown") { + //search if dropdown already exist in other container + $found = $this->find(['id' => ['!=', $input['id']], 'name' => $input['name']]); + //for dropdown, if already exist, don't create files + if (empty($found)) { + PluginFieldsDropdown::create($input); + } + } + + //Create label translation + if (!isset($this->input['clone']) || !$this->input['clone']) { + PluginFieldsLabelTranslation::createForItem($this); + } + } + + public function rawSearchOptions() + { + $tab = []; + + $tab[] = [ + 'id' => 2, + 'table' => self::getTable(), + 'field' => 'label', + 'name' => __('Label'), + 'massiveaction' => false, + 'autocomplete' => true, + ]; + + $tab[] = [ + 'id' => 3, + 'table' => self::getTable(), + 'field' => 'default_value', + 'name' => __('Default values'), + 'massiveaction' => false, + 'autocomplete' => true, + ]; + + return $tab; + } + + public function prepareInputForClone($input) + { + if (array_key_exists('allowed_values', $input) && !empty($input['allowed_values'])) { + // $input has been transformed with `Toolbox::addslashes_deep()`, and `self::prepareInputForAdd()` + // is expecting an array, so it have to be unslashed then json decoded. + $input['allowed_values'] = json_decode(Sanitizer::dbUnescape($input['allowed_values'])); + } else { + unset($input['allowed_values']); + } + + return $input; + } + + public function getCloneRelations(): array + { + return [ + PluginFieldsStatusOverride::class, + PluginFieldsLabelTranslation::class, + ]; + } } diff --git a/inc/inventory.class.php b/inc/inventory.class.php index 54fabfb9..96a5a906 100644 --- a/inc/inventory.class.php +++ b/inc/inventory.class.php @@ -28,95 +28,93 @@ * ------------------------------------------------------------------------- */ -class PluginFieldsInventory extends CommonDBTM { - - - static function updateInventory($params = []) { - - if (!empty($params) - && isset($params['inventory_data']) && !empty($params['inventory_data'])) { - - $availaibleItemType = ["Computer","Printer","NetworkEquipment"]; - foreach (array_keys($params['inventory_data']) as $itemtype) { - - if (in_array($itemtype, $availaibleItemType)) { - //retrive items id switch itemtype - switch ($itemtype) { - case Computer::getType(): - $items_id = $params['computers_id']; - break; - - case NetworkEquipment::getType(): - $items_id = $params['networkequipments_id']; - break; - - case Printer::getType(): - $items_id = $params['printers_id']; - break; - } - - //load inventory from DB because - //FI not update XML file if computer is not update - if ($itemtype == Computer::getType()) { - $db_info = new PluginFusioninventoryInventoryComputerComputer(); - if ($db_info->getFromDBByCrit(['computers_id' => $items_id])) { - - $arrayinventory = unserialize(gzuncompress($db_info->fields['serialized_inventory'])); - if (isset($arrayinventory['custom'])) { - self::updateFields($arrayinventory['custom']['container'], $itemtype, $items_id); - } - } - //Load XML file because FI always update XML file and don't store inventory into DB - } else { - $file = self::loadXMLFile($itemtype, $items_id); - if ($file !== false) { - $arrayinventory = PluginFusioninventoryFormatconvert::XMLtoArray($file); - if (isset($arrayinventory['CUSTOM'])) { - self::updateFields($arrayinventory['CUSTOM']['CONTAINER'], $itemtype, $items_id); - } - } - } +class PluginFieldsInventory extends CommonDBTM +{ + public static function updateInventory($params = []) + { + if ( + !empty($params) + && isset($params['inventory_data']) && !empty($params['inventory_data']) + ) { + $availaibleItemType = ["Computer","Printer","NetworkEquipment"]; + foreach (array_keys($params['inventory_data']) as $itemtype) { + if (in_array($itemtype, $availaibleItemType)) { + //retrive items id switch itemtype + switch ($itemtype) { + case Computer::getType(): + $items_id = $params['computers_id']; + break; + + case NetworkEquipment::getType(): + $items_id = $params['networkequipments_id']; + break; + + case Printer::getType(): + $items_id = $params['printers_id']; + break; + } + + if ($itemtype == Computer::getType()) { + //load inventory from DB because + //FI not update XML file if computer is not update + $db_info = new PluginFusioninventoryInventoryComputerComputer(); + if ($db_info->getFromDBByCrit(['computers_id' => $items_id])) { + $arrayinventory = unserialize(gzuncompress($db_info->fields['serialized_inventory'])); + if (isset($arrayinventory['custom'])) { + self::updateFields($arrayinventory['custom']['container'], $itemtype, $items_id); + } + } + } else { + //Load XML file because FI always update XML file and don't store inventory into DB + $file = self::loadXMLFile($itemtype, $items_id); + if ($file !== false) { + $arrayinventory = PluginFusioninventoryFormatconvert::XMLtoArray($file); + if (isset($arrayinventory['CUSTOM'])) { + self::updateFields($arrayinventory['CUSTOM']['CONTAINER'], $itemtype, $items_id); + } + } + } + } } - } - } - } - - static function updateFields($containersData, $itemtype, $items_id) { - if (isset($containersData['ID'])) { - // $containersData contains only one element, encapsulate it into an array - $containersData = [$containersData]; - } - foreach ($containersData as $key => $containerData) { - $container = new PluginFieldsContainer(); - $container->getFromDB($containerData['ID']); - $data = []; - $data["items_id"] = $items_id; - $data["itemtype"] = $itemtype; - $data["plugin_fields_containers_id"] = $containerData['ID']; - foreach ($containerData['FIELDS'] as $key => $value) { - $data[strtolower($key)] = $value; - } - $container->updateFieldsValues($data, $itemtype, false); - } - } - - static function loadXMLFile($itemtype, $items_id) { - - $pxml = false; - $folder = substr($items_id, 0, -1); - if (empty($folder)) { - $folder = '0'; - } - - //Check if the file exists with the .xml extension (new format) - $file = PLUGIN_FUSIONINVENTORY_XML_DIR . strtolower($itemtype) . "/" . $folder . "/" . $items_id; - if (file_exists($file . '.xml')) { - $file .= '.xml'; - } else if (!file_exists($file)) { - return false; - } - $pxml = simplexml_load_file($file, 'SimpleXMLElement', LIBXML_NOCDATA); - return $pxml; - } - + } + } + + public static function updateFields($containersData, $itemtype, $items_id) + { + if (isset($containersData['ID'])) { + // $containersData contains only one element, encapsulate it into an array + $containersData = [$containersData]; + } + foreach ($containersData as $key => $containerData) { + $container = new PluginFieldsContainer(); + $container->getFromDB($containerData['ID']); + $data = []; + $data["items_id"] = $items_id; + $data["itemtype"] = $itemtype; + $data["plugin_fields_containers_id"] = $containerData['ID']; + foreach ($containerData['FIELDS'] as $key => $value) { + $data[strtolower($key)] = $value; + } + $container->updateFieldsValues($data, $itemtype, false); + } + } + + public static function loadXMLFile($itemtype, $items_id) + { + $pxml = false; + $folder = substr($items_id, 0, -1); + if (empty($folder)) { + $folder = '0'; + } + + //Check if the file exists with the .xml extension (new format) + $file = PLUGIN_FUSIONINVENTORY_XML_DIR . strtolower($itemtype) . "/" . $folder . "/" . $items_id; + if (file_exists($file . '.xml')) { + $file .= '.xml'; + } else if (!file_exists($file)) { + return false; + } + $pxml = simplexml_load_file($file, 'SimpleXMLElement', LIBXML_NOCDATA); + return $pxml; + } } diff --git a/inc/labeltranslation.class.php b/inc/labeltranslation.class.php index 410beefe..2ba87e51 100644 --- a/inc/labeltranslation.class.php +++ b/inc/labeltranslation.class.php @@ -28,33 +28,35 @@ * ------------------------------------------------------------------------- */ -class PluginFieldsLabelTranslation extends CommonDBChild { +class PluginFieldsLabelTranslation extends CommonDBChild +{ use Glpi\Features\Clonable; public static $itemtype = 'itemtype'; public static $items_id = 'items_id'; - /** - * Install or update fields - * - * @param Migration $migration Migration instance - * @param string $version Plugin current version - * - * @return boolean - */ - static function install(Migration $migration, $version) { - global $DB; + /** + * Install or update fields + * + * @param Migration $migration Migration instance + * @param string $version Plugin current version + * + * @return boolean + */ + public static function install(Migration $migration, $version) + { + global $DB; - $default_charset = DBConnection::getDefaultCharset(); - $default_collation = DBConnection::getDefaultCollation(); - $default_key_sign = DBConnection::getDefaultPrimaryKeySignOption(); + $default_charset = DBConnection::getDefaultCharset(); + $default_collation = DBConnection::getDefaultCollation(); + $default_key_sign = DBConnection::getDefaultPrimaryKeySignOption(); - $table = self::getTable(); + $table = self::getTable(); - if (!$DB->tableExists($table)) { - $migration->displayMessage(sprintf(__("Installing %s"), $table)); + if (!$DB->tableExists($table)) { + $migration->displayMessage(sprintf(__("Installing %s"), $table)); - $query = "CREATE TABLE IF NOT EXISTS `$table` ( + $query = "CREATE TABLE IF NOT EXISTS `$table` ( `id` INT {$default_key_sign} NOT NULL auto_increment, `itemtype` VARCHAR(30) NOT NULL, `items_id` INT {$default_key_sign} NOT NULL, @@ -66,256 +68,271 @@ static function install(Migration $migration, $version) { KEY `language` (`language`), UNIQUE KEY `unicity` (`itemtype`, `items_id`, `language`) ) ENGINE=InnoDB DEFAULT CHARSET={$default_charset} COLLATE={$default_collation} ROW_FORMAT=DYNAMIC;"; - $DB->query($query) or die ($DB->error()); - } - - if ($DB->fieldExists($table, 'plugin_fields_itemtype')) { - $migration->dropKey($table, 'plugin_fields_itemtype'); - $migration->migrationOneTable($table); - $migration->changeField($table, 'plugin_fields_itemtype', 'itemtype', 'VARCHAR(30) NOT NULL'); - $migration->addKey($table, 'itemtype'); - } - - if ($DB->fieldExists($table, 'plugin_fields_items_id')) { - $migration->dropKey($table, 'plugin_fields_items_id'); - $migration->migrationOneTable($table); - $migration->changeField($table, 'plugin_fields_items_id', 'items_id', "INT {$default_key_sign} NOT NULL"); - $migration->addKey($table, 'items_id'); - } - - return true; - } - - static function uninstall() { - global $DB; - - $DB->query("DROP TABLE IF EXISTS `".self::getTable()."`"); - - return true; - } - - static function getTypeName($nb = 0) { - return _n("Translation", "Translations", $nb); - } - - static function createForItem(CommonDBTM $item) { - - $translation = new PluginFieldsLabelTranslation(); - $translation->add([ - 'itemtype' => $item::getType(), - 'items_id' => $item->getID(), - 'language' => $_SESSION['glpilanguage'], - 'label' => $item->fields['label'] - ]); - return true; - } - - function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { - $nb = countElementsInTable( - self::getTable(), - [ - 'itemtype' => $item::getType(), - 'items_id' => $item->getID(), - ] - ); - return self::createTabEntry(self::getTypeName($nb), $nb); - - } - - static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { - self::showTranslations($item); - } - - /** - * Display all translations for a label - * - * @param CommonDBTM $item Item instance - * - * @return void - **/ - static function showTranslations(CommonDBTM $item) { - $canedit = $item->can($item->getID(), UPDATE); - $rand = mt_rand(); - if ($canedit) { - echo "
"; - - echo Html::scriptBlock(' - addTranslation' . $item->getID() . $rand . ' = function() { - $("#viewtranslation' . $item->getID() . $rand . '").load( - "' . Plugin::getWebDir('fields') . '/ajax/viewtranslations.php", - ' . json_encode([ - 'type' => __CLASS__, - 'itemtype' => $item::getType(), - 'items_id' => $item->fields['id'], - 'id' => -1 - ]) . ' - ); - }; - '); - - echo "
"; - } - - $obj = new self; - $found = $obj->find( - [ + $DB->query($query) or die($DB->error()); + } + + if ($DB->fieldExists($table, 'plugin_fields_itemtype')) { + $migration->dropKey($table, 'plugin_fields_itemtype'); + $migration->migrationOneTable($table); + $migration->changeField($table, 'plugin_fields_itemtype', 'itemtype', 'VARCHAR(30) NOT NULL'); + $migration->addKey($table, 'itemtype'); + } + + if ($DB->fieldExists($table, 'plugin_fields_items_id')) { + $migration->dropKey($table, 'plugin_fields_items_id'); + $migration->migrationOneTable($table); + $migration->changeField($table, 'plugin_fields_items_id', 'items_id', "INT {$default_key_sign} NOT NULL"); + $migration->addKey($table, 'items_id'); + } + + return true; + } + + public static function uninstall() + { + global $DB; + + $DB->query("DROP TABLE IF EXISTS `" . self::getTable() . "`"); + + return true; + } + + public static function getTypeName($nb = 0) + { + return _n("Translation", "Translations", $nb); + } + + public static function createForItem(CommonDBTM $item) + { + $translation = new PluginFieldsLabelTranslation(); + $translation->add([ 'itemtype' => $item::getType(), 'items_id' => $item->getID(), - ], - "language ASC" - ); - - if (count($found) > 0) { - if ($canedit) { - Html::openMassiveActionsForm('mass'.__CLASS__.$rand); - $massiveactionparams = ['container' => 'mass'.__CLASS__.$rand]; - Html::showMassiveActions($massiveactionparams); - } - echo "
"; - echo ""; - echo ""; - if ($canedit) { - echo ""; - } - echo ""; - echo ""; - foreach ($found as $data) { - echo ""; + 'language' => $_SESSION['glpilanguage'], + 'label' => $item->fields['label'] + ]); + return true; + } + + public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) + { + $nb = countElementsInTable( + self::getTable(), + [ + 'itemtype' => $item::getType(), + 'items_id' => $item->getID(), + ] + ); + return self::createTabEntry(self::getTypeName($nb), $nb); + } + + public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) + { + self::showTranslations($item); + } + + /** + * Display all translations for a label + * + * @param CommonDBTM $item Item instance + * + * @return void + */ + public static function showTranslations(CommonDBTM $item) + { + $canedit = $item->can($item->getID(), UPDATE); + $rand = mt_rand(); + if ($canedit) { + echo "
"; + + $ajax_params = [ + 'type' => __CLASS__, + 'itemtype' => $item::getType(), + 'items_id' => $item->fields['id'], + 'id' => -1 + ]; + echo Html::scriptBlock(' + addTranslation' . $item->getID() . $rand . ' = function() { + $("#viewtranslation' . $item->getID() . $rand . '").load( + "' . Plugin::getWebDir('fields') . '/ajax/viewtranslations.php", + ' . json_encode($ajax_params) . ' + ); + }; + '); + + echo "
"; + } + + $obj = new self(); + $found = $obj->find( + [ + 'itemtype' => $item::getType(), + 'items_id' => $item->getID(), + ], + "language ASC" + ); + + if (count($found) > 0) { if ($canedit) { - echo ""; + Html::openMassiveActionsForm('mass' . __CLASS__ . $rand); + $massiveactionparams = ['container' => 'mass' . __CLASS__ . $rand]; + Html::showMassiveActions($massiveactionparams); } - echo "
".__("List of translations")."
"; - echo Html::getCheckAllAsCheckbox('mass'.__CLASS__.$rand); - echo "".__("Language", "fields")."".__("Label", "fields")."
"; - Html::showMassiveActionCheckBox(__CLASS__, $data["id"]); - echo ""; + echo "
"; + echo ""; + echo ""; if ($canedit) { - echo Html::scriptBlock(' - viewEditTranslation' . $data['id'] . $rand . ' = function() { - $("#viewtranslation' . $item->getID() . $rand . '").load( - "' . Plugin::getWebDir('fields') . '/ajax/viewtranslations.php", - ' . json_encode([ - 'type' => __CLASS__, - 'itemtype' => $item::getType(), - 'items_id' => $item->getID(), - 'id' => $data['id'] - ]) . ' - ); - }; - '); + echo ""; + } + echo ""; + echo ""; + foreach ($found as $data) { + echo ""; + if ($canedit) { + echo ""; + } + echo ""; } - echo Dropdown::getLanguageName($data['language']); - echo ""; - } - echo "
" . __("List of translations") . "
"; + echo Html::getCheckAllAsCheckbox('mass' . __CLASS__ . $rand); + echo "" . __("Language", "fields") . "" . __("Label", "fields") . "
"; + Html::showMassiveActionCheckBox(__CLASS__, $data["id"]); + echo ""; + if ($canedit) { + $ajax_params = [ + 'type' => __CLASS__, + 'itemtype' => $item::getType(), + 'items_id' => $item->getID(), + 'id' => $data['id'] + ]; + echo Html::scriptBlock(' + viewEditTranslation' . $data['id'] . $rand . ' = function() { + $("#viewtranslation' . $item->getID() . $rand . '").load( + "' . Plugin::getWebDir('fields') . '/ajax/viewtranslations.php", + ' . json_encode($ajax_params) . ' + ); + }; + '); + } + echo Dropdown::getLanguageName($data['language']); + echo ""; + echo $data['label']; + echo "
"; - echo $data['label']; - echo "
"; - if ($canedit) { - $massiveactionparams['ontop'] = false; - Html::showMassiveActions($massiveactionparams); - Html::closeForm(); - } - } else { - echo ""; - echo "
".__("No translation found")."
"; - } - - return true; - } - - /** - * Display translation form - * - * @param string $itemtype Item type - * @param int $items_id Item ID - * @param int $id Translation ID (defaults to -1) - * - * @return void + echo "
"; + if ($canedit) { + $massiveactionparams['ontop'] = false; + Html::showMassiveActions($massiveactionparams); + Html::closeForm(); + } + } else { + echo ""; + echo "
" . __("No translation found") . "
"; + } + + return true; + } + + /** + * Display translation form + * + * @param string $itemtype Item type + * @param int $items_id Item ID + * @param int $id Translation ID (defaults to -1) + * + * @return void + */ + public function showFormForItem($itemtype, $items_id, $id = -1) + { + if ($id > 0) { + $this->check($id, READ); + } else { + // Create item + $this->check(-1, CREATE); + } + $this->showFormHeader(); + echo ""; + echo "" . __('Language') . " :"; + echo ""; + echo ""; + echo ""; + if ($id > 0) { + echo Dropdown::getLanguageName($this->fields['language']); + } else { + Dropdown::showLanguages( + "language", + ['display_none' => false, + 'value' => $_SESSION['glpilanguage'], + 'used' => self::getAlreadyTranslatedForItem( + $itemtype, + $items_id + ) + ] + ); + } + echo " "; + + echo ""; + echo ""; + echo ""; + echo Html::input('label', [ + 'value' => $this->fields["label"], + 'id' => 'label' + ]); + echo ""; + + $this->showFormButtons(); + return true; + } + + /** + * Get already translated languages for item + * + * @param string $itemtype Item type + * @param int $items_id Item ID + * + * @return array of already translated languages */ - function showFormForItem($itemtype, $items_id, $id = -1) { - if ($id > 0) { - $this->check($id, READ); - } else { - // Create item - $this->check(-1, CREATE); - - } - $this->showFormHeader(); - echo ""; - echo "".__('Language')." :"; - echo ""; - echo ""; - echo ""; - if ($id > 0) { - echo Dropdown::getLanguageName($this->fields['language']); - } else { - Dropdown::showLanguages("language", - ['display_none' => false, - 'value' => $_SESSION['glpilanguage'], - 'used' => self::getAlreadyTranslatedForItem($itemtype, $items_id)]); - } - echo " "; - - echo ""; - echo ""; - echo ""; - echo Html::input('label', [ - 'value' => $this->fields["label"], - 'id' => 'label' - ]); - echo ""; - - $this->showFormButtons(); - return true; - } - - /** - * Get already translated languages for item - * - * @param string $itemtype Item type - * @param int $items_id Item ID - * - * @return array of already translated languages - **/ - static function getAlreadyTranslatedForItem($itemtype, $items_id) { - global $DB; - - $iterator = $DB->request( - [ - 'FROM' => self::getTable(), - 'WHERE' => [ - 'itemtype' => $itemtype, - 'items_id' => $items_id, + public static function getAlreadyTranslatedForItem($itemtype, $items_id) + { + global $DB; + + $iterator = $DB->request( + [ + 'FROM' => self::getTable(), + 'WHERE' => [ + 'itemtype' => $itemtype, + 'items_id' => $items_id, + ] ] - ] - ); - $tab = []; - foreach ($iterator as $data) { - $tab[$data['language']] = $data['language']; - } - return $tab; - } - - /** - * Get trnaslated label for item - * - * @param array $item Item - * - * @return string - */ - static public function getLabelFor(array $item) { - $obj = new self; - $found = $obj->find(['itemtype' => $item['itemtype'], - 'items_id' => $item['id'], - 'language' => $_SESSION['glpilanguage']]); - - if (count($found) > 0) { - return array_values($found)[0]['label']; - } - - return $item['label']; - } + ); + $tab = []; + foreach ($iterator as $data) { + $tab[$data['language']] = $data['language']; + } + return $tab; + } + + /** + * Get translated label for item + * + * @param array $item Item + * + * @return string + */ + public static function getLabelFor(array $item) + { + $obj = new self(); + $found = $obj->find(['itemtype' => $item['itemtype'], + 'items_id' => $item['id'], + 'language' => $_SESSION['glpilanguage'] + ]); + + if (count($found) > 0) { + return array_values($found)[0]['label']; + } + + return $item['label']; + } } diff --git a/inc/menu.class.php b/inc/menu.class.php index 2237c23d..2ccc125b 100644 --- a/inc/menu.class.php +++ b/inc/menu.class.php @@ -28,44 +28,43 @@ * ------------------------------------------------------------------------- */ -class PluginFieldsMenu extends CommonGLPI { - static $rightname = 'entity'; +class PluginFieldsMenu extends CommonGLPI +{ + public static $rightname = 'entity'; - static function getMenuName() { - return __("Additionnal fields", "fields"); - } + public static function getMenuName() + { + return __("Additionnal fields", "fields"); + } - static function getMenuContent() { + public static function getMenuContent() + { + if (!Session::haveRight('entity', READ)) { + return; + } - if (!Session::haveRight('entity', READ)) { - return; - } + $front_fields = Plugin::getPhpDir('fields', false) . "/front"; + $menu = [ + 'title' => self::getMenuName(), + 'page' => "$front_fields/container.php", + 'icon' => PluginFieldsContainer::getIcon(), + ]; - $front_fields = Plugin::getPhpDir('fields', false)."/front"; - $menu = [ - 'title' => self::getMenuName(), - 'page' => "$front_fields/container.php", - 'icon' => PluginFieldsContainer::getIcon(), - ]; + $itemtypes = ['PluginFieldsContainer' => 'fieldscontainer']; - $itemtypes = ['PluginFieldsContainer' => 'fieldscontainer']; + foreach ($itemtypes as $itemtype => $option) { + $menu['options'][$option] = [ + 'title' => $itemtype::getTypeName(2), + 'page' => $itemtype::getSearchURL(false), + 'links' => [ + 'search' => $itemtype::getSearchURL(false) + ] + ]; - foreach ($itemtypes as $itemtype => $option) { - $menu['options'][$option] = [ - 'title' => $itemtype::getTypeName(2), - 'page' => $itemtype::getSearchURL(false), - 'links' => [ - 'search' => $itemtype::getSearchURL(false) - ] - ]; - - if ($itemtype::canCreate()) { - $menu['options'][$option]['links']['add'] = $itemtype::getFormURL(false); - } - - } - return $menu; - } - - -} \ No newline at end of file + if ($itemtype::canCreate()) { + $menu['options'][$option]['links']['add'] = $itemtype::getFormURL(false); + } + } + return $menu; + } +} diff --git a/inc/migration.class.php b/inc/migration.class.php index 7cdd145b..e4dd8ce8 100644 --- a/inc/migration.class.php +++ b/inc/migration.class.php @@ -28,56 +28,57 @@ * ------------------------------------------------------------------------- */ -class PluginFieldsMigration extends Migration { +class PluginFieldsMigration extends Migration +{ + public function displayMessage($msg) + { + Session::addMessageAfterRedirect($msg); + } - function displayMessage($msg) { - Session::addMessageAfterRedirect($msg); - } + /** + * Return SQL fields corresponding to given additionnal field. + * + * @param string $field_name + * @param string $field_type + * + * @return array + */ + public static function getSQLFields(string $field_name, string $field_type): array + { + $default_key_sign = DBConnection::getDefaultPrimaryKeySignOption(); - /** - * Return SQL fields corresponding to given additionnal field. - * - * @param string $field_name - * @param string $field_type - * - * @return array - */ - public static function getSQLFields(string $field_name, string $field_type): array { + $fields = []; + switch (true) { + case $field_type === 'header': + // header type is for read-only display purpose only and has no SQL field + break; + case $field_type === 'dropdown': + case preg_match('/^dropdown-.+/i', $field_type): + if ($field_type === 'dropdown') { + $field_name = getForeignKeyFieldForItemType(PluginFieldsDropdown::getClassname($field_name)); + } + $fields[$field_name] = "INT {$default_key_sign} NOT NULL DEFAULT 0"; + break; + case $field_type === 'textarea': + case $field_type === 'url': + $fields[$field_name] = 'TEXT DEFAULT NULL'; + break; + case $field_type === 'yesno': + $fields[$field_name] = 'INT NOT NULL DEFAULT 0'; + break; + case $field_type === 'glpi_item': + $fields[sprintf('itemtype_%s', $field_name)] = 'varchar(100) NOT NULL'; + $fields[sprintf('items_id_%s', $field_name)] = "int {$default_key_sign} NOT NULL DEFAULT 0"; + break; + case $field_type === 'date': + case $field_type === 'datetime': + case $field_type === 'number': + case $field_type === 'text': + default: + $fields[$field_name] = 'VARCHAR(255) DEFAULT NULL'; + break; + } - $default_key_sign = DBConnection::getDefaultPrimaryKeySignOption(); - - $fields = []; - switch (true) { - case $field_type === 'header': - // header type is for read-only display purpose only and has no SQL field - break; - case $field_type === 'dropdown': - case preg_match('/^dropdown-.+/i', $field_type): - if ($field_type === 'dropdown') { - $field_name = getForeignKeyFieldForItemType(PluginFieldsDropdown::getClassname($field_name)); - } - $fields[$field_name] = "INT {$default_key_sign} NOT NULL DEFAULT 0"; - break; - case $field_type === 'textarea': - case $field_type === 'url': - $fields[$field_name] = 'TEXT DEFAULT NULL'; - break; - case $field_type === 'yesno': - $fields[$field_name] = 'INT NOT NULL DEFAULT 0'; - break; - case $field_type === 'glpi_item': - $fields[sprintf('itemtype_%s', $field_name)] = 'varchar(100) NOT NULL'; - $fields[sprintf('items_id_%s', $field_name)] = "int {$default_key_sign} NOT NULL DEFAULT 0"; - break; - case $field_type === 'date': - case $field_type === 'datetime': - case $field_type === 'number': - case $field_type === 'text': - default: - $fields[$field_name] = 'VARCHAR(255) DEFAULT NULL'; - break; - } - - return $fields; - } + return $fields; + } } diff --git a/inc/profile.class.php b/inc/profile.class.php index 25b66607..f56a73db 100644 --- a/inc/profile.class.php +++ b/inc/profile.class.php @@ -28,27 +28,29 @@ * ------------------------------------------------------------------------- */ -class PluginFieldsProfile extends CommonDBRelation { - use Glpi\Features\Clonable; +class PluginFieldsProfile extends CommonDBRelation +{ + use Glpi\Features\Clonable; - public static $itemtype_1 = PluginFieldsContainer::class; - public static $items_id_1 = 'plugin_fields_containers_id'; - public static $itemtype_2 = Profile::class; - public static $items_id_2 = 'profiles_id'; + public static $itemtype_1 = PluginFieldsContainer::class; + public static $items_id_1 = 'plugin_fields_containers_id'; + public static $itemtype_2 = Profile::class; + public static $items_id_2 = 'profiles_id'; - static function install(Migration $migration) { - global $DB; + public static function install(Migration $migration) + { + global $DB; - $default_charset = DBConnection::getDefaultCharset(); - $default_collation = DBConnection::getDefaultCollation(); - $default_key_sign = DBConnection::getDefaultPrimaryKeySignOption(); + $default_charset = DBConnection::getDefaultCharset(); + $default_collation = DBConnection::getDefaultCollation(); + $default_key_sign = DBConnection::getDefaultPrimaryKeySignOption(); - $table = self::getTable(); + $table = self::getTable(); - if (!$DB->tableExists($table)) { - $migration->displayMessage(sprintf(__("Installing %s"), $table)); + if (!$DB->tableExists($table)) { + $migration->displayMessage(sprintf(__("Installing %s"), $table)); - $query = "CREATE TABLE IF NOT EXISTS `$table` ( + $query = "CREATE TABLE IF NOT EXISTS `$table` ( `id` INT {$default_key_sign} NOT NULL auto_increment, `profiles_id` INT {$default_key_sign} NOT NULL DEFAULT '0', `plugin_fields_containers_id` INT {$default_key_sign} NOT NULL DEFAULT '0', @@ -57,128 +59,133 @@ static function install(Migration $migration) { KEY `profiles_id` (`profiles_id`), KEY `plugin_fields_containers_id` (`plugin_fields_containers_id`) ) ENGINE=InnoDB DEFAULT CHARSET={$default_charset} COLLATE={$default_collation} ROW_FORMAT=DYNAMIC;"; - $DB->query($query) or die ($DB->error()); - } - - return true; - } - - - static function uninstall() { - global $DB; - - $DB->query("DROP TABLE IF EXISTS `".self::getTable()."`"); - - return true; - } - - - function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { - return self::createTabEntry(_n("Profile", "Profiles", 2)); - } - - - static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { - $profile = new Profile; - $found_profiles = $profile->find(); - - $fields_profile = new self; - echo ""; - echo "
"; - echo ""; - - echo ""; - foreach ($found_profiles as $profile_item) { - //get right for current profile - $found = $fields_profile->find(['profiles_id' => $profile_item['id'], - 'plugin_fields_containers_id' => $item->fields['id']]); - $first_found = array_shift($found); - - //display right - echo ""; - echo ""; - echo ""; - echo ""; - } - echo "
    "; - echo "
"; - echo ""; - echo "
" . _n("Profile", "Profiles", 2) ."
".$profile_item['name'].""; - Profile::dropdownRight("rights[".$profile_item['id']."]", - ['value' => $first_found['right']]); - echo "
"; - echo ""; - echo ""; - echo "
"; - Html::closeForm(); - } - - - - static function updateProfile($input) { - $fields_profile = new self; - foreach ($input['rights'] as $profiles_id => $right) { - $found = $fields_profile->find( - [ - 'profiles_id' => $profiles_id, - 'plugin_fields_containers_id' => $input['plugin_fields_containers_id'] - ] - ); - if (count( $found ) > 0) { + $DB->query($query) or die($DB->error()); + } + + return true; + } + + public static function uninstall() + { + global $DB; + + $DB->query("DROP TABLE IF EXISTS `" . self::getTable() . "`"); + + return true; + } + + + public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) + { + return self::createTabEntry(_n("Profile", "Profiles", 2)); + } + + public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) + { + $profile = new Profile(); + $found_profiles = $profile->find(); + + $fields_profile = new self(); + echo ""; + echo "
"; + echo ""; + + echo ""; + foreach ($found_profiles as $profile_item) { + //get right for current profile + $found = $fields_profile->find([ + 'profiles_id' => $profile_item['id'], + 'plugin_fields_containers_id' => $item->fields['id'] + ]); $first_found = array_shift($found); - $fields_profile->update([ - 'id' => $first_found['id'], - 'profiles_id' => $profiles_id, - 'plugin_fields_containers_id' => $input['plugin_fields_containers_id'], - 'right' => $right + //display right + echo ""; + echo ""; + echo ""; + echo ""; + } + echo "
    "; + echo "
"; + echo ""; + echo "
" . _n("Profile", "Profiles", 2) . "
" . $profile_item['name'] . ""; + Profile::dropdownRight( + "rights[" . $profile_item['id'] . "]", + ['value' => $first_found['right']] + ); + echo "
"; + echo ""; + echo ""; + echo "
"; + Html::closeForm(); + } + + public static function updateProfile($input) + { + $fields_profile = new self(); + foreach ($input['rights'] as $profiles_id => $right) { + $found = $fields_profile->find( + [ + 'profiles_id' => $profiles_id, + 'plugin_fields_containers_id' => $input['plugin_fields_containers_id'] + ] + ); + if (count($found) > 0) { + $first_found = array_shift($found); + + $fields_profile->update([ + 'id' => $first_found['id'], + 'profiles_id' => $profiles_id, + 'plugin_fields_containers_id' => $input['plugin_fields_containers_id'], + 'right' => $right + ]); + } else { + $fields_profile->add([ + 'profiles_id' => $profiles_id, + 'plugin_fields_containers_id' => $input['plugin_fields_containers_id'], + 'right' => $right + ]); + } + } + + return true; + } + + public static function createForContainer(PluginFieldsContainer $container) + { + $profile = new Profile(); + $found_profiles = $profile->find(); + + $fields_profile = new self(); + foreach ($found_profiles as $profile_item) { + $fields_profile->add([ + 'profiles_id' => $profile_item['id'], + 'plugin_fields_containers_id' => $container->fields['id'], + 'right' => CREATE ]); - } else { + } + return true; + } + + public static function addNewProfile(Profile $profile) + { + $containers = new PluginFieldsContainer(); + $found_containers = $containers->find(); + + $fields_profile = new self(); + foreach ($found_containers as $container) { $fields_profile->add([ - 'profiles_id' => $profiles_id, - 'plugin_fields_containers_id' => $input['plugin_fields_containers_id'], - 'right' => $right + 'profiles_id' => $profile->fields['id'], + 'plugin_fields_containers_id' => $container['id'] ]); - } - } - - return true; - } - - - static function createForContainer(PluginFieldsContainer $container) { - $profile = new Profile; - $found_profiles = $profile->find(); - - $fields_profile = new self; - foreach ($found_profiles as $profile_item) { - $fields_profile->add([ - 'profiles_id' => $profile_item['id'], - 'plugin_fields_containers_id' => $container->fields['id'], - 'right' => CREATE - ]); - } - return true; - } - - static function addNewProfile(Profile $profile) { - $containers = new PluginFieldsContainer; - $found_containers = $containers->find(); - - $fields_profile = new self; - foreach ($found_containers as $container) { - $fields_profile->add([ - 'profiles_id' => $profile->fields['id'], - 'plugin_fields_containers_id' => $container['id'] - ]); - } - return true; - } - - static function deleteProfile(Profile $profile) { - $fields_profile = new self; - $fields_profile->deleteByCriteria(['profiles_id' => $profile->fields['id']]); - return true; - } + } + return true; + } + + public static function deleteProfile(Profile $profile) + { + $fields_profile = new self(); + $fields_profile->deleteByCriteria(['profiles_id' => $profile->fields['id']]); + return true; + } } diff --git a/inc/statusoverride.class.php b/inc/statusoverride.class.php index b03b63b8..3f1b7dd9 100644 --- a/inc/statusoverride.class.php +++ b/inc/statusoverride.class.php @@ -30,13 +30,15 @@ use Glpi\Application\View\TemplateRenderer; -class PluginFieldsStatusOverride extends CommonDBChild { +class PluginFieldsStatusOverride extends CommonDBChild +{ use Glpi\Features\Clonable; public static $itemtype = PluginFieldsField::class; public static $items_id = 'plugin_fields_fields_id'; - static function install(Migration $migration, $version) { + public static function install(Migration $migration, $version) + { global $DB; $default_charset = DBConnection::getDefaultCharset(); @@ -58,29 +60,33 @@ static function install(Migration $migration, $version) { PRIMARY KEY (`id`), KEY `plugin_fields_fields_id` (`plugin_fields_fields_id`) ) ENGINE=InnoDB DEFAULT CHARSET={$default_charset} COLLATE={$default_collation} ROW_FORMAT=DYNAMIC;"; - $DB->query($query) or die ($DB->error()); + $DB->query($query) or die($DB->error()); } return true; } - static function uninstall() { + public static function uninstall() + { global $DB; - $DB->query("DROP TABLE IF EXISTS `".self::getTable()."`"); + $DB->query("DROP TABLE IF EXISTS `" . self::getTable() . "`"); return true; } - static function getTypeName($nb = 0) { + public static function getTypeName($nb = 0) + { return __('Override by status', 'fields'); } - function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { + public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) + { return self::createTabEntry(self::getTypeName(), self::countOverridesForContainer($item->getID())); } - static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { + public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) + { if ($item instanceof PluginFieldsContainer) { self::showForTabContainer($item); return true; @@ -88,20 +94,23 @@ static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtem return false; } - public function prepareInputForAdd($input) { + public function prepareInputForAdd($input) + { if (isset($input['states']) && is_array($input['states'])) { $input['states'] = json_encode($input['states']); } return parent::prepareInputForAdd($input); } - public function prepareInputForUpdate($input) { + public function prepareInputForUpdate($input) + { if (isset($input['states']) && is_array($input['states'])) { $input['states'] = json_encode($input['states']); } return parent::prepareInputForUpdate($input); } + // phpcs:ignore PSR1.Methods.CamelCapsMethodName public function post_getFromDB() { if (isset($this->fields['states']) && !empty($this->fields['states'])) { @@ -110,12 +119,14 @@ public function post_getFromDB() parent::post_getFromDB(); } - public static function getStatusItemtypes(): array { + public static function getStatusItemtypes(): array + { global $CFG_GLPI; return array_merge(['Ticket', 'Change', 'Problem', 'Project', 'ProjectTask'], $CFG_GLPI['state_types']); } - public static function countOverridesForContainer(int $container_id) { + public static function countOverridesForContainer(int $container_id) + { global $DB; $fields_table = PluginFieldsField::getTable(); @@ -145,30 +156,31 @@ public static function countOverridesForContainer(int $container_id) { return $iterator->current()['cpt'] ?? 0; } - public static function getOverridesForContainer(int $container_id): array { + public static function getOverridesForContainer(int $container_id): array + { global $DB; $fields_table = PluginFieldsField::getTable(); $container_table = PluginFieldsContainer::getTable(); $iterator = $DB->request([ - 'SELECT' => [ - self::getTable().'.*', - $fields_table.'.label AS field_name', - ], - 'FROM' => self::getTable(), - 'LEFT JOIN' => [ - $fields_table => [ - 'ON' => [ - self::getTable() => 'plugin_fields_fields_id', - $fields_table => 'id' - ] - ], - $container_table => [ - 'ON' => [ - $fields_table => 'plugin_fields_containers_id', - $container_table => 'id' - ] - ], + 'SELECT' => [ + self::getTable() . '.*', + $fields_table . '.label AS field_name', + ], + 'FROM' => self::getTable(), + 'LEFT JOIN' => [ + $fields_table => [ + 'ON' => [ + self::getTable() => 'plugin_fields_fields_id', + $fields_table => 'id' + ] + ], + $container_table => [ + 'ON' => [ + $fields_table => 'plugin_fields_containers_id', + $container_table => 'id' + ] + ], ], 'WHERE' => [ 'plugin_fields_containers_id' => $container_id, @@ -184,7 +196,8 @@ public static function getOverridesForContainer(int $container_id): array { return $overrides; } - public static function getOverridesForItem(int $container_id, CommonDBTM $item): array { + public static function getOverridesForItem(int $container_id, CommonDBTM $item): array + { $status_itemtypes = self::getStatusItemtypes(); if (!in_array($item->getType(), $status_itemtypes)) { return []; @@ -193,13 +206,14 @@ public static function getOverridesForItem(int $container_id, CommonDBTM $item): $status = $item->fields[$status_field_name]; $overrides = self::getOverridesForContainer($container_id); $itemtype = $item->getType(); - $overrides = array_filter($overrides, static function($override) use ($itemtype, $status) { + $overrides = array_filter($overrides, static function ($override) use ($itemtype, $status) { return $override['itemtype'] === $itemtype && in_array($status, $override['states']); }); return $overrides; } - private static function getItemtypesForContainer(int $container_id): array { + private static function getItemtypesForContainer(int $container_id): array + { global $DB; $iterator = $DB->request([ @@ -215,7 +229,7 @@ private static function getItemtypesForContainer(int $container_id): array { $itemtypes = importArrayFromDB($itemtypes); $status_itemtypes = self::getStatusItemtypes(); // Get only itemtypes that exist and have a status field - $itemtypes = array_filter($itemtypes, static function($itemtype) use ($status_itemtypes) { + $itemtypes = array_filter($itemtypes, static function ($itemtype) use ($status_itemtypes) { return class_exists($itemtype) && in_array($itemtype, $status_itemtypes, true); }); $results = []; @@ -227,7 +241,8 @@ private static function getItemtypesForContainer(int $container_id): array { return []; } - public static function getStatusFieldName(string $itemtype): string { + public static function getStatusFieldName(string $itemtype): string + { switch ($itemtype) { case 'Ticket': case 'Change': @@ -241,7 +256,8 @@ public static function getStatusFieldName(string $itemtype): string { } } - private static function addStatusNames(array &$overrides): void { + private static function addStatusNames(array &$overrides): void + { global $DB; $statuses = [ @@ -272,28 +288,29 @@ private static function addStatusNames(array &$overrides): void { foreach ($overrides as &$override) { $names = $statuses[$override['itemtype']] ?? $statuses['Other']; - $override['status_names'] = array_filter($names, static function($name, $id) use ($override) { + $override['status_names'] = array_filter($names, static function ($name, $id) use ($override) { return in_array($id, $override['states']); }, ARRAY_FILTER_USE_BOTH); } } - private static function getFieldsChoiceForContainer(int $container_id): array { + private static function getFieldsChoiceForContainer(int $container_id): array + { global $DB; $iterator = $DB->request([ 'SELECT' => ['glpi_plugin_fields_fields.*'], 'FROM' => 'glpi_plugin_fields_fields', 'LEFT JOIN' => [ - 'glpi_plugin_fields_containers' => [ - 'ON' => [ - 'glpi_plugin_fields_fields' => 'plugin_fields_containers_id', - 'glpi_plugin_fields_containers' => 'id' - ] - ] + 'glpi_plugin_fields_containers' => [ + 'ON' => [ + 'glpi_plugin_fields_fields' => 'plugin_fields_containers_id', + 'glpi_plugin_fields_containers' => 'id' + ] + ] ], 'WHERE' => [ - 'plugin_fields_containers_id' => $container_id, + 'plugin_fields_containers_id' => $container_id, ] ]); @@ -304,7 +321,8 @@ private static function getFieldsChoiceForContainer(int $container_id): array { return $fields; } - public static function getStatusDropdownForItemtype(string $itemtype, array $values = []): string { + public static function getStatusDropdownForItemtype(string $itemtype, array $values = []): string + { global $DB; $statuses = []; @@ -346,10 +364,11 @@ public static function getStatusDropdownForItemtype(string $itemtype, array $val ]); } - public static function showForTabContainer(CommonGLPI $item, $options = []) { + public static function showForTabContainer(CommonGLPI $item, $options = []) + { $container_id = $item->getID(); $has_fields = countElementsInTable(PluginFieldsField::getTable(), [ - 'plugin_fields_containers_id' => $container_id + 'plugin_fields_containers_id' => $container_id ]) > 0; $twig_params = [ 'container_id' => $container_id, @@ -359,7 +378,8 @@ public static function showForTabContainer(CommonGLPI $item, $options = []) { TemplateRenderer::getInstance()->display('@fields/status_overrides.html.twig', $twig_params); } - public function showForm($ID, array $options = []) { + public function showForm($ID, array $options = []) + { $container_id = $options['container_id']; $twig_params = [ diff --git a/inc/toolbox.class.php b/inc/toolbox.class.php index 1b3a8b9c..d2f08163 100644 --- a/inc/toolbox.class.php +++ b/inc/toolbox.class.php @@ -28,8 +28,8 @@ * ------------------------------------------------------------------------- */ -class PluginFieldsToolbox { - +class PluginFieldsToolbox +{ /** * Get a clean system name from a label. * @@ -37,26 +37,27 @@ class PluginFieldsToolbox { * * @return string */ - public function getSystemNameFromLabel($label) { + public function getSystemNameFromLabel($label) + { - $name = strtolower($label); + $name = strtolower($label); - // 1. remove trailing "s" (plural forms) - $name = getSingular($name); + // 1. remove trailing "s" (plural forms) + $name = getSingular($name); - // 2. keep only alphanum - $name = preg_replace('/[^\da-z]/i', '', $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(); - } + // 3. if empty, uses a random number + if (strlen($name) == 0) { + $name = rand(); + } - // 4. replace numbers by letters - $name = $this->replaceIntByLetters($name); + // 4. replace numbers by letters + $name = $this->replaceIntByLetters($name); - return $name; - } + return $name; + } /** * Return system name incremented by given increment. @@ -66,9 +67,10 @@ public function getSystemNameFromLabel($label) { * * @return string */ - public function getIncrementedSystemName($name, $increment) { - return $name . $this->replaceIntByLetters((string)$increment); - } + public function getIncrementedSystemName($name, $increment) + { + return $name . $this->replaceIntByLetters((string)$increment); + } /** * Replace integers by corresponding letters inside given string. @@ -77,13 +79,14 @@ public function getIncrementedSystemName($name, $increment) { * * @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 - ); - } + 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. @@ -93,102 +96,105 @@ private function replaceIntByLetters($str) { * * @return void */ - public function fixFieldsNames(Migration $migration, $condition) { - global $DB; - - $bad_named_fields = $DB->request( - [ - 'FROM' => PluginFieldsField::getTable(), - 'WHERE' => [ - 'name' => [ - 'REGEXP', - $DB->escape('[0-9]+') - ], - $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['name'] = null; - $field_obj = new PluginFieldsField(); - $new_name = $field_obj->prepareName($field); - if ($new_name > 64) { - // limit fields names to 64 chars (MySQL limit) - $new_name = substr($new_name, 0, 64); - } - while ('dropdown' === $field['type'] - && strlen(getTableForItemType(PluginFieldsDropdown::getClassname($new_name))) > 64) { - // limit tables names to 64 chars (MySQL limit) - $new_name = substr($new_name, 0, -1); - } - $field['name'] = $new_name; - $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); + public function fixFieldsNames(Migration $migration, $condition) + { + global $DB; + + $bad_named_fields = $DB->request( + [ + 'FROM' => PluginFieldsField::getTable(), + 'WHERE' => [ + 'name' => [ + 'REGEXP', + $DB->escape('[0-9]+') + ], + $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['name'] = null; + $field_obj = new PluginFieldsField(); + $new_name = $field_obj->prepareName($field); + if ($new_name > 64) { + // limit fields names to 64 chars (MySQL limit) + $new_name = substr($new_name, 0, 64); } - - // 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' => 'TABLE_NAME', - 'DISTINCT' => true, - 'FROM' => 'INFORMATION_SCHEMA.COLUMNS', - 'WHERE' => [ - 'TABLE_SCHEMA' => $DB->dbdefault, - 'TABLE_NAME' => ['LIKE', 'glpi_plugin_fields_%'], - 'COLUMN_NAME' => $old_field_name - ], - ] + while ( + 'dropdown' === $field['type'] + && strlen(getTableForItemType(PluginFieldsDropdown::getClassname($new_name))) > 64 + ) { + // limit tables names to 64 chars (MySQL limit) + $new_name = substr($new_name, 0, -1); + } + $field['name'] = $new_name; + $field_obj->update( + $field, + false ); - foreach ($tables_to_update as $table_to_update) { - $sql_fields = PluginFieldsMigration::getSQLFields($new_field_name, $field['type']); - if (count($sql_fields) !== 1 || !array_key_exists($new_field_name, $sql_fields)) { - // when this method has been made, only fields types that were matching a unique SQL field were existing - // other cases can be ignored - continue; - } - $migration->changeField( - $table_to_update['TABLE_NAME'], - $old_field_name, - $new_field_name, - $sql_fields[$new_field_name] - ); - $migration->migrationOneTable($table_to_update['TABLE_NAME']); + $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' => 'TABLE_NAME', + 'DISTINCT' => true, + 'FROM' => 'INFORMATION_SCHEMA.COLUMNS', + 'WHERE' => [ + 'TABLE_SCHEMA' => $DB->dbdefault, + 'TABLE_NAME' => ['LIKE', 'glpi_plugin_fields_%'], + 'COLUMN_NAME' => $old_field_name + ], + ] + ); + + foreach ($tables_to_update as $table_to_update) { + $sql_fields = PluginFieldsMigration::getSQLFields($new_field_name, $field['type']); + if (count($sql_fields) !== 1 || !array_key_exists($new_field_name, $sql_fields)) { + // when this method has been made, only fields types that were matching a unique SQL field were existing + // other cases can be ignored + continue; + } + $migration->changeField( + $table_to_update['TABLE_NAME'], + $old_field_name, + $new_field_name, + $sql_fields[$new_field_name] + ); + $migration->migrationOneTable($table_to_update['TABLE_NAME']); + } + } + } + } /** * Return a list of GLPI itemtypes. @@ -197,130 +203,131 @@ public function fixFieldsNames(Migration $migration, $condition) { * * @return array */ - public static function getGlpiItemtypes(): array { - global $CFG_GLPI, $PLUGIN_HOOKS; - - $assets_itemtypes = [ - Computer::class, - Monitor::class, - Software::class, - NetworkEquipment::class, - Peripheral::class, - Printer::class, - CartridgeItem::class, - ConsumableItem::class, - Phone::class, - Rack::class, - Enclosure::class, - PDU::class, - PassiveDCEquipment::class, - Cable::class, - ]; - - $assistance_itemtypes = [ - Ticket::class, - Problem::class, - Change::class, - TicketRecurrent::class, - RecurrentChange::class, - PlanningExternalEvent::class, - ]; - - $management_itemtypes = [ - SoftwareLicense::class, - SoftwareVersion::class, - Budget::class, - Supplier::class, - Contact::class, - Contract::class, - Document::class, - Line::class, - Certificate::class, - Datacenter::class, - Cluster::class, - Domain::class, - Appliance::class, - Database::class, - DatabaseInstance::class, - ]; - - $tools_itemtypes = [ - Project::class, - ProjectTask::class, - Reminder::class, - RSSFeed::class, - ]; - - $administration_itemtypes = [ - User::class, - Group::class, - Entity::class, - Profile::class, - ]; - - $components_itemtypes = []; - foreach ($CFG_GLPI['device_types'] as $device_itemtype) { - $components_itemtypes[] = $device_itemtype; - } - sort($components_itemtypes, SORT_NATURAL); - - $plugins_itemtypes = []; - foreach ($PLUGIN_HOOKS['plugin_fields'] as $itemtype) { - $itemtype_specs = isPluginItemType($itemtype); - if ($itemtype_specs) { - $plugins_itemtypes[] = $itemtype; - } - } - - $dropdowns_sections = []; - foreach (Dropdown::getStandardDropdownItemTypes() as $section => $itemtypes) { - $section_name = sprintf( - __('%s: %s'), - _n('Dropdown', 'Dropdowns', Session::getPluralNumber()), - $section - ); - $dropdowns_sections[$section_name] = array_keys($itemtypes); - } - - $other_itemtypes = [ - NetworkPort::class, - Notification::class, - NotificationTemplate::class, - ]; - - $all_itemtypes = [ - _n('Asset', 'Assets', Session::getPluralNumber()) => $assets_itemtypes, - __('Assistance') => $assistance_itemtypes, - __('Management') => $management_itemtypes, - __('Tools') => $tools_itemtypes, - __('Administration') => $administration_itemtypes, - _n('Plugin', 'Plugins', Session::getPluralNumber()) => $plugins_itemtypes, - _n('Component', 'Components', Session::getPluralNumber()) => $components_itemtypes, - ] + $dropdowns_sections + [ - __('Other') => $other_itemtypes, - ]; - - $plugins_names = []; - foreach ($all_itemtypes as $section => $itemtypes) { - $named_itemtypes = []; - foreach ($itemtypes as $itemtype) { - $prefix = ''; - if ($itemtype_specs = isPluginItemType($itemtype)) { - $plugin_key = $itemtype_specs['plugin']; - if (!array_key_exists($plugin_key, $plugins_names)) { - $plugins_names[$plugin_key] = Plugin::getInfo($plugin_key, 'name'); - } - $prefix = $plugins_names[$plugin_key] . ' - '; - } - - $named_itemtypes[$itemtype] = $prefix . $itemtype::getTypeName(Session::getPluralNumber()); - } - $all_itemtypes[$section] = $named_itemtypes; - } - - // Remove empty lists (e.g. Plugin list). - $all_itemtypes = array_filter($all_itemtypes); - - return $all_itemtypes; - } + public static function getGlpiItemtypes(): array + { + global $CFG_GLPI, $PLUGIN_HOOKS; + + $assets_itemtypes = [ + Computer::class, + Monitor::class, + Software::class, + NetworkEquipment::class, + Peripheral::class, + Printer::class, + CartridgeItem::class, + ConsumableItem::class, + Phone::class, + Rack::class, + Enclosure::class, + PDU::class, + PassiveDCEquipment::class, + Cable::class, + ]; + + $assistance_itemtypes = [ + Ticket::class, + Problem::class, + Change::class, + TicketRecurrent::class, + RecurrentChange::class, + PlanningExternalEvent::class, + ]; + + $management_itemtypes = [ + SoftwareLicense::class, + SoftwareVersion::class, + Budget::class, + Supplier::class, + Contact::class, + Contract::class, + Document::class, + Line::class, + Certificate::class, + Datacenter::class, + Cluster::class, + Domain::class, + Appliance::class, + Database::class, + DatabaseInstance::class, + ]; + + $tools_itemtypes = [ + Project::class, + ProjectTask::class, + Reminder::class, + RSSFeed::class, + ]; + + $administration_itemtypes = [ + User::class, + Group::class, + Entity::class, + Profile::class, + ]; + + $components_itemtypes = []; + foreach ($CFG_GLPI['device_types'] as $device_itemtype) { + $components_itemtypes[] = $device_itemtype; + } + sort($components_itemtypes, SORT_NATURAL); + + $plugins_itemtypes = []; + foreach ($PLUGIN_HOOKS['plugin_fields'] as $itemtype) { + $itemtype_specs = isPluginItemType($itemtype); + if ($itemtype_specs) { + $plugins_itemtypes[] = $itemtype; + } + } + + $dropdowns_sections = []; + foreach (Dropdown::getStandardDropdownItemTypes() as $section => $itemtypes) { + $section_name = sprintf( + __('%s: %s'), + _n('Dropdown', 'Dropdowns', Session::getPluralNumber()), + $section + ); + $dropdowns_sections[$section_name] = array_keys($itemtypes); + } + + $other_itemtypes = [ + NetworkPort::class, + Notification::class, + NotificationTemplate::class, + ]; + + $all_itemtypes = [ + _n('Asset', 'Assets', Session::getPluralNumber()) => $assets_itemtypes, + __('Assistance') => $assistance_itemtypes, + __('Management') => $management_itemtypes, + __('Tools') => $tools_itemtypes, + __('Administration') => $administration_itemtypes, + _n('Plugin', 'Plugins', Session::getPluralNumber()) => $plugins_itemtypes, + _n('Component', 'Components', Session::getPluralNumber()) => $components_itemtypes, + ] + $dropdowns_sections + [ + __('Other') => $other_itemtypes, + ]; + + $plugins_names = []; + foreach ($all_itemtypes as $section => $itemtypes) { + $named_itemtypes = []; + foreach ($itemtypes as $itemtype) { + $prefix = ''; + if ($itemtype_specs = isPluginItemType($itemtype)) { + $plugin_key = $itemtype_specs['plugin']; + if (!array_key_exists($plugin_key, $plugins_names)) { + $plugins_names[$plugin_key] = Plugin::getInfo($plugin_key, 'name'); + } + $prefix = $plugins_names[$plugin_key] . ' - '; + } + + $named_itemtypes[$itemtype] = $prefix . $itemtype::getTypeName(Session::getPluralNumber()); + } + $all_itemtypes[$section] = $named_itemtypes; + } + + // Remove empty lists (e.g. Plugin list). + $all_itemtypes = array_filter($all_itemtypes); + + return $all_itemtypes; + } } diff --git a/setup.php b/setup.php index 8302cf55..74968d40 100644 --- a/setup.php +++ b/setup.php @@ -28,7 +28,7 @@ * ------------------------------------------------------------------------- */ -define ('PLUGIN_FIELDS_VERSION', '1.15.3'); +define('PLUGIN_FIELDS_VERSION', '1.15.3'); // Minimal GLPI version, inclusive define("PLUGIN_FIELDS_MIN_GLPI", "10.0.0"); @@ -36,31 +36,31 @@ define("PLUGIN_FIELDS_MAX_GLPI", "10.0.99"); if (!defined("PLUGINFIELDS_DIR")) { - define("PLUGINFIELDS_DIR", Plugin::getPhpDir("fields")); + define("PLUGINFIELDS_DIR", Plugin::getPhpDir("fields")); } if (!defined("PLUGINFIELDS_WEB_DIR")) { - define("PLUGINFIELDS_WEB_DIR", Plugin::getWebDir("fields")); + define("PLUGINFIELDS_WEB_DIR", Plugin::getWebDir("fields")); } if (!defined("PLUGINFIELDS_DOC_DIR")) { - define("PLUGINFIELDS_DOC_DIR", GLPI_PLUGIN_DOC_DIR . "/fields"); + define("PLUGINFIELDS_DOC_DIR", GLPI_PLUGIN_DOC_DIR . "/fields"); } if (!file_exists(PLUGINFIELDS_DOC_DIR)) { - mkdir(PLUGINFIELDS_DOC_DIR); + mkdir(PLUGINFIELDS_DOC_DIR); } if (!defined("PLUGINFIELDS_CLASS_PATH")) { - define("PLUGINFIELDS_CLASS_PATH", PLUGINFIELDS_DOC_DIR . "/inc"); + define("PLUGINFIELDS_CLASS_PATH", PLUGINFIELDS_DOC_DIR . "/inc"); } if (!file_exists(PLUGINFIELDS_CLASS_PATH)) { - mkdir(PLUGINFIELDS_CLASS_PATH); + mkdir(PLUGINFIELDS_CLASS_PATH); } if (!defined("PLUGINFIELDS_FRONT_PATH")) { - define("PLUGINFIELDS_FRONT_PATH", PLUGINFIELDS_DOC_DIR."/front"); + define("PLUGINFIELDS_FRONT_PATH", PLUGINFIELDS_DOC_DIR . "/front"); } if (!file_exists(PLUGINFIELDS_FRONT_PATH)) { - mkdir(PLUGINFIELDS_FRONT_PATH); + mkdir(PLUGINFIELDS_FRONT_PATH); } use Symfony\Component\Yaml\Yaml; @@ -71,110 +71,122 @@ * * @return void */ -function plugin_init_fields() { - global $PLUGIN_HOOKS; - - $PLUGIN_HOOKS['csrf_compliant']['fields'] = true; - - // manage autoload of plugin custom classes - include_once(PLUGINFIELDS_DIR . "/inc/autoload.php"); - - // manage autoload of vendor classes - include_once(PLUGINFIELDS_DIR . "/vendor/autoload.php"); - $pluginfields_autoloader = new PluginFieldsAutoloader([PLUGINFIELDS_CLASS_PATH]); - $pluginfields_autoloader->register(); - - $plugin = new Plugin(); - if ($plugin->isInstalled('fields') - && $plugin->isActivated('fields') - && Session::getLoginUserID()) { - - // Init hook about itemtype(s) for plugin fields - if (!isset($PLUGIN_HOOKS['plugin_fields'])) { - $PLUGIN_HOOKS['plugin_fields'] = []; - } - - // When a Category is changed during ticket creation - if (isset($_POST) && !empty($_POST) - && isset($_POST['_plugin_fields_type']) - && $_SERVER['REQUEST_URI'] ?? '' == Ticket::getFormURL()) { - foreach ($_POST as $key => $value) { - if (!is_array($value)) { - $_SESSION['plugin']['fields']['values_sent'][$key] = stripcslashes($value); +function plugin_init_fields() +{ + global $PLUGIN_HOOKS; + + $PLUGIN_HOOKS['csrf_compliant']['fields'] = true; + + // manage autoload of plugin custom classes + include_once(PLUGINFIELDS_DIR . "/inc/autoload.php"); + + // manage autoload of vendor classes + include_once(PLUGINFIELDS_DIR . "/vendor/autoload.php"); + $pluginfields_autoloader = new PluginFieldsAutoloader([PLUGINFIELDS_CLASS_PATH]); + $pluginfields_autoloader->register(); + + $plugin = new Plugin(); + if ( + $plugin->isInstalled('fields') + && $plugin->isActivated('fields') + && Session::getLoginUserID() + ) { + // Init hook about itemtype(s) for plugin fields + if (!isset($PLUGIN_HOOKS['plugin_fields'])) { + $PLUGIN_HOOKS['plugin_fields'] = []; + } + + // When a Category is changed during ticket creation + if ( + isset($_POST) && !empty($_POST) + && isset($_POST['_plugin_fields_type']) + && $_SERVER['REQUEST_URI'] ?? '' == Ticket::getFormURL() + ) { + foreach ($_POST as $key => $value) { + if (!is_array($value)) { + $_SESSION['plugin']['fields']['values_sent'][$key] = stripcslashes($value); + } } - } - } + } - if ($plugin->isActivated('fusioninventory')) { - $PLUGIN_HOOKS['fusioninventory_inventory']['fields'] + if ($plugin->isActivated('fusioninventory')) { + $PLUGIN_HOOKS['fusioninventory_inventory']['fields'] = ['PluginFieldsInventory', 'updateInventory']; - } + } - // complete rule engine - $PLUGIN_HOOKS['use_rules']['fields'] = ['PluginFusioninventoryTaskpostactionRule']; - $PLUGIN_HOOKS['rule_matched']['fields'] = 'plugin_fields_rule_matched'; + // complete rule engine + $PLUGIN_HOOKS['use_rules']['fields'] = ['PluginFusioninventoryTaskpostactionRule']; + $PLUGIN_HOOKS['rule_matched']['fields'] = 'plugin_fields_rule_matched'; - if (isset($_SESSION['glpiactiveentities'])) { + if (isset($_SESSION['glpiactiveentities'])) { + // add link in plugin page + $PLUGIN_HOOKS['config_page']['fields'] = 'front/container.php'; - // add link in plugin page - $PLUGIN_HOOKS['config_page']['fields'] = 'front/container.php'; + // add entry to configuration menu + $PLUGIN_HOOKS["menu_toadd"]['fields'] = ['config' => 'PluginFieldsMenu']; - // add entry to configuration menu - $PLUGIN_HOOKS["menu_toadd"]['fields'] = ['config' => 'PluginFieldsMenu']; + // add tabs to itemtypes + Plugin::registerClass( + 'PluginFieldsContainer', + ['addtabon' => array_unique(PluginFieldsContainer::getEntries())] + ); - // add tabs to itemtypes - Plugin::registerClass('PluginFieldsContainer', - ['addtabon' => array_unique(PluginFieldsContainer::getEntries())]); - - //include js and css - $debug = (isset($_SESSION['glpi_use_mode']) + //include js and css + $debug = (isset($_SESSION['glpi_use_mode']) && $_SESSION['glpi_use_mode'] == Session::DEBUG_MODE ? true : false); - if (!$debug && file_exists(__DIR__ . '/css/fields.min.css')) { - $PLUGIN_HOOKS['add_css']['fields'][] = 'css/fields.min.css'; - } else { - $PLUGIN_HOOKS['add_css']['fields'][] = 'css/fields.css'; - } - - // Add/delete profiles to automaticaly to container - $PLUGIN_HOOKS['item_add']['fields']['Profile'] - = ["PluginFieldsProfile", "addNewProfile"]; - $PLUGIN_HOOKS['pre_item_purge']['fields']['Profile'] - = ["PluginFieldsProfile", "deleteProfile"]; - - //load drag and drop javascript library on Package Interface - $PLUGIN_HOOKS['add_javascript']['fields'][] = "js/redips-drag-min.js"; - if (!$debug && file_exists(__DIR__ . '/js/drag-field-row.min.js')) { - $PLUGIN_HOOKS['add_javascript']['fields'][] = 'js/drag-field-row.min.js'; - } else { - $PLUGIN_HOOKS['add_javascript']['fields'][] = 'js/drag-field-row.js'; - } - } - - // Add Fields to Datainjection - if ($plugin->isActivated('datainjection')) { - $PLUGIN_HOOKS['plugin_datainjection_populate']['fields'] - = "plugin_datainjection_populate_fields"; - } - - //Retrieve dom container - $itemtypes = PluginFieldsContainer::getUsedItemtypes(); - if ($itemtypes !== false) { - foreach ($itemtypes as $itemtype) { - $PLUGIN_HOOKS['pre_item_update']['fields'][$itemtype] = ["PluginFieldsContainer", - "preItemUpdate"]; - $PLUGIN_HOOKS['pre_item_add']['fields'][$itemtype] = ["PluginFieldsContainer", - "preItem"]; - $PLUGIN_HOOKS['item_add']['fields'][$itemtype] = ["PluginFieldsContainer", - "postItemAdd"]; - $PLUGIN_HOOKS['pre_item_purge'] ['fields'][$itemtype] = ["PluginFieldsContainer", - "preItemPurge"]; - } - } - - // Display fields in any existing tab - $PLUGIN_HOOKS['post_item_form']['fields'] = ['PluginFieldsField', - 'showForTab']; - } + if (!$debug && file_exists(__DIR__ . '/css/fields.min.css')) { + $PLUGIN_HOOKS['add_css']['fields'][] = 'css/fields.min.css'; + } else { + $PLUGIN_HOOKS['add_css']['fields'][] = 'css/fields.css'; + } + + // Add/delete profiles to automaticaly to container + $PLUGIN_HOOKS['item_add']['fields']['Profile'] = ["PluginFieldsProfile", "addNewProfile"]; + $PLUGIN_HOOKS['pre_item_purge']['fields']['Profile'] = ["PluginFieldsProfile", "deleteProfile"]; + + //load drag and drop javascript library on Package Interface + $PLUGIN_HOOKS['add_javascript']['fields'][] = "js/redips-drag-min.js"; + if (!$debug && file_exists(__DIR__ . '/js/drag-field-row.min.js')) { + $PLUGIN_HOOKS['add_javascript']['fields'][] = 'js/drag-field-row.min.js'; + } else { + $PLUGIN_HOOKS['add_javascript']['fields'][] = 'js/drag-field-row.js'; + } + } + + // Add Fields to Datainjection + if ($plugin->isActivated('datainjection')) { + $PLUGIN_HOOKS['plugin_datainjection_populate']['fields'] = "plugin_datainjection_populate_fields"; + } + + //Retrieve dom container + $itemtypes = PluginFieldsContainer::getUsedItemtypes(); + if ($itemtypes !== false) { + foreach ($itemtypes as $itemtype) { + $PLUGIN_HOOKS['pre_item_update']['fields'][$itemtype] = [ + "PluginFieldsContainer", + "preItemUpdate" + ]; + $PLUGIN_HOOKS['pre_item_add']['fields'][$itemtype] = [ + "PluginFieldsContainer", + "preItem" + ]; + $PLUGIN_HOOKS['item_add']['fields'][$itemtype] = [ + "PluginFieldsContainer", + "postItemAdd" + ]; + $PLUGIN_HOOKS['pre_item_purge'] ['fields'][$itemtype] = [ + "PluginFieldsContainer", + "preItemPurge" + ]; + } + } + + // Display fields in any existing tab + $PLUGIN_HOOKS['post_item_form']['fields'] = [ + 'PluginFieldsField', + 'showForTab' + ]; + } } @@ -184,21 +196,22 @@ function plugin_init_fields() { * * @return array */ -function plugin_version_fields() { - return [ - 'name' => __("Additionnal fields", "fields"), - 'version' => PLUGIN_FIELDS_VERSION, - 'author' => 'Teclib\', Olivier Moron', - 'homepage' => 'https://github.com/pluginsGLPI/fields', - 'license' => 'GPLv2+', - 'requirements' => [ - 'glpi' => [ - 'min' => PLUGIN_FIELDS_MIN_GLPI, - 'max' => PLUGIN_FIELDS_MAX_GLPI, - 'dev' => true, //Required to allow 9.2-dev - ] - ] - ]; +function plugin_version_fields() +{ + return [ + 'name' => __("Additionnal fields", "fields"), + 'version' => PLUGIN_FIELDS_VERSION, + 'author' => 'Teclib\', Olivier Moron', + 'homepage' => 'https://github.com/pluginsGLPI/fields', + 'license' => 'GPLv2+', + 'requirements' => [ + 'glpi' => [ + 'min' => PLUGIN_FIELDS_MIN_GLPI, + 'max' => PLUGIN_FIELDS_MAX_GLPI, + 'dev' => true, //Required to allow 9.2-dev + ] + ] + ]; } /** @@ -207,13 +220,14 @@ function plugin_version_fields() { * * @return boolean */ -function plugin_fields_check_prerequisites() { - if (!is_readable(__DIR__ . '/vendor/autoload.php') || !is_file(__DIR__ . '/vendor/autoload.php')) { - echo "Run composer install --no-dev in the plugin directory
"; - return false; - } - - return true; +function plugin_fields_check_prerequisites() +{ + if (!is_readable(__DIR__ . '/vendor/autoload.php') || !is_file(__DIR__ . '/vendor/autoload.php')) { + echo "Run composer install --no-dev in the plugin directory
"; + return false; + } + + return true; } /** @@ -221,135 +235,139 @@ function plugin_fields_check_prerequisites() { * * @return void */ -function plugin_fields_checkFiles() { - global $DB; - - // Clean all existing files - array_map('unlink', glob(PLUGINFIELDS_DOC_DIR.'/*/*')); - - // Regenerate containers - if ($DB->tableExists(PluginFieldsContainer::getTable())) { - $container_obj = new PluginFieldsContainer(); - $containers = $container_obj->find(); - - foreach ($containers as $container) { - PluginFieldsContainer::create($container); - } - } - - // Regenerate dropdowns - if ($DB->tableExists(PluginFieldsField::getTable())) { - $fields_obj = new PluginFieldsField(); - $fields = $fields_obj->find(['type' => 'dropdown']); - foreach ($fields as $field) { - PluginFieldsDropdown::create($field); - } - } +function plugin_fields_checkFiles() +{ + global $DB; + + // Clean all existing files + array_map('unlink', glob(PLUGINFIELDS_DOC_DIR . '/*/*')); + + // Regenerate containers + if ($DB->tableExists(PluginFieldsContainer::getTable())) { + $container_obj = new PluginFieldsContainer(); + $containers = $container_obj->find(); + + foreach ($containers as $container) { + PluginFieldsContainer::create($container); + } + } + + // Regenerate dropdowns + if ($DB->tableExists(PluginFieldsField::getTable())) { + $fields_obj = new PluginFieldsField(); + $fields = $fields_obj->find(['type' => 'dropdown']); + foreach ($fields as $field) { + PluginFieldsDropdown::create($field); + } + } } -function plugin_fields_exportBlockAsYaml($container_id = null) { - global $DB; - - $plugin = new Plugin(); - $yaml_conf = [ - 'container' => [], - ]; - - if (isset($_SESSION['glpiactiveentities']) - && $plugin->isInstalled('fields') - && $plugin->isActivated('fields') - && Session::getLoginUserID()) { - - if ($DB->tableExists(PluginFieldsContainer::getTable())) { - $where = []; - $where["is_active"] = true; - if ($container_id != null) { - $where["id"] = $container_id; - } - $container_obj = new PluginFieldsContainer(); - $containers = $container_obj->find($where); - - foreach ($containers as $container) { - $itemtypes = (strlen($container['itemtypes']) > 0) - ? json_decode($container['itemtypes'], true) - : []; - - foreach ($itemtypes as $itemtype) { - $fields_obj = new PluginFieldsField(); - // to get translation - $container["itemtype"] = PluginFieldsContainer::getType(); - $yaml_conf['container'][$container['id']."-".$itemtype] = [ - "id" => (int) $container['id'], - "name" => PluginFieldsLabelTranslation::getLabelFor($container), - "itemtype" => $itemtype, - "type" => $container['type'], - "subtype" => $container['subtype'], - "fields" => [], - ]; - $fields = $fields_obj->find(["plugin_fields_containers_id" => $container['id'], - "is_active" => true, - "is_readonly" => false]); - if (count($fields)) { - foreach ($fields as $field) { - $tmp_field = []; - $tmp_field['id'] = (int) $field['id']; - - //to get translation - $field["itemtype"] = PluginFieldsField::getType(); - $tmp_field['label'] = PluginFieldsLabelTranslation::getLabelFor($field); - $tmp_field['xml_node'] = strtoupper($field['name']); - $tmp_field['type'] = $field['type']; - $tmp_field['ranking'] = $field['ranking']; - $tmp_field['default_value'] = $field['default_value']; - $tmp_field['mandatory'] = $field['mandatory']; - $tmp_field['possible_value'] = ""; - - switch ($field['type']) { - case 'dropdown': - $obj = new $itemtype; - $obj->getEmpty(); - - $dropdown_itemtype = PluginFieldsDropdown::getClassname($field['name']); - $tmp_field['xml_node'] = strtoupper(getForeignKeyFieldForItemType($dropdown_itemtype)); - - $dropdown_obj = new $dropdown_itemtype(); - $dropdown_datas = $dropdown_obj->find(); - $datas = []; - foreach ($dropdown_datas as $value) { - $items = []; - $items['id'] = (int)$value['id']; - $items['value'] = $value['name']; - $datas[] = $items; - } - $tmp_field['possible_value'] = $datas; - break; - case 'yesno': - $datas = []; - $datas["0"]['id'] = 0; - $datas["0"]['value'] = __('No'); - $datas["1"]['id'] = 1; - $datas["1"]['value'] = __('Yes'); - $tmp_field['possible_value'] = $datas; - break; - case 'dropdownuser': - $datas = Dropdown::getDropdownUsers(['is_active' => 1,'is_deleted' => 0], false); - $tmp_field['possible_value'] = $datas['results']; - break; - } - $yaml_conf['container'][$container['id']."-".$itemtype]["fields"][] = $tmp_field; - } - } +function plugin_fields_exportBlockAsYaml($container_id = null) +{ + global $DB; + + $plugin = new Plugin(); + $yaml_conf = [ + 'container' => [], + ]; + + if ( + isset($_SESSION['glpiactiveentities']) + && $plugin->isInstalled('fields') + && $plugin->isActivated('fields') + && Session::getLoginUserID() + ) { + if ($DB->tableExists(PluginFieldsContainer::getTable())) { + $where = []; + $where["is_active"] = true; + if ($container_id != null) { + $where["id"] = $container_id; } - } - } - } - - if (count($yaml_conf)) { - $dump = Yaml::dump($yaml_conf, 10); - $filename = GLPI_TMP_DIR."/fields_conf.yaml"; - file_put_contents($filename, $dump); - return true; - } - - return false; + $container_obj = new PluginFieldsContainer(); + $containers = $container_obj->find($where); + + foreach ($containers as $container) { + $itemtypes = (strlen($container['itemtypes']) > 0) + ? json_decode($container['itemtypes'], true) + : []; + + foreach ($itemtypes as $itemtype) { + $fields_obj = new PluginFieldsField(); + // to get translation + $container["itemtype"] = PluginFieldsContainer::getType(); + $yaml_conf['container'][$container['id'] . "-" . $itemtype] = [ + "id" => (int) $container['id'], + "name" => PluginFieldsLabelTranslation::getLabelFor($container), + "itemtype" => $itemtype, + "type" => $container['type'], + "subtype" => $container['subtype'], + "fields" => [], + ]; + $fields = $fields_obj->find(["plugin_fields_containers_id" => $container['id'], + "is_active" => true, + "is_readonly" => false + ]); + if (count($fields)) { + foreach ($fields as $field) { + $tmp_field = []; + $tmp_field['id'] = (int) $field['id']; + + //to get translation + $field["itemtype"] = PluginFieldsField::getType(); + $tmp_field['label'] = PluginFieldsLabelTranslation::getLabelFor($field); + $tmp_field['xml_node'] = strtoupper($field['name']); + $tmp_field['type'] = $field['type']; + $tmp_field['ranking'] = $field['ranking']; + $tmp_field['default_value'] = $field['default_value']; + $tmp_field['mandatory'] = $field['mandatory']; + $tmp_field['possible_value'] = ""; + + switch ($field['type']) { + case 'dropdown': + $obj = new $itemtype(); + $obj->getEmpty(); + + $dropdown_itemtype = PluginFieldsDropdown::getClassname($field['name']); + $tmp_field['xml_node'] = strtoupper(getForeignKeyFieldForItemType($dropdown_itemtype)); + + $dropdown_obj = new $dropdown_itemtype(); + $dropdown_datas = $dropdown_obj->find(); + $datas = []; + foreach ($dropdown_datas as $value) { + $items = []; + $items['id'] = (int)$value['id']; + $items['value'] = $value['name']; + $datas[] = $items; + } + $tmp_field['possible_value'] = $datas; + break; + case 'yesno': + $datas = []; + $datas["0"]['id'] = 0; + $datas["0"]['value'] = __('No'); + $datas["1"]['id'] = 1; + $datas["1"]['value'] = __('Yes'); + $tmp_field['possible_value'] = $datas; + break; + case 'dropdownuser': + $datas = Dropdown::getDropdownUsers(['is_active' => 1,'is_deleted' => 0], false); + $tmp_field['possible_value'] = $datas['results']; + break; + } + $yaml_conf['container'][$container['id'] . "-" . $itemtype]["fields"][] = $tmp_field; + } + } + } + } + } + } + + if (count($yaml_conf)) { + $dump = Yaml::dump($yaml_conf, 10); + $filename = GLPI_TMP_DIR . "/fields_conf.yaml"; + file_put_contents($filename, $dump); + return true; + } + + return false; }