From 273998ba2d67ba8750a928325bc4000cf06cb71e Mon Sep 17 00:00:00 2001 From: Rom1-B <8530352+Rom1-B@users.noreply.github.com> Date: Tue, 18 Aug 2026 15:01:51 +0200 Subject: [PATCH 1/7] feature/glpi-12.0 --- .github/workflows/continuous-integration.yml | 2 +- CHANGELOG.md | 4 + Makefile | 1 + ajax/billactions.php | 2 +- ajax/dropdownReference.php | 2 +- ajax/dropdownSupplier.php | 2 +- composer.json | 3 - composer.lock | 876 +------------------ front/bill.form.php | 2 +- front/bill.php | 2 +- front/config.form.php | 2 +- front/order.php | 2 +- front/profile.form.php | 2 +- hook.php | 7 +- inc/accountsection.class.php | 2 +- inc/analyticnature.class.php | 2 +- inc/bill.class.php | 4 +- inc/billstate.class.php | 2 +- inc/billtype.class.php | 2 +- inc/config.class.php | 6 +- inc/link.class.php | 16 +- inc/order.class.php | 38 +- inc/order_item.class.php | 22 +- inc/order_supplier.class.php | 8 +- inc/orderpayment.class.php | 2 +- inc/orderstate.class.php | 2 +- inc/ordertax.class.php | 2 +- inc/ordertype.class.php | 2 +- inc/other.class.php | 2 +- inc/othertype.class.php | 2 +- inc/preference.class.php | 2 +- inc/profile.class.php | 2 +- inc/reception.class.php | 20 +- inc/reference.class.php | 8 +- inc/reference_supplier.class.php | 8 +- inc/referencefree.class.php | 4 +- inc/surveysupplier.class.php | 8 +- setup.php | 6 +- templates/order_getitems.html.twig | 1 - 39 files changed, 106 insertions(+), 976 deletions(-) create mode 100644 Makefile diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 16370820b8..9f751ebeee 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: "11.0.x" + glpi-version: "12.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 9ee8a97de3..a677c5171a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [UNRELEASED] +### Added + +- GLPI 12 compatibility + ### Fixed - Fix `Take item delivery` and `Cancel reception` action for `Software License` diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000..ef1bed5ac8 --- /dev/null +++ b/Makefile @@ -0,0 +1 @@ +include ../../PluginsMakefile.mk diff --git a/ajax/billactions.php b/ajax/billactions.php index 1287c21992..225d2960c2 100644 --- a/ajax/billactions.php +++ b/ajax/billactions.php @@ -28,7 +28,7 @@ * ------------------------------------------------------------------------- */ -Session::checkRight("plugin_order_bill", READ); +Session::checkRight(PluginOrderBill::$rightname, READ); header("Content-Type: text/html; charset=UTF-8"); diff --git a/ajax/dropdownReference.php b/ajax/dropdownReference.php index 33595b0aff..a0bea7b6d9 100644 --- a/ajax/dropdownReference.php +++ b/ajax/dropdownReference.php @@ -33,7 +33,7 @@ include_once(__DIR__ . "/../../../inc/includes.php"); -Session::checkRight("plugin_order_reference", READ); +Session::checkRight(PluginOrderReference::$rightname, READ); // Make a select box for references if (isset($_POST["itemtype"])) { diff --git a/ajax/dropdownSupplier.php b/ajax/dropdownSupplier.php index 43d524dc40..2b142d7507 100644 --- a/ajax/dropdownSupplier.php +++ b/ajax/dropdownSupplier.php @@ -35,7 +35,7 @@ Html::header_nocache(); } -Session::checkRight("contact_enterprise", READ); +Session::checkRight(Contact::$rightname, READ); // Make a select box if (isset($_POST["suppliers_id"])) { diff --git a/composer.json b/composer.json index 263a787aae..0a45531210 100644 --- a/composer.json +++ b/composer.json @@ -4,9 +4,6 @@ "php": ">=8.2", "sboden/odtphp": "^3.2" }, - "require-dev": { - "glpi-project/tools": "^0.8" - }, "config": { "optimize-autoloader": true, "platform": { diff --git a/composer.lock b/composer.lock index 7295f72ee9..5af9ec3850 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": "2bde386e0433e43036c970ecd142d686", + "content-hash": "9983e2a4f2c2e3a6e4da04c757167a2d", "packages": [ { "name": "sboden/odtphp", @@ -61,879 +61,7 @@ "time": "2025-07-24T20:26:09+00:00" } ], - "packages-dev": [ - { - "name": "glpi-project/tools", - "version": "0.8.3", - "source": { - "type": "git", - "url": "https://github.com/glpi-project/tools.git", - "reference": "8ea2a7d4702a858f4b0360ba7d4f1841a5e77026" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/glpi-project/tools/zipball/8ea2a7d4702a858f4b0360ba7d4f1841a5e77026", - "reference": "8ea2a7d4702a858f4b0360ba7d4f1841a5e77026", - "shasum": "" - }, - "require": { - "symfony/console": "^5.4 || ^6.0", - "twig/twig": "^3.3" - }, - "require-dev": { - "nikic/php-parser": "^4.13", - "phpstan/phpstan-src": "^1.10" - }, - "bin": [ - "bin/extract-locales", - "bin/licence-headers-check", - "tools/plugin-release" - ], - "type": "library", - "autoload": { - "psr-4": { - "GlpiProject\\Tools\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "GPL-3.0-or-later" - ], - "authors": [ - { - "name": "Teclib'", - "email": "glpi@teclib.com", - "homepage": "http://teclib-group.com" - } - ], - "description": "Various tools for GLPI and its plugins", - "keywords": [ - "glpi", - "plugins", - "tools" - ], - "support": { - "issues": "https://github.com/glpi-project/tools/issues", - "source": "https://github.com/glpi-project/tools" - }, - "time": "2025-10-14T10:26:06+00:00" - }, - { - "name": "psr/container", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" - }, - "dist": { - "type": "zip", - "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/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/2.0.2" - }, - "time": "2021-11-05T16:47:00+00:00" - }, - { - "name": "symfony/console", - "version": "v6.4.43", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "3b643aa587acbc42f967a429af088a56ed8f046d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/3b643aa587acbc42f967a429af088a56ed8f046d", - "reference": "3b643aa587acbc42f967a429af088a56ed8f046d", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^5.4|^6.0|^7.0" - }, - "conflict": { - "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|3.0" - }, - "require-dev": { - "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": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Eases the creation of beautiful and testable command line interfaces", - "homepage": "https://symfony.com", - "keywords": [ - "cli", - "command-line", - "console", - "terminal" - ], - "support": { - "source": "https://github.com/symfony/console/tree/v6.4.43" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "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": "2026-07-26T14:44:19+00:00" - }, - { - "name": "symfony/deprecation-contracts", - "version": "v3.7.1", - "source": { - "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/f3202fa1b5097b0af062dc978b32ecf63404e31d", - "reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/contracts", - "name": "symfony/contracts" - }, - "branch-alias": { - "dev-main": "3.7-dev" - } - }, - "autoload": { - "files": [ - "function.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "A generic function and convention to trigger deprecation notices", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.7.1" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "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": "2026-06-05T06:23:12+00:00" - }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.37.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "141046a8f9477948ff284fa65be2095baafb94f2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/141046a8f9477948ff284fa65be2095baafb94f2", - "reference": "141046a8f9477948ff284fa65be2095baafb94f2", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "provide": { - "ext-ctype": "*" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], - "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.37.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "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": "2026-04-10T16:19:22+00:00" - }, - { - "name": "symfony/polyfill-intl-grapheme", - "version": "v1.41.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/bb899c1db0aa8127dc3afe8cda4a67eb24915f8d", - "reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Grapheme\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's grapheme_* functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "grapheme", - "intl", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.41.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "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": "2026-07-28T08:25:59+00:00" - }, - { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.38.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "2d446c214bdbe5b71bde5011b060a05fece3ae6b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/2d446c214bdbe5b71bde5011b060a05fece3ae6b", - "reference": "2d446c214bdbe5b71bde5011b060a05fece3ae6b", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Normalizer\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's Normalizer class and related functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "intl", - "normalizer", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.38.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "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": "2026-05-25T13:48:31+00:00" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.38.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6", - "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6", - "shasum": "" - }, - "require": { - "ext-iconv": "*", - "php": ">=7.2" - }, - "provide": { - "ext-mbstring": "*" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.38.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "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": "2026-05-27T06:59:30+00:00" - }, - { - "name": "symfony/service-contracts", - "version": "v3.7.1", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "c0a284bab1ed8aa0417e3d69250ab437739563a0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/c0a284bab1ed8aa0417e3d69250ab437739563a0", - "reference": "c0a284bab1ed8aa0417e3d69250ab437739563a0", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.5|^3" - }, - "conflict": { - "ext-psr": "<1.1|>=2" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/contracts", - "name": "symfony/contracts" - }, - "branch-alias": { - "dev-main": "3.7-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Service\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to writing services", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.7.1" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "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": "2026-06-16T09:55:08+00:00" - }, - { - "name": "symfony/string", - "version": "v7.4.15", - "source": { - "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "e394af32256bf9e7bf80849d95e589167c10097b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/e394af32256bf9e7bf80849d95e589167c10097b", - "reference": "e394af32256bf9e7bf80849d95e589167c10097b", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3.0", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.33", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/translation-contracts": "<2.5" - }, - "require-dev": { - "symfony/emoji": "^7.1|^8.0", - "symfony/http-client": "^6.4|^7.0|^8.0", - "symfony/intl": "^6.4|^7.0|^8.0", - "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^6.4|^7.0|^8.0" - }, - "type": "library", - "autoload": { - "files": [ - "Resources/functions.php" - ], - "psr-4": { - "Symfony\\Component\\String\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", - "homepage": "https://symfony.com", - "keywords": [ - "grapheme", - "i18n", - "string", - "unicode", - "utf-8", - "utf8" - ], - "support": { - "source": "https://github.com/symfony/string/tree/v7.4.15" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "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": "2026-07-28T07:33:02+00:00" - }, - { - "name": "twig/twig", - "version": "v3.28.0", - "source": { - "type": "git", - "url": "https://github.com/twigphp/Twig.git", - "reference": "597c12ed286fb9d1701a36684ce6e0cbe28ebc8b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/597c12ed286fb9d1701a36684ce6e0cbe28ebc8b", - "reference": "597c12ed286fb9d1701a36684ce6e0cbe28ebc8b", - "shasum": "" - }, - "require": { - "php": ">=8.1.0", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-ctype": "^1.8", - "symfony/polyfill-mbstring": "^1.3" - }, - "require-dev": { - "php-cs-fixer/shim": "^3.0@stable", - "phpstan/phpstan": "^2.0@stable", - "psr/container": "^1.0|^2.0", - "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0" - }, - "type": "library", - "autoload": { - "files": [ - "src/Resources/core.php", - "src/Resources/debug.php", - "src/Resources/escaper.php", - "src/Resources/string_loader.php" - ], - "psr-4": { - "Twig\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" - }, - { - "name": "Twig Team", - "role": "Contributors" - }, - { - "name": "Armin Ronacher", - "email": "armin.ronacher@active-4.com", - "role": "Project Founder" - } - ], - "description": "Twig, the flexible, fast, and secure template language for PHP", - "homepage": "https://twig.symfony.com", - "keywords": [ - "templating" - ], - "support": { - "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.28.0" - }, - "funding": [ - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/twig/twig", - "type": "tidelift" - } - ], - "time": "2026-07-03T20:44:34+00:00" - } - ], + "packages-dev": [], "aliases": [], "minimum-stability": "stable", "stability-flags": {}, diff --git a/front/bill.form.php b/front/bill.form.php index 8bb949881b..fade990cf4 100644 --- a/front/bill.form.php +++ b/front/bill.form.php @@ -93,7 +93,7 @@ Html::back(); } -Session::checkRight("plugin_order_bill", READ); +Session::checkRight(PluginOrderBill::$rightname, READ); Html::header(PluginOrderBill::getTypeName(), $_SERVER['PHP_SELF'], "management", "PluginOrderMenu", "bill"); if (isset($_REQUEST['id'])) { diff --git a/front/bill.php b/front/bill.php index a3b0c2b8cc..813a90c93e 100644 --- a/front/bill.php +++ b/front/bill.php @@ -28,7 +28,7 @@ * ------------------------------------------------------------------------- */ -Session::checkRight("plugin_order_bill", READ); +Session::checkRight(PluginOrderBill::$rightname, READ); Html::header(PluginOrderBill::getTypeName(), $_SERVER['PHP_SELF'], "management", "PluginOrderMenu", "bill"); diff --git a/front/config.form.php b/front/config.form.php index 78faf46627..0607409ba2 100644 --- a/front/config.form.php +++ b/front/config.form.php @@ -40,7 +40,7 @@ } else { Html::header(__s("Orders", "order"), $_SERVER['PHP_SELF'], "management", "PluginOrderMenu", "order"); - Session::checkRight("config", UPDATE); + Session::checkRight(Config::$rightname, UPDATE); $config->showForm(1); Html::footer(); diff --git a/front/order.php b/front/order.php index 8711a2b1aa..0a1eb07b0e 100644 --- a/front/order.php +++ b/front/order.php @@ -42,7 +42,7 @@ "order", ); -if (PluginOrderOrder::canView() || Session::haveRight("config", UPDATE)) { +if (PluginOrderOrder::canView() || Session::haveRight(Config::$rightname, UPDATE)) { Search::show("PluginOrderOrder"); } else { echo "


isInstalled('order') && $plugin->isActivated('order') && Session::haveRight("plugin_order_order", READ) && in_array($itemtype, PluginOrderOrder_Item::getClasses(true))) { + if ( + $plugin->isInstalled('order') + && $plugin->isActivated('order') + && Session::haveRight(PluginOrderOrder::$rightname, READ) + && in_array($itemtype, PluginOrderOrder_Item::getClasses(true)) + ) { $sopt[3160]['table'] = 'glpi_plugin_order_orders'; $sopt[3160]['field'] = 'name'; $sopt[3160]['linkfield'] = ''; diff --git a/inc/accountsection.class.php b/inc/accountsection.class.php index dde22de35c..a7c4e74500 100644 --- a/inc/accountsection.class.php +++ b/inc/accountsection.class.php @@ -32,7 +32,7 @@ class PluginOrderAccountsection extends CommonDropdown { - public static $rightname = 'plugin_order_order'; + public static string $rightname = 'plugin_order_order'; public static function getTypeName($nb = 0) { diff --git a/inc/analyticnature.class.php b/inc/analyticnature.class.php index 57dec6e214..b991120fa9 100644 --- a/inc/analyticnature.class.php +++ b/inc/analyticnature.class.php @@ -32,7 +32,7 @@ class PluginOrderAnalyticnature extends CommonDropdown { - public static $rightname = 'plugin_order_order'; + public static string $rightname = 'plugin_order_order'; public static function getTypeName($nb = 0) { diff --git a/inc/bill.class.php b/inc/bill.class.php index 773f982e62..c0239ba5c4 100644 --- a/inc/bill.class.php +++ b/inc/bill.class.php @@ -32,9 +32,9 @@ class PluginOrderBill extends CommonDropdown { - public static $rightname = 'plugin_order_bill'; + public static string $rightname = 'plugin_order_bill'; - public $dohistory = true; + public bool $dohistory = true; public $first_level_menu = "plugins"; diff --git a/inc/billstate.class.php b/inc/billstate.class.php index 14b09fa49d..4be48cadff 100644 --- a/inc/billstate.class.php +++ b/inc/billstate.class.php @@ -36,7 +36,7 @@ class PluginOrderBillState extends CommonDropdown public const PAID = 1; - public static $rightname = 'plugin_order_bill'; + public static string $rightname = 'plugin_order_bill'; public static function getTypeName($nb = 0) diff --git a/inc/billtype.class.php b/inc/billtype.class.php index 93dc5f2e62..7a4baf2130 100644 --- a/inc/billtype.class.php +++ b/inc/billtype.class.php @@ -32,7 +32,7 @@ class PluginOrderBillType extends CommonDropdown { - public static $rightname = 'plugin_order_bill'; + public static string $rightname = 'plugin_order_bill'; public static function getTypeName($nb = 0) diff --git a/inc/config.class.php b/inc/config.class.php index 8e170183e9..5e53cfab48 100644 --- a/inc/config.class.php +++ b/inc/config.class.php @@ -32,7 +32,7 @@ class PluginOrderConfig extends CommonDBTM { - public static $rightname = 'config'; + public static string $rightname = 'config'; public const CONFIG_NEVER = 0; @@ -53,13 +53,13 @@ public function __construct() public static function canView(): bool { - return Session::haveRight('config', READ); + return Session::haveRight(Config::$rightname, READ); } public static function canCreate(): bool { - return Session::haveRight('config', UPDATE); + return Session::haveRight(Config::$rightname, UPDATE); } diff --git a/inc/link.class.php b/inc/link.class.php index e66b6a16d9..35185be4b2 100644 --- a/inc/link.class.php +++ b/inc/link.class.php @@ -33,15 +33,15 @@ class PluginOrderLink extends CommonDBChild { - public static $rightname = 'plugin_order_order'; + public static string $rightname = 'plugin_order_order'; - public $dohistory = true; + public bool $dohistory = true; - public static $itemtype = 'PluginOrderOrder'; + public static string $itemtype = 'PluginOrderOrder'; - public static $items_id = 'plugin_order_orders_id'; + public static string $items_id = 'plugin_order_orders_id'; - public static $checkParentRights = self::DONT_CHECK_ITEM_RIGHTS; + public static int $checkParentRights = self::DONT_CHECK_ITEM_RIGHTS; public static function getTypeName($nb = 0) @@ -639,7 +639,7 @@ public static function processMassiveActionsForOneItemtype( // For consumables and cartridges, createLinkWithItem creates a new item // (glpi_consumables/glpi_cartridges) for each selected detail line; // therefore, multiple items can be linked to the same reference item at once - $allow_multiple_link = isset($ma->POST['add_items']) && $ma->POST['add_items'] !== [] && array_reduce( + $allow_multiple_link = $ma->POST['add_items'] !== [] && array_reduce( $ma->POST['add_items'], fn($carry, $data) => $carry && in_array( $data['itemtype'] ?? '', @@ -1446,7 +1446,7 @@ public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) if ( $item instanceof PluginOrderOrder && $item->checkIfDetailExists($item->getID(), true) - && Session::haveRight('plugin_order_order', READ) + && Session::haveRight(PluginOrderOrder::$rightname, READ) ) { return self::createTabEntry( _sn("Associated item", "Associated items", 2), @@ -1515,7 +1515,7 @@ public static function copyDocuments($itemtype, $items_id, $orders_id, $entity) 'sha1sum' => $document->fields['sha1sum'], ], ); - if (empty($found_docs)) { + if ($found_docs === []) { $tmpdoc = $document->fields; $tmpdoc['entities_id'] = $entity; unset($tmpdoc['id']); diff --git a/inc/order.class.php b/inc/order.class.php index 15f6e1be35..341f98c2cf 100644 --- a/inc/order.class.php +++ b/inc/order.class.php @@ -40,17 +40,17 @@ class PluginOrderOrder extends CommonDBTM { use Clonable; - public static $rightname = 'plugin_order_order'; + public static string $rightname = 'plugin_order_order'; public $is_template = true; - public $dohistory = true; + public bool $dohistory = true; protected $usenotepadrights = true; - protected $usenotepad = true; + protected bool $usenotepad = true; - public static $forward_entity_to = [ + public static array $forward_entity_to = [ "PluginOrderOrder_Item", "PluginOrderOrder_Supplier", "PluginOrderSurveySupplier", @@ -108,37 +108,37 @@ public function getState() public static function canCancel() { - return Session::haveRight("plugin_order_order", self::RIGHT_CANCEL); + return Session::haveRight(self::$rightname, self::RIGHT_CANCEL); } public static function canUndo() { - return Session::haveRight("plugin_order_order", self::RIGHT_UNDO_VALIDATION); + return Session::haveRight(self::$rightname, self::RIGHT_UNDO_VALIDATION); } public static function canValidate() { - return Session::haveRight("plugin_order_order", self::RIGHT_VALIDATION); + return Session::haveRight(self::$rightname, self::RIGHT_VALIDATION); } public static function canGenerateWithoutValidation() { - return Session::haveRight("plugin_order_order", self::RIGHT_GENERATEODT_WITHOUT_VALIDATION); + return Session::haveRight(self::$rightname, self::RIGHT_GENERATEODT_WITHOUT_VALIDATION); } public static function canGenerate() { - return Session::haveRight("plugin_order_order", self::RIGHT_GENERATEODT); + return Session::haveRight(self::$rightname, self::RIGHT_GENERATEODT); } public static function canDeliver() { - return Session::haveRight("plugin_order_order", self::RIGHT_DELIVERY); + return Session::haveRight(self::$rightname, self::RIGHT_DELIVERY); } @@ -635,7 +635,7 @@ public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) $ong = []; $config = PluginOrderConfig::getConfig(); if ( - Session::haveRightsOr("plugin_order_order", [ + Session::haveRightsOr(self::$rightname, [ self::RIGHT_VALIDATION, self::RIGHT_CANCEL, self::RIGHT_UNDO_VALIDATION, @@ -754,14 +754,12 @@ public function post_addItem() 'itemtype' => $this->getType(), ], ); - if (!empty($docs)) { - foreach ($docs as $doc) { - $docitem->add([ - 'documents_id' => $doc["documents_id"], - 'itemtype' => $this->getType(), - 'items_id' => $this->fields['id'], - ]); - } + foreach ($docs as $doc) { + $docitem->add([ + 'documents_id' => $doc["documents_id"], + 'itemtype' => $this->getType(), + 'items_id' => $this->fields['id'], + ]); } } } @@ -2571,7 +2569,7 @@ public function getSpecificMassiveActions($checkitem = null) $isadmin = static::canUpdate(); $actions = parent::getSpecificMassiveActions($checkitem); - if ($isadmin && (Session::haveRight('transfer', READ) && Session::isMultiEntitiesMode())) { + if ($isadmin && (Session::haveRight(Transfer::$rightname, READ) && Session::isMultiEntitiesMode())) { $actions['PluginOrderOrder:transfert'] = __s('Transfer'); } diff --git a/inc/order_item.class.php b/inc/order_item.class.php index 596a1131d1..7ebf696fdc 100644 --- a/inc/order_item.class.php +++ b/inc/order_item.class.php @@ -36,24 +36,24 @@ class PluginOrderOrder_Item extends CommonDBRelation // phpcs:ignore { - public static $rightname = 'plugin_order_order'; + public static string $rightname = 'plugin_order_order'; - public $dohistory = true; + public bool $dohistory = true; // From CommonDBRelation - public static $itemtype_1 = "PluginOrderOrder"; + public static ?string $itemtype_1 = "PluginOrderOrder"; - public static $items_id_1 = 'plugin_order_orders_id'; + public static ?string $items_id_1 = 'plugin_order_orders_id'; - public static $checkItem_1_Rights = self::DONT_CHECK_ITEM_RIGHTS; + public static int $checkItem_1_Rights = self::DONT_CHECK_ITEM_RIGHTS; - public static $itemtype_2 = 'itemtype'; + public static ?string $itemtype_2 = 'itemtype'; - public static $items_id_2 = 'items_id'; + public static ?string $items_id_2 = 'items_id'; - public static $checkItem_2_Rights = self::DONT_CHECK_ITEM_RIGHTS; + public static int $checkItem_2_Rights = self::DONT_CHECK_ITEM_RIGHTS; - public static $check_entity_coherency = false; + public static bool $check_entity_coherency = false; //TODO better right and entity menber (ex Computer_Item) @@ -1434,11 +1434,11 @@ public function showPluginFromItems($itemtype, $ID) 'items_id' => $ID, ], ); - if (!empty($result)) { + if ($result !== []) { $link = array_shift($result); $reference = new PluginOrderReference(); $reference->getFromDB($link['plugin_order_references_id']); - if (Session::haveRight('plugin_order_reference', READ)) { + if (Session::haveRight(PluginOrderReference::$rightname, READ)) { $twig_option['reference_link'] = $reference->getLink(); } diff --git a/inc/order_supplier.class.php b/inc/order_supplier.class.php index a0c8c5fb1e..c585c3d0cf 100644 --- a/inc/order_supplier.class.php +++ b/inc/order_supplier.class.php @@ -32,13 +32,13 @@ class PluginOrderOrder_Supplier extends CommonDBChild // phpcs:ignore { - public static $rightname = 'plugin_order_order'; + public static string $rightname = 'plugin_order_order'; - public static $itemtype = 'PluginOrderOrder'; + public static string $itemtype = 'PluginOrderOrder'; - public static $items_id = 'plugin_order_orders_id'; + public static string $items_id = 'plugin_order_orders_id'; - public $dohistory = true; + public bool $dohistory = true; public static function getTypeName($nb = 0) diff --git a/inc/orderpayment.class.php b/inc/orderpayment.class.php index de87bbdaa9..9f1e01cf93 100644 --- a/inc/orderpayment.class.php +++ b/inc/orderpayment.class.php @@ -33,7 +33,7 @@ // Class for a Dropdown class PluginOrderOrderPayment extends CommonDropdown { - public static $rightname = 'plugin_order_order'; //'plugin_order_order'; + public static string $rightname = 'plugin_order_order'; //'plugin_order_order'; public static function getTypeName($nb = 0) { diff --git a/inc/orderstate.class.php b/inc/orderstate.class.php index 8f39b80338..3a6633e68c 100644 --- a/inc/orderstate.class.php +++ b/inc/orderstate.class.php @@ -47,7 +47,7 @@ class PluginOrderOrderState extends CommonDropdown public const PAID = 7; - public static $rightname = 'plugin_order_order'; + public static string $rightname = 'plugin_order_order'; public static function getTypeName($nb = 0) diff --git a/inc/ordertax.class.php b/inc/ordertax.class.php index ca8a167e91..d826f37421 100644 --- a/inc/ordertax.class.php +++ b/inc/ordertax.class.php @@ -33,7 +33,7 @@ // Class for a Dropdown class PluginOrderOrderTax extends CommonDropdown { - public static $rightname = 'plugin_order_order'; + public static string $rightname = 'plugin_order_order'; public static function getTypeName($nb = 0) diff --git a/inc/ordertype.class.php b/inc/ordertype.class.php index f484a20040..b270d3c645 100644 --- a/inc/ordertype.class.php +++ b/inc/ordertype.class.php @@ -33,7 +33,7 @@ // Class for a Dropdown class PluginOrderOrdertype extends CommonDropdown { - public static $rightname = 'plugin_order_order'; + public static string $rightname = 'plugin_order_order'; public static function getTypeName($nb = 0) diff --git a/inc/other.class.php b/inc/other.class.php index 20e0682e53..27e316650c 100644 --- a/inc/other.class.php +++ b/inc/other.class.php @@ -32,7 +32,7 @@ class PluginOrderOther extends CommonDBTM { - public static $rightname = 'plugin_order_order'; + public static string $rightname = 'plugin_order_order'; public static function getTypeName($nb = 0) diff --git a/inc/othertype.class.php b/inc/othertype.class.php index 71879d0774..d9d5cb0efa 100644 --- a/inc/othertype.class.php +++ b/inc/othertype.class.php @@ -32,7 +32,7 @@ class PluginOrderOthertype extends CommonDropdown { - public static $rightname = 'plugin_order_order'; + public static string $rightname = 'plugin_order_order'; public static function getTypeName($nb = 0) diff --git a/inc/preference.class.php b/inc/preference.class.php index 413127177c..d0273d4fb7 100644 --- a/inc/preference.class.php +++ b/inc/preference.class.php @@ -65,7 +65,7 @@ public function addDefaultPreference($users_id) public static function checkPreferenceValue($field, $users_id = 0) { $data = getAllDataFromTable(self::getTable(), ['users_id' => $users_id]); - if (!empty($data)) { + if ($data !== []) { $first = array_pop($data); return $first[$field]; } else { diff --git a/inc/profile.class.php b/inc/profile.class.php index c39ddf708f..f2dfed0203 100644 --- a/inc/profile.class.php +++ b/inc/profile.class.php @@ -32,7 +32,7 @@ class PluginOrderProfile extends CommonDBTM { - public static $rightname = 'profile'; + public static string $rightname = 'profile'; public static function createFirstAccess($ID) diff --git a/inc/reception.class.php b/inc/reception.class.php index 70fed233f0..74c4516f25 100644 --- a/inc/reception.class.php +++ b/inc/reception.class.php @@ -32,15 +32,15 @@ class PluginOrderReception extends CommonDBChild { - public static $rightname = 'plugin_order_order'; + public static string $rightname = 'plugin_order_order'; - public $dohistory = true; + public bool $dohistory = true; - public static $itemtype = 'PluginOrderOrder'; + public static string $itemtype = 'PluginOrderOrder'; - public static $items_id = 'plugin_order_orders_id'; + public static string $items_id = 'plugin_order_orders_id'; - public static $checkParentRights = self::DONT_CHECK_ITEM_RIGHTS; + public static int $checkParentRights = self::DONT_CHECK_ITEM_RIGHTS; public static function getTable($classname = null) @@ -61,14 +61,14 @@ public static function getIcon() public function canUpdateItem(): bool { - return Session::haveRight('plugin_order_order', PluginOrderOrder::RIGHT_DELIVERY); + return Session::haveRight(PluginOrderOrder::$rightname, PluginOrderOrder::RIGHT_DELIVERY); } public function canViewItem(): bool { - return Session::haveRight('plugin_order_order', PluginOrderOrder::RIGHT_DELIVERY) - && Session::haveRight('plugin_order_order', READ); + return Session::haveRight(PluginOrderOrder::$rightname, PluginOrderOrder::RIGHT_DELIVERY) + && Session::haveRight(PluginOrderOrder::$rightname, READ); } @@ -272,12 +272,12 @@ public function showForm($ID, $options = []) echo "" . __s("Bill", "order") . ""; echo ""; - if (Session::haveRight("plugin_order_bill", UPDATE)) { + if (Session::haveRight(PluginOrderBill::$rightname, UPDATE)) { PluginOrderBill::Dropdown([ 'name' => "plugin_order_bills_id", 'value' => $this->fields["plugin_order_bills_id"], ]); - } elseif (Session::haveRight("plugin_order_bill", READ)) { + } elseif (Session::haveRight(PluginOrderBill::$rightname, READ)) { echo Dropdown::getDropdownName( "glpi_plugin_order_bills", $this->fields["plugin_order_bills_id"], diff --git a/inc/reference.class.php b/inc/reference.class.php index 36e101151d..b832b1ca03 100644 --- a/inc/reference.class.php +++ b/inc/reference.class.php @@ -59,11 +59,11 @@ */ class PluginOrderReference extends CommonDBTM { - public static $rightname = 'plugin_order_reference'; //'plugin_order_reference'; //TODO : A développer + public static string $rightname = 'plugin_order_reference'; //'plugin_order_reference'; //TODO : A développer - public $dohistory = true; + public bool $dohistory = true; - public static $forward_entity_to = ['PluginOrderReference_Supplier']; + public static array $forward_entity_to = ['PluginOrderReference_Supplier']; public static function getTypeName($nb = 0) @@ -1029,7 +1029,7 @@ public function getSpecificMassiveActions($checkitem = null) if ($isadmin) { if ( - Session::haveRight('transfer', READ) + Session::haveRight(Transfer::$rightname, READ) && Session::isMultiEntitiesMode() ) { $actions['PluginOrderReference:transfert'] = __s('Transfer'); diff --git a/inc/reference_supplier.class.php b/inc/reference_supplier.class.php index bdb4ac5156..5f6edb04cc 100644 --- a/inc/reference_supplier.class.php +++ b/inc/reference_supplier.class.php @@ -32,13 +32,13 @@ class PluginOrderReference_Supplier extends CommonDBChild // phpcs:ignore { - public static $rightname = 'plugin_order_reference'; + public static string $rightname = 'plugin_order_reference'; - public static $itemtype = 'PluginOrderReference'; + public static string $itemtype = 'PluginOrderReference'; - public static $items_id = 'plugin_order_references_id'; + public static string $items_id = 'plugin_order_references_id'; - public $dohistory = true; + public bool $dohistory = true; public static function getTypeName($nb = 0) diff --git a/inc/referencefree.class.php b/inc/referencefree.class.php index 860d53d75b..ffcc9198b1 100644 --- a/inc/referencefree.class.php +++ b/inc/referencefree.class.php @@ -32,9 +32,9 @@ class PluginOrderReferenceFree extends CommonDBTM { - public static $rightname = 'plugin_order_reference'; + public static string $rightname = 'plugin_order_reference'; - public $dohistory = true; + public bool $dohistory = true; public static function getTypeName($nb = 0) { diff --git a/inc/surveysupplier.class.php b/inc/surveysupplier.class.php index 306af52697..2f21193d40 100644 --- a/inc/surveysupplier.class.php +++ b/inc/surveysupplier.class.php @@ -32,11 +32,11 @@ class PluginOrderSurveySupplier extends CommonDBChild { - public static $rightname = 'plugin_order_order'; + public static string $rightname = 'plugin_order_order'; - public static $itemtype = 'PluginOrderOrder'; + public static string $itemtype = 'PluginOrderOrder'; - public static $items_id = 'plugin_order_orders_id'; + public static string $items_id = 'plugin_order_orders_id'; public static function getTypeName($nb = 0) @@ -175,8 +175,6 @@ public static function showGlobalNotation($suppliers_id) $survey = new self(); $survey_table = $survey->getTable(); - getEntitiesRestrictRequest(" AND ", "orders", "entities_id", '', true); - $criteria = [ 'SELECT' => [ 'orders.id', diff --git a/setup.php b/setup.php index 7768b99afc..a2b78815c0 100644 --- a/setup.php +++ b/setup.php @@ -35,9 +35,9 @@ define('PLUGIN_ORDER_VERSION', '2.12.9'); // Minimal GLPI version, inclusive -define("PLUGIN_ORDER_MIN_GLPI", "11.0.0"); +define("PLUGIN_ORDER_MIN_GLPI", "12.0.0"); // Maximum GLPI version, exclusive -define("PLUGIN_ORDER_MAX_GLPI", "11.0.99"); +define("PLUGIN_ORDER_MAX_GLPI", "12.0.99"); if (!defined('PLUGIN_ORDER_DIR')) { define("PLUGIN_ORDER_DIR", Plugin::getPhpDir('order')); @@ -200,7 +200,7 @@ function plugin_init_order() $PLUGIN_HOOKS['add_css']['order'][] = 'css/order.css'; /* link to the config page in plugins menu */ - if (Session::haveRight("config", UPDATE)) { + if (Session::haveRight(Config::$rightname, UPDATE)) { $PLUGIN_HOOKS['config_page']['order'] = 'front/config.form.php'; } diff --git a/templates/order_getitems.html.twig b/templates/order_getitems.html.twig index 5c8ab6d274..517bc6dd5d 100644 --- a/templates/order_getitems.html.twig +++ b/templates/order_getitems.html.twig @@ -60,7 +60,6 @@ {% if form_action is defined %}
- {% endif %} {% if hidden_fields is defined %} From 53ab440d16ba65727c9ef050e7311f039b69c9da Mon Sep 17 00:00:00 2001 From: Lainow Date: Mon, 31 Aug 2026 16:49:01 +0200 Subject: [PATCH 2/7] Add tests --- .phpunit.result.cache | 1 + ajax/dropdownReference.php | 2 - composer.json | 8 + hook.php | 2 +- phpunit.xml | 7 + report/deliveryinfos/deliveryinfos.php | 6 - report/orderdelivery/orderdelivery.php | 6 - tests/OrderTestCase.php | 120 +++++++++++++++ tests/Units/BillTest.php | 104 +++++++++++++ tests/Units/DropdownsTest.php | 78 ++++++++++ tests/Units/OrderItemTest.php | 107 +++++++++++++ tests/Units/OrderTest.php | 202 +++++++++++++++++++++++++ tests/Units/OrderableCapacityTest.php | 110 ++++++++++++++ tests/Units/ProfileTest.php | 87 +++++++++++ tests/Units/ReferenceTest.php | 158 +++++++++++++++++++ tests/bootstrap.php | 36 +++++ 16 files changed, 1019 insertions(+), 15 deletions(-) create mode 100644 .phpunit.result.cache create mode 100644 phpunit.xml create mode 100644 tests/OrderTestCase.php create mode 100644 tests/Units/BillTest.php create mode 100644 tests/Units/DropdownsTest.php create mode 100644 tests/Units/OrderItemTest.php create mode 100644 tests/Units/OrderTest.php create mode 100644 tests/Units/OrderableCapacityTest.php create mode 100644 tests/Units/ProfileTest.php create mode 100644 tests/Units/ReferenceTest.php create mode 100644 tests/bootstrap.php diff --git a/.phpunit.result.cache b/.phpunit.result.cache new file mode 100644 index 0000000000..f24212ede7 --- /dev/null +++ b/.phpunit.result.cache @@ -0,0 +1 @@ +{"version":2,"defects":{"GlpiPlugin\\Order\\Tests\\Units\\BillTest::testCreateBillRequiresNumber":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #0":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #1":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #2":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #3":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #4":8,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #5":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #6":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #7":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #8":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #9":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testCreateOrderWithoutNumOrderFails":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderableCapacityTest::testCapacityUsageDescriptionReflectsLinkedReferences":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderableCapacityTest::testDisablingCapacityCleansUpLinkedReferencesAndOrderItems":7,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testCreateReferenceWithoutNameFails":7,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testCreateReferenceWithoutItemtypeFails":7,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testDuplicateNameInSameEntityIsRejected":7,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testDeletingReferenceInUseIsBlocked":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderItemTest::testAddDetailsCreatesOneLinePerQuantity":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testCanceledOrderCannotBeCanceledAgain":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderItemTest::testGetAllPricesSumsOrderLines":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testDeliveredStateSetsDeliveryDate":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testUndoValidationRequiresRightAndValidatedState":7,"GlpiPlugin\\Order\\Tests\\Units\\ProfileTest::testGetAllRightsDeclaresTheThreeRightBuckets":7},"times":{"GlpiPlugin\\Order\\Tests\\Units\\BillTest::testCreateBillRequiresNumber":0.106,"GlpiPlugin\\Order\\Tests\\Units\\BillTest::testCreateBillLinkedToOrderAndSupplier":0.07,"GlpiPlugin\\Order\\Tests\\Units\\BillTest::testUpdateBill":0.064,"GlpiPlugin\\Order\\Tests\\Units\\BillTest::testDeleteBill":0.222,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #0":0.089,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #1":0.09,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #2":0.09,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #3":0.09,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #4":0.089,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #5":0.089,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #6":0.089,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #7":0.091,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #8":0.089,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #9":0.089,"GlpiPlugin\\Order\\Tests\\Units\\OrderItemTest::testGetClassesIncludesNativeGlpiAssets":0.053,"GlpiPlugin\\Order\\Tests\\Units\\OrderItemTest::testAddDetailsCreatesOneLinePerQuantity":0.075,"GlpiPlugin\\Order\\Tests\\Units\\OrderItemTest::testGetAllPricesSumsOrderLines":0.068,"GlpiPlugin\\Order\\Tests\\Units\\OrderItemTest::testDeletingOrderItemDoesNotDeleteTheOrder":0.098,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testCreateOrderIsDraftByDefault":0.056,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testCreateOrderWithoutNumOrderFails":0.054,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testUpdateOrder":0.058,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testUpdateOrderStatusAddsHistoryLog":0.058,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testDeliveredStateSetsDeliveryDate":0.057,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testCanValidateOrderWithoutValidationProcessDependsOnDraftState":0.06,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testCanCancelOrderRequiresRight":0.098,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testCanceledOrderCannotBeCanceledAgain":0.067,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testUndoValidationRequiresRightAndValidatedState":0.091,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testPurgingOrderCascadesToRelatedItems":0.137,"GlpiPlugin\\Order\\Tests\\Units\\OrderableCapacityTest::testCapacityUsageDescriptionReflectsLinkedReferences":0.124,"GlpiPlugin\\Order\\Tests\\Units\\OrderableCapacityTest::testDisablingCapacityCleansUpLinkedReferencesAndOrderItems":0.203,"GlpiPlugin\\Order\\Tests\\Units\\ProfileTest::testGetAllRightsDeclaresTheThreeRightBuckets":0.001,"GlpiPlugin\\Order\\Tests\\Units\\ProfileTest::testEveryDeclaredRightIsRegisteredInProfileRights":0.003,"GlpiPlugin\\Order\\Tests\\Units\\ProfileTest::testToggleOrderRightBitOnProfile":0.016,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testCreateReference":0.061,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testCreateReferenceWithoutNameFails":0.059,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testCreateReferenceWithoutItemtypeFails":0.055,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testDuplicateNameInSameEntityIsRejected":0.078,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testLinkReferenceToSupplier":0.087,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testUpdateReference":0.062,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testDeleteUnusedReference":0.098,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testDeletingReferenceInUseIsBlocked":0.072}} \ No newline at end of file diff --git a/ajax/dropdownReference.php b/ajax/dropdownReference.php index a0bea7b6d9..f68164d7d7 100644 --- a/ajax/dropdownReference.php +++ b/ajax/dropdownReference.php @@ -31,8 +31,6 @@ /** @var DBmysql $DB */ global $DB; -include_once(__DIR__ . "/../../../inc/includes.php"); - Session::checkRight(PluginOrderReference::$rightname, READ); // Make a select box for references diff --git a/composer.json b/composer.json index 0a45531210..29b65e40f3 100644 --- a/composer.json +++ b/composer.json @@ -4,6 +4,9 @@ "php": ">=8.2", "sboden/odtphp": "^3.2" }, + "require-dev": { + "glpi-project/tools": "^0.8" + }, "config": { "optimize-autoloader": true, "platform": { @@ -17,6 +20,11 @@ "url": "https://github.com/teclib/odtphp/" } ], + "autoload": { + "psr-4": { + "GlpiPlugin\\Order\\Tests\\": "tests" + } + }, "autoload-dev": { "psr-4": { "Glpi\\Tools\\": "../../tools/src/" diff --git a/hook.php b/hook.php index 5a30ee1894..104e4e563b 100644 --- a/hook.php +++ b/hook.php @@ -177,7 +177,7 @@ function plugin_order_getDatabaseRelations() "glpi_plugin_order_orders" => "plugin_order_orderstates_id", ], "glpi_plugin_order_accountsections" => [ - "glpi_plugin_order_accountsections" => "plugin_order_accountsections_id", + "glpi_plugin_order_orders" => "plugin_order_accountsections_id", ], "glpi_plugin_order_analyticnatures" => [ "glpi_plugin_order_orders_items" => "plugin_order_analyticnatures_id", diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000000..e9f60d9f8c --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,7 @@ + + + + tests/Units + + + diff --git a/report/deliveryinfos/deliveryinfos.php b/report/deliveryinfos/deliveryinfos.php index b63e36e3d8..e19fb7f008 100644 --- a/report/deliveryinfos/deliveryinfos.php +++ b/report/deliveryinfos/deliveryinfos.php @@ -38,12 +38,6 @@ * ---------------------------------------------------------------------- */ -//Options for GLPI 0.71 and newer : need slave db to access the report -$USEDBREPLICATE = 1; -$DBCONNECTION_REQUIRED = 0; // Really a big SQL request - -include(__DIR__ . "/../../../../inc/includes.php"); - $report = new PluginReportsAutoReport(__s("deliveryinfos_report_title", "order")); new PluginReportsDateIntervalCriteria($report, 'order_date', __s("Date of order", "order")); new PluginReportsDateIntervalCriteria($report, 'deliverydate', __s("Delivery date")); diff --git a/report/orderdelivery/orderdelivery.php b/report/orderdelivery/orderdelivery.php index cfd9449bb9..8fb40e07ab 100644 --- a/report/orderdelivery/orderdelivery.php +++ b/report/orderdelivery/orderdelivery.php @@ -38,12 +38,6 @@ * ---------------------------------------------------------------------- */ -//Options for GLPI 0.71 and newer : need slave db to access the report -$USEDBREPLICATE = 1; -$DBCONNECTION_REQUIRED = 0; // Really a big SQL request - -include(__DIR__ . "/../../../../inc/includes.php"); - $report = new PluginReportsAutoReport(__s("orderdelivery_report_title", "order")); new PluginReportsDateIntervalCriteria($report, 'order_date', __s("Date of order", "order")); new PluginReportsDateIntervalCriteria($report, 'deliverydate', __s("Delivery date")); diff --git a/tests/OrderTestCase.php b/tests/OrderTestCase.php new file mode 100644 index 0000000000..3d62c73ae4 --- /dev/null +++ b/tests/OrderTestCase.php @@ -0,0 +1,120 @@ +. + * ------------------------------------------------------------------------- + * @copyright Copyright (C) 2009-2023 by Order plugin team. + * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html + * @link https://github.com/pluginsGLPI/order + * ------------------------------------------------------------------------- + */ + +namespace GlpiPlugin\Order\Tests; + +use Glpi\Tests\DbTestCase; +use PluginOrderOrder; +use PluginOrderOrder_Item; +use PluginOrderReference; +use PluginOrderReference_Supplier; +use Supplier; + +abstract class OrderTestCase extends DbTestCase +{ + /** + * Create a Supplier fixture, usable both as an order supplier and a + * reference supplier. + */ + public function createSupplier(string $name = 'Test Supplier'): Supplier + { + return $this->createItem(Supplier::class, [ + 'name' => $name . '_' . $this->getUniqueString(), + 'entities_id' => $this->getTestRootEntity(true), + ]); + } + + /** + * Create a catalog Product reference (PluginOrderReference), optionally + * linked to a Supplier via PluginOrderReference_Supplier. + */ + public function createReference( + ?Supplier $supplier = null, + string $itemtype = 'Computer', + float $price_taxfree = 100, + ): PluginOrderReference { + $reference = $this->createItem(PluginOrderReference::class, [ + 'name' => 'Test Reference_' . $this->getUniqueString(), + 'entities_id' => $this->getTestRootEntity(true), + 'itemtype' => $itemtype, + ]); + + if ($supplier !== null) { + $this->createItem(PluginOrderReference_Supplier::class, [ + 'plugin_order_references_id' => $reference->getID(), + 'suppliers_id' => $supplier->getID(), + 'price_taxfree' => $price_taxfree, + ]); + } + + return $reference; + } + + /** + * Create a draft PluginOrderOrder fixture. + */ + public function createOrder(array $input = []): PluginOrderOrder + { + return $this->createItem(PluginOrderOrder::class, array_merge([ + 'name' => 'Test Order_' . $this->getUniqueString(), + 'num_order' => 'CMD_' . $this->getUniqueString(), + 'entities_id' => $this->getTestRootEntity(true), + ], $input)); + } + + /** + * Link a Product reference to an order, as PluginOrderOrder_Item does + * through PluginOrderOrder::showAddForm() / addDetails(). + */ + public function addReferenceToOrder( + PluginOrderOrder $order, + PluginOrderReference $reference, + int $quantity = 1, + float $price = 100, + float $discount = 0, + ): array { + $order_item = new PluginOrderOrder_Item(); + $order_item->addDetails( + $reference->getID(), + $reference->fields['itemtype'], + $order->getID(), + $quantity, + $price, + $discount, + 0, + 0, + ); + + return array_values($order_item->find([ + 'plugin_order_orders_id' => $order->getID(), + 'plugin_order_references_id' => $reference->getID(), + ])); + } +} diff --git a/tests/Units/BillTest.php b/tests/Units/BillTest.php new file mode 100644 index 0000000000..4bea55186c --- /dev/null +++ b/tests/Units/BillTest.php @@ -0,0 +1,104 @@ +. + * ------------------------------------------------------------------------- + * @copyright Copyright (C) 2009-2023 by Order plugin team. + * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html + * @link https://github.com/pluginsGLPI/order + * ------------------------------------------------------------------------- + */ + +namespace GlpiPlugin\Order\Tests\Units; + +use GlpiPlugin\Order\Tests\OrderTestCase; +use PluginOrderBill; + +final class BillTest extends OrderTestCase +{ + public function testCreateBillRequiresNumber(): void + { + $this->login(); + + $bill = new PluginOrderBill(); + $id = $bill->add([ + 'name' => 'Bill without number', + 'entities_id' => $this->getTestRootEntity(true), + ]); + + $this->assertFalse($id); + $this->hasSessionMessages(ERROR, ['A bill number is mandatory']); + } + + public function testCreateBillLinkedToOrderAndSupplier(): void + { + $this->login(); + + $supplier = $this->createSupplier(); + $order = $this->createOrder(); + + $bill = $this->createItem(PluginOrderBill::class, [ + 'name' => 'Test bill', + 'number' => 'INV-' . $this->getUniqueString(), + 'entities_id' => $this->getTestRootEntity(true), + 'suppliers_id' => $supplier->getID(), + 'plugin_order_orders_id' => $order->getID(), + 'value' => 199.99, + ]); + + $this->assertSame($supplier->getID(), (int) $bill->fields['suppliers_id']); + $this->assertSame($order->getID(), (int) $bill->fields['plugin_order_orders_id']); + $this->assertEqualsWithDelta(199.99, (float) $bill->fields['value'], 0.001); + } + + public function testUpdateBill(): void + { + $this->login(); + + $bill = $this->createItem(PluginOrderBill::class, [ + 'name' => 'Test bill', + 'number' => 'INV-' . $this->getUniqueString(), + 'entities_id' => $this->getTestRootEntity(true), + ]); + + $this->updateItem(PluginOrderBill::class, $bill->getID(), [ + 'value' => 42.5, + ]); + + $bill->getFromDB($bill->getID()); + $this->assertEqualsWithDelta(42.5, (float) $bill->fields['value'], 0.001); + } + + public function testDeleteBill(): void + { + $this->login(); + + $bill = $this->createItem(PluginOrderBill::class, [ + 'name' => 'Test bill', + 'number' => 'INV-' . $this->getUniqueString(), + 'entities_id' => $this->getTestRootEntity(true), + ]); + + $this->assertTrue($bill->delete(['id' => $bill->getID()], true)); + $this->assertFalse((new PluginOrderBill())->getFromDB($bill->getID())); + } +} diff --git a/tests/Units/DropdownsTest.php b/tests/Units/DropdownsTest.php new file mode 100644 index 0000000000..6e7228daa2 --- /dev/null +++ b/tests/Units/DropdownsTest.php @@ -0,0 +1,78 @@ +. + * ------------------------------------------------------------------------- + * @copyright Copyright (C) 2009-2023 by Order plugin team. + * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html + * @link https://github.com/pluginsGLPI/order + * ------------------------------------------------------------------------- + */ + +namespace GlpiPlugin\Order\Tests\Units; + +use GlpiPlugin\Order\Tests\OrderTestCase; +use PHPUnit\Framework\Attributes\DataProvider; + +/** + * Generic CRUD coverage for every simple CommonDropdown exposed by the + * plugin. These are all used as reference data on Orders / Order items / + * Bills, so a regression here (e.g. a rightname or table change breaking + * under a newer GLPI) would silently break every form relying on them. + */ +final class DropdownsTest extends OrderTestCase +{ + public static function dropdownClassesProvider(): array + { + return [ + ['PluginOrderOrderState'], + ['PluginOrderOrdertype'], + ['PluginOrderOrderTax'], + ['PluginOrderOrderPayment'], + ['PluginOrderAccountsection'], + ['PluginOrderAnalyticnature'], + ['PluginOrderDeliverystate'], + ['PluginOrderBillState'], + ['PluginOrderBillType'], + ['PluginOrderOthertype'], + ]; + } + + #[DataProvider('dropdownClassesProvider')] + public function testCreateUpdateAndDeleteDropdown(string $itemtype): void + { + $this->login(); + + $item = $this->createItem($itemtype, [ + 'name' => 'Test ' . $itemtype . '_' . $this->getUniqueString(), + ]); + + $this->updateItem($itemtype, $item->getID(), [ + 'comment' => 'Updated via functional test', + ]); + $item->getFromDB($item->getID()); + $this->assertSame('Updated via functional test', $item->fields['comment']); + + $this->assertTrue($item->delete(['id' => $item->getID()], true)); + $this->assertFalse((new $itemtype())->getFromDB($item->getID())); + } +} diff --git a/tests/Units/OrderItemTest.php b/tests/Units/OrderItemTest.php new file mode 100644 index 0000000000..3e8f179b39 --- /dev/null +++ b/tests/Units/OrderItemTest.php @@ -0,0 +1,107 @@ +. + * ------------------------------------------------------------------------- + * @copyright Copyright (C) 2009-2023 by Order plugin team. + * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html + * @link https://github.com/pluginsGLPI/order + * ------------------------------------------------------------------------- + */ + +namespace GlpiPlugin\Order\Tests\Units; + +use Computer; +use GlpiPlugin\Order\Tests\OrderTestCase; +use PluginOrderOrder_Item; + +final class OrderItemTest extends OrderTestCase +{ + public function testGetClassesIncludesNativeGlpiAssets(): void + { + $this->login(); + + $classes = PluginOrderOrder_Item::getClasses(true); + + // Order lines can natively point to these core GLPI asset types. + $this->assertContains(Computer::class, $classes); + $this->assertContains('Monitor', $classes); + $this->assertContains('NetworkEquipment', $classes); + $this->assertContains('Printer', $classes); + $this->assertContains('SoftwareLicense', $classes); + } + + public function testAddDetailsCreatesOneLinePerQuantity(): void + { + $this->login(); + + $supplier = $this->createSupplier(); + $order = $this->createOrder(); + $reference = $this->createReference($supplier, Computer::class, 250); + + $lines = $this->addReferenceToOrder($order, $reference, 3, 250, 10); + + $this->assertCount(3, $lines); + foreach ($lines as $line) { + $this->assertSame($order->getID(), (int) $line['plugin_order_orders_id']); + $this->assertSame($reference->getID(), (int) $line['plugin_order_references_id']); + $this->assertSame(Computer::class, $line['itemtype']); + // 250 - 10% discount = 225 + $this->assertEqualsWithDelta(225.0, (float) $line['price_discounted'], 0.001); + } + } + + public function testGetAllPricesSumsOrderLines(): void + { + $this->login(); + + $supplier = $this->createSupplier(); + $order = $this->createOrder(); + $reference = $this->createReference($supplier, Computer::class, 100); + + $this->addReferenceToOrder($order, $reference, 2, 100, 0); + + $order_item = new PluginOrderOrder_Item(); + $prices = $order_item->getAllPrices($order->getID()); + + $this->assertEqualsWithDelta(200.0, (float) $prices['priceHT'], 0.001); + } + + public function testDeletingOrderItemDoesNotDeleteTheOrder(): void + { + $this->login(); + + $supplier = $this->createSupplier(); + $order = $this->createOrder(); + $reference = $this->createReference($supplier, Computer::class, 100); + $lines = $this->addReferenceToOrder($order, $reference, 1, 100, 0); + + $order_item = new PluginOrderOrder_Item(); + $this->assertTrue($order_item->delete(['id' => $lines[0]['id']], true)); + + $this->assertCount( + 0, + $order_item->find(['id' => $lines[0]['id']]), + ); + $this->assertTrue($order->getFromDB($order->getID())); + } +} diff --git a/tests/Units/OrderTest.php b/tests/Units/OrderTest.php new file mode 100644 index 0000000000..de16ec9fd8 --- /dev/null +++ b/tests/Units/OrderTest.php @@ -0,0 +1,202 @@ +. + * ------------------------------------------------------------------------- + * @copyright Copyright (C) 2009-2023 by Order plugin team. + * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html + * @link https://github.com/pluginsGLPI/order + * ------------------------------------------------------------------------- + */ + +namespace GlpiPlugin\Order\Tests\Units; + +use GlpiPlugin\Order\Tests\OrderTestCase; +use PluginOrderOrder; +use PluginOrderOrder_Item; +use PluginOrderOrder_Supplier; +use PluginOrderOrderState; + +final class OrderTest extends OrderTestCase +{ + public function testCreateOrderIsDraftByDefault(): void + { + $this->login(); + + $order = $this->createOrder(); + + $this->assertSame( + PluginOrderOrderState::DRAFT, + (int) $order->fields['plugin_order_orderstates_id'], + ); + $this->assertTrue($order->isDraft()); + $this->assertFalse($order->isCanceled()); + $this->assertFalse($order->isDelivered()); + } + + public function testCreateOrderWithoutNumOrderFails(): void + { + $this->login(); + + $order = new PluginOrderOrder(); + $id = $order->add([ + 'name' => 'Missing num_order', + 'entities_id' => $this->getTestRootEntity(true), + ]); + + $this->assertFalse($id); + $this->hasSessionMessages(ERROR, ['An order number is mandatory !']); + } + + public function testUpdateOrder(): void + { + $this->login(); + + $order = $this->createOrder(); + + $this->updateItem(PluginOrderOrder::class, $order->getID(), [ + 'comment' => 'Updated comment', + ]); + + $order->getFromDB($order->getID()); + $this->assertSame('Updated comment', $order->fields['comment']); + } + + public function testUpdateOrderStatusAddsHistoryLog(): void + { + $this->login(); + + $order = $this->createOrder(); + $order->updateOrderStatus($order->getID(), PluginOrderOrderState::VALIDATED, 'validated for test'); + + $order->getFromDB($order->getID()); + $this->assertSame(PluginOrderOrderState::VALIDATED, (int) $order->fields['plugin_order_orderstates_id']); + $this->assertTrue($order->isApproved()); + } + + public function testDeliveredStateSetsDeliveryDate(): void + { + $this->login(); + + $order = $this->createOrder(); + $this->assertEmpty($order->fields['deliverydate']); + + $order->updateOrderStatus($order->getID(), PluginOrderOrderState::DELIVERED); + + $order->getFromDB($order->getID()); + $this->assertTrue($order->isDelivered()); + $this->assertNotEmpty($order->fields['deliverydate']); + } + + public function testCanValidateOrderWithoutValidationProcessDependsOnDraftState(): void + { + $this->login(); + + $order = $this->createOrder(); + + // No validation workflow configured by default: draft orders can be validated directly. + $this->assertTrue($order->canValidateOrder()); + + $order->updateOrderStatus($order->getID(), PluginOrderOrderState::VALIDATED); + $order->getFromDB($order->getID()); + $this->assertFalse($order->canValidateOrder()); + } + + public function testCanCancelOrderRequiresRight(): void + { + $this->removeRightFromProfile('Super-Admin', PluginOrderOrder::$rightname, PluginOrderOrder::RIGHT_CANCEL); + $this->login(); + + $order = $this->createOrder(); + $this->assertFalse($order->canCancelOrder()); + + $this->logOut(); + $this->addRightToProfile('Super-Admin', PluginOrderOrder::$rightname, PluginOrderOrder::RIGHT_CANCEL); + $this->login(); + + $order->getFromDB($order->getID()); + $this->assertTrue($order->canCancelOrder()); + } + + public function testCanceledOrderCannotBeCanceledAgain(): void + { + $this->addRightToProfile('Super-Admin', PluginOrderOrder::$rightname, PluginOrderOrder::RIGHT_CANCEL); + $this->login(); + + $order = $this->createOrder(); + $order->updateOrderStatus($order->getID(), PluginOrderOrderState::CANCELED); + $order->getFromDB($order->getID()); + + $this->assertTrue($order->isCanceled()); + $this->assertFalse($order->canCancelOrder()); + } + + public function testUndoValidationRequiresRightAndValidatedState(): void + { + $this->addRightToProfile('Super-Admin', PluginOrderOrder::$rightname, PluginOrderOrder::RIGHT_UNDO_VALIDATION); + $this->login(); + + $order = $this->createOrder(); + // Still draft: nothing to undo. + $this->assertFalse($order->canUndoValidation()); + + $order->updateOrderStatus($order->getID(), PluginOrderOrderState::VALIDATED); + $order->getFromDB($order->getID()); + $this->assertTrue($order->canUndoValidation()); + + $this->logOut(); + $this->removeRightFromProfile('Super-Admin', PluginOrderOrder::$rightname, PluginOrderOrder::RIGHT_UNDO_VALIDATION); + $this->login(); + + $order->getFromDB($order->getID()); + $this->assertFalse($order->canUndoValidation()); + } + + public function testPurgingOrderCascadesToRelatedItems(): void + { + $this->login(); + + $supplier = $this->createSupplier(); + $order = $this->createOrder(); + + $order_supplier = $this->createItem(PluginOrderOrder_Supplier::class, [ + 'plugin_order_orders_id' => $order->getID(), + 'suppliers_id' => $supplier->getID(), + ]); + + $reference = $this->createReference($supplier); + $this->addReferenceToOrder($order, $reference); + + $this->assertNotCount( + 0, + (new PluginOrderOrder_Item())->find(['plugin_order_orders_id' => $order->getID()]), + ); + + $this->assertTrue($order->delete(['id' => $order->getID()], true)); + + $this->assertFalse((new PluginOrderOrder_Supplier())->getFromDB($order_supplier->getID())); + $this->assertCount( + 0, + (new PluginOrderOrder_Item())->find(['plugin_order_orders_id' => $order->getID()]), + ); + } +} diff --git a/tests/Units/OrderableCapacityTest.php b/tests/Units/OrderableCapacityTest.php new file mode 100644 index 0000000000..fe50c9fffd --- /dev/null +++ b/tests/Units/OrderableCapacityTest.php @@ -0,0 +1,110 @@ +. + * ------------------------------------------------------------------------- + * @copyright Copyright (C) 2009-2023 by Order plugin team. + * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html + * @link https://github.com/pluginsGLPI/order + * ------------------------------------------------------------------------- + */ + +namespace GlpiPlugin\Order\Tests\Units; + +use Glpi\Asset\AssetDefinitionManager; +use Glpi\Asset\Capacity; +use GlpiPlugin\Order\Tests\OrderTestCase; +use PluginOrderOrder_Item; +use PluginOrderOrderableCapacity; +use PluginOrderReference; + +/** + * Coverage for the GLPI 11/12 custom-asset integration: enabling the + * "Orderable" capacity on a custom asset definition must make its class + * usable as a Product reference itemtype, and disabling it must clean up + * any plugin data that referenced it. + */ +final class OrderableCapacityTest extends OrderTestCase +{ + /** + * GLPITestCase::tearDown() resets the AssetDefinitionManager singleton + * after every test, which discards the capacity registration normally + * done once by plugin_init_order(). Re-register it before each test + * that needs to create/toggle it on a definition. + */ + private function registerOrderableCapacity(): void + { + AssetDefinitionManager::getInstance()->registerCapacity(new PluginOrderOrderableCapacity()); + } + + public function testCapacityUsageDescriptionReflectsLinkedReferences(): void + { + $this->login(); + $this->registerOrderableCapacity(); + + $capacity = new PluginOrderOrderableCapacity(); + + $definition = $this->initAssetDefinition( + capacities: [new Capacity(name: PluginOrderOrderableCapacity::class)], + ); + $classname = $definition->getAssetClassName(); + + $this->assertSame(0, (int) filter_var( + $capacity->getCapacityUsageDescription($classname), + FILTER_SANITIZE_NUMBER_INT, + )); + + $reference = $this->createReference(itemtype: $classname); + + $this->assertSame(1, (int) filter_var( + $capacity->getCapacityUsageDescription($classname), + FILTER_SANITIZE_NUMBER_INT, + )); + + // Sanity check: the created reference is retrievable and points to the custom asset class. + $this->assertSame($classname, $reference->fields['itemtype']); + } + + public function testDisablingCapacityCleansUpLinkedReferencesAndOrderItems(): void + { + $this->login(); + $this->registerOrderableCapacity(); + + $definition = $this->initAssetDefinition( + capacities: [new Capacity(name: PluginOrderOrderableCapacity::class)], + ); + $classname = $definition->getAssetClassName(); + + $supplier = $this->createSupplier(); + $order = $this->createOrder(); + $reference = $this->createReference($supplier, $classname); + $this->addReferenceToOrder($order, $reference); + + $this->assertNotCount(0, (new PluginOrderReference())->find(['itemtype' => $classname])); + $this->assertNotCount(0, (new PluginOrderOrder_Item())->find(['itemtype' => $classname])); + + $this->disableCapacity($definition, PluginOrderOrderableCapacity::class); + + $this->assertCount(0, (new PluginOrderReference())->find(['itemtype' => $classname])); + $this->assertCount(0, (new PluginOrderOrder_Item())->find(['itemtype' => $classname])); + } +} diff --git a/tests/Units/ProfileTest.php b/tests/Units/ProfileTest.php new file mode 100644 index 0000000000..627b78f1c5 --- /dev/null +++ b/tests/Units/ProfileTest.php @@ -0,0 +1,87 @@ +. + * ------------------------------------------------------------------------- + * @copyright Copyright (C) 2009-2023 by Order plugin team. + * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html + * @link https://github.com/pluginsGLPI/order + * ------------------------------------------------------------------------- + */ + +namespace GlpiPlugin\Order\Tests\Units; + +use GlpiPlugin\Order\Tests\OrderTestCase; +use PluginOrderBill; +use PluginOrderOrder; +use PluginOrderProfile; +use PluginOrderReference; +use ProfileRight; + +final class ProfileTest extends OrderTestCase +{ + public function testGetAllRightsDeclaresTheThreeRightBuckets(): void + { + $rights = PluginOrderProfile::getAllRights(); + + $fields = array_column($rights, 'field'); + $this->assertContains(PluginOrderOrder::$rightname, $fields); + $this->assertContains(PluginOrderReference::$rightname, $fields); + $this->assertContains(PluginOrderBill::$rightname, $fields); + + $itemtypes = array_column($rights, 'itemtype'); + $this->assertContains(PluginOrderOrder::class, $itemtypes); + $this->assertContains(PluginOrderReference::class, $itemtypes); + $this->assertContains(PluginOrderBill::class, $itemtypes); + } + + public function testEveryDeclaredRightIsRegisteredInProfileRights(): void + { + // initProfile() is run on plugin activation; the columns must already exist. + foreach (PluginOrderProfile::getAllRights(true) as $data) { + $this->assertGreaterThan( + 0, + countElementsInTable('glpi_profilerights', ['name' => $data['field']]), + sprintf('Right "%s" is not registered in glpi_profilerights', $data['field']), + ); + } + } + + public function testToggleOrderRightBitOnProfile(): void + { + $profile_right = new ProfileRight(); + $profile_right->getFromDBByCrit([ + 'profiles_id' => getItemByTypeName('Profile', 'Super-Admin', true), + 'name' => PluginOrderOrder::$rightname, + ]); + + $this->addRightToProfile('Super-Admin', PluginOrderOrder::$rightname, PluginOrderOrder::RIGHT_DELIVERY); + + $profile_right->getFromDB($profile_right->getID()); + $this->assertNotSame(0, (int) $profile_right->fields['rights'] & PluginOrderOrder::RIGHT_DELIVERY); + + $this->removeRightFromProfile('Super-Admin', PluginOrderOrder::$rightname, PluginOrderOrder::RIGHT_DELIVERY); + + $profile_right->getFromDB($profile_right->getID()); + $this->assertSame(0, (int) $profile_right->fields['rights'] & PluginOrderOrder::RIGHT_DELIVERY); + } +} diff --git a/tests/Units/ReferenceTest.php b/tests/Units/ReferenceTest.php new file mode 100644 index 0000000000..9d7d6d0a93 --- /dev/null +++ b/tests/Units/ReferenceTest.php @@ -0,0 +1,158 @@ +. + * ------------------------------------------------------------------------- + * @copyright Copyright (C) 2009-2023 by Order plugin team. + * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html + * @link https://github.com/pluginsGLPI/order + * ------------------------------------------------------------------------- + */ + +namespace GlpiPlugin\Order\Tests\Units; + +use Computer; +use GlpiPlugin\Order\Tests\OrderTestCase; +use PluginOrderReference; +use PluginOrderReference_Supplier; + +final class ReferenceTest extends OrderTestCase +{ + public function testCreateReference(): void + { + $this->login(); + + $reference = $this->createReference(); + + $this->assertSame(Computer::class, $reference->fields['itemtype']); + $this->assertSame(1, (int) $reference->fields['is_active']); + } + + public function testCreateReferenceWithoutNameFails(): void + { + $this->login(); + + $reference = new PluginOrderReference(); + $id = $reference->add([ + 'entities_id' => $this->getTestRootEntity(true), + 'itemtype' => Computer::class, + ]); + + $this->assertFalse($id); + $this->hasSessionMessages(ERROR, ['Cannot create reference without a name']); + } + + public function testCreateReferenceWithoutItemtypeFails(): void + { + $this->login(); + + $reference = new PluginOrderReference(); + $id = $reference->add([ + 'name' => 'No itemtype', + 'entities_id' => $this->getTestRootEntity(true), + 'itemtype' => '', + ]); + + $this->assertFalse($id); + $this->hasSessionMessages(ERROR, ['Cannot create reference without a type']); + } + + public function testDuplicateNameInSameEntityIsRejected(): void + { + $this->login(); + + $name = 'Duplicate Reference_' . $this->getUniqueString(); + $entities_id = $this->getTestRootEntity(true); + + $reference1 = new PluginOrderReference(); + $id1 = $reference1->add([ + 'name' => $name, + 'entities_id' => $entities_id, + 'itemtype' => Computer::class, + ]); + $this->assertGreaterThan(0, $id1); + + $reference2 = new PluginOrderReference(); + $id2 = $reference2->add([ + 'name' => $name, + 'entities_id' => $entities_id, + 'itemtype' => Computer::class, + ]); + $this->assertFalse($id2); + $this->hasSessionMessages(ERROR, ['A reference with the same name still exists']); + } + + public function testLinkReferenceToSupplier(): void + { + $this->login(); + + $supplier = $this->createSupplier(); + $reference = $this->createReference($supplier, Computer::class, 150.5); + + $links = (new PluginOrderReference_Supplier())->find([ + 'plugin_order_references_id' => $reference->getID(), + 'suppliers_id' => $supplier->getID(), + ]); + + $this->assertCount(1, $links); + $link = reset($links); + $this->assertEqualsWithDelta(150.5, (float) $link['price_taxfree'], 0.001); + } + + public function testUpdateReference(): void + { + $this->login(); + + $reference = $this->createReference(); + + $this->updateItem(PluginOrderReference::class, $reference->getID(), [ + 'comment' => 'Updated reference comment', + ]); + + $reference->getFromDB($reference->getID()); + $this->assertSame('Updated reference comment', $reference->fields['comment']); + } + + public function testDeleteUnusedReference(): void + { + $this->login(); + + $reference = $this->createReference(); + + $this->assertTrue($reference->delete(['id' => $reference->getID()], true)); + $this->assertFalse((new PluginOrderReference())->getFromDB($reference->getID())); + } + + public function testDeletingReferenceInUseIsBlocked(): void + { + $this->login(); + + $supplier = $this->createSupplier(); + $order = $this->createOrder(); + $reference = $this->createReference($supplier); + $this->addReferenceToOrder($order, $reference); + + $this->assertFalse($reference->delete(['id' => $reference->getID()], true)); + $this->assertTrue((new PluginOrderReference())->getFromDB($reference->getID())); + $this->hasSessionMessages(ERROR, ['Reference(s) in use']); + } +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 0000000000..dd47afaba5 --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,36 @@ +. + * ------------------------------------------------------------------------- + * @copyright Copyright (C) 2009-2023 by Order plugin team. + * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html + * @link https://github.com/pluginsGLPI/order + * ------------------------------------------------------------------------- + */ + +require __DIR__ . '/../../../tests/bootstrap.php'; +require __DIR__ . '/../vendor/autoload.php'; + +if (!Plugin::isPluginActive('order')) { + throw new RuntimeException('Plugin order is not active in the test database'); +} From 3fde95230c784670027efa703eadb570d8324f52 Mon Sep 17 00:00:00 2001 From: Lainow Date: Mon, 31 Aug 2026 17:29:41 +0200 Subject: [PATCH 3/7] Fix lints --- .phpunit.result.cache | 2 +- composer.lock | 882 +++++++++++++++++++++++++- inc/bill.class.php | 2 +- inc/documentcategory.class.php | 6 +- inc/link.class.php | 20 +- inc/menu.class.php | 6 +- inc/notificationtargetorder.class.php | 2 +- inc/order.class.php | 14 +- inc/order_item.class.php | 8 +- inc/reception.class.php | 6 +- inc/reference.class.php | 6 +- inc/reference_supplier.class.php | 6 +- plugin.xml | 5 + 13 files changed, 921 insertions(+), 44 deletions(-) diff --git a/.phpunit.result.cache b/.phpunit.result.cache index f24212ede7..faa1fa2bf2 100644 --- a/.phpunit.result.cache +++ b/.phpunit.result.cache @@ -1 +1 @@ -{"version":2,"defects":{"GlpiPlugin\\Order\\Tests\\Units\\BillTest::testCreateBillRequiresNumber":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #0":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #1":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #2":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #3":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #4":8,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #5":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #6":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #7":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #8":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #9":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testCreateOrderWithoutNumOrderFails":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderableCapacityTest::testCapacityUsageDescriptionReflectsLinkedReferences":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderableCapacityTest::testDisablingCapacityCleansUpLinkedReferencesAndOrderItems":7,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testCreateReferenceWithoutNameFails":7,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testCreateReferenceWithoutItemtypeFails":7,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testDuplicateNameInSameEntityIsRejected":7,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testDeletingReferenceInUseIsBlocked":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderItemTest::testAddDetailsCreatesOneLinePerQuantity":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testCanceledOrderCannotBeCanceledAgain":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderItemTest::testGetAllPricesSumsOrderLines":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testDeliveredStateSetsDeliveryDate":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testUndoValidationRequiresRightAndValidatedState":7,"GlpiPlugin\\Order\\Tests\\Units\\ProfileTest::testGetAllRightsDeclaresTheThreeRightBuckets":7},"times":{"GlpiPlugin\\Order\\Tests\\Units\\BillTest::testCreateBillRequiresNumber":0.106,"GlpiPlugin\\Order\\Tests\\Units\\BillTest::testCreateBillLinkedToOrderAndSupplier":0.07,"GlpiPlugin\\Order\\Tests\\Units\\BillTest::testUpdateBill":0.064,"GlpiPlugin\\Order\\Tests\\Units\\BillTest::testDeleteBill":0.222,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #0":0.089,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #1":0.09,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #2":0.09,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #3":0.09,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #4":0.089,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #5":0.089,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #6":0.089,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #7":0.091,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #8":0.089,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #9":0.089,"GlpiPlugin\\Order\\Tests\\Units\\OrderItemTest::testGetClassesIncludesNativeGlpiAssets":0.053,"GlpiPlugin\\Order\\Tests\\Units\\OrderItemTest::testAddDetailsCreatesOneLinePerQuantity":0.075,"GlpiPlugin\\Order\\Tests\\Units\\OrderItemTest::testGetAllPricesSumsOrderLines":0.068,"GlpiPlugin\\Order\\Tests\\Units\\OrderItemTest::testDeletingOrderItemDoesNotDeleteTheOrder":0.098,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testCreateOrderIsDraftByDefault":0.056,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testCreateOrderWithoutNumOrderFails":0.054,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testUpdateOrder":0.058,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testUpdateOrderStatusAddsHistoryLog":0.058,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testDeliveredStateSetsDeliveryDate":0.057,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testCanValidateOrderWithoutValidationProcessDependsOnDraftState":0.06,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testCanCancelOrderRequiresRight":0.098,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testCanceledOrderCannotBeCanceledAgain":0.067,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testUndoValidationRequiresRightAndValidatedState":0.091,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testPurgingOrderCascadesToRelatedItems":0.137,"GlpiPlugin\\Order\\Tests\\Units\\OrderableCapacityTest::testCapacityUsageDescriptionReflectsLinkedReferences":0.124,"GlpiPlugin\\Order\\Tests\\Units\\OrderableCapacityTest::testDisablingCapacityCleansUpLinkedReferencesAndOrderItems":0.203,"GlpiPlugin\\Order\\Tests\\Units\\ProfileTest::testGetAllRightsDeclaresTheThreeRightBuckets":0.001,"GlpiPlugin\\Order\\Tests\\Units\\ProfileTest::testEveryDeclaredRightIsRegisteredInProfileRights":0.003,"GlpiPlugin\\Order\\Tests\\Units\\ProfileTest::testToggleOrderRightBitOnProfile":0.016,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testCreateReference":0.061,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testCreateReferenceWithoutNameFails":0.059,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testCreateReferenceWithoutItemtypeFails":0.055,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testDuplicateNameInSameEntityIsRejected":0.078,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testLinkReferenceToSupplier":0.087,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testUpdateReference":0.062,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testDeleteUnusedReference":0.098,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testDeletingReferenceInUseIsBlocked":0.072}} \ No newline at end of file +{"version":2,"defects":{"GlpiPlugin\\Order\\Tests\\Units\\BillTest::testCreateBillRequiresNumber":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #0":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #1":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #2":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #3":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #4":8,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #5":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #6":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #7":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #8":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #9":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testCreateOrderWithoutNumOrderFails":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderableCapacityTest::testCapacityUsageDescriptionReflectsLinkedReferences":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderableCapacityTest::testDisablingCapacityCleansUpLinkedReferencesAndOrderItems":7,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testCreateReferenceWithoutNameFails":7,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testCreateReferenceWithoutItemtypeFails":7,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testDuplicateNameInSameEntityIsRejected":7,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testDeletingReferenceInUseIsBlocked":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderItemTest::testAddDetailsCreatesOneLinePerQuantity":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testCanceledOrderCannotBeCanceledAgain":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderItemTest::testGetAllPricesSumsOrderLines":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testDeliveredStateSetsDeliveryDate":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testUndoValidationRequiresRightAndValidatedState":7,"GlpiPlugin\\Order\\Tests\\Units\\ProfileTest::testGetAllRightsDeclaresTheThreeRightBuckets":7},"times":{"GlpiPlugin\\Order\\Tests\\Units\\BillTest::testCreateBillRequiresNumber":0.11,"GlpiPlugin\\Order\\Tests\\Units\\BillTest::testCreateBillLinkedToOrderAndSupplier":0.079,"GlpiPlugin\\Order\\Tests\\Units\\BillTest::testUpdateBill":0.071,"GlpiPlugin\\Order\\Tests\\Units\\BillTest::testDeleteBill":0.247,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #0":0.096,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #1":0.094,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #2":0.093,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #3":0.091,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #4":0.089,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #5":0.09,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #6":0.089,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #7":0.088,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #8":0.088,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #9":0.088,"GlpiPlugin\\Order\\Tests\\Units\\OrderItemTest::testGetClassesIncludesNativeGlpiAssets":0.052,"GlpiPlugin\\Order\\Tests\\Units\\OrderItemTest::testAddDetailsCreatesOneLinePerQuantity":0.071,"GlpiPlugin\\Order\\Tests\\Units\\OrderItemTest::testGetAllPricesSumsOrderLines":0.07,"GlpiPlugin\\Order\\Tests\\Units\\OrderItemTest::testDeletingOrderItemDoesNotDeleteTheOrder":0.099,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testCreateOrderIsDraftByDefault":0.056,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testCreateOrderWithoutNumOrderFails":0.053,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testUpdateOrder":0.058,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testUpdateOrderStatusAddsHistoryLog":0.058,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testDeliveredStateSetsDeliveryDate":0.06,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testCanValidateOrderWithoutValidationProcessDependsOnDraftState":0.061,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testCanCancelOrderRequiresRight":0.101,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testCanceledOrderCannotBeCanceledAgain":0.075,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testUndoValidationRequiresRightAndValidatedState":0.092,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testPurgingOrderCascadesToRelatedItems":0.15,"GlpiPlugin\\Order\\Tests\\Units\\OrderableCapacityTest::testCapacityUsageDescriptionReflectsLinkedReferences":0.126,"GlpiPlugin\\Order\\Tests\\Units\\OrderableCapacityTest::testDisablingCapacityCleansUpLinkedReferencesAndOrderItems":0.202,"GlpiPlugin\\Order\\Tests\\Units\\ProfileTest::testGetAllRightsDeclaresTheThreeRightBuckets":0.002,"GlpiPlugin\\Order\\Tests\\Units\\ProfileTest::testEveryDeclaredRightIsRegisteredInProfileRights":0.002,"GlpiPlugin\\Order\\Tests\\Units\\ProfileTest::testToggleOrderRightBitOnProfile":0.013,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testCreateReference":0.056,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testCreateReferenceWithoutNameFails":0.055,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testCreateReferenceWithoutItemtypeFails":0.054,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testDuplicateNameInSameEntityIsRejected":0.057,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testLinkReferenceToSupplier":0.062,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testUpdateReference":0.058,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testDeleteUnusedReference":0.091,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testDeletingReferenceInUseIsBlocked":0.065}} \ No newline at end of file diff --git a/composer.lock b/composer.lock index 5af9ec3850..62c91af32c 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": "9983e2a4f2c2e3a6e4da04c757167a2d", + "content-hash": "2bde386e0433e43036c970ecd142d686", "packages": [ { "name": "sboden/odtphp", @@ -61,18 +61,890 @@ "time": "2025-07-24T20:26:09+00:00" } ], - "packages-dev": [], + "packages-dev": [ + { + "name": "glpi-project/tools", + "version": "0.8.3", + "source": { + "type": "git", + "url": "https://github.com/glpi-project/tools.git", + "reference": "8ea2a7d4702a858f4b0360ba7d4f1841a5e77026" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/glpi-project/tools/zipball/8ea2a7d4702a858f4b0360ba7d4f1841a5e77026", + "reference": "8ea2a7d4702a858f4b0360ba7d4f1841a5e77026", + "shasum": "" + }, + "require": { + "symfony/console": "^5.4 || ^6.0", + "twig/twig": "^3.3" + }, + "require-dev": { + "nikic/php-parser": "^4.13", + "phpstan/phpstan-src": "^1.10" + }, + "bin": [ + "bin/extract-locales", + "bin/licence-headers-check", + "tools/plugin-release" + ], + "type": "library", + "autoload": { + "psr-4": { + "GlpiProject\\Tools\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-3.0-or-later" + ], + "authors": [ + { + "name": "Teclib'", + "email": "glpi@teclib.com", + "homepage": "http://teclib-group.com" + } + ], + "description": "Various tools for GLPI and its plugins", + "keywords": [ + "glpi", + "plugins", + "tools" + ], + "support": { + "issues": "https://github.com/glpi-project/tools/issues", + "source": "https://github.com/glpi-project/tools" + }, + "time": "2025-10-14T10:26:06+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "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/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "symfony/console", + "version": "v6.4.45", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "3b8473e0d14157f2d22b0a0d7259ad23483d1e6d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/3b8473e0d14157f2d22b0a0d7259ad23483d1e6d", + "reference": "3b8473e0d14157f2d22b0a0d7259ad23483d1e6d", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^5.4|^6.0|^7.0" + }, + "conflict": { + "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|3.0" + }, + "require-dev": { + "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": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command-line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v6.4.45" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "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": "2026-08-25T13:08:31+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.7.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/f3202fa1b5097b0af062dc978b32ecf63404e31d", + "reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.7-dev" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.7.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "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": "2026-06-05T06:23:12+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.37.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "141046a8f9477948ff284fa65be2095baafb94f2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/141046a8f9477948ff284fa65be2095baafb94f2", + "reference": "141046a8f9477948ff284fa65be2095baafb94f2", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.37.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "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": "2026-04-10T16:19:22+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.41.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/bb899c1db0aa8127dc3afe8cda4a67eb24915f8d", + "reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.41.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "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": "2026-07-28T08:25:59+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.42.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "aa20edea75bd9c48cfecc8360922e5a6e5c44502" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/aa20edea75bd9c48cfecc8360922e5a6e5c44502", + "reference": "aa20edea75bd9c48cfecc8360922e5a6e5c44502", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.42.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "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": "2026-08-07T06:33:24+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.38.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6", + "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "php": ">=7.2" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.38.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "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": "2026-05-27T06:59:30+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.7.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "15e6a07ec2a2c75ceb1b21dd98105ee8456d2257" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/15e6a07ec2a2c75ceb1b21dd98105ee8456d2257", + "reference": "15e6a07ec2a2c75ceb1b21dd98105ee8456d2257", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.7.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "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": "2026-07-27T15:39:01+00:00" + }, + { + "name": "symfony/string", + "version": "v7.4.15", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "e394af32256bf9e7bf80849d95e589167c10097b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/e394af32256bf9e7bf80849d95e589167c10097b", + "reference": "e394af32256bf9e7bf80849d95e589167c10097b", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.33", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.5" + }, + "require-dev": { + "symfony/emoji": "^7.1|^8.0", + "symfony/http-client": "^6.4|^7.0|^8.0", + "symfony/intl": "^6.4|^7.0|^8.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^6.4|^7.0|^8.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v7.4.15" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "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": "2026-07-28T07:33:02+00:00" + }, + { + "name": "twig/twig", + "version": "v3.28.0", + "source": { + "type": "git", + "url": "https://github.com/twigphp/Twig.git", + "reference": "597c12ed286fb9d1701a36684ce6e0cbe28ebc8b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/597c12ed286fb9d1701a36684ce6e0cbe28ebc8b", + "reference": "597c12ed286fb9d1701a36684ce6e0cbe28ebc8b", + "shasum": "" + }, + "require": { + "php": ">=8.1.0", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-mbstring": "^1.3" + }, + "require-dev": { + "php-cs-fixer/shim": "^3.0@stable", + "phpstan/phpstan": "^2.0@stable", + "psr/container": "^1.0|^2.0", + "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "src/Resources/core.php", + "src/Resources/debug.php", + "src/Resources/escaper.php", + "src/Resources/string_loader.php" + ], + "psr-4": { + "Twig\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + }, + { + "name": "Twig Team", + "role": "Contributors" + }, + { + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "role": "Project Founder" + } + ], + "description": "Twig, the flexible, fast, and secure template language for PHP", + "homepage": "https://twig.symfony.com", + "keywords": [ + "templating" + ], + "support": { + "issues": "https://github.com/twigphp/Twig/issues", + "source": "https://github.com/twigphp/Twig/tree/v3.28.0" + }, + "funding": [ + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/twig/twig", + "type": "tidelift" + } + ], + "time": "2026-07-03T20:44:34+00:00" + } + ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { "php": ">=8.2" }, - "platform-dev": {}, + "platform-dev": [], "platform-overrides": { "php": "8.2.99" }, - "plugin-api-version": "2.9.0" + "plugin-api-version": "2.6.0" } diff --git a/inc/bill.class.php b/inc/bill.class.php index c0239ba5c4..a1ed70bc0d 100644 --- a/inc/bill.class.php +++ b/inc/bill.class.php @@ -641,7 +641,7 @@ public static function uninstall() public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { if (!$withtemplate) { - switch ($item->getType()) { + switch ($item::class) { case 'PluginOrderOrder': return self::createTabEntry( self::getTypeName(), diff --git a/inc/documentcategory.class.php b/inc/documentcategory.class.php index b674ec1150..2e91df91d7 100644 --- a/inc/documentcategory.class.php +++ b/inc/documentcategory.class.php @@ -42,7 +42,7 @@ public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { $config = PluginOrderConfig::getConfig(); - if ($item->getType() == "DocumentCategory" && $config->canRenameDocuments()) { + if ($item::class == "DocumentCategory" && $config->canRenameDocuments()) { return __s("Orders", "order"); } @@ -54,7 +54,7 @@ public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $ { $config = PluginOrderConfig::getConfig(); - if ($item->getType() == "DocumentCategory" && $config->canRenameDocuments()) { + if ($item::class == "DocumentCategory" && $config->canRenameDocuments()) { self::showForDocumentCategory($item); } @@ -79,7 +79,7 @@ public static function showForDocumentCategory($item) } echo ""; + . Toolbox::getItemTypeFormURL($documentCategory::class) . "'>"; echo "
"; echo ""; diff --git a/inc/link.class.php b/inc/link.class.php index 35185be4b2..69a5efecad 100644 --- a/inc/link.class.php +++ b/inc/link.class.php @@ -625,11 +625,11 @@ public static function processMassiveActionsForOneItemtype( foreach ($ma->getItems()[self::class] as $key => $val) { $itemtype = $ma->POST['add_items'][$key]['itemtype'] ?? ''; if (in_array($itemtype, self::getTypesThanCannotBeGenerated()) && $itemtype !== 'SoftwareLicense') { - $ma->itemDone($item->getType(), $key, MassiveAction::ACTION_OK); + $ma->itemDone($item::class, $key, MassiveAction::ACTION_OK); } elseif (isset($newIDs[$key]) && $newIDs[$key]) { - $ma->itemDone($item->getType(), $key, MassiveAction::ACTION_OK); + $ma->itemDone($item::class, $key, MassiveAction::ACTION_OK); } else { - $ma->itemDone($item->getType(), $key, MassiveAction::ACTION_KO); + $ma->itemDone($item::class, $key, MassiveAction::ACTION_KO); } } @@ -652,7 +652,7 @@ public static function processMassiveActionsForOneItemtype( if (!$allow_multiple_link && count($ids) > 1) { $ma->addMessage(__s("Cannot link several items to one detail line", "order")); foreach ($ids as $id) { - $ma->itemDone($item->getType(), $id, MassiveAction::ACTION_KO); + $ma->itemDone($item::class, $id, MassiveAction::ACTION_KO); } break; @@ -663,7 +663,7 @@ public static function processMassiveActionsForOneItemtype( $order_item->getFromDB($val); if ($order_item->fields["states_id"] == PluginOrderOrder::ORDER_DEVICE_NOT_DELIVRED) { $ma->addMessage(__s("Cannot link items not delivered", "order")); - $ma->itemDone($item->getType(), $key, MassiveAction::ACTION_KO); + $ma->itemDone($item::class, $key, MassiveAction::ACTION_KO); } else { $link->createLinkWithItem( $key, @@ -671,7 +671,7 @@ public static function processMassiveActionsForOneItemtype( $ma->POST['add_items'][$key]['itemtype'], $ma->POST['plugin_order_orders_id'], ); - $ma->itemDone($item->getType(), $key, MassiveAction::ACTION_OK); + $ma->itemDone($item::class, $key, MassiveAction::ACTION_OK); } } @@ -684,7 +684,7 @@ public static function processMassiveActionsForOneItemtype( $ma->POST['add_items'][$key]['itemtype'], $ma->POST['plugin_order_orders_id'], ); - $ma->itemDone($item->getType(), $val, MassiveAction::ACTION_OK); + $ma->itemDone($item::class, $val, MassiveAction::ACTION_OK); } break; @@ -695,11 +695,11 @@ public static function processMassiveActionsForOneItemtype( $order_item->getFromDB($key); if ($order_item->fields["items_id"] != 0) { $ma->addMessage(__s("Unable to cancel reception when items are already linked, please unlink them before trying again.", "order")); - $ma->itemDone($item->getType(), $key, MassiveAction::ACTION_KO); + $ma->itemDone($item::class, $key, MassiveAction::ACTION_KO); } elseif (!$link->cancelReception($key)) { - $ma->itemDone($item->getType(), $key, MassiveAction::ACTION_KO); + $ma->itemDone($item::class, $key, MassiveAction::ACTION_KO); } else { - $ma->itemDone($item->getType(), $key, MassiveAction::ACTION_OK); + $ma->itemDone($item::class, $key, MassiveAction::ACTION_OK); } } diff --git a/inc/menu.class.php b/inc/menu.class.php index 5c6b5571c6..fe58f9abf6 100644 --- a/inc/menu.class.php +++ b/inc/menu.class.php @@ -66,7 +66,7 @@ public static function getMenuContent() } $menu['options']['order']['links']['lists'] = ""; - $menu['options']['order']['lists_itemtype'] = PluginOrderOrder::getType(); + $menu['options']['order']['lists_itemtype'] = PluginOrderOrder::class; } if (PluginOrderBill::canView()) { @@ -87,7 +87,7 @@ public static function getMenuContent() } $menu['options']['bill']['links']['lists'] = ""; - $menu['options']['bill']['lists_itemtype'] = PluginOrderBill::getType(); + $menu['options']['bill']['lists_itemtype'] = PluginOrderBill::class; } if (PluginOrderReference::canView()) { @@ -108,7 +108,7 @@ public static function getMenuContent() } $menu['options']['references']['links']['lists'] = ""; - $menu['options']['references']['lists_itemtype'] = PluginOrderReference::getType(); + $menu['options']['references']['lists_itemtype'] = PluginOrderReference::class; } return $menu; diff --git a/inc/notificationtargetorder.class.php b/inc/notificationtargetorder.class.php index 940d2907c7..58fa934aa3 100644 --- a/inc/notificationtargetorder.class.php +++ b/inc/notificationtargetorder.class.php @@ -157,7 +157,7 @@ public function addDataForTemplate($event, $options = []) $this->data['##lang.ordervalidation.url##'] = "URL"; $this->data['##ordervalidation.url##'] = $this->formatURL( $options['additionnaloption']['usertype'], - $this->obj->getType() . "_" . $this->obj->getField("id"), + $this->obj::class . "_" . $this->obj->getField("id"), ); } } diff --git a/inc/order.class.php b/inc/order.class.php index 341f98c2cf..577d4eb5fc 100644 --- a/inc/order.class.php +++ b/inc/order.class.php @@ -751,13 +751,13 @@ public function post_addItem() "glpi_documents_items", [ 'items_id' => $this->input["_oldID"], - 'itemtype' => $this->getType(), + 'itemtype' => static::class, ], ); foreach ($docs as $doc) { $docitem->add([ 'documents_id' => $doc["documents_id"], - 'itemtype' => $this->getType(), + 'itemtype' => static::class, 'items_id' => $this->fields['id'], ]); } @@ -913,7 +913,7 @@ public function showForm($ID, $options = []) $this->fields["name"], "name", ($template === "newcomp"), - $this->getType(), + static::class, $this->fields["entities_id"], ); echo Html::input( @@ -960,7 +960,7 @@ public function showForm($ID, $options = []) $this->fields["num_order"], "num_order", ($template === "newcomp"), - $this->getType(), + static::class, $this->fields["entities_id"], ); echo Html::input( @@ -1579,7 +1579,7 @@ public function addStatusLog($orders_id, $status, $comments = '') $changes .= " : " . $comments; } - $this->addHistory($this->getType(), '', $changes, $orders_id); + $this->addHistory(static::class, '', $changes, $orders_id); } @@ -2519,7 +2519,7 @@ public static function addDocumentCategory(Document $document) // Get order linked to document $document_item = new Document_Item(); - if ($document_item->getFromDBByCrit(['documents_id' => $document->fields['id'], 'itemtype' => self::getType()])) { + if ($document_item->getFromDBByCrit(['documents_id' => $document->fields['id'], 'itemtype' => static::class])) { // Update document name $order = new self(); $order->getFromDB($document_item->fields['items_id']); @@ -2594,7 +2594,7 @@ public static function processMassiveActionsForOneItemtype(MassiveAction $ma, Co "entities_id" => $entities_id, "update" => __s('Update'), ]); - $ma->itemDone($item->getType(), $id, MassiveAction::ACTION_OK); + $ma->itemDone($item::class, $id, MassiveAction::ACTION_OK); } } diff --git a/inc/order_item.class.php b/inc/order_item.class.php index 7ebf696fdc..808ef145f2 100644 --- a/inc/order_item.class.php +++ b/inc/order_item.class.php @@ -918,7 +918,7 @@ public function showFormDetail($plugin_order_orders_id) $canedit = $order->can($plugin_order_orders_id, UPDATE) && $order->canUpdateOrder(); Session::initNavigateListItems( - $this->getType(), + static::class, __s("Order", "order") . " = " . $order->getName(), ); foreach ($result_ref as $data_ref) { @@ -1201,7 +1201,7 @@ public function getItems($rand, $data_ref, $plugin_order_orders_id, $numref, $ca $visible = $_GET[$countainer_name . 'visible'] ?? false; foreach ($iterator as $data) { - Session::addToNavigateListItems($this->getType(), (int) $data['IDD']); + Session::addToNavigateListItems(static::class, (int) $data['IDD']); // Build entry for this row $entry = []; @@ -2219,7 +2219,7 @@ public static function countForItem(CommonDBTM $item) return countElementsInTable( 'glpi_plugin_order_orders_items', [ - 'itemtype' => $item->getType(), + 'itemtype' => $item::class, 'items_id' => $item->getID(), ], ); @@ -2271,7 +2271,7 @@ public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $ } } elseif ( is_subclass_of($item, CommonDBTM::class) - && in_array($item->getType(), PluginOrderOrder_Item::getClasses(true)) + && in_array($item::class, PluginOrderOrder_Item::getClasses(true)) ) { $order_item = new self(); $order_item->showPluginFromItems($item::class, $item->fields['id']); diff --git a/inc/reception.class.php b/inc/reception.class.php index 74c4516f25..24bdbea6bf 100644 --- a/inc/reception.class.php +++ b/inc/reception.class.php @@ -318,7 +318,7 @@ public function showOrderReception($orders_id) $order_order->getFromDB($orders_id); Session::initNavigateListItems( - $this->getType(), + static::class, __s("Order", "order") . " = " . $order_order->fields["name"], ); @@ -531,7 +531,7 @@ public function showOrderReceptionItem($data_ref, $numref, $canedit, $reference, foreach ($all_data as $data) { $detailID = $data["IDD"]; - Session::addToNavigateListItems($this->getType(), (int) $detailID); + Session::addToNavigateListItems(static::class, (int) $detailID); echo ""; $status = 1; if ($typeRef != 'SoftwareLicense') { @@ -562,7 +562,7 @@ public function showOrderReceptionItem($data_ref, $numref, $canedit, $reference, } echo ""; echo ""; - $link = Toolbox::getItemTypeFormURL($this->getType()); + $link = Toolbox::getItemTypeFormURL(static::class); echo ""; echo "
" . __s('Document category prefix', 'order') . "
"; - $link = Toolbox::getItemTypeFormURL($this->getType()); + $link = Toolbox::getItemTypeFormURL(static::class); if ($canedit && $data["states_id"] == PluginOrderOrder::ORDER_DEVICE_DELIVRED) { echo ''; } diff --git a/inc/reference.class.php b/inc/reference.class.php index b832b1ca03..5fbba29882 100644 --- a/inc/reference.class.php +++ b/inc/reference.class.php @@ -355,7 +355,7 @@ public function referenceInUse() public function getReceptionReferenceLink($data) { - $link = Toolbox::getItemTypeFormURL($this->getType()); + $link = Toolbox::getItemTypeFormURL(static::class); if (self::canView()) { return '' . $data["name"] . ""; @@ -1061,7 +1061,7 @@ public static function processMassiveActionsForOneItemtype(MassiveAction $ma, Co "entities_id" => $entities_id, "update" => __s('Update'), ]); - $ma->itemDone($item->getType(), $id, MassiveAction::ACTION_OK); + $ma->itemDone($item::class, $id, MassiveAction::ACTION_OK); } } @@ -1075,7 +1075,7 @@ public static function processMassiveActionsForOneItemtype(MassiveAction $ma, Co $item->copy($id); } - $ma->itemDone($item->getType(), $id, MassiveAction::ACTION_OK); + $ma->itemDone($item::class, $id, MassiveAction::ACTION_OK); } return; diff --git a/inc/reference_supplier.class.php b/inc/reference_supplier.class.php index 5f6edb04cc..72d186c812 100644 --- a/inc/reference_supplier.class.php +++ b/inc/reference_supplier.class.php @@ -273,7 +273,7 @@ public function showReferenceManufacturers($ID) $target = Toolbox::getItemTypeFormURL(self::class); Session::initNavigateListItems( - $this->getType(), + static::class, __s("Product reference", "order") . " = " . $ref->fields["name"], ); @@ -308,7 +308,7 @@ public function showReferenceManufacturers($ID) echo Html::hidden('plugin_order_references_id', ['value' => $ID]); foreach ($result as $data) { - Session::addToNavigateListItems($this->getType(), (int) $data['id']); + Session::addToNavigateListItems(static::class, (int) $data['id']); echo Html::hidden("item[" . $data["id"] . "]", ['value' => $ID]); echo "
"; @@ -332,7 +332,7 @@ public function showReferenceManufacturers($ID) echo "" . Dropdown::getDropdownName("glpi_suppliers", (int) $data["suppliers_id"]) . ""; diff --git a/plugin.xml b/plugin.xml index b7d44e3bfb..b5855c4725 100644 --- a/plugin.xml +++ b/plugin.xml @@ -29,6 +29,11 @@ Benjamin Fontan + + 2.13.0 + ~12.0.0 + https://github.com/pluginsGLPI/order/releases/download/2.13.0/glpi-order-2.13.0.tar.bz2 + 2.12.9 ~11.0.0 From 1ee28f817ae509656b8ccb03055e5ab9d19fda29 Mon Sep 17 00:00:00 2001 From: Lainow Date: Tue, 1 Sep 2026 09:58:27 +0200 Subject: [PATCH 4/7] 2.13.0 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a677c5171a..f885b14f81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ 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] +## [2.13.0] ### Added From 0a0c352f3a70ecc0934a87fa5c512ef953ad2aa8 Mon Sep 17 00:00:00 2001 From: Stanislas Kita <7335054+stonebuzz@users.noreply.github.com> Date: Tue, 1 Sep 2026 11:07:00 +0200 Subject: [PATCH 5/7] fix composer --- composer.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/composer.json b/composer.json index 29b65e40f3..36ee69f733 100644 --- a/composer.json +++ b/composer.json @@ -4,9 +4,6 @@ "php": ">=8.2", "sboden/odtphp": "^3.2" }, - "require-dev": { - "glpi-project/tools": "^0.8" - }, "config": { "optimize-autoloader": true, "platform": { From 10ff383db51107cbe50fc606c98a68677b7d0e63 Mon Sep 17 00:00:00 2001 From: Lainow Date: Tue, 1 Sep 2026 11:48:11 +0200 Subject: [PATCH 6/7] Remove version number --- .gitignore | 1 + .phpunit.result.cache | 1 - CHANGELOG.md | 2 +- plugin.xml | 5 ----- 4 files changed, 2 insertions(+), 7 deletions(-) delete mode 100644 .phpunit.result.cache diff --git a/.gitignore b/.gitignore index 044ece9716..8b75e501cf 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ vendor/ .gh_token *.min.* var/ +.phpunit.result.cache \ No newline at end of file diff --git a/.phpunit.result.cache b/.phpunit.result.cache deleted file mode 100644 index faa1fa2bf2..0000000000 --- a/.phpunit.result.cache +++ /dev/null @@ -1 +0,0 @@ -{"version":2,"defects":{"GlpiPlugin\\Order\\Tests\\Units\\BillTest::testCreateBillRequiresNumber":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #0":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #1":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #2":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #3":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #4":8,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #5":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #6":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #7":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #8":7,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #9":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testCreateOrderWithoutNumOrderFails":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderableCapacityTest::testCapacityUsageDescriptionReflectsLinkedReferences":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderableCapacityTest::testDisablingCapacityCleansUpLinkedReferencesAndOrderItems":7,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testCreateReferenceWithoutNameFails":7,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testCreateReferenceWithoutItemtypeFails":7,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testDuplicateNameInSameEntityIsRejected":7,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testDeletingReferenceInUseIsBlocked":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderItemTest::testAddDetailsCreatesOneLinePerQuantity":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testCanceledOrderCannotBeCanceledAgain":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderItemTest::testGetAllPricesSumsOrderLines":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testDeliveredStateSetsDeliveryDate":7,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testUndoValidationRequiresRightAndValidatedState":7,"GlpiPlugin\\Order\\Tests\\Units\\ProfileTest::testGetAllRightsDeclaresTheThreeRightBuckets":7},"times":{"GlpiPlugin\\Order\\Tests\\Units\\BillTest::testCreateBillRequiresNumber":0.11,"GlpiPlugin\\Order\\Tests\\Units\\BillTest::testCreateBillLinkedToOrderAndSupplier":0.079,"GlpiPlugin\\Order\\Tests\\Units\\BillTest::testUpdateBill":0.071,"GlpiPlugin\\Order\\Tests\\Units\\BillTest::testDeleteBill":0.247,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #0":0.096,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #1":0.094,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #2":0.093,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #3":0.091,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #4":0.089,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #5":0.09,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #6":0.089,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #7":0.088,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #8":0.088,"GlpiPlugin\\Order\\Tests\\Units\\DropdownsTest::testCreateUpdateAndDeleteDropdown with data set #9":0.088,"GlpiPlugin\\Order\\Tests\\Units\\OrderItemTest::testGetClassesIncludesNativeGlpiAssets":0.052,"GlpiPlugin\\Order\\Tests\\Units\\OrderItemTest::testAddDetailsCreatesOneLinePerQuantity":0.071,"GlpiPlugin\\Order\\Tests\\Units\\OrderItemTest::testGetAllPricesSumsOrderLines":0.07,"GlpiPlugin\\Order\\Tests\\Units\\OrderItemTest::testDeletingOrderItemDoesNotDeleteTheOrder":0.099,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testCreateOrderIsDraftByDefault":0.056,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testCreateOrderWithoutNumOrderFails":0.053,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testUpdateOrder":0.058,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testUpdateOrderStatusAddsHistoryLog":0.058,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testDeliveredStateSetsDeliveryDate":0.06,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testCanValidateOrderWithoutValidationProcessDependsOnDraftState":0.061,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testCanCancelOrderRequiresRight":0.101,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testCanceledOrderCannotBeCanceledAgain":0.075,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testUndoValidationRequiresRightAndValidatedState":0.092,"GlpiPlugin\\Order\\Tests\\Units\\OrderTest::testPurgingOrderCascadesToRelatedItems":0.15,"GlpiPlugin\\Order\\Tests\\Units\\OrderableCapacityTest::testCapacityUsageDescriptionReflectsLinkedReferences":0.126,"GlpiPlugin\\Order\\Tests\\Units\\OrderableCapacityTest::testDisablingCapacityCleansUpLinkedReferencesAndOrderItems":0.202,"GlpiPlugin\\Order\\Tests\\Units\\ProfileTest::testGetAllRightsDeclaresTheThreeRightBuckets":0.002,"GlpiPlugin\\Order\\Tests\\Units\\ProfileTest::testEveryDeclaredRightIsRegisteredInProfileRights":0.002,"GlpiPlugin\\Order\\Tests\\Units\\ProfileTest::testToggleOrderRightBitOnProfile":0.013,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testCreateReference":0.056,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testCreateReferenceWithoutNameFails":0.055,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testCreateReferenceWithoutItemtypeFails":0.054,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testDuplicateNameInSameEntityIsRejected":0.057,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testLinkReferenceToSupplier":0.062,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testUpdateReference":0.058,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testDeleteUnusedReference":0.091,"GlpiPlugin\\Order\\Tests\\Units\\ReferenceTest::testDeletingReferenceInUseIsBlocked":0.065}} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index f885b14f81..5a04aea38e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ 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/). -## [2.13.0] +## [unreleased] ### Added diff --git a/plugin.xml b/plugin.xml index b5855c4725..b7d44e3bfb 100644 --- a/plugin.xml +++ b/plugin.xml @@ -29,11 +29,6 @@ Benjamin Fontan - - 2.13.0 - ~12.0.0 - https://github.com/pluginsGLPI/order/releases/download/2.13.0/glpi-order-2.13.0.tar.bz2 - 2.12.9 ~11.0.0 From bf38d77072b54687df993c416dbdcadf2390b647 Mon Sep 17 00:00:00 2001 From: Lainow Date: Thu, 3 Sep 2026 17:16:12 +0200 Subject: [PATCH 7/7] Fix suggestions --- public/css/order.css | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/public/css/order.css b/public/css/order.css index 8bbc0f5417..694aba60cd 100644 --- a/public/css/order.css +++ b/public/css/order.css @@ -37,7 +37,9 @@ input[type="number"].quantity { input[type="number"].decimal, input[type="number"].smalldecimal, input[type="number"].quantity { - width: 100px; + width: 100%; + max-width: 100px; + box-sizing: border-box; } input[type="number"].decimal::-webkit-inner-spin-button, @@ -70,6 +72,30 @@ input[type="number"].quantity::-webkit-inner-spin-button { width: 25%; } +/* quantity */ +.tab_order_add_items th:nth-child(4), +.tab_order_add_items td:nth-child(4) { + width: 90px; +} + +/* unit price tax free */ +.tab_order_add_items th:nth-child(5), +.tab_order_add_items td:nth-child(5) { + width: 100px; +} + +/* VAT */ +.tab_order_add_items th:nth-child(6), +.tab_order_add_items td:nth-child(6) { + width: 130px; +} + +/* discount */ +.tab_order_add_items th:nth-child(7), +.tab_order_add_items td:nth-child(7) { + width: 100px; +} + /* ADD button */ .tab_order_add_items th:nth-child(8), .tab_order_add_items td:nth-child(8) {