diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 31e9e8e4..850f4482 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -20,7 +20,7 @@ jobs: name: "Generate CI matrix" uses: "glpi-project/plugin-ci-workflows/.github/workflows/generate-ci-matrix.yml@v1" with: - glpi-version: "10.0.x" + glpi-version: "11.0.x" ci: name: "GLPI ${{ matrix.glpi-version }} - php:${{ matrix.php-version }} - ${{ matrix.db-image }}" needs: "generate-ci-matrix" diff --git a/CHANGELOG.md b/CHANGELOG.md index e63d0a1f..e77b78ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -## [UNRELEASED] +## [1.22.0] - 2025-09-30 + +### Added + +- GLPI 11 compatibility ### Fixed diff --git a/ajax/container.php b/ajax/container.php index 5bdea933..d3bf41fb 100644 --- a/ajax/container.php +++ b/ajax/container.php @@ -31,14 +31,12 @@ include('../../../inc/includes.php'); Session::checkLoginUser(); -use Glpi\Http\Response; if (isset($_GET['action']) && $_GET['action'] === 'get_fields_html') { $right = PluginFieldsProfile::getRightOnContainer($_SESSION['glpiactiveprofile']['id'], $_GET['id']); if ($right < READ) { - Response::sendError(403, 'Forbidden'); - return; + throw new \Glpi\Exception\Http\AccessDeniedHttpException(); } $containers_id = $_GET['id']; @@ -48,9 +46,10 @@ $subtype = $_GET['subtype']; $input = $_GET['input']; - $item = new $itemtype(); + $dbu = new DbUtils(); + $item = $dbu->getItemForItemtype($itemtype); if ($items_id > 0 && !$item->getFromDB($items_id)) { - Response::sendError(404, 'Not Found'); + throw new \Glpi\Exception\Http\NotFoundHttpException(); } $item->input = $input; @@ -66,5 +65,5 @@ echo ''; } } else { - Response::sendError(404, 'Not Found'); + throw new \Glpi\Exception\Http\NotFoundHttpException(); } diff --git a/ajax/container_display_condition.php b/ajax/container_display_condition.php index 4988d99e..be7ef2d7 100644 --- a/ajax/container_display_condition.php +++ b/ajax/container_display_condition.php @@ -55,6 +55,5 @@ } } } else { - http_response_code(400); - die(); + throw new \RuntimeException('Invalid request', 400); } diff --git a/ajax/reorder.php b/ajax/reorder.php index 9ee4516d..38ff3c18 100644 --- a/ajax/reorder.php +++ b/ajax/reorder.php @@ -37,7 +37,7 @@ || !array_key_exists('new_order', $_POST) ) { // Missing input - exit(); + throw new \RuntimeException('Missing input', 400); } $table = PluginFieldsField::getTable(); @@ -62,7 +62,7 @@ if (0 === $field_iterator->count()) { // Unknown field - exit(); + throw new \RuntimeException('Unknown field', 404); } $field_id = $field_iterator->current()['id']; @@ -72,7 +72,7 @@ $DB->update( $table, [ - 'ranking' => new \QueryExpression($DB->quoteName('ranking') . ' - 1'), + 'ranking' => new \Glpi\DBAL\QueryExpression($DB->quoteName('ranking') . ' - 1'), ], [ 'plugin_fields_containers_id' => $container_id, @@ -84,7 +84,7 @@ $DB->update( $table, [ - 'ranking' => new \QueryExpression($DB->quoteName('ranking') . ' + 1'), + 'ranking' => new \Glpi\DBAL\QueryExpression($DB->quoteName('ranking') . ' + 1'), ], [ 'plugin_fields_containers_id' => $container_id, diff --git a/ajax/status_override.php b/ajax/status_override.php index f5554387..0e1d2681 100644 --- a/ajax/status_override.php +++ b/ajax/status_override.php @@ -43,6 +43,5 @@ $status_override->showForm($_GET['id'], $_GET); } } else { - http_response_code(400); - die(); + throw new \RuntimeException('Invalid request', 400); } diff --git a/ajax/viewtranslations.php b/ajax/viewtranslations.php index df0dbc0e..995f1e9a 100644 --- a/ajax/viewtranslations.php +++ b/ajax/viewtranslations.php @@ -39,7 +39,7 @@ Session::checkLoginUser(); if (!isset($_POST['itemtype']) || !isset($_POST['items_id']) || !isset($_POST['id'])) { - exit(); + throw new \RuntimeException('Missing required parameters', 400); } $translation = new PluginFieldsLabelTranslation(); @@ -53,5 +53,3 @@ } else { echo __('Access denied'); } - -Html::ajaxFooter(); diff --git a/composer.json b/composer.json index 7c79a173..f5164c95 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "require": { - "php": ">=7.4", - "symfony/yaml": "^5.4" + "php": ">=8.2", + "symfony/yaml": "^7.3" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.86", @@ -15,7 +15,7 @@ "config": { "optimize-autoloader": true, "platform": { - "php": "7.4.0" + "php": "8.2.99" }, "sort-packages": true, "allow-plugins": { diff --git a/composer.lock b/composer.lock index 7c1ba7e5..24927189 100644 --- a/composer.lock +++ b/composer.lock @@ -4,24 +4,24 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "44d06ff8f58689d0eed5370308775f1e", + "content-hash": "90b0ff0911aff25de523680b8c6c7235", "packages": [ { "name": "symfony/deprecation-contracts", - "version": "v2.5.4", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "605389f2a7e5625f273b53960dc46aeaf9c62918" + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/605389f2a7e5625f273b53960dc46aeaf9c62918", - "reference": "605389f2a7e5625f273b53960dc46aeaf9c62918", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.1" }, "type": "library", "extra": { @@ -30,7 +30,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -55,7 +55,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.4" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" }, "funding": [ { @@ -71,7 +71,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:11:13+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/polyfill-ctype", @@ -158,31 +158,28 @@ }, { "name": "symfony/yaml", - "version": "v5.4.45", + "version": "v7.3.3", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "a454d47278cc16a5db371fe73ae66a78a633371e" + "reference": "d4f4a66866fe2451f61296924767280ab5732d9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/a454d47278cc16a5db371fe73ae66a78a633371e", - "reference": "a454d47278cc16a5db371fe73ae66a78a633371e", + "url": "https://api.github.com/repos/symfony/yaml/zipball/d4f4a66866fe2451f61296924767280ab5732d9d", + "reference": "d4f4a66866fe2451f61296924767280ab5732d9d", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", "symfony/polyfill-ctype": "^1.8" }, "conflict": { - "symfony/console": "<5.3" + "symfony/console": "<6.4" }, "require-dev": { - "symfony/console": "^5.3|^6.0" - }, - "suggest": { - "symfony/console": "For validating YAML files using the lint command" + "symfony/console": "^6.4|^7.0" }, "bin": [ "Resources/bin/yaml-lint" @@ -213,7 +210,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v5.4.45" + "source": "https://github.com/symfony/yaml/tree/v7.3.3" }, "funding": [ { @@ -224,12 +221,16 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-25T14:11:13+00:00" + "time": "2025-08-27T11:34:33+00:00" } ], "packages-dev": [ @@ -629,16 +630,16 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.86.0", + "version": "v3.88.2", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "4a952bd19dc97879b0620f495552ef09b55f7d36" + "reference": "a8d15584bafb0f0d9d938827840060fd4a3ebc99" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/4a952bd19dc97879b0620f495552ef09b55f7d36", - "reference": "4a952bd19dc97879b0620f495552ef09b55f7d36", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/a8d15584bafb0f0d9d938827840060fd4a3ebc99", + "reference": "a8d15584bafb0f0d9d938827840060fd4a3ebc99", "shasum": "" }, "require": { @@ -649,39 +650,38 @@ "ext-hash": "*", "ext-json": "*", "ext-tokenizer": "*", - "fidry/cpu-core-counter": "^1.2", + "fidry/cpu-core-counter": "^1.3", "php": "^7.4 || ^8.0", "react/child-process": "^0.6.6", "react/event-loop": "^1.5", - "react/promise": "^3.2", + "react/promise": "^3.3", "react/socket": "^1.16", "react/stream": "^1.4", "sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0", - "symfony/console": "^5.4.47 || ^6.4.13 || ^7.0", - "symfony/event-dispatcher": "^5.4.45 || ^6.4.13 || ^7.0", - "symfony/filesystem": "^5.4.45 || ^6.4.13 || ^7.0", - "symfony/finder": "^5.4.45 || ^6.4.17 || ^7.0", - "symfony/options-resolver": "^5.4.45 || ^6.4.16 || ^7.0", - "symfony/polyfill-mbstring": "^1.32", - "symfony/polyfill-php80": "^1.32", - "symfony/polyfill-php81": "^1.32", - "symfony/process": "^5.4.47 || ^6.4.20 || ^7.2", - "symfony/stopwatch": "^5.4.45 || ^6.4.19 || ^7.0" + "symfony/console": "^5.4.47 || ^6.4.24 || ^7.0", + "symfony/event-dispatcher": "^5.4.45 || ^6.4.24 || ^7.0", + "symfony/filesystem": "^5.4.45 || ^6.4.24 || ^7.0", + "symfony/finder": "^5.4.45 || ^6.4.24 || ^7.0", + "symfony/options-resolver": "^5.4.45 || ^6.4.24 || ^7.0", + "symfony/polyfill-mbstring": "^1.33", + "symfony/polyfill-php80": "^1.33", + "symfony/polyfill-php81": "^1.33", + "symfony/polyfill-php84": "^1.33", + "symfony/process": "^5.4.47 || ^6.4.24 || ^7.2", + "symfony/stopwatch": "^5.4.45 || ^6.4.24 || ^7.0" }, "require-dev": { - "facile-it/paraunit": "^1.3.1 || ^2.6", - "infection/infection": "^0.29.14", - "justinrainbow/json-schema": "^5.3 || ^6.4", + "facile-it/paraunit": "^1.3.1 || ^2.7", + "infection/infection": "^0.31.0", + "justinrainbow/json-schema": "^6.5", "keradus/cli-executor": "^2.2", "mikey179/vfsstream": "^1.6.12", "php-coveralls/php-coveralls": "^2.8", - "php-cs-fixer/accessible-object": "^1.1", "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6", "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6", - "phpunit/phpunit": "^9.6.23 || ^10.5.47 || ^11.5.25", - "symfony/polyfill-php84": "^1.32", - "symfony/var-dumper": "^5.4.48 || ^6.4.23 || ^7.3.1", - "symfony/yaml": "^5.4.45 || ^6.4.23 || ^7.3.1" + "phpunit/phpunit": "^9.6.25 || ^10.5.53 || ^11.5.34", + "symfony/var-dumper": "^5.4.48 || ^6.4.24 || ^7.3.2", + "symfony/yaml": "^5.4.45 || ^6.4.24 || ^7.3.2" }, "suggest": { "ext-dom": "For handling output formats in XML", @@ -722,7 +722,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.86.0" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.88.2" }, "funding": [ { @@ -730,20 +730,20 @@ "type": "github" } ], - "time": "2025-08-13T22:36:21+00:00" + "time": "2025-09-27T00:24:15+00:00" }, { "name": "friendsoftwig/twigcs", - "version": "v6.1.0", + "version": "6.5.0", "source": { "type": "git", "url": "https://github.com/friendsoftwig/twigcs.git", - "reference": "3c36d606c4f19db0dd2a01b735ec7a8151b7f182" + "reference": "aaa3ba112bf4fcee7b51a00d9b45b13bc2cc23bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/friendsoftwig/twigcs/zipball/3c36d606c4f19db0dd2a01b735ec7a8151b7f182", - "reference": "3c36d606c4f19db0dd2a01b735ec7a8151b7f182", + "url": "https://api.github.com/repos/friendsoftwig/twigcs/zipball/aaa3ba112bf4fcee7b51a00d9b45b13bc2cc23bc", + "reference": "aaa3ba112bf4fcee7b51a00d9b45b13bc2cc23bc", "shasum": "" }, "require": { @@ -752,14 +752,14 @@ "ext-json": "*", "ext-mbstring": "*", "ext-simplexml": "*", - "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0", - "symfony/console": "^4.4 || ^5.3 || ^6.0", - "symfony/filesystem": "^4.4 || ^5.3 || ^6.0", - "symfony/finder": "^4.4 || ^5.3 || ^6.0" + "php": "~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0", + "symfony/console": "^4.4 || ^5.3 || ^6.0 || ^7.0", + "symfony/filesystem": "^4.4 || ^5.3 || ^6.0 || ^7.0", + "symfony/finder": "^4.4 || ^5.3 || ^6.0 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "^9.5.20", - "symfony/phpunit-bridge": "^6.2.3" + "phpunit/phpunit": "^9.6.19", + "symfony/phpunit-bridge": "^7.1.4" }, "bin": [ "bin/twigcs" @@ -783,22 +783,22 @@ "description": "Checkstyle automation for Twig", "support": { "issues": "https://github.com/friendsoftwig/twigcs/issues", - "source": "https://github.com/friendsoftwig/twigcs/tree/v6.1.0" + "source": "https://github.com/friendsoftwig/twigcs/tree/6.5.0" }, - "time": "2023-01-04T16:01:24+00:00" + "time": "2024-11-27T21:59:24+00:00" }, { "name": "glpi-project/tools", - "version": "0.8.0", + "version": "0.8.1", "source": { "type": "git", "url": "https://github.com/glpi-project/tools.git", - "reference": "7c2dcec105ed3427183bdfd382d785363aade436" + "reference": "cf182b1a6bd1a73c5c6469dbbd0edabf7cb5857e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/glpi-project/tools/zipball/7c2dcec105ed3427183bdfd382d785363aade436", - "reference": "7c2dcec105ed3427183bdfd382d785363aade436", + "url": "https://api.github.com/repos/glpi-project/tools/zipball/cf182b1a6bd1a73c5c6469dbbd0edabf7cb5857e", + "reference": "cf182b1a6bd1a73c5c6469dbbd0edabf7cb5857e", "shasum": "" }, "require": { @@ -841,7 +841,7 @@ "issues": "https://github.com/glpi-project/tools/issues", "source": "https://github.com/glpi-project/tools" }, - "time": "2025-08-26T10:18:38+00:00" + "time": "2025-09-08T09:45:41+00:00" }, { "name": "php-parallel-lint/php-parallel-lint", @@ -954,16 +954,16 @@ }, { "name": "phpstan/phpstan", - "version": "2.1.22", + "version": "2.1.29", "source": { "type": "git", - "url": "https://github.com/phpstan/phpstan.git", - "reference": "41600c8379eb5aee63e9413fe9e97273e25d57e4" + "url": "https://github.com/phpstan/phpstan-phar-composer-source.git", + "reference": "git" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/41600c8379eb5aee63e9413fe9e97273e25d57e4", - "reference": "41600c8379eb5aee63e9413fe9e97273e25d57e4", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/d618573eed4a1b6b75e37b2e0b65ac65c885d88e", + "reference": "d618573eed4a1b6b75e37b2e0b65ac65c885d88e", "shasum": "" }, "require": { @@ -1008,7 +1008,7 @@ "type": "github" } ], - "time": "2025-08-04T19:17:37+00:00" + "time": "2025-09-25T06:58:18+00:00" }, { "name": "phpstan/phpstan-deprecation-rules", @@ -1059,22 +1059,27 @@ }, { "name": "psr/container", - "version": "1.1.2", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", "shasum": "" }, "require": { "php": ">=7.4.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, "autoload": { "psr-4": { "Psr\\Container\\": "src/" @@ -1101,9 +1106,9 @@ ], "support": { "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/1.1.2" + "source": "https://github.com/php-fig/container/tree/2.0.2" }, - "time": "2021-11-05T16:50:12+00:00" + "time": "2021-11-05T16:47:00+00:00" }, { "name": "psr/event-dispatcher", @@ -1157,30 +1162,30 @@ }, { "name": "psr/log", - "version": "1.1.4", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=8.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "3.x-dev" } }, "autoload": { "psr-4": { - "Psr\\Log\\": "Psr/Log/" + "Psr\\Log\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -1201,9 +1206,9 @@ "psr-3" ], "support": { - "source": "https://github.com/php-fig/log/tree/1.1.4" + "source": "https://github.com/php-fig/log/tree/3.0.2" }, - "time": "2021-05-03T11:20:27+00:00" + "time": "2024-09-11T13:17:53+00:00" }, { "name": "react/cache", @@ -1733,29 +1738,29 @@ }, { "name": "sebastian/diff", - "version": "4.0.6", + "version": "6.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc" + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc", - "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^9.3", + "phpunit/phpunit": "^11.0", "symfony/process": "^4.2 || ^5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -1787,7 +1792,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6" + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" }, "funding": [ { @@ -1795,56 +1801,51 @@ "type": "github" } ], - "time": "2024-03-02T06:30:58+00:00" + "time": "2024-07-03T04:53:05+00:00" }, { "name": "symfony/console", - "version": "v5.4.47", + "version": "v6.4.26", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed" + "reference": "492de6dfd93910d7d7a729c5a04ddcd2b9e99c4f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed", - "reference": "c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed", + "url": "https://api.github.com/repos/symfony/console/zipball/492de6dfd93910d7d7a729c5a04ddcd2b9e99c4f", + "reference": "492de6dfd93910d7d7a729c5a04ddcd2b9e99c4f", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.9", - "symfony/polyfill-php80": "^1.16", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/string": "^5.1|^6.0" + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^5.4|^6.0|^7.0" }, "conflict": { - "psr/log": ">=3", - "symfony/dependency-injection": "<4.4", - "symfony/dotenv": "<5.1", - "symfony/event-dispatcher": "<4.4", - "symfony/lock": "<4.4", - "symfony/process": "<4.4" + "symfony/dependency-injection": "<5.4", + "symfony/dotenv": "<5.4", + "symfony/event-dispatcher": "<5.4", + "symfony/lock": "<5.4", + "symfony/process": "<5.4" }, "provide": { - "psr/log-implementation": "1.0|2.0" + "psr/log-implementation": "1.0|2.0|3.0" }, "require-dev": { - "psr/log": "^1|^2", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/event-dispatcher": "^4.4|^5.0|^6.0", - "symfony/lock": "^4.4|^5.0|^6.0", - "symfony/process": "^4.4|^5.0|^6.0", - "symfony/var-dumper": "^4.4|^5.0|^6.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^5.4|^6.0|^7.0", + "symfony/messenger": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/stopwatch": "^5.4|^6.0|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -1878,7 +1879,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.4.47" + "source": "https://github.com/symfony/console/tree/v6.4.26" }, "funding": [ { @@ -1889,53 +1890,52 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-11-06T11:30:55+00:00" + "time": "2025-09-26T12:13:46+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v5.4.45", + "version": "v7.3.3", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "72982eb416f61003e9bb6e91f8b3213600dcf9e9" + "reference": "b7dc69e71de420ac04bc9ab830cf3ffebba48191" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/72982eb416f61003e9bb6e91f8b3213600dcf9e9", - "reference": "72982eb416f61003e9bb6e91f8b3213600dcf9e9", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b7dc69e71de420ac04bc9ab830cf3ffebba48191", + "reference": "b7dc69e71de420ac04bc9ab830cf3ffebba48191", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/event-dispatcher-contracts": "^2|^3", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.2", + "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/dependency-injection": "<4.4" + "symfony/dependency-injection": "<6.4", + "symfony/service-contracts": "<2.5" }, "provide": { "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "2.0" + "symfony/event-dispatcher-implementation": "2.0|3.0" }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/http-foundation": "^4.4|^5.0|^6.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/stopwatch": "^4.4|^5.0|^6.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/error-handler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/stopwatch": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -1963,7 +1963,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.45" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.3.3" }, "funding": [ { @@ -1974,34 +1974,35 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-25T14:11:13+00:00" + "time": "2025-08-13T11:49:31+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v2.5.4", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "e0fe3d79b516eb75126ac6fa4cbf19b79b08c99f" + "reference": "59eb412e93815df44f05f342958efa9f46b1e586" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/e0fe3d79b516eb75126ac6fa4cbf19b79b08c99f", - "reference": "e0fe3d79b516eb75126ac6fa4cbf19b79b08c99f", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586", + "reference": "59eb412e93815df44f05f342958efa9f46b1e586", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.1", "psr/event-dispatcher": "^1" }, - "suggest": { - "symfony/event-dispatcher-implementation": "" - }, "type": "library", "extra": { "thanks": { @@ -2009,7 +2010,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -2042,7 +2043,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.4" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0" }, "funding": [ { @@ -2058,30 +2059,29 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:11:13+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/filesystem", - "version": "v5.4.45", + "version": "v7.3.2", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "57c8294ed37d4a055b77057827c67f9558c95c54" + "reference": "edcbb768a186b5c3f25d0643159a787d3e63b7fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/57c8294ed37d4a055b77057827c67f9558c95c54", - "reference": "57c8294ed37d4a055b77057827c67f9558c95c54", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/edcbb768a186b5c3f25d0643159a787d3e63b7fd", + "reference": "edcbb768a186b5c3f25d0643159a787d3e63b7fd", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.2", "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8", - "symfony/polyfill-php80": "^1.16" + "symfony/polyfill-mbstring": "~1.8" }, "require-dev": { - "symfony/process": "^5.4|^6.4" + "symfony/process": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -2109,7 +2109,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v5.4.45" + "source": "https://github.com/symfony/filesystem/tree/v7.3.2" }, "funding": [ { @@ -2120,31 +2120,36 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-10-22T13:05:35+00:00" + "time": "2025-07-07T08:17:47+00:00" }, { "name": "symfony/finder", - "version": "v5.4.45", + "version": "v7.3.2", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "63741784cd7b9967975eec610b256eed3ede022b" + "reference": "2a6614966ba1074fa93dae0bc804227422df4dfe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/63741784cd7b9967975eec610b256eed3ede022b", - "reference": "63741784cd7b9967975eec610b256eed3ede022b", + "url": "https://api.github.com/repos/symfony/finder/zipball/2a6614966ba1074fa93dae0bc804227422df4dfe", + "reference": "2a6614966ba1074fa93dae0bc804227422df4dfe", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.2" + }, + "require-dev": { + "symfony/filesystem": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -2172,7 +2177,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v5.4.45" + "source": "https://github.com/symfony/finder/tree/v7.3.2" }, "funding": [ { @@ -2183,32 +2188,34 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-28T13:32:08+00:00" + "time": "2025-07-15T13:41:35+00:00" }, { "name": "symfony/options-resolver", - "version": "v5.4.45", + "version": "v7.3.3", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "74e5b6f0db3e8589e6cfd5efb317a1fc2bb52fb6" + "reference": "0ff2f5c3df08a395232bbc3c2eb7e84912df911d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/74e5b6f0db3e8589e6cfd5efb317a1fc2bb52fb6", - "reference": "74e5b6f0db3e8589e6cfd5efb317a1fc2bb52fb6", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/0ff2f5c3df08a395232bbc3c2eb7e84912df911d", + "reference": "0ff2f5c3df08a395232bbc3c2eb7e84912df911d", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php73": "~1.0", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3" }, "type": "library", "autoload": { @@ -2241,7 +2248,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v5.4.45" + "source": "https://github.com/symfony/options-resolver/tree/v7.3.3" }, "funding": [ { @@ -2252,12 +2259,16 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-25T14:11:13+00:00" + "time": "2025-08-05T10:16:07+00:00" }, { "name": "symfony/polyfill-intl-grapheme", @@ -2512,17 +2523,17 @@ "time": "2024-12-23T08:48:59+00:00" }, { - "name": "symfony/polyfill-php73", + "name": "symfony/polyfill-php80", "version": "v1.33.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb" + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f68c03565dcaaf25a890667542e8bd75fe7e5bb", - "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", "shasum": "" }, "require": { @@ -2540,7 +2551,7 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Php73\\": "" + "Symfony\\Polyfill\\Php80\\": "" }, "classmap": [ "Resources/stubs" @@ -2551,6 +2562,10 @@ "MIT" ], "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, { "name": "Nicolas Grekas", "email": "p@tchwork.com" @@ -2560,7 +2575,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", @@ -2569,7 +2584,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0" }, "funding": [ { @@ -2589,20 +2604,20 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2025-01-02T08:10:11+00:00" }, { - "name": "symfony/polyfill-php80", + "name": "symfony/polyfill-php81", "version": "v1.33.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", - "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", "shasum": "" }, "require": { @@ -2620,7 +2635,7 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" + "Symfony\\Polyfill\\Php81\\": "" }, "classmap": [ "Resources/stubs" @@ -2631,10 +2646,6 @@ "MIT" ], "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, { "name": "Nicolas Grekas", "email": "p@tchwork.com" @@ -2644,7 +2655,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", @@ -2653,7 +2664,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.33.0" }, "funding": [ { @@ -2673,20 +2684,20 @@ "type": "tidelift" } ], - "time": "2025-01-02T08:10:11+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { - "name": "symfony/polyfill-php81", + "name": "symfony/polyfill-php84", "version": "v1.33.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c" + "url": "https://github.com/symfony/polyfill-php84.git", + "reference": "d8ced4d875142b6a7426000426b8abc631d6b191" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", - "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191", + "reference": "d8ced4d875142b6a7426000426b8abc631d6b191", "shasum": "" }, "require": { @@ -2704,7 +2715,7 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Php81\\": "" + "Symfony\\Polyfill\\Php84\\": "" }, "classmap": [ "Resources/stubs" @@ -2724,7 +2735,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", @@ -2733,7 +2744,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php84/tree/v1.33.0" }, "funding": [ { @@ -2753,25 +2764,24 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2025-06-24T13:30:11+00:00" }, { "name": "symfony/process", - "version": "v5.4.47", + "version": "v7.3.4", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "5d1662fb32ebc94f17ddb8d635454a776066733d" + "reference": "f24f8f316367b30810810d4eb30c543d7003ff3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/5d1662fb32ebc94f17ddb8d635454a776066733d", - "reference": "5d1662fb32ebc94f17ddb8d635454a776066733d", + "url": "https://api.github.com/repos/symfony/process/zipball/f24f8f316367b30810810d4eb30c543d7003ff3b", + "reference": "f24f8f316367b30810810d4eb30c543d7003ff3b", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.2" }, "type": "library", "autoload": { @@ -2799,7 +2809,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v5.4.47" + "source": "https://github.com/symfony/process/tree/v7.3.4" }, "funding": [ { @@ -2810,38 +2820,39 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-11-06T11:36:42+00:00" + "time": "2025-09-11T10:12:26+00:00" }, { "name": "symfony/service-contracts", - "version": "v2.5.4", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "f37b419f7aea2e9abf10abd261832cace12e3300" + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f37b419f7aea2e9abf10abd261832cace12e3300", - "reference": "f37b419f7aea2e9abf10abd261832cace12e3300", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", "shasum": "" }, "require": { - "php": ">=7.2.5", - "psr/container": "^1.1", - "symfony/deprecation-contracts": "^2.1|^3" + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" }, "conflict": { "ext-psr": "<1.1|>=2" }, - "suggest": { - "symfony/service-implementation": "" - }, "type": "library", "extra": { "thanks": { @@ -2849,13 +2860,16 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { "psr-4": { "Symfony\\Contracts\\Service\\": "" - } + }, + "exclude-from-classmap": [ + "/Test/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2882,7 +2896,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v2.5.4" + "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" }, "funding": [ { @@ -2898,25 +2912,25 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:11:13+00:00" + "time": "2025-04-25T09:37:31+00:00" }, { "name": "symfony/stopwatch", - "version": "v5.4.45", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "fb2c199cf302eb207f8c23e7ee174c1c31a5c004" + "reference": "5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/fb2c199cf302eb207f8c23e7ee174c1c31a5c004", - "reference": "fb2c199cf302eb207f8c23e7ee174c1c31a5c004", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd", + "reference": "5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/service-contracts": "^1|^2|^3" + "php": ">=8.2", + "symfony/service-contracts": "^2.5|^3" }, "type": "library", "autoload": { @@ -2944,7 +2958,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v5.4.45" + "source": "https://github.com/symfony/stopwatch/tree/v7.3.0" }, "funding": [ { @@ -2960,38 +2974,38 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:11:13+00:00" + "time": "2025-02-24T10:49:57+00:00" }, { "name": "symfony/string", - "version": "v5.4.47", + "version": "v7.3.4", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "136ca7d72f72b599f2631aca474a4f8e26719799" + "reference": "f96476035142921000338bad71e5247fbc138872" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/136ca7d72f72b599f2631aca474a4f8e26719799", - "reference": "136ca7d72f72b599f2631aca474a4f8e26719799", + "url": "https://api.github.com/repos/symfony/string/zipball/f96476035142921000338bad71e5247fbc138872", + "reference": "f96476035142921000338bad71e5247fbc138872", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.2", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "~1.15" + "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/translation-contracts": ">=3.0" + "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/http-client": "^4.4|^5.0|^6.0", - "symfony/translation-contracts": "^1.1|^2", - "symfony/var-exporter": "^4.4|^5.0|^6.0" + "symfony/emoji": "^7.1", + "symfony/http-client": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -3030,7 +3044,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.4.47" + "source": "https://github.com/symfony/string/tree/v7.3.4" }, "funding": [ { @@ -3041,36 +3055,39 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-11-10T20:33:58+00:00" + "time": "2025-09-11T14:36:48+00:00" }, { "name": "twig/twig", - "version": "v3.11.3", + "version": "v3.21.1", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "3b06600ff3abefaf8ff55d5c336cd1c4253f8c7e" + "reference": "285123877d4dd97dd7c11842ac5fb7e86e60d81d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/3b06600ff3abefaf8ff55d5c336cd1c4253f8c7e", - "reference": "3b06600ff3abefaf8ff55d5c336cd1c4253f8c7e", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/285123877d4dd97dd7c11842ac5fb7e86e60d81d", + "reference": "285123877d4dd97dd7c11842ac5fb7e86e60d81d", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.1.0", "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "^1.8", - "symfony/polyfill-mbstring": "^1.3", - "symfony/polyfill-php80": "^1.22", - "symfony/polyfill-php81": "^1.29" + "symfony/polyfill-mbstring": "^1.3" }, "require-dev": { + "phpstan/phpstan": "^2.0", "psr/container": "^1.0|^2.0", "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0" }, @@ -3114,7 +3131,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.11.3" + "source": "https://github.com/twigphp/Twig/tree/v3.21.1" }, "funding": [ { @@ -3126,7 +3143,7 @@ "type": "tidelift" } ], - "time": "2024-11-07T12:34:41+00:00" + "time": "2025-05-03T07:21:55+00:00" } ], "aliases": [], @@ -3135,11 +3152,11 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=7.4" + "php": ">=8.2" }, "platform-dev": {}, "platform-overrides": { - "php": "7.4.0" + "php": "8.2.99" }, "plugin-api-version": "2.6.0" } diff --git a/front/container.form.php b/front/container.form.php index 8a80410a..68968f4d 100644 --- a/front/container.form.php +++ b/front/container.form.php @@ -28,7 +28,8 @@ * ------------------------------------------------------------------------- */ -include('../../../inc/includes.php'); +use Glpi\Exception\Http\AccessDeniedHttpException; + Session::checkLoginUser(); if (empty($_GET['id'])) { @@ -64,7 +65,7 @@ if ((int) $_GET['id'] > 0) { $right = PluginFieldsProfile::getRightOnContainer($_SESSION['glpiactiveprofile']['id'], $_GET['id']); if ($right < READ) { - Html::displayRightError("User is missing the " . READ . " ('read') right for container"); + throw new AccessDeniedHttpException(); } } diff --git a/front/export_to_yaml.php b/front/export_to_yaml.php index 16e8afb7..cfd132d4 100644 --- a/front/export_to_yaml.php +++ b/front/export_to_yaml.php @@ -41,7 +41,7 @@ if (plugin_fields_exportBlockAsYaml($ID)) { $filename = 'fields_conf.yaml'; $path = GLPI_TMP_DIR . '/fields_conf.yaml'; - Toolbox::sendFile($path, $filename, 'text/yaml'); + Toolbox::getFileAsResponse($path, $filename, 'text/yaml')->send(); } else { Session::addMessageAfterRedirect('No data to export', false, INFO); Html::back(); diff --git a/hook.php b/hook.php index e1683f12..4daa672f 100644 --- a/hook.php +++ b/hook.php @@ -72,6 +72,7 @@ function plugin_fields_install() PluginFieldsStatusOverride::class, ]; + // First, install base data foreach ($classesToInstall as $class) { if (method_exists($class, 'installBaseData')) { @@ -309,7 +310,7 @@ function plugin_fields_rule_matched($params = []) function plugin_fields_giveItem($itemtype, $ID, $data, $num) { - $searchopt = &Search::getOptions($itemtype); + $searchopt = Search::getOptions($itemtype); $table = $searchopt[$ID]['table']; //fix glpi default Search::giveItem who for empty date display "--" diff --git a/inc/abstractcontainerinstance.class.php b/inc/abstractcontainerinstance.class.php index 64678aee..3a6a875d 100644 --- a/inc/abstractcontainerinstance.class.php +++ b/inc/abstractcontainerinstance.class.php @@ -62,16 +62,12 @@ public function addNeededInfoToInput($input) $completeinput, ) ) { - if ( - ($itemToGetEntity instanceof CommonDBTM) - ) { - if ($itemToGetEntity->isEntityAssign()) { - $input['entities_id'] = $itemToGetEntity->getEntityID(); - } + if ($itemToGetEntity->isEntityAssign()) { + $input['entities_id'] = $itemToGetEntity->getEntityID(); + } - if ($itemToGetEntity->maybeRecursive()) { - $input['is_recursive'] = intval($itemToGetEntity->isRecursive()); - } + if ($itemToGetEntity->maybeRecursive()) { + $input['is_recursive'] = intval($itemToGetEntity->isRecursive()); } } } @@ -179,4 +175,28 @@ public static function getSpecificValueToDisplay($field, $values, array $options return parent::getSpecificValueToDisplay($field, $values, $options); } + + public static function addField($fieldname, $type, array $options = []) + { + $migration = new PluginFieldsMigration('0'); + + $sql_fields = PluginFieldsMigration::getSQLFields($fieldname, $type, $options); + foreach ($sql_fields as $sql_field_name => $sql_field_type) { + $migration->addField(self::getTable(), $sql_field_name, $sql_field_type); + } + + $migration->migrationOneTable(self::getTable()); + } + + public static function removeField($fieldname, $type) + { + $migration = new PluginFieldsMigration('0'); + + $sql_fields = PluginFieldsMigration::getSQLFields($fieldname, $type); + foreach (array_keys($sql_fields) as $sql_field_name) { + $migration->dropField(self::getTable(), $sql_field_name); + } + + $migration->migrationOneTable(self::getTable()); + } } diff --git a/inc/container.class.php b/inc/container.class.php index 7e906230..2a98cc66 100644 --- a/inc/container.class.php +++ b/inc/container.class.php @@ -28,20 +28,18 @@ * ------------------------------------------------------------------------- */ -use Glpi\Toolbox\Sanitizer; - class PluginFieldsContainer extends CommonDBTM { use Glpi\Features\Clonable; public static $rightname = 'config'; - public static function canCreate() + public static function canCreate(): bool { return self::canUpdate(); } - public static function canPurge() + public static function canPurge(): bool { return self::canUpdate(); } @@ -96,7 +94,9 @@ public static function installBaseData(Migration $migration, $version) PRIMARY KEY (`id`), KEY `entities_id` (`entities_id`) ) ENGINE=InnoDB DEFAULT CHARSET={$default_charset} COLLATE={$default_collation} ROW_FORMAT=DYNAMIC;"; - $DB->doQuery($query) or die($DB->error()); + if (!$DB->doQuery($query)) { + throw new \RuntimeException('Error creating plugin_fields_containers table: ' . $DB->error()); + } } // multiple itemtype for one container @@ -104,10 +104,10 @@ public static function installBaseData(Migration $migration, $version) $migration->changeField($table, 'itemtype', 'itemtypes', 'longtext'); $migration->migrationOneTable($table); - $DB->updateOrDie( + $DB->update( $table, [ - 'itemtypes' => new QueryExpression( + 'itemtypes' => new \Glpi\DBAL\QueryExpression( sprintf( 'CONCAT(%s, %s, %s)', $DB->quoteValue('[\"'), @@ -147,6 +147,72 @@ public static function installBaseData(Migration $migration, $version) $migration->migrationOneTable($table); } + // Get itemtypes from PluginGenericobject + if ($DB->tableExists('glpi_plugin_genericobject_types')) { + // Check GenericObject version + $genericobject_info = Plugin::getInfo('genericobject'); + if (version_compare($genericobject_info['version'] ?? '0', '3.0.0', '<')) { + throw new \RuntimeException( + 'GenericObject plugin cannot be migrated. Please update it to the latest version.', + ); + } + + // Check glpi_plugin_genericobject_types table + if (!$DB->fieldExists('glpi_plugin_genericobject_types', 'itemtype')) { + throw new \RuntimeException( + 'Integrity error on the glpi_plugin_genericobject_types table from the GenericObject plugin.', + ); + } + + $migration_genericobject_itemtype = []; + $result = $DB->request(['FROM' => 'glpi_plugin_genericobject_types']); + foreach ($result as $type) { + $migration_genericobject_itemtype[$type['itemtype']] = [ + 'genericobject_itemtype' => $type['itemtype'], + 'itemtype' => 'Glpi\CustomAsset\\' . $type['name'] . 'Asset', + 'genericobject_name' => $type['name'], + 'name' => $type['name'] . 'Asset', + ]; + } + + // Get containers with PluginGenericobject itemtype + $result = $DB->request([ + 'FROM' => $table, + 'WHERE' => [ + new Glpi\DBAL\QueryExpression( + $table . ".itemtypes LIKE '%PluginGenericobject%'", + ), + ], + ]); + + $container_class = new self(); + foreach ($result as $container) { + self::generateTemplate($container); + foreach (json_decode($container['itemtypes']) as $itemtype) { + $classname = self::getClassname($itemtype, $container["name"]); + $old_table = $classname::getTable(); + // Rename genericobject container table + if ( + $DB->tableExists($old_table) && + isset($migration_genericobject_itemtype[$itemtype]) && + strpos($old_table, 'glpi_plugin_fields_plugingenericobject' . $migration_genericobject_itemtype[$itemtype]['genericobject_name']) !== false + ) { + $new_table = str_replace('plugingenericobject' . $migration_genericobject_itemtype[$itemtype]['genericobject_name'], 'glpicustomasset' . strtolower($migration_genericobject_itemtype[$itemtype]['name']), $old_table); + $migration->renameTable($old_table, $new_table); + } + } + // Update old genericobject itemtypes in container + $map = array_column($migration_genericobject_itemtype, 'itemtype', 'genericobject_itemtype'); + $itemtypes = strtr($container['itemtypes'], $map); + $container_class->update( + [ + 'id' => $container['id'], + 'itemtypes' => $itemtypes, + ], + ); + } + } + return true; } @@ -256,9 +322,10 @@ public static function installUserData(Migration $migration, $version) $fieldsdata = $fields->find(['plugin_fields_containers_id' => $ostab]); $classname = self::getClassname(Computer::getType(), $oscontainer->fields['name']); - $osdata = new $classname(); + $dbu = new DbUtils(); + $osdata = $dbu->getItemForItemtype($classname); $classname = self::getClassname(Computer::getType(), $compcontainer->fields['name']); - $compdata = new $classname(); + $compdata = $dbu->getItemForItemtype($classname); $fieldnames = []; //add fields to compcontainer @@ -278,7 +345,9 @@ public static function installUserData(Migration $migration, $version) ], ); } - $compdata::addField($newname, $field['type']); + if ($compdata instanceof PluginFieldsAbstractContainerInstance) { + $compdata->addField($newname, $field['type']); + } $fieldnames[$field['name']] = $newname; } @@ -409,6 +478,8 @@ public function rawSearchOptions() 'table' => self::getTable(), 'field' => 'label', 'name' => __('Label'), + 'datatype' => 'itemlink', + 'itemlink_type' => self::getType(), 'massiveaction' => false, 'autocomplete' => true, ]; @@ -482,7 +553,7 @@ public static function getSpecificValueToDisplay($field, $values, array $options return $types[$values[$field]]; case 'itemtypes': - $types = json_decode($values[$field]); + $types = PluginFieldsToolbox::decodeJSONItemtypes($values[$field]); $obj = ''; $count = count($types); $i = 1; @@ -620,7 +691,7 @@ public function prepareInputForAdd($input) } } - $input['itemtypes'] = Sanitizer::dbEscape(json_encode($input['itemtypes'])); + $input['itemtypes'] = json_encode($input['itemtypes']); return $input; } @@ -645,7 +716,7 @@ public static function create($fields) return false; } - foreach (json_decode($fields['itemtypes']) as $itemtype) { + foreach (PluginFieldsToolbox::decodeJSONItemtypes($fields['itemtypes']) as $itemtype) { //install table for receive field $classname = self::getClassname($itemtype, $fields['name']); $classname::install(); @@ -655,7 +726,7 @@ public static function create($fields) public static function generateTemplate($fields) { $itemtypes = strlen($fields['itemtypes']) > 0 - ? json_decode($fields['itemtypes'], true) + ? PluginFieldsToolbox::decodeJSONItemtypes($fields['itemtypes'], true) : []; foreach ($itemtypes as $itemtype) { // prevent usage of plugin class if not loaded @@ -784,10 +855,13 @@ public static function getTypeName($nb = 0) public function showForm($ID, $options = []) { + /** @var array $CFG_GLPI */ + global $CFG_GLPI; + $this->initForm($ID, $options); if (!$this->isNewID($ID)) { - $btn_url = Plugin::getWebDir('fields') . '/front/export_to_yaml.php?id=' . $ID; + $btn_url = $CFG_GLPI['root_doc'] . '/plugins/fields/front/export_to_yaml.php?id=' . $ID; $btn_label = __('Export to YAML', 'fields'); $export_btn = << 0 && !empty($this->fields['subtype'])) { $itemtypes = json_decode($this->fields['itemtypes'], true); $itemtype = array_shift($itemtypes); - $item = new $itemtype(); + $dbu = new DbUtils(); + $item = $dbu->getItemForItemtype($itemtype); $item->getEmpty(); $tabs = self::getSubtypes($item); echo $tabs[$this->fields['subtype']]; @@ -960,41 +1035,44 @@ 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); + $dbu = new DbUtils(); + $item = $dbu->getItemForItemtype($params['itemtype']); + if ($item !== false) { + $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]); + } + } - 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); + } } - } - // 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; } - } - if (!isset($params['subtype'])) { - $params['subtype'] = null; + $out .= Dropdown::showFromArray( + 'subtype', + $tabs, + ['value' => $params['subtype'], + 'width' => '100%', + 'display' => false, + ], + ); + $out .= ""; } - - $out .= Dropdown::showFromArray( - 'subtype', - $tabs, - ['value' => $params['subtype'], - 'width' => '100%', - 'display' => false, - ], - ); - $out .= ""; } } } @@ -1090,7 +1168,7 @@ public static function getEntries($type = 'tab', $full = false): array continue; } - $jsonitemtypes = json_decode($item['itemtypes']); + $jsonitemtypes = PluginFieldsToolbox::decodeJSONItemtypes($item['itemtypes']); //show more info or not foreach ($jsonitemtypes as $v) { if ($full) { @@ -1130,8 +1208,10 @@ public static function getUsedItemtypes($type = 'all', $must_be_active = false) ]); foreach ($iterator as $data) { - $jsonitemtype = json_decode($data['itemtypes']); - $itemtypes = array_merge($itemtypes, $jsonitemtype); + $jsonitemtype = PluginFieldsToolbox::decodeJSONItemtypes($data['itemtypes']); + if (is_array($jsonitemtype)) { + $itemtypes = array_merge($itemtypes, $jsonitemtype); + } } return $itemtypes; @@ -1161,7 +1241,7 @@ public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) 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] = $data['label']; + $tabs_entries[$tab_name] = self::createTabEntry($data['label'], 0, null, PluginFieldsContainer::getIcon()); } } } @@ -1183,7 +1263,7 @@ public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $ //retrieve container for current tab $container = new self(); - $found_c = $container->find(['type' => 'tab', 'name' => Sanitizer::sanitize($tabnum), 'is_active' => 1]); + $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) { @@ -1252,28 +1332,41 @@ public function updateFieldsValues($data, $itemtype, $massiveaction = false) } } - if ($exist === false) { - // add fields data - $obj->add($data); - } else { - // update fields data - $data['id'] = $obj->fields['id']; - $obj->update($data); - } + $container_obj = new PluginFieldsContainer(); + $container_obj->getFromDB($data['plugin_fields_containers_id']); - // Add files and images for richtext fields - $this->addRichTextFiles($obj); + $items_id = $data['items_id']; + $classname = self::getClassname($itemtype, $container_obj->fields['name']); - //construct history on itemtype object (Historical tab) - self::constructHistory( - $obj->input['plugin_fields_containers_id'], - $items_id, - $itemtype, - $obj->input, - $obj, - ); + $dbu = new DbUtils(); + $obj = $dbu->getItemForItemtype($classname); - return true; + if ($obj !== false) { + if ($obj->getFromDBByCrit(['items_id' => $items_id]) === false) { + // add fields data + $obj->add($data); + } else { + // update fields data + $data['id'] = $obj->fields['id']; + $obj->update($data); + } + + // Add files and images for richtext fields + $this->addRichTextFiles($obj); + + //construct history on itemtype object (Historical tab) + self::constructHistory( + $obj->input['plugin_fields_containers_id'], + $items_id, + $itemtype, + $obj->input, + $obj, + ); + + return true; + } + + return false; } private function addRichTextFiles(CommonDBTM $object): void @@ -1325,7 +1418,8 @@ public static function constructHistory( $field_obj ) { // Don't log few itemtypes - $obj = new $itemtype(); + $dbu = new DbUtils(); + $obj = $dbu->getItemForItemtype($itemtype); if ($obj->dohistory == false) { return; } @@ -1477,7 +1571,8 @@ public static function validateValues($data, $itemtype, $massiveaction) if ($container->fields['type'] === 'dom') { $status_value = $data[$status_field_name] ?? null; } else { - $relatedItem = new $itemtype(); + $dbu = new DbUtils(); + $relatedItem = $dbu->getItemForItemtype($itemtype); $status_value = $relatedItem->fields[$status_field_name] ?? null; } // Apply status overrides @@ -1600,7 +1695,7 @@ public static function findContainer($itemtype, $type = 'tab', $subtype = '') } foreach ($itemtypes as $data) { - $dataitemtypes = json_decode($data['itemtypes']); + $dataitemtypes = PluginFieldsToolbox::decodeJSONItemtypes($data['itemtypes']); if (in_array($itemtype, $dataitemtypes) != false) { $id = $data['id']; } @@ -1906,7 +2001,7 @@ public static function getAddSearchOptions($itemtype, $containers_id = false) 'glpi_plugin_fields_containers.label AS container_label', ( Session::isCron() - ? new QueryExpression(sprintf('%s AS %s', READ + CREATE, $DB->quoteName('right'))) + ? new \Glpi\DBAL\QueryExpression(sprintf('%s AS %s', READ + CREATE, $DB->quoteName('right'))) : 'glpi_plugin_fields_profiles.right' ), ], @@ -2156,7 +2251,7 @@ 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'])); + $input['itemtypes'] = json_decode($input['itemtypes']); } else { unset($input['itemtypes']); } diff --git a/inc/containerdisplaycondition.class.php b/inc/containerdisplaycondition.class.php index bd108987..3ce821ff 100644 --- a/inc/containerdisplaycondition.class.php +++ b/inc/containerdisplaycondition.class.php @@ -77,7 +77,7 @@ public static function installBaseData(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->doQuery($query) or die($DB->error()); + $DB->doQuery($query); } return true; @@ -163,6 +163,8 @@ public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) return self::createTabEntry( self::getTypeName(Session::getPluralNumber()), countElementsInTable(self::getTable(), ['plugin_fields_containers_id' => $item->getID()]), + null, + 'ti ti-eye-off', ); } @@ -232,6 +234,9 @@ public static function getFieldName($so_id, $itemtype) public static function showItemtypeFieldForm($itemtype) { + /** @var array $CFG_GLPI */ + global $CFG_GLPI; + $rand = mt_rand(); $out = ''; $out .= Dropdown::showFromArray('search_option', self::removeBlackListedOption(Search::getOptions($itemtype), $itemtype), ['display_emptychoice' => true, 'display' => false, 'rand' => $rand]); @@ -239,7 +244,7 @@ public static function showItemtypeFieldForm($itemtype) $out .= Ajax::updateItemOnSelectEvent( 'dropdown_search_option' . $rand, 'results_condition', - Plugin::getWebDir('fields') . '/ajax/container_display_condition.php', + $CFG_GLPI['root_doc'] . '/plugins/fields/ajax/container_display_condition.php', [ 'search_option_id' => '__VALUE__', 'itemtype' => $itemtype, @@ -292,7 +297,8 @@ public static function showSearchOptionCondition($searchoption_id, $itemtype, ?s case 'impact': case 'urgency': case 'priority': - $twig_params['item'] = new $itemtype(); + $dbu = new DbUtils(); + $twig_params['item'] = $dbu->getItemForItemtype($itemtype); $twig_params['itemtype_field'] = $so['field']; break; case 'global_validation': @@ -316,7 +322,8 @@ public static function getRawValue($searchoption_id, $itemtype, $value) if ($so['datatype'] == 'dropdown' || ($so['datatype'] == 'itemlink' && $so['table'] !== $itemtypetable)) { $dropdown_itemtype = getItemTypeForTable($so['table']); - $dropdown = new $dropdown_itemtype(); + $dbu = new DbUtils(); + $dropdown = $dbu->getItemForItemtype($dropdown_itemtype); if ($dropdown->getFromDB($value)) { $raw_value = $dropdown->fields['name']; } @@ -350,7 +357,8 @@ public static function getRawValue($searchoption_id, $itemtype, $value) public static function removeBlackListedOption($array, $itemtype_class) { - $itemtype_object = new $itemtype_class(); + $dbu = new DbUtils(); + $itemtype_object = $dbu->getItemForItemtype($itemtype_class); $allowed_so = []; //remove "Common" @@ -457,7 +465,6 @@ public function checkCondition($item) case self::SHOW_CONDITION_REGEX: //'regex'; if (self::checkRegex($value)) { - $value = Sanitizer::unsanitize($value); if (preg_match_all($value . 'i', $fields[$searchOption['linkfield']]) > 0) { return false; } diff --git a/inc/field.class.php b/inc/field.class.php index 7f5383d6..1acb2c88 100644 --- a/inc/field.class.php +++ b/inc/field.class.php @@ -92,24 +92,26 @@ public static function installBaseData(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->doQuery($query) or die($DB->error()); + if (!$DB->doQuery($query)) { + throw new \RuntimeException('Error creating plugin_fields_fields table: ' . $DB->error()); + } } $migration->displayMessage("Updating $table"); if (!$DB->fieldExists($table, 'is_active')) { - $migration->addField($table, 'is_active', 'bool', ['value' => 1]); + $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->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]); + $migration->addField($table, 'mandatory', 'bool', ['value' => '0']); } if (!$DB->fieldExists($table, 'multiple')) { - $migration->addField($table, 'multiple', 'bool', ['value' => 0]); + $migration->addField($table, 'multiple', 'bool', ['value' => '0']); } //increase the size of column 'type' (25 to 255) @@ -313,7 +315,7 @@ public function prepareInputForAdd($input) } if (isset($input['allowed_values'])) { - $input['allowed_values'] = Sanitizer::dbEscape(json_encode($input['allowed_values'])); + $input['allowed_values'] = json_encode($input['allowed_values']); } return $input; @@ -431,7 +433,7 @@ public function post_purgeItem() $DB->update( $table, [ - 'ranking' => new QueryExpression($DB->quoteName('ranking') . ' - 1'), + 'ranking' => new \Glpi\DBAL\QueryExpression($DB->quoteName('ranking') . ' - 1'), ], [ 'plugin_fields_containers_id' => $old_container, @@ -510,7 +512,7 @@ public function getNextRanking() global $DB; $iterator = $DB->request([ - 'SELECT' => new \QueryExpression( + 'SELECT' => new \Glpi\DBAL\QueryExpression( 'max(' . $DB->quoteName('ranking') . ') AS ' . $DB->quoteName('rank'), ), 'FROM' => self::getTable(), @@ -547,6 +549,8 @@ public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) self::getTable(), ['plugin_fields_containers_id' => $item->getID()], ), + null, + 'ti ti-forms', ); } @@ -636,7 +640,7 @@ public function showSummary($container) echo ''; $label = !empty($this->fields['label']) ? $this->fields['label'] : NOT_AVAILABLE; - echo "getID()}'>{$label}"; + echo "getID()}'>{$label}"; echo ''; echo '' . $fields_type[$this->fields['type']] . ''; echo '' ; @@ -815,6 +819,9 @@ public function showForm($ID, $options = []) public static function showForTabContainer($c_id, $item) { + /** @var array $CFG_GLPI */ + global $CFG_GLPI; + //profile restriction $right = PluginFieldsProfile::getRightOnContainer($_SESSION['glpiactiveprofile']['id'], $c_id); if ($right < READ) { @@ -825,7 +832,7 @@ public static function showForTabContainer($c_id, $item) //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 ""; echo Html::hidden('plugin_fields_containers_id', ['value' => $c_id]); echo Html::hidden('items_id', ['value' => $item->getID()]); echo Html::hidden('itemtype', ['value' => $item->getType()]); @@ -885,6 +892,9 @@ public static function showDomContainer($id, $item, $type = 'dom', $subtype = '' */ public static function showForTab($params) { + /** @var array $CFG_GLPI */ + global $CFG_GLPI; + $item = $params['item']; $functions = array_column(debug_backtrace(), 'function'); @@ -983,7 +993,7 @@ public static function showForTab($params) echo ''; //JS to trigger any change and check if container need to be display or not - $ajax_url = Plugin::getWebDir('fields') . '/ajax/container.php'; + $ajax_url = $CFG_GLPI['root_doc'] . '/plugins/fields/ajax/container.php'; $items_id = !$item->isNewItem() ? $item->getID() : 0; echo Html::scriptBlock( <<isNewItem()) { //find row for this object with the items_id $classname = PluginFieldsContainer::getClassname($item->getType(), $container_obj->fields['name']); - $obj = new $classname(); + $dbu = new DbUtils(); + $obj = $dbu->getItemForItemtype($classname); $found_values = $obj->find( [ 'plugin_fields_containers_id' => $first_field['plugin_fields_containers_id'], @@ -1157,12 +1168,15 @@ public static function prepareHtmlFields( $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; + $dbu = new DbUtils(); + $object = $dbu->getItemForItemtype($dropdown_class); + if ($object !== false) { + if ($object->maybeDeleted()) { + $field['dropdown_condition']['is_deleted'] = false; + } + if ($object->maybeActive()) { + $field['dropdown_condition']['is_active'] = true; + } } } @@ -1277,6 +1291,7 @@ public static function showSingle($itemtype, $searchOption, $massiveaction = fal 'fields.is_readonly', 'fields.multiple', 'fields.default_value', + 'fields.mandatory', ], 'FROM' => self::getTable() . ' AS fields', 'LEFT JOIN' => [ @@ -1311,11 +1326,13 @@ public static function showSingle($itemtype, $searchOption, $massiveaction = fal 'is_readonly' => $data['is_readonly'], 'default_value' => $data['default_value'], 'multiple' => $data['multiple'], + 'mandatory' => $data['mandatory'], ], ]; //show field - $item = new $itemtype(); + $dbu = new DbUtils(); + $item = $dbu->getItemForItemtype($itemtype); $item->getEmpty(); echo self::prepareHtmlFields($fields, $item, true, false, $massiveaction); @@ -1411,7 +1428,7 @@ 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'])); + $input['allowed_values'] = json_decode($input['allowed_values']); } else { unset($input['allowed_values']); } diff --git a/inc/labeltranslation.class.php b/inc/labeltranslation.class.php index a8b844df..54cae675 100644 --- a/inc/labeltranslation.class.php +++ b/inc/labeltranslation.class.php @@ -69,7 +69,9 @@ public static function installBaseData(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->doQuery($query) or die($DB->error()); + if (!$DB->doQuery($query)) { + throw new \RuntimeException('Error creating plugin_fields_labeltranslations table: ' . $DB->error()); + } } if ($DB->fieldExists($table, 'plugin_fields_itemtype')) { @@ -130,7 +132,12 @@ public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) ], ); - return self::createTabEntry(self::getTypeName($nb), $nb); + return self::createTabEntry( + self::getTypeName($nb), + $nb, + null, + 'ti ti-language', + ); } public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) @@ -153,6 +160,9 @@ public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $ */ public static function showTranslations(CommonDBTM $item) { + /** @var array $CFG_GLPI */ + global $CFG_GLPI; + $canedit = $item->can($item->getID(), UPDATE); $rand = mt_rand(); if ($canedit) { @@ -167,7 +177,7 @@ public static function showTranslations(CommonDBTM $item) echo Html::scriptBlock(' addTranslation' . $item->getID() . $rand . ' = function() { $("#viewtranslation' . $item->getID() . $rand . '").load( - "' . Plugin::getWebDir('fields') . '/ajax/viewtranslations.php", + "' . $CFG_GLPI['root_doc'] . '/plugins/fields/ajax/viewtranslations.php", ' . json_encode($ajax_params) . ' ); }; @@ -222,7 +232,7 @@ public static function showTranslations(CommonDBTM $item) echo Html::scriptBlock(' viewEditTranslation' . $data['id'] . $rand . ' = function() { $("#viewtranslation' . $item->getID() . $rand . '").load( - "' . Plugin::getWebDir('fields') . '/ajax/viewtranslations.php", + "' . $CFG_GLPI['root_doc'] . '/plugins/fields/ajax/viewtranslations.php", ' . json_encode($ajax_params) . ' ); }; diff --git a/inc/profile.class.php b/inc/profile.class.php index d6c72c3a..587eaf66 100644 --- a/inc/profile.class.php +++ b/inc/profile.class.php @@ -68,7 +68,9 @@ public static function installBaseData(Migration $migration, $version) 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->doQuery($query) or die($DB->error()); + if (!$DB->doQuery($query)) { + throw new \RuntimeException('Error creating plugin_fields_profiles table: ' . $DB->error()); + } } return true; @@ -86,7 +88,12 @@ public static function uninstall() public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { - return self::createTabEntry(_n('Profile', 'Profiles', 2)); + return self::createTabEntry( + _n('Profile', 'Profiles', 2), + 0, + null, + 'ti ti-user-check', + ); } public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) diff --git a/inc/statusoverride.class.php b/inc/statusoverride.class.php index 73e52581..cc68e194 100644 --- a/inc/statusoverride.class.php +++ b/inc/statusoverride.class.php @@ -69,7 +69,9 @@ public static function installBaseData(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->doQuery($query) or die($DB->error()); + if (!$DB->doQuery($query)) { + throw new \RuntimeException('Error creating plugin_fields_statusoverrides table: ' . $DB->error()); + } } return true; @@ -93,7 +95,12 @@ public static function getTypeName($nb = 0) public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { if ($item instanceof CommonDBTM) { - return self::createTabEntry(self::getTypeName(), self::countOverridesForContainer($item->getID())); + return self::createTabEntry( + self::getTypeName(), + self::countOverridesForContainer($item->getID()), + null, + 'ti ti-adjustments-alt', + ); } return ''; } diff --git a/inc/toolbox.class.php b/inc/toolbox.class.php index 91c412d0..8f4e6da0 100644 --- a/inc/toolbox.class.php +++ b/inc/toolbox.class.php @@ -308,7 +308,7 @@ public static function getGlpiItemtypes(): array NetworkPort::class, Notification::class, NotificationTemplate::class, - ComputerVirtualMachine::class, + ItemVirtualMachine::class, ]; $all_itemtypes = [ @@ -361,4 +361,14 @@ public static function getGlpiItemtypes(): array return $all_itemtypes; } + + public static function decodeJSONItemtypes(string $itemtypes, ?bool $associative = null) + { + $jsonitemtype = json_decode($itemtypes, $associative); + if ($jsonitemtype === null && json_last_error() !== JSON_ERROR_NONE) { + $fixed_json = str_replace('\\', '\\\\', $itemtypes); + $jsonitemtype = json_decode($fixed_json, $associative); + } + return $jsonitemtype; + } } diff --git a/phpstan.neon b/phpstan.neon index 455f2e74..3054ca3d 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -3,7 +3,8 @@ parameters: maximumNumberOfProcesses: 2 level: 5 bootstrapFiles: - - ../../inc/based_config.php + - ../../stubs/glpi_constants.php + - ../../vendor/autoload.php paths: - inc - front @@ -15,5 +16,4 @@ parameters: - ../../src stubFiles: - ../../stubs/glpi_constants.php -rules: - - GlpiProject\Tools\PHPStan\Rules\GlobalVarTypeRule + diff --git a/plugin.xml b/plugin.xml index 38e82b8d..a98f02f2 100644 --- a/plugin.xml +++ b/plugin.xml @@ -104,9 +104,9 @@ Il existe un [script de migration](https://github.com/pluginsGLPI/customfields/b https://github.com/pluginsGLPI/fields/releases/download/1.21.23/glpi-fields-1.21.23.tar.bz2 - 1.22.0-beta3 + 1.22.0 ~11.0.0 - https://github.com/pluginsGLPI/fields/releases/download/1.22.0-beta3/glpi-fields-1.22.0-beta3.tar.bz2 + https://github.com/pluginsGLPI/fields/releases/download/1.22.0/glpi-fields-1.22.0.tar.bz2 1.21.22 diff --git a/css/fields.css b/public/css/fields.css similarity index 100% rename from css/fields.css rename to public/css/fields.css diff --git a/js/drag-field-row.js b/public/js/drag-field-row.js similarity index 100% rename from js/drag-field-row.js rename to public/js/drag-field-row.js diff --git a/lib/redips-drag-min.js b/public/lib/redips-drag-min.js similarity index 100% rename from lib/redips-drag-min.js rename to public/lib/redips-drag-min.js diff --git a/setup.php b/setup.php index 619c27dc..55aebf66 100644 --- a/setup.php +++ b/setup.php @@ -28,18 +28,21 @@ * ------------------------------------------------------------------------- */ -define('PLUGIN_FIELDS_VERSION', '1.21.23'); +/** @var array $CFG_GLPI */ +global $CFG_GLPI; + +define('PLUGIN_FIELDS_VERSION', '1.22.0'); // Minimal GLPI version, inclusive -define('PLUGIN_FIELDS_MIN_GLPI', '10.0.11'); +define('PLUGIN_FIELDS_MIN_GLPI', '11.0.0'); // Maximum GLPI version, exclusive -define('PLUGIN_FIELDS_MAX_GLPI', '10.0.99'); +define('PLUGIN_FIELDS_MAX_GLPI', '11.0.99'); if (!defined('PLUGINFIELDS_DIR')) { define('PLUGINFIELDS_DIR', Plugin::getPhpDir('fields')); } if (!defined('PLUGINFIELDS_WEB_DIR')) { - define('PLUGINFIELDS_WEB_DIR', Plugin::getWebDir('fields')); + define('PLUGINFIELDS_WEB_DIR', $CFG_GLPI['root_doc'] . '/plugins/fields'); } if (!defined('PLUGINFIELDS_DOC_DIR')) { @@ -133,7 +136,7 @@ function plugin_init_fields() //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')) { + if (!$debug && file_exists(__DIR__ . '/public/css/fields.min.css')) { $PLUGIN_HOOKS['add_css']['fields'][] = 'css/fields.min.css'; } else { $PLUGIN_HOOKS['add_css']['fields'][] = 'css/fields.css'; @@ -149,7 +152,7 @@ function plugin_init_fields() plugin_fields_script_endswith('container.form.php') ) { $PLUGIN_HOOKS['add_javascript']['fields'][] = 'lib/redips-drag-min.js'; - if (!$debug && file_exists(__DIR__ . '/js/drag-field-row.min.js')) { + if (!$debug && file_exists(__DIR__ . '/public/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'; @@ -347,13 +350,14 @@ function plugin_fields_exportBlockAsYaml($container_id = null) switch ($field['type']) { case 'dropdown': - $obj = new $itemtype(); + $dbu = new DbUtils(); + $obj = $dbu->getItemForItemtype($itemtype); $obj->getEmpty(); $dropdown_itemtype = PluginFieldsDropdown::getClassname($field['name']); $tmp_field['xml_node'] = strtoupper(getForeignKeyFieldForItemType($dropdown_itemtype)); - $dropdown_obj = new $dropdown_itemtype(); + $dropdown_obj = $dbu->getItemForItemtype($dropdown_itemtype); $dropdown_datas = $dropdown_obj->find(); $datas = []; foreach ($dropdown_datas as $value) { diff --git a/templates/container.class.tpl b/templates/container.class.tpl index 58bd527f..5fb10fd2 100644 --- a/templates/container.class.tpl +++ b/templates/container.class.tpl @@ -26,11 +26,11 @@ class %%CLASSNAME%% extends PluginFieldsAbstractContainerInstance UNIQUE INDEX `itemtype_item_container` (`itemtype`, `items_id`, `plugin_fields_containers_id`) ) ENGINE=InnoDB DEFAULT CHARSET={$default_charset} COLLATE={$default_collation} ROW_FORMAT=DYNAMIC;"; - $DB->query($query) or die ($DB->error()); + $DB->doQuery($query); } else { // 1.15.4 // fix nullable state for 'glpi_item' field - $result = $DB->query("SHOW COLUMNS FROM `$table`"); + $result = $DB->doQuery("SHOW COLUMNS FROM `$table`"); if ($result && $DB->numrows($result) > 0) { $changed = false; while ($data = $DB->fetchAssoc($result)) { @@ -51,7 +51,7 @@ class %%CLASSNAME%% extends PluginFieldsAbstractContainerInstance * This block ensures that the 'entities_id' field is created and populated if it * associated item type requires entity assignment */ - if (getItemForItemtype("%%ITEMTYPE%%")->isEntityAssign() && !$DB->fieldExists($table, 'entities_id')) { + if (getItemForItemtype('%%ITEMTYPE%%')->isEntityAssign() && !$DB->fieldExists($table, 'entities_id')) { $migration->addField($table, 'entities_id', 'fkey', ['after' => 'plugin_fields_containers_id']); $migration->addKey($table, 'entities_id'); $migration->executeMigration(); @@ -107,7 +107,7 @@ class %%CLASSNAME%% extends PluginFieldsAbstractContainerInstance * associated item type requires recursive assignment */ if ( - getItemForItemtype("%%ITEMTYPE%%")->maybeRecursive() + getItemForItemtype('%%ITEMTYPE%%')->maybeRecursive() && !$DB->fieldExists($table, 'is_recursive') && $DB->fieldExists($table, 'entities_id')) { $migration->addField($table, 'is_recursive', 'bool', ['after' => 'entities_id']); @@ -163,28 +163,6 @@ class %%CLASSNAME%% extends PluginFieldsAbstractContainerInstance global $DB; $obj = new self(); - return $DB->query("DROP TABLE IF EXISTS `".$obj->getTable()."`"); - } - - static function addField($fieldname, $type, array $options) { - $migration = new PluginFieldsMigration(0); - - $sql_fields = PluginFieldsMigration::getSQLFields($fieldname, $type, $options); - foreach ($sql_fields as $sql_field_name => $sql_field_type) { - $migration->addField(self::getTable(), $sql_field_name, $sql_field_type); - } - - $migration->migrationOneTable(self::getTable()); - } - - static function removeField($fieldname, $type) { - $migration = new PluginFieldsMigration(0); - - $sql_fields = PluginFieldsMigration::getSQLFields($fieldname, $type); - foreach (array_keys($sql_fields) as $sql_field_name) { - $migration->dropField(self::getTable(), $sql_field_name); - } - - $migration->migrationOneTable(self::getTable()); + return $DB->doQuery("DROP TABLE IF EXISTS `".$obj->getTable()."`"); } } diff --git a/templates/container_display_conditions.html.twig b/templates/container_display_conditions.html.twig index 6e95ca43..bcd543ce 100644 --- a/templates/container_display_conditions.html.twig +++ b/templates/container_display_conditions.html.twig @@ -114,7 +114,7 @@ glpi_ajax_dialog( { title: __('Edit condition to hide block', 'fields'), - url: CFG_GLPI.root_doc + '/' + GLPI_PLUGINS_PATH.fields + '/ajax/container_display_condition.php', + url: CFG_GLPI.root_doc + '/plugins/fields/ajax/container_display_condition.php', method: 'get', params: { action: 'get_edit_form', @@ -133,7 +133,7 @@ glpi_ajax_dialog( { title: __('Add condition to hide block', 'fields'), - url: CFG_GLPI.root_doc + '/' + GLPI_PLUGINS_PATH.fields + '/ajax/container_display_condition.php', + url: CFG_GLPI.root_doc + '/plugins/fields/ajax/container_display_condition.php', method: 'get', params: { action: 'get_add_form', diff --git a/templates/dropdown.class.tpl b/templates/dropdown.class.tpl index 77929514..93a23171 100644 --- a/templates/dropdown.class.tpl +++ b/templates/dropdown.class.tpl @@ -42,7 +42,7 @@ class %%CLASSNAME%% extends CommonTreeDropdown { KEY `plugin_fields_%%FIELDNAME%%dropdowns_id` (`plugin_fields_%%FIELDNAME%%dropdowns_id`) ) ENGINE=InnoDB DEFAULT CHARSET={$default_charset} COLLATE={$default_collation} ROW_FORMAT=DYNAMIC;"; - $DB->query($query) or die ($DB->error()); + $DB->doQuery($query); } } @@ -50,7 +50,7 @@ class %%CLASSNAME%% extends CommonTreeDropdown { global $DB; $obj = new self(); - return $DB->query("DROP TABLE IF EXISTS `".$obj->getTable()."`"); + return $DB->doQuery("DROP TABLE IF EXISTS `".$obj->getTable()."`"); } /** diff --git a/templates/fields.html.twig b/templates/fields.html.twig index fa568b2c..0a8b43a7 100644 --- a/templates/fields.html.twig +++ b/templates/fields.html.twig @@ -43,7 +43,7 @@ {% set type = field['type'] %} {% set name = field['name'] %} {% set label = field['label'] %} - {% set value = item.input[name] ?: field['value'] %} + {% set value = item.input[name]|default(field['value']) %} {% set readonly = field['is_readonly'] %} {% set rand = random() %} @@ -139,7 +139,7 @@
{% endif %} - {{ macros.dropdownArrayField(itemtype_prefix ~ name, value.itemtype, field['allowed_values'], label, field_options|merge({ + {{ macros.dropdownArrayField(itemtype_prefix ~ name, value.itemtype|default(''), field['allowed_values'], label, field_options|merge({ 'rand': rand, 'display_emptychoice': true, })) }} @@ -167,9 +167,9 @@
- {% if value.itemtype != '' %} - {{ macros.dropdownField(value.itemtype, items_id_prefix ~ name, value.items_id, ' ', field_options|merge({ - 'entity': value.itemtype == 'User' ? -1 : item.getEntityID(), + {% if value.itemtype|default('') != '' %} + {{ macros.dropdownField(value.itemtype, items_id_prefix ~ name, value.items_id|default(''), ' ', field_options|merge({ + 'entity': value.itemtype|default('') == 'User' ? -1 : item.getEntityID(), 'rand': rand, 'right': 'all', 'displaywith': ['otherserial', 'serial'], diff --git a/templates/forms/status_override.html.twig b/templates/forms/status_override.html.twig index 85b344d6..9c52a5a8 100644 --- a/templates/forms/status_override.html.twig +++ b/templates/forms/status_override.html.twig @@ -39,7 +39,7 @@ {% set itemtype = override.fields['itemtype']|default(container_itemtypes|keys|first) %} {{ fields.dropdownArrayField('itemtype', itemtype, container_itemtypes, __('Item type')) }} - {{ fields.dropdownArrayField('plugin_fields_fields_id', override.fields['plugin_fields_fields_id'], container_fields, __('Field', 'fields')) }} + {{ fields.dropdownArrayField('plugin_fields_fields_id', override.fields['plugin_fields_fields_id']|default(null), container_fields, __('Field', 'fields')) }} {% set status_field_html %}
@@ -58,7 +58,7 @@ {{ _x('button', 'Add') }} {% else %} - +