From b1d912114a154631bdee537831c4ccd54a6cc657 Mon Sep 17 00:00:00 2001 From: Rom1-B <8530352+Rom1-B@users.noreply.github.com> Date: Mon, 17 Aug 2026 10:58:57 +0200 Subject: [PATCH 1/3] feature/glpi-12.0 --- CHANGELOG.md | 6 + composer.json | 3 - composer.lock | 722 +------------------ inc/abstractcontainerinstance.class.php | 4 +- inc/checkdatabasecommand.class.php | 2 +- inc/command/regeneratefilescommand.class.php | 4 +- inc/container.class.php | 2 +- inc/containerdisplaycondition.class.php | 4 +- inc/dropdown.class.php | 4 +- inc/field.class.php | 4 +- inc/labeltranslation.class.php | 4 +- inc/menu.class.php | 2 +- inc/profile.class.php | 8 +- inc/statusoverride.class.php | 4 +- setup.php | 4 +- templates/container.class.tpl | 2 +- templates/dropdown.class.tpl | 2 +- templates/injection.class.tpl | 2 +- 18 files changed, 35 insertions(+), 748 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7ff05c1..4b8b2c2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ 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] + +### Added + +- GLPI 12 compatibility + ## [1.24.4] - 2026-08-06 ### Fixed diff --git a/composer.json b/composer.json index 27d0106e..b5809263 100644 --- a/composer.json +++ b/composer.json @@ -3,9 +3,6 @@ "php": ">=8.2", "symfony/yaml": "^7.4" }, - "require-dev": { - "glpi-project/tools": "^0.8.3" - }, "config": { "optimize-autoloader": true, "platform": { diff --git a/composer.lock b/composer.lock index 75765ee6..bcc4234c 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": "bad011ca3a9a9c1776c1e7cc4b1e6d85", + "content-hash": "b87a0b8a1b33072443a8af342f9afbf9", "packages": [ { "name": "symfony/deprecation-contracts", @@ -237,725 +237,7 @@ "time": "2026-07-21T15:13:06+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/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/inc/abstractcontainerinstance.class.php b/inc/abstractcontainerinstance.class.php index 7b918fd2..871bb916 100644 --- a/inc/abstractcontainerinstance.class.php +++ b/inc/abstractcontainerinstance.class.php @@ -30,9 +30,9 @@ abstract class PluginFieldsAbstractContainerInstance extends CommonDBChild { - public static $itemtype = 'itemtype'; + public static string $itemtype = 'itemtype'; - public static $items_id = 'items_id'; + public static string $items_id = 'items_id'; /** * This function relies on the static property `static::$plugins_forward_entity`, diff --git a/inc/checkdatabasecommand.class.php b/inc/checkdatabasecommand.class.php index 758ac783..df0db760 100644 --- a/inc/checkdatabasecommand.class.php +++ b/inc/checkdatabasecommand.class.php @@ -58,7 +58,7 @@ protected function configure() ); } - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { // Read option $fix = $input->getOption('fix'); diff --git a/inc/command/regeneratefilescommand.class.php b/inc/command/regeneratefilescommand.class.php index ef69ca1c..8c9636c4 100644 --- a/inc/command/regeneratefilescommand.class.php +++ b/inc/command/regeneratefilescommand.class.php @@ -32,6 +32,8 @@ use Glpi\Console\AbstractCommand; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; class RegenerateFilesCommand extends AbstractCommand { @@ -44,7 +46,7 @@ protected function configure() ); } - protected function execute($input, $output) + protected function execute(InputInterface $input, OutputInterface $output): int { plugin_fields_checkFiles(); diff --git a/inc/container.class.php b/inc/container.class.php index 0c0b2ebb..c809f4aa 100644 --- a/inc/container.class.php +++ b/inc/container.class.php @@ -35,7 +35,7 @@ class PluginFieldsContainer extends CommonDBTM { use Clonable; - public static $rightname = 'config'; + public static string $rightname = 'config'; public static function canCreate(): bool { diff --git a/inc/containerdisplaycondition.class.php b/inc/containerdisplaycondition.class.php index 8c87b234..891907e5 100644 --- a/inc/containerdisplaycondition.class.php +++ b/inc/containerdisplaycondition.class.php @@ -34,9 +34,9 @@ class PluginFieldsContainerDisplayCondition extends CommonDBChild { use Clonable; - public static $itemtype = PluginFieldsContainer::class; + public static string $itemtype = PluginFieldsContainer::class; - public static $items_id = 'plugin_fields_containers_id'; + public static string $items_id = 'plugin_fields_containers_id'; public const SHOW_CONDITION_EQ = 1; diff --git a/inc/dropdown.class.php b/inc/dropdown.class.php index 3ec0d2eb..ba0e9bab 100644 --- a/inc/dropdown.class.php +++ b/inc/dropdown.class.php @@ -30,9 +30,9 @@ class PluginFieldsDropdown { - public static $rightname = 'dropdown'; + public static string $rightname = 'dropdown'; - public $can_be_translated = true; + public bool $can_be_translated = true; /** * Install or update user data. diff --git a/inc/field.class.php b/inc/field.class.php index 07f25d69..37212ada 100644 --- a/inc/field.class.php +++ b/inc/field.class.php @@ -42,9 +42,9 @@ class PluginFieldsField extends CommonDBChild */ public const SEARCH_OPTION_STARTING_INDEX = 76665; - public static $itemtype = PluginFieldsContainer::class; + public static string $itemtype = PluginFieldsContainer::class; - public static $items_id = 'plugin_fields_containers_id'; + public static string $items_id = 'plugin_fields_containers_id'; public function getForbiddenStandardMassiveAction() { diff --git a/inc/labeltranslation.class.php b/inc/labeltranslation.class.php index 8b1ff9ac..8a863742 100644 --- a/inc/labeltranslation.class.php +++ b/inc/labeltranslation.class.php @@ -34,9 +34,9 @@ class PluginFieldsLabelTranslation extends CommonDBChild { use Clonable; - public static $itemtype = 'itemtype'; + public static string $itemtype = 'itemtype'; - public static $items_id = 'items_id'; + public static string $items_id = 'items_id'; /** * Install or update plugin base data. diff --git a/inc/menu.class.php b/inc/menu.class.php index e1dda5bf..47277b1a 100644 --- a/inc/menu.class.php +++ b/inc/menu.class.php @@ -30,7 +30,7 @@ class PluginFieldsMenu extends CommonGLPI { - public static $rightname = 'entity'; + public static string $rightname = 'entity'; public static function getMenuName() { diff --git a/inc/profile.class.php b/inc/profile.class.php index 6cd97e32..e419340d 100644 --- a/inc/profile.class.php +++ b/inc/profile.class.php @@ -34,13 +34,13 @@ class PluginFieldsProfile extends CommonDBRelation { use Clonable; - public static $itemtype_1 = PluginFieldsContainer::class; + public static ?string $itemtype_1 = PluginFieldsContainer::class; - public static $items_id_1 = 'plugin_fields_containers_id'; + public static ?string $items_id_1 = 'plugin_fields_containers_id'; - public static $itemtype_2 = Profile::class; + public static ?string $itemtype_2 = Profile::class; - public static $items_id_2 = 'profiles_id'; + public static ?string $items_id_2 = 'profiles_id'; /** * Install or update plugin base data. diff --git a/inc/statusoverride.class.php b/inc/statusoverride.class.php index e60eda37..87c10f60 100644 --- a/inc/statusoverride.class.php +++ b/inc/statusoverride.class.php @@ -34,9 +34,9 @@ class PluginFieldsStatusOverride extends CommonDBChild { use Clonable; - public static $itemtype = PluginFieldsField::class; + public static string $itemtype = PluginFieldsField::class; - public static $items_id = 'plugin_fields_fields_id'; + public static string $items_id = 'plugin_fields_fields_id'; /** * Install or update plugin base data. diff --git a/setup.php b/setup.php index 78127f31..8109f6ee 100644 --- a/setup.php +++ b/setup.php @@ -34,9 +34,9 @@ define('PLUGIN_FIELDS_VERSION', '1.24.4'); // Minimal GLPI version, inclusive -define('PLUGIN_FIELDS_MIN_GLPI', '11.0.2'); +define('PLUGIN_FIELDS_MIN_GLPI', '12.0.0'); // Maximum GLPI version, exclusive -define('PLUGIN_FIELDS_MAX_GLPI', '11.0.99'); +define('PLUGIN_FIELDS_MAX_GLPI', '12.0.99'); if (!defined('PLUGINFIELDS_DIR')) { define('PLUGINFIELDS_DIR', Plugin::getPhpDir('fields')); diff --git a/templates/container.class.tpl b/templates/container.class.tpl index b1c7c04c..6c5a147d 100644 --- a/templates/container.class.tpl +++ b/templates/container.class.tpl @@ -4,7 +4,7 @@ use Glpi\DBAL\QueryParam; class %%CLASSNAME%% extends PluginFieldsAbstractContainerInstance { - static $rightname = %%ITEMTYPE_RIGHT%%; + public static string $rightname = %%ITEMTYPE_RIGHT%%; static function install() { global $DB; diff --git a/templates/dropdown.class.tpl b/templates/dropdown.class.tpl index 851fbacc..7ddd9b07 100644 --- a/templates/dropdown.class.tpl +++ b/templates/dropdown.class.tpl @@ -2,7 +2,7 @@ class %%CLASSNAME%% extends CommonTreeDropdown { public $field_name = %%FIELDNAME%%; - public $can_be_translated = true; + public bool $can_be_translated = true; static function getTypeName($nb=0) { $item = [ diff --git a/templates/injection.class.tpl b/templates/injection.class.tpl index 9568df20..3f0547b4 100644 --- a/templates/injection.class.tpl +++ b/templates/injection.class.tpl @@ -2,7 +2,7 @@ class %%CLASSNAME%%Injection extends %%CLASSNAME%% implements PluginDatainjectionInjectionInterface { - static $rightname = 'plugin_datainjection_model'; + public static string $rightname = 'plugin_datainjection_model'; /** * Return the table used to store this object From 5e7ca47b997454439ea26ddd1a0100691ed8f0fe Mon Sep 17 00:00:00 2001 From: Rom1-B <8530352+Rom1-B@users.noreply.github.com> Date: Mon, 17 Aug 2026 11:25:25 +0200 Subject: [PATCH 2/3] lint --- .github/workflows/continuous-integration.yml | 2 +- inc/container.class.php | 2 +- inc/containerdisplaycondition.class.php | 2 +- inc/destinationfield.class.php | 2 +- src/Controller/QuestionTypeAjaxController.php | 2 +- tests/QuestionTypeTestCase.php | 13 ++++--------- tests/Units/FieldDestinationFieldTest.php | 2 -- tests/Units/FieldQuestionTypeTest.php | 18 +++++++++--------- 8 files changed, 18 insertions(+), 25 deletions(-) diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 850f4482..4f6d5c53 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/inc/container.class.php b/inc/container.class.php index c809f4aa..d77714c4 100644 --- a/inc/container.class.php +++ b/inc/container.class.php @@ -1935,7 +1935,7 @@ public static function preItem(CommonDBTM $item) $entities = getSonsOf(getTableForItemType('Entity'), $loc_c->fields['entities_id']); } - if (count($item->fields) === 0) { + if ($item->fields === []) { $item->fields = $item->input; } diff --git a/inc/containerdisplaycondition.class.php b/inc/containerdisplaycondition.class.php index 891907e5..5aea4261 100644 --- a/inc/containerdisplaycondition.class.php +++ b/inc/containerdisplaycondition.class.php @@ -383,7 +383,7 @@ public static function removeBlackListedOption($array, $itemtype_class) $main_table == getTableForItemType($itemtype_class) ) { foreach ($foreignKey as $foreign_class) { - if (!is_array($foreign_class) && getTableNameForForeignKeyField($foreign_class) != getTableForItemType(Location::getType())) { + if (!is_array($foreign_class) && getTableNameForForeignKeyField($foreign_class) !== getTableForItemType(Location::getType())) { $allowed_table[] = getTableForItemType(getItemtypeForForeignKeyField($foreign_class)); } } diff --git a/inc/destinationfield.class.php b/inc/destinationfield.class.php index b55be89c..bacd9722 100644 --- a/inc/destinationfield.class.php +++ b/inc/destinationfield.class.php @@ -106,7 +106,7 @@ public function applyConfiguratedValueToInputUsingAnswers( continue; } - /** @var object{field_name: string} $item */ + /** @var CommonGLPI&object{field_name: string} $item */ $item = getItemForItemtype($itemtype); $field = new PluginFieldsField(); if (!$field->getFromDBByCrit(['name' => $item->field_name])) { diff --git a/src/Controller/QuestionTypeAjaxController.php b/src/Controller/QuestionTypeAjaxController.php index 0fc4a9b3..03d7c6d2 100644 --- a/src/Controller/QuestionTypeAjaxController.php +++ b/src/Controller/QuestionTypeAjaxController.php @@ -76,7 +76,7 @@ public function __invoke(Request $request): Response $current_container = PluginFieldsContainer::getById((int) $block_id); $current_field = PluginFieldsField::getById($current_field_id); - if (!$current_container || !$current_field || empty($current_field->fields)) { + if (!$current_container || !$current_field || $current_field->fields === []) { return new Response('Invalid container or field', Response::HTTP_BAD_REQUEST); } diff --git a/tests/QuestionTypeTestCase.php b/tests/QuestionTypeTestCase.php index 1aaba5a5..e3fd1c3b 100644 --- a/tests/QuestionTypeTestCase.php +++ b/tests/QuestionTypeTestCase.php @@ -104,15 +104,10 @@ protected function renderHelpdeskForm(Form $form): Crawler { $this->login(); $controller = new RendererController(); - $response = $controller->__invoke( - Request::create( - '', - 'GET', - [ - 'id' => $form->getID(), - ], - ), - ); + $request = Request::create('', 'GET', ['id' => $form->getID()]); + $request->attributes->set('id', $form->getID()); + + $response = $controller->__invoke($request); return new Crawler($response->getContent()); } diff --git a/tests/Units/FieldDestinationFieldTest.php b/tests/Units/FieldDestinationFieldTest.php index 7a6f5e89..50d48a46 100644 --- a/tests/Units/FieldDestinationFieldTest.php +++ b/tests/Units/FieldDestinationFieldTest.php @@ -51,8 +51,6 @@ use Ticket; use User; -include_once __DIR__ . '/../../../../tests/abstracts/AbstractDestinationFieldTest.php'; - final class FieldDestinationFieldTest extends AbstractDestinationFieldTest { use FormTesterTrait; diff --git a/tests/Units/FieldQuestionTypeTest.php b/tests/Units/FieldQuestionTypeTest.php index afccf7f6..856fca89 100644 --- a/tests/Units/FieldQuestionTypeTest.php +++ b/tests/Units/FieldQuestionTypeTest.php @@ -275,11 +275,11 @@ public function testDropdownConditionHandlerEqualsOperator(): void ); // Test: matching item → question is visible - $engine = new Engine($form, new EngineInput([$dropdown_question_id => ['itemtype' => $itemtype, 'items_id' => $item1_id]])); + $engine = new Engine($form, new EngineInput([$dropdown_question_id => ['itemtype' => $itemtype, 'items_ids' => [$item1_id]]])); $this->assertTrue($engine->computeVisibility()->isQuestionVisible($question_id)); // Test: different item → question is not visible - $engine = new Engine($form, new EngineInput([$dropdown_question_id => ['itemtype' => $itemtype, 'items_id' => $item2_id]])); + $engine = new Engine($form, new EngineInput([$dropdown_question_id => ['itemtype' => $itemtype, 'items_ids' => [$item2_id]]])); $this->assertFalse($engine->computeVisibility()->isQuestionVisible($question_id)); } @@ -292,11 +292,11 @@ public function testDropdownConditionHandlerNotEqualsOperator(): void ); // Test: same item → question is not visible - $engine = new Engine($form, new EngineInput([$dropdown_question_id => ['itemtype' => $itemtype, 'items_id' => $item1_id]])); + $engine = new Engine($form, new EngineInput([$dropdown_question_id => ['itemtype' => $itemtype, 'items_ids' => [$item1_id]]])); $this->assertFalse($engine->computeVisibility()->isQuestionVisible($question_id)); // Test: different item → question is visible - $engine = new Engine($form, new EngineInput([$dropdown_question_id => ['itemtype' => $itemtype, 'items_id' => $item2_id]])); + $engine = new Engine($form, new EngineInput([$dropdown_question_id => ['itemtype' => $itemtype, 'items_ids' => [$item2_id]]])); $this->assertTrue($engine->computeVisibility()->isQuestionVisible($question_id)); } @@ -330,7 +330,7 @@ public function testDropdownConditionHandlerContainsOperator(): void $dropdown_question_id = $this->getQuestionId($form, "Dropdown question"); // Test: item name contains the condition value → question is visible - $engine = new Engine($form, new EngineInput([$dropdown_question_id => ['itemtype' => $itemtype, 'items_id' => $item_id]])); + $engine = new Engine($form, new EngineInput([$dropdown_question_id => ['itemtype' => $itemtype, 'items_ids' => [$item_id]]])); $this->assertTrue($engine->computeVisibility()->isQuestionVisible($question_id)); // Test: item name does not contain the condition value → question is not visible @@ -354,7 +354,7 @@ public function testDropdownConditionHandlerContainsOperator(): void $question_id2 = $this->getQuestionId($form2, "Subject"); $dropdown_question_id2 = $this->getQuestionId($form2, "Dropdown question"); - $engine = new Engine($form2, new EngineInput([$dropdown_question_id2 => ['itemtype' => $itemtype, 'items_id' => $item_id]])); + $engine = new Engine($form2, new EngineInput([$dropdown_question_id2 => ['itemtype' => $itemtype, 'items_ids' => [$item_id]]])); $this->assertFalse($engine->computeVisibility()->isQuestionVisible($question_id2)); } @@ -388,7 +388,7 @@ public function testDropdownConditionHandlerNotContainsOperator(): void $dropdown_question_id = $this->getQuestionId($form, "Dropdown question"); // Test: item name does not contain the value → question is visible - $engine = new Engine($form, new EngineInput([$dropdown_question_id => ['itemtype' => $itemtype, 'items_id' => $item_id]])); + $engine = new Engine($form, new EngineInput([$dropdown_question_id => ['itemtype' => $itemtype, 'items_ids' => [$item_id]]])); $this->assertTrue($engine->computeVisibility()->isQuestionVisible($question_id)); // Test: item name contains the value → question is not visible @@ -412,7 +412,7 @@ public function testDropdownConditionHandlerNotContainsOperator(): void $question_id2 = $this->getQuestionId($form2, "Subject"); $dropdown_question_id2 = $this->getQuestionId($form2, "Dropdown question"); - $engine = new Engine($form2, new EngineInput([$dropdown_question_id2 => ['itemtype' => $itemtype, 'items_id' => $item_id]])); + $engine = new Engine($form2, new EngineInput([$dropdown_question_id2 => ['itemtype' => $itemtype, 'items_ids' => [$item_id]]])); $this->assertFalse($engine->computeVisibility()->isQuestionVisible($question_id2)); } @@ -436,7 +436,7 @@ private function createDropdownConditionForm(ValueOperator $operator): array $item1_id = $dropdown_item->add(['name' => 'First Option']); $item2_id = $dropdown_item->add(['name' => 'Second Option']); - $condition_value = ['itemtype' => $itemtype, 'items_id' => $item1_id]; + $condition_value = ['itemtype' => $itemtype, 'items_ids' => [$item1_id]]; $builder = new FormBuilder("Dropdown condition form"); $builder->addQuestion( From 8efbc2bf139c9e5ebb39410f3b03a0cd9c027ad7 Mon Sep 17 00:00:00 2001 From: Stanislas Kita <7335054+stonebuzz@users.noreply.github.com> Date: Tue, 18 Aug 2026 14:43:20 +0200 Subject: [PATCH 3/3] add missing icon --- inc/container.class.php | 2 +- inc/menu.class.php | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/inc/container.class.php b/inc/container.class.php index d77714c4..0f2f1d42 100644 --- a/inc/container.class.php +++ b/inc/container.class.php @@ -2387,7 +2387,7 @@ protected static function getSystemName(string $itemtype, string $container_name public static function getIcon() { - return 'fas fa-tasks'; + return 'ti ti-blocks'; } public static function getNameField() diff --git a/inc/menu.class.php b/inc/menu.class.php index 47277b1a..6cdb6a44 100644 --- a/inc/menu.class.php +++ b/inc/menu.class.php @@ -49,7 +49,7 @@ public static function getMenuContent() $menu = [ 'title' => self::getMenuName(), 'page' => PluginFieldsContainer::getSearchURL(false), - 'icon' => PluginFieldsContainer::getIcon(), + 'icon' => self::getIcon(), ]; $itemtypes = ['PluginFieldsContainer' => 'fieldscontainer']; @@ -57,6 +57,7 @@ public static function getMenuContent() foreach ($itemtypes as $itemtype => $option) { $menu['options'][$option] = [ 'title' => $itemtype::getTypeName(2), + 'icon' => $itemtype::getIcon(), 'page' => $itemtype::getSearchURL(false), 'links' => [ 'search' => $itemtype::getSearchURL(false), @@ -70,4 +71,9 @@ public static function getMenuContent() return $menu; } + + public static function getIcon() + { + return 'fas fa-tasks'; + } }