From cfa0a09cea022d308a35be8f5e90892a85cd4a48 Mon Sep 17 00:00:00 2001 From: Stanislas Date: Thu, 26 Jun 2025 16:16:43 +0200 Subject: [PATCH] Feature GLP11 --- .php-cs-fixer.php | 21 + composer.json | 19 +- composer.lock | 2298 ++++++++++++++++++++++++--- front/config.php | 2 +- front/devicecamera.form.php | 4 +- front/devicecamera.php | 4 +- front/dropdown.form.php | 4 +- front/dropdown.php | 4 +- front/example.form.php | 6 +- front/example.php | 6 +- front/popup.php | 38 +- front/ruletest.form.php | 4 +- front/ruletest.php | 4 +- hook.php | 852 +++++----- report.php | 2 +- setup.php | 452 +++--- src/Child.php | 93 +- src/Computer.php | 70 +- src/Config.php | 96 +- src/DeviceCamera.php | 18 +- src/Document.php | 342 ++-- src/Dropdown.php | 20 +- src/Example.php | 914 ++++++----- src/Filters/ComputerModelFilter.php | 11 +- src/ItemForm.php | 228 +-- src/Item_DeviceCamera.php | 15 +- src/NotificationTargetExample.php | 25 +- src/Profile.php | 22 +- src/RuleTest.php | 60 +- src/RuleTestCollection.php | 27 +- src/Showtabitem.php | 236 +-- stat.php | 2 +- 32 files changed, 3916 insertions(+), 1983 deletions(-) create mode 100644 .php-cs-fixer.php diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php new file mode 100644 index 0000000..7a81c5b --- /dev/null +++ b/.php-cs-fixer.php @@ -0,0 +1,21 @@ +in(__DIR__) + ->name('*.php') + ->ignoreVCSIgnored(true); + +$config = new Config(); + +$rules = [ + '@PER-CS2.0' => true, + 'trailing_comma_in_multiline' => ['elements' => ['arguments', 'array_destructuring', 'arrays']], // For PHP 7.4 compatibility +]; + +return $config + ->setRules($rules) + ->setFinder($finder) + ->setUsingCache(false); diff --git a/composer.json b/composer.json index 903a755..54fed37 100644 --- a/composer.json +++ b/composer.json @@ -1,15 +1,26 @@ { "require": { - "php": ">=7.4" + "php": ">=8.2" }, "require-dev": { - "glpi-project/tools": "^0.5" + "friendsofphp/php-cs-fixer": "^3.75", + "friendsoftwig/twigcs": "^6.1", + "glpi-project/tools": "^0.7.5", + "php-parallel-lint/php-parallel-lint": "^1.4" }, "config": { "optimize-autoloader": true, "platform": { - "php": "7.4.0" + "php": "8.2.99" }, - "sort-packages": true + "sort-packages": true, + "allow-plugins": { + "phpstan/extension-installer": true + } + }, + "autoload-dev": { + "psr-4": { + "Glpi\\Tools\\": "../../tools/src/" + } } } diff --git a/composer.lock b/composer.lock index da853a5..418b7c3 100644 --- a/composer.lock +++ b/composer.lock @@ -4,27 +4,588 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "0163b1c6232cea04e21b7dbb15bbf8e8", + "content-hash": "981190cd221bfc071af80a355f4b0b57", "packages": [], "packages-dev": [ { - "name": "glpi-project/tools", - "version": "0.5.1", + "name": "clue/ndjson-react", + "version": "v1.3.0", "source": { "type": "git", - "url": "https://github.com/glpi-project/tools.git", - "reference": "8d32c53bd9fb6c4cd85cbbb405a63ea88ca033e4" + "url": "https://github.com/clue/reactphp-ndjson.git", + "reference": "392dc165fce93b5bb5c637b67e59619223c931b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/glpi-project/tools/zipball/8d32c53bd9fb6c4cd85cbbb405a63ea88ca033e4", - "reference": "8d32c53bd9fb6c4cd85cbbb405a63ea88ca033e4", + "url": "https://api.github.com/repos/clue/reactphp-ndjson/zipball/392dc165fce93b5bb5c637b67e59619223c931b0", + "reference": "392dc165fce93b5bb5c637b67e59619223c931b0", "shasum": "" }, "require": { - "symfony/console": "^4.4 || ^5.0", + "php": ">=5.3", + "react/stream": "^1.2" + }, + "require-dev": { + "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35", + "react/event-loop": "^1.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Clue\\React\\NDJson\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering" + } + ], + "description": "Streaming newline-delimited JSON (NDJSON) parser and encoder for ReactPHP.", + "homepage": "https://github.com/clue/reactphp-ndjson", + "keywords": [ + "NDJSON", + "json", + "jsonlines", + "newline", + "reactphp", + "streaming" + ], + "support": { + "issues": "https://github.com/clue/reactphp-ndjson/issues", + "source": "https://github.com/clue/reactphp-ndjson/tree/v1.3.0" + }, + "funding": [ + { + "url": "https://clue.engineering/support", + "type": "custom" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2022-12-23T10:58:28+00:00" + }, + { + "name": "composer/pcre", + "version": "3.3.2", + "source": { + "type": "git", + "url": "https://github.com/composer/pcre.git", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<1.11.10" + }, + "require-dev": { + "phpstan/phpstan": "^1.12 || ^2", + "phpstan/phpstan-strict-rules": "^1 || ^2", + "phpunit/phpunit": "^8 || ^9" + }, + "type": "library", + "extra": { + "phpstan": { + "includes": [ + "extension.neon" + ] + }, + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Pcre\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "keywords": [ + "PCRE", + "preg", + "regex", + "regular expression" + ], + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/3.3.2" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-11-12T16:29:46+00:00" + }, + { + "name": "composer/semver", + "version": "3.4.3", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", + "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.11", + "symfony/phpunit-bridge": "^3 || ^7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.4.3" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-09-19T14:15:21+00:00" + }, + { + "name": "composer/xdebug-handler", + "version": "3.0.5", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef", + "shasum": "" + }, + "require": { + "composer/pcre": "^1 || ^2 || ^3", + "php": "^7.2.5 || ^8.0", + "psr/log": "^1 || ^2 || ^3" + }, + "require-dev": { + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without Xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/3.0.5" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-05-06T16:37:16+00:00" + }, + { + "name": "evenement/evenement", + "version": "v3.0.2", + "source": { + "type": "git", + "url": "https://github.com/igorw/evenement.git", + "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/igorw/evenement/zipball/0a16b0d71ab13284339abb99d9d2bd813640efbc", + "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc", + "shasum": "" + }, + "require": { + "php": ">=7.0" + }, + "require-dev": { + "phpunit/phpunit": "^9 || ^6" + }, + "type": "library", + "autoload": { + "psr-4": { + "Evenement\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" + } + ], + "description": "Événement is a very simple event dispatching library for PHP", + "keywords": [ + "event-dispatcher", + "event-emitter" + ], + "support": { + "issues": "https://github.com/igorw/evenement/issues", + "source": "https://github.com/igorw/evenement/tree/v3.0.2" + }, + "time": "2023-08-08T05:53:35+00:00" + }, + { + "name": "fidry/cpu-core-counter", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/theofidry/cpu-core-counter.git", + "reference": "8520451a140d3f46ac33042715115e290cf5785f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/8520451a140d3f46ac33042715115e290cf5785f", + "reference": "8520451a140d3f46ac33042715115e290cf5785f", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "fidry/makefile": "^0.2.0", + "fidry/php-cs-fixer-config": "^1.1.2", + "phpstan/extension-installer": "^1.2.0", + "phpstan/phpstan": "^1.9.2", + "phpstan/phpstan-deprecation-rules": "^1.0.0", + "phpstan/phpstan-phpunit": "^1.2.2", + "phpstan/phpstan-strict-rules": "^1.4.4", + "phpunit/phpunit": "^8.5.31 || ^9.5.26", + "webmozarts/strict-phpunit": "^7.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Fidry\\CpuCoreCounter\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Théo FIDRY", + "email": "theo.fidry@gmail.com" + } + ], + "description": "Tiny utility to get the number of CPU cores.", + "keywords": [ + "CPU", + "core" + ], + "support": { + "issues": "https://github.com/theofidry/cpu-core-counter/issues", + "source": "https://github.com/theofidry/cpu-core-counter/tree/1.2.0" + }, + "funding": [ + { + "url": "https://github.com/theofidry", + "type": "github" + } + ], + "time": "2024-08-06T10:04:20+00:00" + }, + { + "name": "friendsofphp/php-cs-fixer", + "version": "v3.75.0", + "source": { + "type": "git", + "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", + "reference": "399a128ff2fdaf4281e4e79b755693286cdf325c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/399a128ff2fdaf4281e4e79b755693286cdf325c", + "reference": "399a128ff2fdaf4281e4e79b755693286cdf325c", + "shasum": "" + }, + "require": { + "clue/ndjson-react": "^1.0", + "composer/semver": "^3.4", + "composer/xdebug-handler": "^3.0.3", + "ext-filter": "*", + "ext-hash": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "fidry/cpu-core-counter": "^1.2", + "php": "^7.4 || ^8.0", + "react/child-process": "^0.6.5", + "react/event-loop": "^1.0", + "react/promise": "^2.0 || ^3.0", + "react/socket": "^1.0", + "react/stream": "^1.0", + "sebastian/diff": "^4.0 || ^5.1 || ^6.0 || ^7.0", + "symfony/console": "^5.4 || ^6.4 || ^7.0", + "symfony/event-dispatcher": "^5.4 || ^6.4 || ^7.0", + "symfony/filesystem": "^5.4 || ^6.4 || ^7.0", + "symfony/finder": "^5.4 || ^6.4 || ^7.0", + "symfony/options-resolver": "^5.4 || ^6.4 || ^7.0", + "symfony/polyfill-mbstring": "^1.31", + "symfony/polyfill-php80": "^1.31", + "symfony/polyfill-php81": "^1.31", + "symfony/process": "^5.4 || ^6.4 || ^7.2", + "symfony/stopwatch": "^5.4 || ^6.4 || ^7.0" + }, + "require-dev": { + "facile-it/paraunit": "^1.3.1 || ^2.6", + "infection/infection": "^0.29.14", + "justinrainbow/json-schema": "^5.3 || ^6.2", + "keradus/cli-executor": "^2.1", + "mikey179/vfsstream": "^1.6.12", + "php-coveralls/php-coveralls": "^2.7", + "php-cs-fixer/accessible-object": "^1.1", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6", + "phpunit/phpunit": "^9.6.22 || ^10.5.45 || ^11.5.12", + "symfony/var-dumper": "^5.4.48 || ^6.4.18 || ^7.2.3", + "symfony/yaml": "^5.4.45 || ^6.4.18 || ^7.2.3" + }, + "suggest": { + "ext-dom": "For handling output formats in XML", + "ext-mbstring": "For handling non-UTF8 characters." + }, + "bin": [ + "php-cs-fixer" + ], + "type": "application", + "autoload": { + "psr-4": { + "PhpCsFixer\\": "src/" + }, + "exclude-from-classmap": [ + "src/Fixer/Internal/*" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Dariusz Rumiński", + "email": "dariusz.ruminski@gmail.com" + } + ], + "description": "A tool to automatically fix PHP code style", + "keywords": [ + "Static code analysis", + "fixer", + "standards", + "static analysis" + ], + "support": { + "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.75.0" + }, + "funding": [ + { + "url": "https://github.com/keradus", + "type": "github" + } + ], + "time": "2025-03-31T18:40:42+00:00" + }, + { + "name": "friendsoftwig/twigcs", + "version": "6.5.0", + "source": { + "type": "git", + "url": "https://github.com/friendsoftwig/twigcs.git", + "reference": "aaa3ba112bf4fcee7b51a00d9b45b13bc2cc23bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/friendsoftwig/twigcs/zipball/aaa3ba112bf4fcee7b51a00d9b45b13bc2cc23bc", + "reference": "aaa3ba112bf4fcee7b51a00d9b45b13bc2cc23bc", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-hash": "*", + "ext-json": "*", + "ext-mbstring": "*", + "ext-simplexml": "*", + "php": "~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0", + "symfony/console": "^4.4 || ^5.3 || ^6.0 || ^7.0", + "symfony/filesystem": "^4.4 || ^5.3 || ^6.0 || ^7.0", + "symfony/finder": "^4.4 || ^5.3 || ^6.0 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.6.19", + "symfony/phpunit-bridge": "^7.1.4" + }, + "bin": [ + "bin/twigcs" + ], + "type": "library", + "autoload": { + "psr-4": { + "FriendsOfTwig\\Twigcs\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Tristan Maindron", + "email": "tmaindron@gmail.com" + } + ], + "description": "Checkstyle automation for Twig", + "support": { + "issues": "https://github.com/friendsoftwig/twigcs/issues", + "source": "https://github.com/friendsoftwig/twigcs/tree/6.5.0" + }, + "time": "2024-11-27T21:59:24+00:00" + }, + { + "name": "glpi-project/tools", + "version": "0.7.5", + "source": { + "type": "git", + "url": "https://github.com/glpi-project/tools.git", + "reference": "c6ff4a7640384232ead150b46d4a647a14d12ab3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/glpi-project/tools/zipball/c6ff4a7640384232ead150b46d4a647a14d12ab3", + "reference": "c6ff4a7640384232ead150b46d4a647a14d12ab3", + "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", @@ -33,7 +594,7 @@ "type": "library", "autoload": { "psr-4": { - "Glpi\\": "src/" + "GlpiProject\\Tools\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -57,26 +618,92 @@ "issues": "https://github.com/glpi-project/tools/issues", "source": "https://github.com/glpi-project/tools" }, - "time": "2022-06-28T11:18:30+00:00" + "time": "2025-05-22T07:31:28+00:00" }, { - "name": "psr/container", - "version": "1.1.2", + "name": "php-parallel-lint/php-parallel-lint", + "version": "v1.4.0", "source": { "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" + "url": "https://github.com/php-parallel-lint/PHP-Parallel-Lint.git", + "reference": "6db563514f27e19595a19f45a4bf757b6401194e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", + "url": "https://api.github.com/repos/php-parallel-lint/PHP-Parallel-Lint/zipball/6db563514f27e19595a19f45a4bf757b6401194e", + "reference": "6db563514f27e19595a19f45a4bf757b6401194e", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=5.3.0" + }, + "replace": { + "grogy/php-parallel-lint": "*", + "jakub-onderka/php-parallel-lint": "*" + }, + "require-dev": { + "nette/tester": "^1.3 || ^2.0", + "php-parallel-lint/php-console-highlighter": "0.* || ^1.0", + "squizlabs/php_codesniffer": "^3.6" + }, + "suggest": { + "php-parallel-lint/php-console-highlighter": "Highlight syntax in code snippet" + }, + "bin": [ + "parallel-lint" + ], + "type": "library", + "autoload": { + "classmap": [ + "./src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Jakub Onderka", + "email": "ahoj@jakubonderka.cz" + } + ], + "description": "This tool checks the syntax of PHP files about 20x faster than serial check.", + "homepage": "https://github.com/php-parallel-lint/PHP-Parallel-Lint", + "keywords": [ + "lint", + "static analysis" + ], + "support": { + "issues": "https://github.com/php-parallel-lint/PHP-Parallel-Lint/issues", + "source": "https://github.com/php-parallel-lint/PHP-Parallel-Lint/tree/v1.4.0" + }, + "time": "2024-03-27T12:14:49+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/" @@ -103,58 +730,746 @@ ], "support": { "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/1.1.2" + "source": "https://github.com/php-fig/container/tree/2.0.2" }, - "time": "2021-11-05T16:50:12+00:00" + "time": "2021-11-05T16:47:00+00:00" }, { - "name": "symfony/console", - "version": "v5.4.10", + "name": "psr/event-dispatcher", + "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "4d671ab4ddac94ee439ea73649c69d9d200b5000" + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/4d671ab4ddac94ee439ea73649c69d9d200b5000", - "reference": "4d671ab4ddac94ee439ea73649c69d9d200b5000", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.9", - "symfony/polyfill-php80": "^1.16", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/string": "^5.1|^6.0" + "php": ">=7.2.0" }, - "conflict": { - "psr/log": ">=3", - "symfony/dependency-injection": "<4.4", - "symfony/dotenv": "<5.1", - "symfony/event-dispatcher": "<4.4", - "symfony/lock": "<4.4", - "symfony/process": "<4.4" + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } }, - "provide": { - "psr/log-implementation": "1.0|2.0" + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/log", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.2" + }, + "time": "2024-09-11T13:17:53+00:00" + }, + { + "name": "react/cache", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/cache.git", + "reference": "d47c472b64aa5608225f47965a484b75c7817d5b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/cache/zipball/d47c472b64aa5608225f47965a484b75c7817d5b", + "reference": "d47c472b64aa5608225f47965a484b75c7817d5b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "react/promise": "^3.0 || ^2.0 || ^1.1" }, "require-dev": { - "psr/log": "^1|^2", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/event-dispatcher": "^4.4|^5.0|^6.0", - "symfony/lock": "^4.4|^5.0|^6.0", - "symfony/process": "^4.4|^5.0|^6.0", - "symfony/var-dumper": "^4.4|^5.0|^6.0" + "phpunit/phpunit": "^9.5 || ^5.7 || ^4.8.35" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Async, Promise-based cache interface for ReactPHP", + "keywords": [ + "cache", + "caching", + "promise", + "reactphp" + ], + "support": { + "issues": "https://github.com/reactphp/cache/issues", + "source": "https://github.com/reactphp/cache/tree/v1.2.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2022-11-30T15:59:55+00:00" + }, + { + "name": "react/child-process", + "version": "v0.6.6", + "source": { + "type": "git", + "url": "https://github.com/reactphp/child-process.git", + "reference": "1721e2b93d89b745664353b9cfc8f155ba8a6159" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/child-process/zipball/1721e2b93d89b745664353b9cfc8f155ba8a6159", + "reference": "1721e2b93d89b745664353b9cfc8f155ba8a6159", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.0", + "react/event-loop": "^1.2", + "react/stream": "^1.4" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "react/socket": "^1.16", + "sebastian/environment": "^5.0 || ^3.0 || ^2.0 || ^1.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\ChildProcess\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Event-driven library for executing child processes with ReactPHP.", + "keywords": [ + "event-driven", + "process", + "reactphp" + ], + "support": { + "issues": "https://github.com/reactphp/child-process/issues", + "source": "https://github.com/reactphp/child-process/tree/v0.6.6" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2025-01-01T16:37:48+00:00" + }, + { + "name": "react/dns", + "version": "v1.13.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/dns.git", + "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/dns/zipball/eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", + "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "react/cache": "^1.0 || ^0.6 || ^0.5", + "react/event-loop": "^1.2", + "react/promise": "^3.2 || ^2.7 || ^1.2.1" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "react/async": "^4.3 || ^3 || ^2", + "react/promise-timer": "^1.11" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Dns\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Async DNS resolver for ReactPHP", + "keywords": [ + "async", + "dns", + "dns-resolver", + "reactphp" + ], + "support": { + "issues": "https://github.com/reactphp/dns/issues", + "source": "https://github.com/reactphp/dns/tree/v1.13.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-06-13T14:18:03+00:00" + }, + { + "name": "react/event-loop", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/event-loop.git", + "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/event-loop/zipball/bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", + "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" }, "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" + "ext-pcntl": "For signal handling support when using the StreamSelectLoop" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\EventLoop\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "ReactPHP's core reactor event loop that libraries can use for evented I/O.", + "keywords": [ + "asynchronous", + "event-loop" + ], + "support": { + "issues": "https://github.com/reactphp/event-loop/issues", + "source": "https://github.com/reactphp/event-loop/tree/v1.5.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2023-11-13T13:48:05+00:00" + }, + { + "name": "react/promise", + "version": "v3.2.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/promise.git", + "reference": "8a164643313c71354582dc850b42b33fa12a4b63" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/promise/zipball/8a164643313c71354582dc850b42b33fa12a4b63", + "reference": "8a164643313c71354582dc850b42b33fa12a4b63", + "shasum": "" + }, + "require": { + "php": ">=7.1.0" + }, + "require-dev": { + "phpstan/phpstan": "1.10.39 || 1.4.10", + "phpunit/phpunit": "^9.6 || ^7.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "React\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "A lightweight implementation of CommonJS Promises/A for PHP", + "keywords": [ + "promise", + "promises" + ], + "support": { + "issues": "https://github.com/reactphp/promise/issues", + "source": "https://github.com/reactphp/promise/tree/v3.2.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-05-24T10:39:05+00:00" + }, + { + "name": "react/socket", + "version": "v1.16.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/socket.git", + "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/socket/zipball/23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", + "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.0", + "react/dns": "^1.13", + "react/event-loop": "^1.2", + "react/promise": "^3.2 || ^2.6 || ^1.2.1", + "react/stream": "^1.4" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "react/async": "^4.3 || ^3.3 || ^2", + "react/promise-stream": "^1.4", + "react/promise-timer": "^1.11" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Socket\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Async, streaming plaintext TCP/IP and secure TLS socket server and client connections for ReactPHP", + "keywords": [ + "Connection", + "Socket", + "async", + "reactphp", + "stream" + ], + "support": { + "issues": "https://github.com/reactphp/socket/issues", + "source": "https://github.com/reactphp/socket/tree/v1.16.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-07-26T10:38:09+00:00" + }, + { + "name": "react/stream", + "version": "v1.4.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/stream.git", + "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/stream/zipball/1e5b0acb8fe55143b5b426817155190eb6f5b18d", + "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.8", + "react/event-loop": "^1.2" + }, + "require-dev": { + "clue/stream-filter": "~1.2", + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Stream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Event-driven readable and writable streams for non-blocking I/O in ReactPHP", + "keywords": [ + "event-driven", + "io", + "non-blocking", + "pipe", + "reactphp", + "readable", + "stream", + "writable" + ], + "support": { + "issues": "https://github.com/reactphp/stream/issues", + "source": "https://github.com/reactphp/stream/tree/v1.4.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-06-11T12:45:25+00:00" + }, + { + "name": "sebastian/diff", + "version": "6.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:53:05+00:00" + }, + { + "name": "symfony/console", + "version": "v6.4.22", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "7d29659bc3c9d8e9a34e2c3414ef9e9e003e6cf3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/7d29659bc3c9d8e9a34e2c3414ef9e9e003e6cf3", + "reference": "7d29659bc3c9d8e9a34e2c3414ef9e9e003e6cf3", + "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": { @@ -183,12 +1498,12 @@ "homepage": "https://symfony.com", "keywords": [ "cli", - "command line", + "command-line", "console", "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.4.10" + "source": "https://github.com/symfony/console/tree/v6.4.22" }, "funding": [ { @@ -204,33 +1519,33 @@ "type": "tidelift" } ], - "time": "2022-06-26T13:00:04+00:00" + "time": "2025-05-07T07:05:04+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v2.5.2", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.1" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "autoload": { @@ -255,7 +1570,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" }, "funding": [ { @@ -271,24 +1586,377 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { - "name": "symfony/polyfill-ctype", - "version": "v1.26.0", + "name": "symfony/event-dispatcher", + "version": "v7.3.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4" + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "497f73ac996a598c92409b44ac43b6690c4f666d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4", - "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/497f73ac996a598c92409b44ac43b6690c4f666d", + "reference": "497f73ac996a598c92409b44ac43b6690c4f666d", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.2", + "symfony/event-dispatcher-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/dependency-injection": "<6.4", + "symfony/service-contracts": "<2.5" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/error-handler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/stopwatch": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "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": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-22T09:11:45+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "59eb412e93815df44f05f342958efa9f46b1e586" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586", + "reference": "59eb412e93815df44f05f342958efa9f46b1e586", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/event-dispatcher": "^1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "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 dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/b8dce482de9d7c9fe2891155035a7248ab5c7fdb", + "reference": "b8dce482de9d7c9fe2891155035a7248ab5c7fdb", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8" + }, + "require-dev": { + "symfony/process": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "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": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-10-25T15:15:23+00:00" + }, + { + "name": "symfony/finder", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "ec2344cf77a48253bbca6939aa3d2477773ea63d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/ec2344cf77a48253bbca6939aa3d2477773ea63d", + "reference": "ec2344cf77a48253bbca6939aa3d2477773ea63d", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "symfony/filesystem": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "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": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-12-30T19:00:26+00:00" + }, + { + "name": "symfony/options-resolver", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "afb9a8038025e5dbc657378bfab9198d75f10fca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/afb9a8038025e5dbc657378bfab9198d75f10fca", + "reference": "afb9a8038025e5dbc657378bfab9198d75f10fca", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "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": "Provides an improved replacement for the array_replace PHP function", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "support": { + "source": "https://github.com/symfony/options-resolver/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-04T13:12:05+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.32.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "shasum": "" + }, + "require": { + "php": ">=7.2" }, "provide": { "ext-ctype": "*" @@ -298,12 +1966,9 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -337,7 +2002,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0" }, "funding": [ { @@ -353,36 +2018,33 @@ "type": "tidelift" } ], - "time": "2022-05-24T11:49:31+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.26.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "433d05519ce6990bf3530fba6957499d327395c2" + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/433d05519ce6990bf3530fba6957499d327395c2", - "reference": "433d05519ce6990bf3530fba6957499d327395c2", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -418,7 +2080,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.26.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.32.0" }, "funding": [ { @@ -434,36 +2096,33 @@ "type": "tidelift" } ], - "time": "2022-05-24T11:49:31+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.26.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "219aa369ceff116e673852dce47c3a41794c14bd" + "reference": "3833d7255cc303546435cb650316bff708a1c75c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd", - "reference": "219aa369ceff116e673852dce47c3a41794c14bd", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -502,7 +2161,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0" }, "funding": [ { @@ -518,24 +2177,25 @@ "type": "tidelift" } ], - "time": "2022-05-24T11:49:31+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.26.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e" + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e", - "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", "shasum": "" }, "require": { - "php": ">=7.1" + "ext-iconv": "*", + "php": ">=7.2" }, "provide": { "ext-mbstring": "*" @@ -545,12 +2205,9 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -585,7 +2242,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0" }, "funding": [ { @@ -601,112 +2258,30 @@ "type": "tidelift" } ], - "time": "2022-05-24T11:49:31+00:00" - }, - { - "name": "symfony/polyfill-php73", - "version": "v1.26.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/e440d35fa0286f77fb45b79a03fedbeda9307e85", - "reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php73\\": "" - }, - "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 backporting some PHP 7.3+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.26.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-24T11:49:31+00:00" + "time": "2024-12-23T08:48:59+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.26.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace" + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace", - "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.26-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -747,7 +2322,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.32.0" }, "funding": [ { @@ -763,47 +2338,184 @@ "type": "tidelift" } ], - "time": "2022-05-10T07:21:04+00:00" + "time": "2025-01-02T08:10:11+00:00" }, { - "name": "symfony/service-contracts", - "version": "v2.5.2", + "name": "symfony/polyfill-php81", + "version": "v1.32.0", "source": { "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", + "reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c", "shasum": "" }, "require": { - "php": ">=7.2.5", - "psr/container": "^1.1", - "symfony/deprecation-contracts": "^2.1|^3" + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php81\\": "" + }, + "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 backporting some PHP 8.1+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php81/tree/v1.32.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/process", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/40c295f2deb408d5e9d2d32b8ba1dd61e36f05af", + "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "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": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-17T09:11:12+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.6.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" }, "conflict": { "ext-psr": "<1.1|>=2" }, - "suggest": { - "symfony/service-implementation": "" - }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "autoload": { "psr-4": { "Symfony\\Contracts\\Service\\": "" - } + }, + "exclude-from-classmap": [ + "/Test/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -830,7 +2542,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v2.5.2" + "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" }, "funding": [ { @@ -846,38 +2558,101 @@ "type": "tidelift" } ], - "time": "2022-05-30T19:17:29+00:00" + "time": "2025-04-25T09:37:31+00:00" }, { - "name": "symfony/string", - "version": "v5.4.10", + "name": "symfony/stopwatch", + "version": "v7.3.0", "source": { "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "4432bc7df82a554b3e413a8570ce2fea90e94097" + "url": "https://github.com/symfony/stopwatch.git", + "reference": "5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/4432bc7df82a554b3e413a8570ce2fea90e94097", - "reference": "4432bc7df82a554b3e413a8570ce2fea90e94097", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd", + "reference": "5a49289e2b308214c8b9c2fda4ea454d8b8ad7cd", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.2", + "symfony/service-contracts": "^2.5|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Stopwatch\\": "" + }, + "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": "Provides a way to profile code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/stopwatch/tree/v7.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-02-24T10:49:57+00:00" + }, + { + "name": "symfony/string", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/f3570b8c61ca887a9e2938e85cb6458515d2b125", + "reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125", + "shasum": "" + }, + "require": { + "php": ">=8.2", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "~1.15" + "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/translation-contracts": ">=3.0" + "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/http-client": "^4.4|^5.0|^6.0", - "symfony/translation-contracts": "^1.1|^2", - "symfony/var-exporter": "^4.4|^5.0|^6.0" + "symfony/emoji": "^7.1", + "symfony/error-handler": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -916,7 +2691,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.4.10" + "source": "https://github.com/symfony/string/tree/v7.3.0" }, "funding": [ { @@ -932,38 +2707,41 @@ "type": "tidelift" } ], - "time": "2022-06-26T15:57:47+00:00" + "time": "2025-04-20T20:19:01+00:00" }, { "name": "twig/twig", - "version": "v3.4.1", + "version": "v3.21.1", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "e939eae92386b69b49cfa4599dd9bead6bf4a342" + "reference": "285123877d4dd97dd7c11842ac5fb7e86e60d81d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/e939eae92386b69b49cfa4599dd9bead6bf4a342", - "reference": "e939eae92386b69b49cfa4599dd9bead6bf4a342", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/285123877d4dd97dd7c11842ac5fb7e86e60d81d", + "reference": "285123877d4dd97dd7c11842ac5fb7e86e60d81d", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.1.0", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "^1.8", "symfony/polyfill-mbstring": "^1.3" }, "require-dev": { - "psr/container": "^1.0", - "symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0" + "phpstan/phpstan": "^2.0", + "psr/container": "^1.0|^2.0", + "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, "autoload": { + "files": [ + "src/Resources/core.php", + "src/Resources/debug.php", + "src/Resources/escaper.php", + "src/Resources/string_loader.php" + ], "psr-4": { "Twig\\": "src/" } @@ -996,7 +2774,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.4.1" + "source": "https://github.com/twigphp/Twig/tree/v3.21.1" }, "funding": [ { @@ -1008,7 +2786,7 @@ "type": "tidelift" } ], - "time": "2022-05-17T05:48:52+00:00" + "time": "2025-05-03T07:21:55+00:00" } ], "aliases": [], @@ -1017,11 +2795,11 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=7.4" + "php": ">=8.2" }, "platform-dev": [], "platform-overrides": { - "php": "7.4.0" + "php": "8.2.99" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } diff --git a/front/config.php b/front/config.php index 516e32a..d280f91 100644 --- a/front/config.php +++ b/front/config.php @@ -37,7 +37,7 @@ //header("Location:../../central.php"); // Entry menu case -include ("../../../inc/includes.php"); +include("../../../inc/includes.php"); Session::checkRight("config", UPDATE); diff --git a/front/devicecamera.form.php b/front/devicecamera.form.php index 2da3152..c06b9ca 100644 --- a/front/devicecamera.form.php +++ b/front/devicecamera.form.php @@ -35,8 +35,8 @@ use GlpiPlugin\Example\DeviceCamera; -include ('../../../inc/includes.php'); +include('../../../inc/includes.php'); Session::checkLoginUser(); $dropdown = new DeviceCamera(); -include (GLPI_ROOT . "/front/dropdown.common.form.php"); +include(GLPI_ROOT . "/front/dropdown.common.form.php"); diff --git a/front/devicecamera.php b/front/devicecamera.php index be1a436..9ca24f7 100644 --- a/front/devicecamera.php +++ b/front/devicecamera.php @@ -33,8 +33,8 @@ // Purpose of file: // ---------------------------------------------------------------------- -include ('../../../inc/includes.php'); +include('../../../inc/includes.php'); Session::checkLoginUser(); $dropdown = new DeviceCamera(); -include (GLPI_ROOT . "/front/dropdown.common.php"); +include(GLPI_ROOT . "/front/dropdown.common.php"); diff --git a/front/dropdown.form.php b/front/dropdown.form.php index cf88c33..1b084b5 100644 --- a/front/dropdown.form.php +++ b/front/dropdown.form.php @@ -35,10 +35,10 @@ use GlpiPlugin\Example\Dropdown; -include ('../../../inc/includes.php'); +include('../../../inc/includes.php'); Session::checkLoginUser(); Plugin::load('example', true); $dropdown = new Dropdown(); -include (GLPI_ROOT . "/front/dropdown.common.form.php"); +include(GLPI_ROOT . "/front/dropdown.common.form.php"); diff --git a/front/dropdown.php b/front/dropdown.php index df91884..add6ba9 100644 --- a/front/dropdown.php +++ b/front/dropdown.php @@ -35,10 +35,10 @@ use GlpiPlugin\Example\Dropdown; -include ('../../../inc/includes.php'); +include('../../../inc/includes.php'); Session::checkLoginUser(); Plugin::load('example', true); $dropdown = new Dropdown(); -include (GLPI_ROOT . "/front/dropdown.common.php"); +include(GLPI_ROOT . "/front/dropdown.common.php"); diff --git a/front/example.form.php b/front/example.form.php index 9650560..47f403b 100644 --- a/front/example.form.php +++ b/front/example.form.php @@ -35,13 +35,13 @@ use GlpiPlugin\Example\Example; -include ('../../../inc/includes.php'); +include('../../../inc/includes.php'); Session::checkLoginUser(); if ($_SESSION["glpiactiveprofile"]["interface"] == "central") { - Html::header("TITRE", $_SERVER['PHP_SELF'], "plugins", Example::class, ""); + Html::header("TITRE", $_SERVER['PHP_SELF'], "plugins", Example::class, ""); } else { - Html::helpHeader("TITRE", $_SERVER['PHP_SELF']); + Html::helpHeader("TITRE", $_SERVER['PHP_SELF']); } $example = new Example(); diff --git a/front/example.php b/front/example.php index 64def29..81324dc 100644 --- a/front/example.php +++ b/front/example.php @@ -35,13 +35,13 @@ use GlpiPlugin\Example\Example; -include ('../../../inc/includes.php'); +include('../../../inc/includes.php'); Session::checkRight(Example::$rightname, READ); if ($_SESSION["glpiactiveprofile"]["interface"] == "central") { - Html::header("TITRE", $_SERVER['PHP_SELF'], "plugins", Example::class, ""); + Html::header("TITRE", $_SERVER['PHP_SELF'], "plugins", Example::class, ""); } else { - Html::helpHeader("TITRE", $_SERVER['PHP_SELF']); + Html::helpHeader("TITRE", $_SERVER['PHP_SELF']); } diff --git a/front/popup.php b/front/popup.php index 36f19f8..83a3c04 100644 --- a/front/popup.php +++ b/front/popup.php @@ -28,32 +28,32 @@ * ------------------------------------------------------------------------- */ -include ('../../../inc/includes.php'); +include('../../../inc/includes.php'); Session::checkLoginUser(); if (isset($_GET["popup"])) { - $_SESSION["glpipopup"]["name"] = $_GET["popup"]; + $_SESSION["glpipopup"]["name"] = $_GET["popup"]; } if (isset($_SESSION["glpipopup"]["name"])) { - switch ($_SESSION["glpipopup"]["name"]) { - case "test_rule" : - Html::popHeader(__('Test'), $_SERVER['PHP_SELF']); - include "../../../front/rule.test.php"; - break; + switch ($_SESSION["glpipopup"]["name"]) { + case "test_rule": + Html::popHeader(__('Test'), $_SERVER['PHP_SELF']); + include "../../../front/rule.test.php"; + break; - case "test_all_rules" : - Html::popHeader(__('Test rules engine'), $_SERVER['PHP_SELF']); - include "../../../front/rulesengine.test.php"; - break; + case "test_all_rules": + Html::popHeader(__('Test rules engine'), $_SERVER['PHP_SELF']); + include "../../../front/rulesengine.test.php"; + break; - case "show_cache" : - Html::popHeader(__('Cache information'), $_SERVER['PHP_SELF']); - include "../../../front/rule.cache.php"; - break; - } - echo "

".__('Back').""; - echo "
"; - Html::popFooter(); + case "show_cache": + Html::popHeader(__('Cache information'), $_SERVER['PHP_SELF']); + include "../../../front/rule.cache.php"; + break; + } + echo "

" . __('Back') . ""; + echo "
"; + Html::popFooter(); } diff --git a/front/ruletest.form.php b/front/ruletest.form.php index 5578d10..a0ca8e8 100644 --- a/front/ruletest.form.php +++ b/front/ruletest.form.php @@ -35,9 +35,9 @@ use GlpiPlugin\Example\RuleTestCollection; -include ('../../../inc/includes.php'); +include('../../../inc/includes.php'); Session::checkLoginUser(); $rulecollection = new RuleTestCollection(); -include (GLPI_ROOT . "/front/rule.common.form.php"); +include(GLPI_ROOT . "/front/rule.common.form.php"); diff --git a/front/ruletest.php b/front/ruletest.php index 8976275..77eb496 100644 --- a/front/ruletest.php +++ b/front/ruletest.php @@ -35,9 +35,9 @@ use GlpiPlugin\Example\RuleTestCollection; -include ('../../../inc/includes.php'); +include('../../../inc/includes.php'); Session::checkLoginUser(); $rulecollection = new RuleTestCollection(); -include (GLPI_ROOT . "/front/rule.common.php"); +include(GLPI_ROOT . "/front/rule.common.php"); diff --git a/hook.php b/hook.php index 73e0af8..56ed5f0 100644 --- a/hook.php +++ b/hook.php @@ -33,25 +33,26 @@ // Purpose of file: // ---------------------------------------------------------------------- -use GlpiPlugin\Example\Dropdown; use GlpiPlugin\Example\Example; -use Dropdown as GlpiDropdown; -function plugin_change_profile_example() { - // Some logic that runs when the profile is changed +function plugin_change_profile_example() +{ + // Some logic that runs when the profile is changed } // Define dropdown relations -function plugin_example_getDatabaseRelations() { - return ["glpi_plugin_example_dropdowns" => ["glpi_plugin_example" => "plugin_example_dropdowns_id"]]; +function plugin_example_getDatabaseRelations() +{ + return ["glpi_plugin_example_dropdowns" => ["glpi_plugin_example" => "plugin_example_dropdowns_id"]]; } // Define Dropdown tables to be manage in GLPI : -function plugin_example_getDropdown() { - // Table => Name - return [Dropdown::class => __("Plugin Example Dropdown", 'example')]; +function plugin_example_getDropdown() +{ + // Table => Name + return [Dropdown::class => __("Plugin Example Dropdown", 'example')]; } @@ -59,199 +60,217 @@ function plugin_example_getDropdown() { ////// SEARCH FUNCTIONS ///////(){ // Define Additionnal search options for types (other than the plugin ones) -function plugin_example_getAddSearchOptions($itemtype) { - $sopt = []; - if ($itemtype == 'Computer') { - // Just for example, not working... - $sopt[1001]['table'] = 'glpi_plugin_example_dropdowns'; - $sopt[1001]['field'] = 'name'; - $sopt[1001]['linkfield'] = 'plugin_example_dropdowns_id'; - $sopt[1001]['name'] = __('Example plugin', 'example'); - } - return $sopt; +function plugin_example_getAddSearchOptions($itemtype) +{ + $sopt = []; + if ($itemtype == 'Computer') { + // Just for example, not working... + $sopt[1001]['table'] = 'glpi_plugin_example_dropdowns'; + $sopt[1001]['field'] = 'name'; + $sopt[1001]['linkfield'] = 'plugin_example_dropdowns_id'; + $sopt[1001]['name'] = __('Example plugin', 'example'); + } + return $sopt; } -function plugin_example_getAddSearchOptionsNew($itemtype) { - $options = []; - if ($itemtype == 'Computer') { - //Just for example, not working - $options[] = [ - 'id' => '1002', - 'table' => 'glpi_plugin_example_dropdowns', - 'field' => 'name', - 'linkfield' => 'plugin_example_dropdowns_id', - 'name' => __('Example plugin new', 'example') - ]; - } - return $options; +function plugin_example_getAddSearchOptionsNew($itemtype) +{ + $options = []; + if ($itemtype == 'Computer') { + //Just for example, not working + $options[] = [ + 'id' => '1002', + 'table' => 'glpi_plugin_example_dropdowns', + 'field' => 'name', + 'linkfield' => 'plugin_example_dropdowns_id', + 'name' => __('Example plugin new', 'example'), + ]; + } + return $options; } // See also GlpiPlugin\Example\Example::getSpecificValueToDisplay() -function plugin_example_giveItem($type, $ID, $data, $num) { - $searchopt = &Search::getOptions($type); - $table = $searchopt[$ID]["table"]; - $field = $searchopt[$ID]["field"]; +function plugin_example_giveItem($type, $ID, $data, $num) +{ + $searchopt = &Search::getOptions($type); + $table = $searchopt[$ID]["table"]; + $field = $searchopt[$ID]["field"]; - switch ($table.'.'.$field) { - case "glpi_plugin_example_examples.name" : - $out = ""; - $out .= $data[$num][0]['name']; - if ($_SESSION["glpiis_ids_visible"] || empty($data[$num][0]['name'])) { - $out .= " (".$data["id"].")"; - } - $out .= ""; - return $out; - } - return ""; + switch ($table . '.' . $field) { + case "glpi_plugin_example_examples.name": + $out = ""; + $out .= $data[$num][0]['name']; + if ($_SESSION["glpiis_ids_visible"] || empty($data[$num][0]['name'])) { + $out .= " (" . $data["id"] . ")"; + } + $out .= ""; + return $out; + } + return ""; } -function plugin_example_displayConfigItem($type, $ID, $data, $num) { - $searchopt = &Search::getOptions($type); - $table = $searchopt[$ID]["table"]; - $field = $searchopt[$ID]["field"]; +function plugin_example_displayConfigItem($type, $ID, $data, $num) +{ + $searchopt = &Search::getOptions($type); + $table = $searchopt[$ID]["table"]; + $field = $searchopt[$ID]["field"]; - // Example of specific style options - // No need of the function if you do not have specific cases - switch ($table.'.'.$field) { - case "glpi_plugin_example_examples.name" : - return " style=\"background-color:#DDDDDD;\" "; - } - return ""; + // Example of specific style options + // No need of the function if you do not have specific cases + switch ($table . '.' . $field) { + case "glpi_plugin_example_examples.name": + return " style=\"background-color:#DDDDDD;\" "; + } + return ""; } -function plugin_example_addDefaultJoin($type, $ref_table, &$already_link_tables) { - // Example of default JOIN clause - // No need of the function if you do not have specific cases - switch ($type) { - // case Example::class : - case "MyType" : - return Search::addLeftJoin($type, $ref_table, $already_link_tables, - "newtable", "linkfield"); - } - return ""; +function plugin_example_addDefaultJoin($type, $ref_table, &$already_link_tables) +{ + // Example of default JOIN clause + // No need of the function if you do not have specific cases + switch ($type) { + // case Example::class : + case "MyType": + return Search::addLeftJoin( + $type, + $ref_table, + $already_link_tables, + "newtable", + "linkfield", + ); + } + return ""; } -function plugin_example_addDefaultSelect($type) { - // Example of default SELECT item to be added - // No need of the function if you do not have specific cases - switch ($type) { - // case Example::class : - case "MyType" : - return "`mytable`.`myfield` = 'myvalue' AS MYNAME, "; - } - return ""; +function plugin_example_addDefaultSelect($type) +{ + // Example of default SELECT item to be added + // No need of the function if you do not have specific cases + switch ($type) { + // case Example::class : + case "MyType": + return "`mytable`.`myfield` = 'myvalue' AS MYNAME, "; + } + return ""; } -function plugin_example_addDefaultWhere($type) { - // Example of default WHERE item to be added - // No need of the function if you do not have specific cases - switch ($type) { - // case Example::class : - case "MyType" : - return " `mytable`.`myfield` = 'myvalue' "; - } - return ""; +function plugin_example_addDefaultWhere($type) +{ + // Example of default WHERE item to be added + // No need of the function if you do not have specific cases + switch ($type) { + // case Example::class : + case "MyType": + return " `mytable`.`myfield` = 'myvalue' "; + } + return ""; } -function plugin_example_addLeftJoin($type, $ref_table, $new_table, $linkfield) { - // Example of standard LEFT JOIN clause but use it ONLY for specific LEFT JOIN - // No need of the function if you do not have specific cases - switch ($new_table) { - case "glpi_plugin_example_dropdowns" : - return " LEFT JOIN `$new_table` ON (`$ref_table`.`$linkfield` = `$new_table`.`id`) "; - } - return ""; +function plugin_example_addLeftJoin($type, $ref_table, $new_table, $linkfield) +{ + // Example of standard LEFT JOIN clause but use it ONLY for specific LEFT JOIN + // No need of the function if you do not have specific cases + switch ($new_table) { + case "glpi_plugin_example_dropdowns": + return " LEFT JOIN `$new_table` ON (`$ref_table`.`$linkfield` = `$new_table`.`id`) "; + } + return ""; } -function plugin_example_forceGroupBy($type) { - switch ($type) { - case Example::class : - // Force add GROUP BY IN REQUEST - return true; - } - return false; +function plugin_example_forceGroupBy($type) +{ + switch ($type) { + case Example::class: + // Force add GROUP BY IN REQUEST + return true; + } + return false; } -function plugin_example_addWhere($link, $nott, $type, $ID, $val, $searchtype) { - $searchopt = &Search::getOptions($type); - $table = $searchopt[$ID]["table"]; - $field = $searchopt[$ID]["field"]; +function plugin_example_addWhere($link, $nott, $type, $ID, $val, $searchtype) +{ + $searchopt = &Search::getOptions($type); + $table = $searchopt[$ID]["table"]; + $field = $searchopt[$ID]["field"]; - $SEARCH = Search::makeTextSearch($val, $nott); + $SEARCH = Search::makeTextSearch($val, $nott); - // Example of standard Where clause but use it ONLY for specific Where - // No need of the function if you do not have specific cases - switch ($table.".".$field) { - /*case "glpi_plugin_example.name" : - $ADD = ""; - if ($nott && $val!="NULL") { - $ADD = " OR `$table`.`$field` IS NULL"; - } - return $link." (`$table`.`$field` $SEARCH ".$ADD." ) ";*/ - case "glpi_plugin_example_examples.serial" : - return $link." `$table`.`$field` = '$val' "; - } - return ""; + // Example of standard Where clause but use it ONLY for specific Where + // No need of the function if you do not have specific cases + switch ($table . "." . $field) { + /*case "glpi_plugin_example.name" : + $ADD = ""; + if ($nott && $val!="NULL") { + $ADD = " OR `$table`.`$field` IS NULL"; + } + return $link." (`$table`.`$field` $SEARCH ".$ADD." ) ";*/ + case "glpi_plugin_example_examples.serial": + return $link . " `$table`.`$field` = '$val' "; + } + return ""; } // This is not a real example because the use of Having condition in this case is not suitable -function plugin_example_addHaving($link, $nott, $type, $ID, $val, $num) { - $searchopt = &Search::getOptions($type); - $table = $searchopt[$ID]["table"]; - $field = $searchopt[$ID]["field"]; +function plugin_example_addHaving($link, $nott, $type, $ID, $val, $num) +{ + $searchopt = &Search::getOptions($type); + $table = $searchopt[$ID]["table"]; + $field = $searchopt[$ID]["field"]; - $SEARCH = Search::makeTextSearch($val, $nott); + $SEARCH = Search::makeTextSearch($val, $nott); - // Example of standard Having clause but use it ONLY for specific Having - // No need of the function if you do not have specific cases - switch ($table.".".$field) { - case "glpi_plugin_example.serial" : - $ADD = ""; - if (($nott && $val!="NULL") - || $val == '^$') { - $ADD = " OR ITEM_$num IS NULL"; - } - return " $LINK ( ITEM_".$num.$SEARCH." $ADD ) "; - } - return ""; + // Example of standard Having clause but use it ONLY for specific Having + // No need of the function if you do not have specific cases + switch ($table . "." . $field) { + case "glpi_plugin_example.serial": + $ADD = ""; + if (($nott && $val != "NULL") + || $val == '^$') { + $ADD = " OR ITEM_$num IS NULL"; + } + return " $link ( ITEM_" . $num . $SEARCH . " $ADD ) "; + } + return ""; } -function plugin_example_addSelect($type, $ID, $num) { - $searchopt = &Search::getOptions($type); - $table = $searchopt[$ID]["table"]; - $field = $searchopt[$ID]["field"]; +function plugin_example_addSelect($type, $ID, $num) +{ + $searchopt = &Search::getOptions($type); + $table = $searchopt[$ID]["table"]; + $field = $searchopt[$ID]["field"]; - // Example of standard Select clause but use it ONLY for specific Select - // No need of the function if you do not have specific cases - // switch ($table.".".$field) { - // case "glpi_plugin_example.name" : - // return $table.".".$field." AS ITEM_$num, "; - // } - return ""; + // Example of standard Select clause but use it ONLY for specific Select + // No need of the function if you do not have specific cases + // switch ($table.".".$field) { + // case "glpi_plugin_example.name" : + // return $table.".".$field." AS ITEM_$num, "; + // } + return ""; } -function plugin_example_addOrderBy($type, $ID, $order, $key = 0) { - $searchopt = &Search::getOptions($type); - $table = $searchopt[$ID]["table"]; - $field = $searchopt[$ID]["field"]; +function plugin_example_addOrderBy($type, $ID, $order, $key = 0) +{ + $searchopt = &Search::getOptions($type); + $table = $searchopt[$ID]["table"]; + $field = $searchopt[$ID]["field"]; - // Example of standard OrderBy clause but use it ONLY for specific order by - // No need of the function if you do not have specific cases - // switch ($table.".".$field) { - // case "glpi_plugin_example.name" : - // return " ORDER BY $table.$field $order "; - // } - return ""; + // Example of standard OrderBy clause but use it ONLY for specific order by + // No need of the function if you do not have specific cases + // switch ($table.".".$field) { + // case "glpi_plugin_example.name" : + // return " ORDER BY $table.$field $order "; + // } + return ""; } @@ -260,192 +279,214 @@ function plugin_example_addOrderBy($type, $ID, $order, $key = 0) { // Define actions : -function plugin_example_MassiveActions($type) { - switch ($type) { - // New action for core and other plugin types : name = plugin_PLUGINNAME_actionname - case 'Computer' : - return [Example::class . MassiveAction::CLASS_ACTION_SEPARATOR . 'DoIt' => - __("plugin_example_DoIt", 'example')]; +function plugin_example_MassiveActions($type) +{ + switch ($type) { + // New action for core and other plugin types : name = plugin_PLUGINNAME_actionname + case 'Computer': + return [Example::class . MassiveAction::CLASS_ACTION_SEPARATOR . 'DoIt' => + __("plugin_example_DoIt", 'example')]; - // Actions for types provided by the plugin are included inside the classes - } - return []; + // Actions for types provided by the plugin are included inside the classes + } + return []; } // How to display specific update fields ? // options must contain at least itemtype and options array -function plugin_example_MassiveActionsFieldsDisplay($options = []) { - //$type,$table,$field,$linkfield +function plugin_example_MassiveActionsFieldsDisplay($options = []) +{ + //$type,$table,$field,$linkfield - $table = $options['options']['table']; - $field = $options['options']['field']; - $linkfield = $options['options']['linkfield']; + $table = $options['options']['table']; + $field = $options['options']['field']; + $linkfield = $options['options']['linkfield']; - if ($table == getTableForItemType($options['itemtype'])) { - // Table fields - switch ($table.".".$field) { - case 'glpi_plugin_example_examples.serial' : - echo __("Not really specific - Just for example", 'example'); - // Dropdown::showYesNo($linkfield); - // Need to return true if specific display - return true; - } + if ($table == getTableForItemType($options['itemtype'])) { + // Table fields + switch ($table . "." . $field) { + case 'glpi_plugin_example_examples.serial': + echo __("Not really specific - Just for example", 'example'); + // Dropdown::showYesNo($linkfield); + // Need to return true if specific display + return true; + } - } else { - // Linked Fields - switch ($table.".".$field) { - case "glpi_plugin_example_dropdowns.name" : - echo __("Not really specific - Just for example", 'example'); - // Need to return true if specific display - return true; - } - } - // Need to return false on non display item - return false; + } else { + // Linked Fields + switch ($table . "." . $field) { + case "glpi_plugin_example_dropdowns.name": + echo __("Not really specific - Just for example", 'example'); + // Need to return true if specific display + return true; + } + } + // Need to return false on non display item + return false; } // How to display specific search fields or dropdown ? // options must contain at least itemtype and options array // MUST Use a specific AddWhere & $tab[X]['searchtype'] = 'equals'; declaration -function plugin_example_searchOptionsValues($options = []) { - $table = $options['searchoption']['table']; - $field = $options['searchoption']['field']; +function plugin_example_searchOptionsValues($options = []) +{ + $table = $options['searchoption']['table']; + $field = $options['searchoption']['field']; // Table fields - switch ($table.".".$field) { - case "glpi_plugin_example_examples.serial" : + switch ($table . "." . $field) { + case "glpi_plugin_example_examples.serial": echo __("Not really specific - Use your own dropdown - Just for example", 'example'); - GlpiDropdown::show(getItemTypeForTable($options['searchoption']['table']), - ['value' => $options['value'], - 'name' => $options['name'], - 'comments' => 0]); + Dropdown::show( + getItemTypeForTable($options['searchoption']['table']), + ['value' => $options['value'], + 'name' => $options['name'], + 'comments' => 0], + ); // Need to return true if specific display return true; - } - return false; + } + return false; } ////////////////////////////// // Hook done on before update item case -function plugin_pre_item_update_example($item) { - /* Manipulate data if needed - if (!isset($item->input['comment'])) { - $item->input['comment'] = addslashes($item->fields['comment']); - } - $item->input['comment'] .= addslashes("\nUpdate: ".date('r')); - */ - Session::addMessageAfterRedirect(__("Pre Update Computer Hook", 'example'), true); +function plugin_pre_item_update_example($item) +{ + /* Manipulate data if needed + if (!isset($item->input['comment'])) { + $item->input['comment'] = addslashes($item->fields['comment']); + } + $item->input['comment'] .= addslashes("\nUpdate: ".date('r')); + */ + Session::addMessageAfterRedirect(__("Pre Update Computer Hook", 'example'), true); } // Hook done on update item case -function plugin_item_update_example($item) { - Session::addMessageAfterRedirect(sprintf(__("Update Computer Hook (%s)", 'example'), implode(',', $item->updates)), true); - return true; +function plugin_item_update_example($item) +{ + Session::addMessageAfterRedirect(sprintf(__("Update Computer Hook (%s)", 'example'), implode(',', $item->updates)), true); + return true; } // Hook done on get empty item case -function plugin_item_empty_example($item) { - if (empty($_SESSION['Already displayed "Empty Computer Hook"'])) { - Session::addMessageAfterRedirect(__("Empty Computer Hook", 'example'), true); - $_SESSION['Already displayed "Empty Computer Hook"'] = true; - } - return true; +function plugin_item_empty_example($item) +{ + if (empty($_SESSION['Already displayed "Empty Computer Hook"'])) { + Session::addMessageAfterRedirect(__("Empty Computer Hook", 'example'), true); + $_SESSION['Already displayed "Empty Computer Hook"'] = true; + } + return true; } // Hook done on before delete item case -function plugin_pre_item_delete_example($object) { - // Manipulate data if needed - Session::addMessageAfterRedirect(__("Pre Delete Computer Hook", 'example'), true); +function plugin_pre_item_delete_example($object) +{ + // Manipulate data if needed + Session::addMessageAfterRedirect(__("Pre Delete Computer Hook", 'example'), true); } // Hook done on delete item case -function plugin_item_delete_example($object) { - Session::addMessageAfterRedirect(__("Delete Computer Hook", 'example'), true); - return true; +function plugin_item_delete_example($object) +{ + Session::addMessageAfterRedirect(__("Delete Computer Hook", 'example'), true); + return true; } // Hook done on before purge item case -function plugin_pre_item_purge_example($object) { - // Manipulate data if needed - Session::addMessageAfterRedirect(__("Pre Purge Computer Hook", 'example'), true); +function plugin_pre_item_purge_example($object) +{ + // Manipulate data if needed + Session::addMessageAfterRedirect(__("Pre Purge Computer Hook", 'example'), true); } // Hook done on purge item case -function plugin_item_purge_example($object) { - Session::addMessageAfterRedirect(__("Purge Computer Hook", 'example'), true); - return true; +function plugin_item_purge_example($object) +{ + Session::addMessageAfterRedirect(__("Purge Computer Hook", 'example'), true); + return true; } // Hook done on before restore item case -function plugin_pre_item_restore_example($item) { - // Manipulate data if needed - Session::addMessageAfterRedirect(__("Pre Restore Computer Hook", 'example')); +function plugin_pre_item_restore_example($item) +{ + // Manipulate data if needed + Session::addMessageAfterRedirect(__("Pre Restore Computer Hook", 'example')); } // Hook done on before restore item case -function plugin_pre_item_restore_example2($item) { - // Manipulate data if needed - Session::addMessageAfterRedirect(__("Pre Restore Phone Hook", 'example')); +function plugin_pre_item_restore_example2($item) +{ + // Manipulate data if needed + Session::addMessageAfterRedirect(__("Pre Restore Phone Hook", 'example')); } // Hook done on restore item case -function plugin_item_restore_example($item) { - Session::addMessageAfterRedirect(__("Restore Computer Hook", 'example')); - return true; +function plugin_item_restore_example($item) +{ + Session::addMessageAfterRedirect(__("Restore Computer Hook", 'example')); + return true; } // Hook done on restore item case -function plugin_item_transfer_example($parm) { - //TRANS: %1$s is the source type, %2$d is the source ID, %3$d is the destination ID - Session::addMessageAfterRedirect(sprintf(__('Transfer Computer Hook %1$s %2$d -> %3$d', 'example'), $parm['type'], $parm['id'], - $parm['newID'])); +function plugin_item_transfer_example($parm) +{ + //TRANS: %1$s is the source type, %2$d is the source ID, %3$d is the destination ID + Session::addMessageAfterRedirect(sprintf( + __('Transfer Computer Hook %1$s %2$d -> %3$d', 'example'), + $parm['type'], + $parm['id'], + $parm['newID'], + )); - return false; + return false; } // Do special actions for dynamic report -function plugin_example_dynamicReport($parm) { - if ($parm["item_type"] == Example::class) { - // Do all what you want for export depending on $parm - echo "Personalized export for type ".$parm["display_type"]; - echo 'with additional datas :
'; - echo "Single data : add1
"; - print $parm['add1'].'
'; - echo "Array data : add2
"; - Html::printCleanArray($parm['add2']); - // Return true if personalized display is done - return true; - } - // Return false if no specific display is done, then use standard display - return false; +function plugin_example_dynamicReport($parm) +{ + if ($parm["item_type"] == Example::class) { + // Do all what you want for export depending on $parm + echo "Personalized export for type " . $parm["display_type"]; + echo 'with additional datas :
'; + echo "Single data : add1
"; + print $parm['add1'] . '
'; + echo "Array data : add2
"; + Html::printCleanArray($parm['add2']); + // Return true if personalized display is done + return true; + } + // Return false if no specific display is done, then use standard display + return false; } // Add parameters to Html::printPager in search system -function plugin_example_addParamFordynamicReport($itemtype) { - if ($itemtype == Example::class) { - // Return array data containing all params to add : may be single data or array data - // Search config are available from session variable - return ['add1' => $_SESSION['glpisearch'][$itemtype]['order'], - 'add2' => ['tutu' => 'Second Add', - 'Other Data']]; - } - // Return false or a non array data if not needed - return false; +function plugin_example_addParamFordynamicReport($itemtype) +{ + if ($itemtype == Example::class) { + // Return array data containing all params to add : may be single data or array data + // Search config are available from session variable + return ['add1' => $_SESSION['glpisearch'][$itemtype]['order'], + 'add2' => ['tutu' => 'Second Add', + 'Other Data']]; + } + // Return false or a non array data if not needed + return false; } @@ -454,24 +495,26 @@ function plugin_example_addParamFordynamicReport($itemtype) { * * @return boolean */ -function plugin_example_install() { - global $DB; +function plugin_example_install() +{ + /** @var DBmysql $DB */ + global $DB; - $migration = new Migration(PLUGIN_EXAMPLE_VERSION); - Config::setConfigurationValues('plugin:Example', ['configuration' => false]); + $migration = new Migration(PLUGIN_EXAMPLE_VERSION); + Config::setConfigurationValues('plugin:Example', ['configuration' => false]); - // Adds the right(s) to all pre-existing profiles with no access by default - ProfileRight::addProfileRights([Example::$rightname]); + // Adds the right(s) to all pre-existing profiles with no access by default + ProfileRight::addProfileRights([Example::$rightname]); - // Grants full access to profiles that can update the Config (super-admins) - $migration->addRight(Example::$rightname, ALLSTANDARDRIGHT, [Config::$rightname => UPDATE]); + // Grants full access to profiles that can update the Config (super-admins) + $migration->addRight(Example::$rightname, ALLSTANDARDRIGHT, [Config::$rightname => UPDATE]); - $default_charset = DBConnection::getDefaultCharset(); - $default_collation = DBConnection::getDefaultCollation(); - $default_key_sign = DBConnection::getDefaultPrimaryKeySignOption(); + $default_charset = DBConnection::getDefaultCharset(); + $default_collation = DBConnection::getDefaultCollation(); + $default_key_sign = DBConnection::getDefaultPrimaryKeySignOption(); - if (!$DB->tableExists("glpi_plugin_example_examples")) { - $query = "CREATE TABLE `glpi_plugin_example_examples` ( + if (!$DB->tableExists("glpi_plugin_example_examples")) { + $query = "CREATE TABLE `glpi_plugin_example_examples` ( `id` int {$default_key_sign} NOT NULL auto_increment, `name` varchar(255) default NULL, `serial` varchar(255) NOT NULL, @@ -482,19 +525,19 @@ function plugin_example_install() { PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET={$default_charset} COLLATE={$default_collation} ROW_FORMAT=DYNAMIC;"; - $DB->query($query) or die("error creating glpi_plugin_example_examples ". $DB->error()); + $DB->doQuery($query); - $query = "INSERT INTO `glpi_plugin_example_examples` + $query = "INSERT INTO `glpi_plugin_example_examples` (`id`, `name`, `serial`, `plugin_example_dropdowns_id`, `is_deleted`, `is_template`, `template_name`) VALUES (1, 'example 1', 'serial 1', 1, 0, 0, NULL), (2, 'example 2', 'serial 2', 2, 0, 0, NULL), (3, 'example 3', 'serial 3', 1, 0, 0, NULL)"; - $DB->query($query) or die("error populate glpi_plugin_example ". $DB->error()); - } + $DB->doQuery($query); + } - if (!$DB->tableExists("glpi_plugin_example_dropdowns")) { - $query = "CREATE TABLE `glpi_plugin_example_dropdowns` ( + if (!$DB->tableExists("glpi_plugin_example_dropdowns")) { + $query = "CREATE TABLE `glpi_plugin_example_dropdowns` ( `id` int {$default_key_sign} NOT NULL auto_increment, `name` varchar(255) default NULL, `comment` text, @@ -502,19 +545,19 @@ function plugin_example_install() { KEY `name` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET={$default_charset} COLLATE={$default_collation} ROW_FORMAT=DYNAMIC;"; - $DB->query($query) or die("error creating glpi_plugin_example_dropdowns". $DB->error()); + $DB->doQuery($query); - $query = "INSERT INTO `glpi_plugin_example_dropdowns` + $query = "INSERT INTO `glpi_plugin_example_dropdowns` (`id`, `name`, `comment`) VALUES (1, 'dp 1', 'comment 1'), (2, 'dp2', 'comment 2')"; - $DB->query($query) or die("error populate glpi_plugin_example_dropdowns". $DB->error()); + $DB->doQuery($query); - } + } - if (!$DB->tableExists('glpi_plugin_example_devicecameras')) { - $query = "CREATE TABLE `glpi_plugin_example_devicecameras` ( + if (!$DB->tableExists('glpi_plugin_example_devicecameras')) { + $query = "CREATE TABLE `glpi_plugin_example_devicecameras` ( `id` int {$default_key_sign} NOT NULL AUTO_INCREMENT, `designation` varchar(255) DEFAULT NULL, `comment` text, @@ -524,11 +567,11 @@ function plugin_example_install() { KEY `manufacturers_id` (`manufacturers_id`) ) ENGINE=InnoDB DEFAULT CHARSET={$default_charset} COLLATE={$default_collation} ROW_FORMAT=DYNAMIC;"; - $DB->query($query) or die("error creating glpi_plugin_example_examples ". $DB->error()); - } + $DB->doQuery($query); + } - if (!$DB->tableExists('glpi_plugin_example_items_devicecameras')) { - $query = "CREATE TABLE `glpi_plugin_example_items_devicecameras` ( + if (!$DB->tableExists('glpi_plugin_example_items_devicecameras')) { + $query = "CREATE TABLE `glpi_plugin_example_items_devicecameras` ( `id` int {$default_key_sign} NOT NULL AUTO_INCREMENT, `items_id` int {$default_key_sign} NOT NULL DEFAULT '0', `itemtype` varchar(255) DEFAULT NULL, @@ -542,13 +585,13 @@ function plugin_example_install() { KEY `is_dynamic` (`is_dynamic`) ) ENGINE=InnoDB DEFAULT CHARSET={$default_charset} COLLATE={$default_collation} ROW_FORMAT=DYNAMIC;"; - $DB->query($query) or die("error creating glpi_plugin_example_examples ". $DB->error()); - } + $DB->doQuery($query); + } - // To be called for each task the plugin manage - // task in class - CronTask::Register(Example::class, 'Sample', DAY_TIMESTAMP, ['param' => 50]); - return true; + // To be called for each task the plugin manage + // task in class + CronTask::Register(Example::class, 'Sample', DAY_TIMESTAMP, ['param' => 50]); + return true; } @@ -557,74 +600,83 @@ function plugin_example_install() { * * @return boolean */ -function plugin_example_uninstall() { - global $DB; +function plugin_example_uninstall() +{ + /** @var DBmysql $DB */ + global $DB; - $config = new Config(); - $config->deleteConfigurationValues('plugin:Example', ['configuration' => false]); + $config = new Config(); + $config->deleteConfigurationValues('plugin:Example', ['configuration' => false]); - ProfileRight::deleteProfileRights([Example::$rightname]); + ProfileRight::deleteProfileRights([Example::$rightname]); - $notif = new Notification(); - $options = ['itemtype' => 'Ticket', - 'event' => 'plugin_example', - 'FIELDS' => 'id']; - foreach ($DB->request('glpi_notifications', $options) as $data) { - $notif->delete($data); - } - // Old version tables - if ($DB->tableExists("glpi_dropdown_plugin_example")) { - $query = "DROP TABLE `glpi_dropdown_plugin_example`"; - $DB->query($query) or die("error deleting glpi_dropdown_plugin_example"); - } - if ($DB->tableExists("glpi_plugin_example")) { - $query = "DROP TABLE `glpi_plugin_example`"; - $DB->query($query) or die("error deleting glpi_plugin_example"); - } - // Current version tables - if ($DB->tableExists("glpi_plugin_example_example")) { - $query = "DROP TABLE `glpi_plugin_example_example`"; - $DB->query($query) or die("error deleting glpi_plugin_example_example"); - } - if ($DB->tableExists("glpi_plugin_example_dropdowns")) { - $query = "DROP TABLE `glpi_plugin_example_dropdowns`;"; - $DB->query($query) or die("error deleting glpi_plugin_example_dropdowns"); - } - if ($DB->tableExists("glpi_plugin_example_devicecameras")) { - $query = "DROP TABLE `glpi_plugin_example_devicecameras`;"; - $DB->query($query) or die("error deleting glpi_plugin_example_devicecameras"); - } - if ($DB->tableExists("glpi_plugin_example_items_devicecameras")) { - $query = "DROP TABLE `glpi_plugin_example_items_devicecameras`;"; - $DB->query($query) or die("error deleting glpi_plugin_example_items_devicecameras"); - } - return true; + $notif = new Notification(); + $criteria = [ + 'SELECT' => 'id', + 'FROM' => 'glpi_notifications', + 'WHERE' => [ + 'itemtype' => 'Ticket', + 'event' => 'plugin_example', + ], + ]; + foreach ($DB->request($criteria) as $data) { + $notif->delete($data); + } + // Old version tables + if ($DB->tableExists("glpi_dropdown_plugin_example")) { + $query = "DROP TABLE `glpi_dropdown_plugin_example`"; + $DB->doQuery($query); + } + if ($DB->tableExists("glpi_plugin_example")) { + $query = "DROP TABLE `glpi_plugin_example`"; + $DB->doQuery($query); + } + // Current version tables + if ($DB->tableExists("glpi_plugin_example_example")) { + $query = "DROP TABLE `glpi_plugin_example_example`"; + $DB->doQuery($query); + } + if ($DB->tableExists("glpi_plugin_example_dropdowns")) { + $query = "DROP TABLE `glpi_plugin_example_dropdowns`;"; + $DB->doQuery($query); + } + if ($DB->tableExists("glpi_plugin_example_devicecameras")) { + $query = "DROP TABLE `glpi_plugin_example_devicecameras`;"; + $DB->doQuery($query); + } + if ($DB->tableExists("glpi_plugin_example_items_devicecameras")) { + $query = "DROP TABLE `glpi_plugin_example_items_devicecameras`;"; + $DB->doQuery($query); + } + return true; } -function plugin_example_AssignToTicket($types) { - $types[Example::class] = "Example"; - return $types; +function plugin_example_AssignToTicket($types) +{ + $types[Example::class] = "Example"; + return $types; } -function plugin_example_get_events(NotificationTargetTicket $target) { - $target->events['plugin_example'] = __("Example event", 'example'); +function plugin_example_get_events(NotificationTargetTicket $target) +{ + $target->events['plugin_example'] = __("Example event", 'example'); } -function plugin_example_get_datas(NotificationTargetTicket $target) { - $target->data['##ticket.example##'] = __("Example datas", 'example'); +function plugin_example_get_datas(NotificationTargetTicket $target) +{ + $target->data['##ticket.example##'] = __("Example datas", 'example'); } -function plugin_example_postinit() { - global $CFG_GLPI; - - // All plugins are initialized, so all types are registered - //foreach (Infocom::getItemtypesThatCanHave() as $type) { - // do something - //} +function plugin_example_postinit() +{ + // All plugins are initialized, so all types are registered + //foreach (Infocom::getItemtypesThatCanHave() as $type) { + // do something + //} } @@ -634,10 +686,11 @@ function plugin_example_postinit() { * * @param $datas array * - * @return un tableau + * @return array **/ -function plugin_retrieve_more_data_from_ldap_example(array $datas) { - return $datas; +function plugin_retrieve_more_data_from_ldap_example(array $datas) +{ + return $datas; } @@ -646,49 +699,56 @@ function plugin_retrieve_more_data_from_ldap_example(array $datas) { * * @param $fields array * - * @return un tableau + * @return array **/ -function plugin_retrieve_more_field_from_ldap_example($fields) { - return $fields; +function plugin_retrieve_more_field_from_ldap_example($fields) +{ + return $fields; } // Check to add to status page -function plugin_example_Status($param) { - // Do checks (no check for example) - $ok = true; - echo "example plugin: example"; - if ($ok) { - echo "_OK"; - } else { - echo "_PROBLEM"; - // Only set ok to false if trouble (global status) - $param['ok'] = false; - } - echo "\n"; - return $param; +function plugin_example_Status($param) +{ + // Do checks (no check for example) + $ok = true; + echo "example plugin: example"; + + if ($ok) { + echo "_OK"; + } else { + echo "_PROBLEM"; + // Only set ok to false if trouble (global status) + $param['ok'] = false; + } + echo "\n"; + return $param; } -function plugin_example_display_central() { - echo ""; - echo "
"; - echo __("Plugin example displays on central page", "example"); - echo "
"; - echo ""; +function plugin_example_display_central() +{ + echo ""; + echo "
"; + echo __("Plugin example displays on central page", "example"); + echo "
"; + echo ""; } -function plugin_example_display_login() { - echo "
"; - echo __("Plugin example displays on login page", "example"); - echo "
"; +function plugin_example_display_login() +{ + echo "
"; + echo __("Plugin example displays on login page", "example"); + echo "
"; } -function plugin_example_infocom_hook($params) { - echo ""; - echo __("Plugin example displays on central page", "example"); - echo ""; +function plugin_example_infocom_hook($params) +{ + echo ""; + echo __("Plugin example displays on central page", "example"); + echo ""; } -function plugin_example_filter_actors(array $params = []): array { +function plugin_example_filter_actors(array $params = []): array +{ $itemtype = $params['params']['itemtype']; $items_id = $params['params']['items_id']; @@ -704,13 +764,17 @@ function plugin_example_filter_actors(array $params = []): array { return $params; } -function plugin_example_set_impact_icon(array $params) { +function plugin_example_set_impact_icon(array $params) +{ + /** @var array $CFG_GLPI */ + global $CFG_GLPI; + $itemtype = $params['itemtype']; $items_id = $params['items_id']; $item = getItemForItemtype($itemtype); if ($item instanceof Computer && $item->getFromDB($items_id)) { - return Plugin::getWebDir('example', true, false) . '/public/computer_icon.svg'; + return $CFG_GLPI['root_doc'] . '/plugins/example/public/computer_icon.svg'; } return null; } diff --git a/report.php b/report.php index 51853f3..55d9bb2 100644 --- a/report.php +++ b/report.php @@ -38,7 +38,7 @@ // Entry menu case define('GLPI_ROOT', '../..'); -include (GLPI_ROOT . "/inc/includes.php"); +include(GLPI_ROOT . "/inc/includes.php"); Session::checkRight(Config::$rightname, UPDATE); diff --git a/setup.php b/setup.php index 6d3c216..d00ffa5 100644 --- a/setup.php +++ b/setup.php @@ -42,9 +42,9 @@ use GlpiPlugin\Example\Showtabitem; define('PLUGIN_EXAMPLE_VERSION', '0.0.1'); // Minimal GLPI version, inclusive -define('PLUGIN_EXAMPLE_MIN_GLPI', '10.0.0'); +define('PLUGIN_EXAMPLE_MIN_GLPI', '11.0.0'); // Maximum GLPI version, exclusive -define('PLUGIN_EXAMPLE_MAX_GLPI', '10.0.99'); +define('PLUGIN_EXAMPLE_MAX_GLPI', '11.0.99'); /** * Init hooks of the plugin. @@ -52,249 +52,250 @@ define('PLUGIN_EXAMPLE_MAX_GLPI', '10.0.99'); * * @return void */ -function plugin_init_example() { - global $PLUGIN_HOOKS,$CFG_GLPI; +function plugin_init_example() +{ - // Params : plugin name - string type - ID - Array of attributes - // No specific information passed so not needed - //Plugin::registerClass(Example::getType(), - // array('classname' => Example::class, - // )); + /** @var array $CFG_GLPI */ + /** @var array $PLUGIN_HOOKS */ + global $CFG_GLPI, $PLUGIN_HOOKS; - Plugin::registerClass(Config::class, ['addtabon' => 'Config']); + // Params : plugin name - string type - ID - Array of attributes + // No specific information passed so not needed + //Plugin::registerClass(Example::getType(), + // array('classname' => Example::class, + // )); - // Params : plugin name - string type - ID - Array of attributes - Plugin::registerClass(Dropdown::class); + require_once(__DIR__ . '/vendor/autoload.php'); - $types = ['Central', 'Computer', 'ComputerDisk', 'Notification', 'Phone', - 'Preference', 'Profile', 'Supplier']; - Plugin::registerClass(Example::class, - ['notificationtemplates_types' => true, - 'addtabon' => $types, - 'link_types' => true]); + Plugin::registerClass(Config::class, ['addtabon' => 'Config']); - Plugin::registerClass(RuleTestCollection::class, - ['rulecollections_types' => true]); + // Params : plugin name - string type - ID - Array of attributes + Plugin::registerClass(Dropdown::class); - Plugin::registerClass(DeviceCamera::class, - ['device_types' => true]); + $types = ['Central', 'Computer', 'ComputerDisk', 'Notification', 'Phone', + 'Preference', 'Profile', 'Supplier']; + Plugin::registerClass( + Example::class, + ['notificationtemplates_types' => true, + 'addtabon' => $types, + 'link_types' => true], + ); - if (version_compare(GLPI_VERSION, '9.1', 'ge')) { - if (class_exists(Example::class)) { - Link::registerTag(Example::$tags); - } - } - // Display a menu entry ? - Plugin::registerClass(\GlpiPlugin\Example\Profile::class, ['addtabon' => ['Profile']]); - if (Example::canView()) { // Right set in change_profile hook - $PLUGIN_HOOKS['menu_toadd']['example'] = ['plugins' => Example::class, - 'tools' => Example::class]; + Plugin::registerClass( + RuleTestCollection::class, + ['rulecollections_types' => true], + ); - // Old menu style - // $PLUGIN_HOOKS['menu_entry']['example'] = 'front/example.php'; - // - // $PLUGIN_HOOKS['submenu_entry']['example']['options']['optionname']['title'] = "Search"; - // $PLUGIN_HOOKS['submenu_entry']['example']['options']['optionname']['page'] = '/plugins/example/front/example.php'; - // $PLUGIN_HOOKS['submenu_entry']['example']['options']['optionname']['links']['search'] = '/plugins/example/front/example.php'; - // $PLUGIN_HOOKS['submenu_entry']['example']['options']['optionname']['links']['add'] = '/plugins/example/front/example.form.php'; - // $PLUGIN_HOOKS['submenu_entry']['example']['options']['optionname']['links']['config'] = '/plugins/example/index.php'; - // $PLUGIN_HOOKS['submenu_entry']['example']['options']['optionname']['links']["".__s("] = '/plugins/example/index.php'; - // $PLUGIN_HOOKS['submenu_entry']['example']['options']['optionname']['links'][__s('Test link', 'example')] = '/plugins/example/index.php'; + Plugin::registerClass( + DeviceCamera::class, + ['device_types' => true], + ); - $PLUGIN_HOOKS[Hooks::HELPDESK_MENU_ENTRY]['example'] = true; - $PLUGIN_HOOKS[Hooks::HELPDESK_MENU_ENTRY_ICON]['example'] = 'fas fa-puzzle-piece'; - } + if (class_exists(Example::class)) { + Link::registerTag(Example::$tags); + } - // Config page - if (Session::haveRight('config', UPDATE)) { - $PLUGIN_HOOKS['config_page']['example'] = 'front/config.php'; - } + // Display a menu entry ? + Plugin::registerClass(\GlpiPlugin\Example\Profile::class, ['addtabon' => ['Profile']]); + if (Example::canView()) { // Right set in change_profile hook + $PLUGIN_HOOKS['menu_toadd']['example'] = ['plugins' => Example::class, + 'tools' => Example::class]; - // Init session - //$PLUGIN_HOOKS['init_session']['example'] = 'plugin_init_session_example'; - // Change profile - $PLUGIN_HOOKS['change_profile']['example'] = 'plugin_change_profile_example'; - // Change entity - //$PLUGIN_HOOKS['change_entity']['example'] = 'plugin_change_entity_example'; + // Old menu style + // $PLUGIN_HOOKS['menu_entry']['example'] = 'front/example.php'; + // + // $PLUGIN_HOOKS['submenu_entry']['example']['options']['optionname']['title'] = "Search"; + // $PLUGIN_HOOKS['submenu_entry']['example']['options']['optionname']['page'] = '/plugins/example/front/example.php'; + // $PLUGIN_HOOKS['submenu_entry']['example']['options']['optionname']['links']['search'] = '/plugins/example/front/example.php'; + // $PLUGIN_HOOKS['submenu_entry']['example']['options']['optionname']['links']['add'] = '/plugins/example/front/example.form.php'; + // $PLUGIN_HOOKS['submenu_entry']['example']['options']['optionname']['links']['config'] = '/plugins/example/index.php'; + // $PLUGIN_HOOKS['submenu_entry']['example']['options']['optionname']['links']["".__s("] = '/plugins/example/index.php'; + // $PLUGIN_HOOKS['submenu_entry']['example']['options']['optionname']['links'][__s('Test link', 'example')] = '/plugins/example/index.php'; - // Item action event // See define.php for defined ITEM_TYPE - $PLUGIN_HOOKS[Hooks::PRE_ITEM_UPDATE]['example'] = [Computer::class => 'plugin_pre_item_update_example']; - $PLUGIN_HOOKS[hooks::ITEM_UPDATE]['example'] = [Computer::class => 'plugin_item_update_example']; + $PLUGIN_HOOKS[Hooks::HELPDESK_MENU_ENTRY]['example'] = true; + $PLUGIN_HOOKS[Hooks::HELPDESK_MENU_ENTRY_ICON]['example'] = 'fas fa-puzzle-piece'; + } - $PLUGIN_HOOKS[Hooks::ITEM_EMPTY]['example'] = [Computer::class => 'plugin_item_empty_example']; + // Config page + if (Session::haveRight('config', UPDATE)) { + $PLUGIN_HOOKS['config_page']['example'] = 'front/config.php'; + } - // Restrict right - $PLUGIN_HOOKS[Hooks::ITEM_CAN]['example'] = [Computer::class => [Example::class, 'item_can']]; - $PLUGIN_HOOKS['add_default_where']['example'] = [Computer::class => [Example::class, 'add_default_where']]; + // Init session + //$PLUGIN_HOOKS['init_session']['example'] = 'plugin_init_session_example'; + // Change profile + $PLUGIN_HOOKS['change_profile']['example'] = 'plugin_change_profile_example'; + // Change entity + //$PLUGIN_HOOKS['change_entity']['example'] = 'plugin_change_entity_example'; - // Example using a method in class - $PLUGIN_HOOKS[Hooks::PRE_ITEM_ADD]['example'] = [Computer::class => [Example::class, - 'pre_item_add_computer']]; - $PLUGIN_HOOKS[Hooks::POST_PREPAREADD]['example'] = [Computer::class => [Example::class, - 'post_prepareadd_computer']]; - $PLUGIN_HOOKS[Hooks::ITEM_ADD]['example'] = [Computer::class => [Example::class, - 'item_add_computer']]; + // Item action event // See define.php for defined ITEM_TYPE + $PLUGIN_HOOKS[Hooks::PRE_ITEM_UPDATE]['example'] = [Computer::class => 'plugin_pre_item_update_example']; + $PLUGIN_HOOKS[hooks::ITEM_UPDATE]['example'] = [Computer::class => 'plugin_item_update_example']; - $PLUGIN_HOOKS[Hooks::PRE_ITEM_DELETE]['example'] = [Computer::class => 'plugin_pre_item_delete_example']; - $PLUGIN_HOOKS[Hooks::ITEM_DELETE]['example'] = [Computer::class => 'plugin_item_delete_example']; + $PLUGIN_HOOKS[Hooks::ITEM_EMPTY]['example'] = [Computer::class => 'plugin_item_empty_example']; - // Example using the same function - $PLUGIN_HOOKS[Hooks::PRE_ITEM_PURGE]['example'] = [Computer::class => 'plugin_pre_item_purge_example', - 'Phone' => 'plugin_pre_item_purge_example']; - $PLUGIN_HOOKS[Hooks::ITEM_PURGE]['example'] = [Computer::class => 'plugin_item_purge_example', - 'Phone' => 'plugin_item_purge_example']; + // Restrict right + $PLUGIN_HOOKS[Hooks::ITEM_CAN]['example'] = [Computer::class => [Example::class, 'item_can']]; + $PLUGIN_HOOKS['add_default_where']['example'] = [Computer::class => [Example::class, 'add_default_where']]; - // Example with 2 different functions - $PLUGIN_HOOKS[Hooks::PRE_ITEM_RESTORE]['example'] = [Computer::class => 'plugin_pre_item_restore_example', - 'Phone' => 'plugin_pre_item_restore_example2']; - $PLUGIN_HOOKS[Hooks::ITEM_RESTORE]['example'] = [Computer::class => 'plugin_item_restore_example']; + // Example using a method in class + $PLUGIN_HOOKS[Hooks::PRE_ITEM_ADD]['example'] = [Computer::class => [Example::class, + 'pre_item_add_computer']]; + $PLUGIN_HOOKS[Hooks::POST_PREPAREADD]['example'] = [Computer::class => [Example::class, + 'post_prepareadd_computer']]; + $PLUGIN_HOOKS[Hooks::ITEM_ADD]['example'] = [Computer::class => [Example::class, + 'item_add_computer']]; - // Add event to GLPI core itemtype, event will be raised by the plugin. - // See plugin_example_uninstall for cleanup of notification - $PLUGIN_HOOKS[Hooks::ITEM_GET_EVENTS]['example'] - = ['NotificationTargetTicket' => 'plugin_example_get_events']; + $PLUGIN_HOOKS[Hooks::PRE_ITEM_DELETE]['example'] = [Computer::class => 'plugin_pre_item_delete_example']; + $PLUGIN_HOOKS[Hooks::ITEM_DELETE]['example'] = [Computer::class => 'plugin_item_delete_example']; - // Add datas to GLPI core itemtype for notifications template. - $PLUGIN_HOOKS[Hooks::ITEM_GET_DATA]['example'] - = ['NotificationTargetTicket' => 'plugin_example_get_datas']; + // Example using the same function + $PLUGIN_HOOKS[Hooks::PRE_ITEM_PURGE]['example'] = [Computer::class => 'plugin_pre_item_purge_example', + 'Phone' => 'plugin_pre_item_purge_example']; + $PLUGIN_HOOKS[Hooks::ITEM_PURGE]['example'] = [Computer::class => 'plugin_item_purge_example', + 'Phone' => 'plugin_item_purge_example']; - $PLUGIN_HOOKS[Hooks::ITEM_TRANSFER]['example'] = 'plugin_item_transfer_example'; + // Example with 2 different functions + $PLUGIN_HOOKS[Hooks::PRE_ITEM_RESTORE]['example'] = [Computer::class => 'plugin_pre_item_restore_example', + 'Phone' => 'plugin_pre_item_restore_example2']; + $PLUGIN_HOOKS[Hooks::ITEM_RESTORE]['example'] = [Computer::class => 'plugin_item_restore_example']; - // function to populate planning - // No more used since GLPI 0.84 - // $PLUGIN_HOOKS['planning_populate']['example'] = 'plugin_planning_populate_example'; - // Use instead : add class to planning types and define populatePlanning in class - $CFG_GLPI['planning_types'][] = Example::class; + // Add event to GLPI core itemtype, event will be raised by the plugin. + // See plugin_example_uninstall for cleanup of notification + $PLUGIN_HOOKS[Hooks::ITEM_GET_EVENTS]['example'] + = ['NotificationTargetTicket' => 'plugin_example_get_events']; - //function to display planning items - // No more used sinc GLPi 0.84 - // $PLUGIN_HOOKS['display_planning']['example'] = 'plugin_display_planning_example'; - // Use instead : displayPlanningItem of the specific itemtype + // Add datas to GLPI core itemtype for notifications template. + $PLUGIN_HOOKS[Hooks::ITEM_GET_DATA]['example'] + = ['NotificationTargetTicket' => 'plugin_example_get_datas']; - // Massive Action definition - $PLUGIN_HOOKS['use_massive_action']['example'] = 1; + $PLUGIN_HOOKS[Hooks::ITEM_TRANSFER]['example'] = 'plugin_item_transfer_example'; - $PLUGIN_HOOKS['assign_to_ticket']['example'] = 1; + // function to populate planning + // No more used since GLPI 0.84 + // $PLUGIN_HOOKS['planning_populate']['example'] = 'plugin_planning_populate_example'; + // Use instead : add class to planning types and define populatePlanning in class + $CFG_GLPI['planning_types'][] = Example::class; - // Add specific files to add to the header : javascript or css - $PLUGIN_HOOKS[Hooks::ADD_JAVASCRIPT]['example'] = 'example.js'; - $PLUGIN_HOOKS[Hooks::ADD_CSS]['example'] = 'example.css'; + //function to display planning items + // No more used sinc GLPi 0.84 + // $PLUGIN_HOOKS['display_planning']['example'] = 'plugin_display_planning_example'; + // Use instead : displayPlanningItem of the specific itemtype - // Add specific tags to the header - $PLUGIN_HOOKS[Hooks::ADD_HEADER_TAG]['example'] = [ - [ - 'tag' => 'meta', - 'properties' => [ - 'name' => 'robots', - 'content' => 'noindex, nofollow', - ] - ], - [ - 'tag' => 'link', - 'properties' => [ - 'rel' => 'alternate', - 'type' => 'application/rss+xml', - 'title' => 'The company RSS feed', - 'href' => 'https://example.org/feed.xml', - ] - ], - ]; + // Massive Action definition + $PLUGIN_HOOKS['use_massive_action']['example'] = 1; - // Add specific files to add to the header into anonymous page : javascript or css - $PLUGIN_HOOKS[Hooks::ADD_CSS_ANONYMOUS_PAGE]['example'] = 'example_anonymous.css'; - $PLUGIN_HOOKS[Hooks::ADD_JAVASCRIPT_MODULE_ANONYMOUS_PAGE]['example'] = 'mymodule_anonymous.js'; - $PLUGIN_HOOKS[Hooks::ADD_JAVASCRIPT_ANONYMOUS_PAGE]['example'] = 'example_anonymous.js'; + $PLUGIN_HOOKS['assign_to_ticket']['example'] = 1; - // Add specific tags to the header into anonymous page - $PLUGIN_HOOKS[Hooks::ADD_HEADER_TAG_ANONYMOUS_PAGE]['example'] = [ - [ - 'tag' => 'meta', - 'properties' => [ - 'name' => 'robots', - 'content' => 'noindex, nofollow', - ] - ], - [ - 'tag' => 'link', - 'properties' => [ - 'rel' => 'alternate', - 'type' => 'application/rss+xml', - 'title' => 'The company RSS feed', - 'href' => 'https://example.org/feed.xml', - ] - ], - ]; + // Add specific files to add to the header : javascript or css + $PLUGIN_HOOKS[Hooks::ADD_JAVASCRIPT]['example'] = 'example.js'; + $PLUGIN_HOOKS[Hooks::ADD_CSS]['example'] = 'example.css'; - // request more attributes from ldap - //$PLUGIN_HOOKS['retrieve_more_field_from_ldap']['example']="plugin_retrieve_more_field_from_ldap_example"; + // Add specific tags to the header + $PLUGIN_HOOKS[Hooks::ADD_HEADER_TAG]['example'] = [ + [ + 'tag' => 'meta', + 'properties' => [ + 'name' => 'robots', + 'content' => 'noindex, nofollow', + ], + ], + [ + 'tag' => 'link', + 'properties' => [ + 'rel' => 'alternate', + 'type' => 'application/rss+xml', + 'title' => 'The company RSS feed', + 'href' => 'https://example.org/feed.xml', + ], + ], + ]; - // Retrieve others datas from LDAP - //$PLUGIN_HOOKS['retrieve_more_data_from_ldap']['example']="plugin_retrieve_more_data_from_ldap_example"; + // Add specific files to add to the header into anonymous page : javascript or css + $PLUGIN_HOOKS[Hooks::ADD_CSS_ANONYMOUS_PAGE]['example'] = 'example_anonymous.css'; + $PLUGIN_HOOKS[Hooks::ADD_JAVASCRIPT_MODULE_ANONYMOUS_PAGE]['example'] = 'mymodule_anonymous.js'; + $PLUGIN_HOOKS[Hooks::ADD_JAVASCRIPT_ANONYMOUS_PAGE]['example'] = 'example_anonymous.js'; - // Reports - $PLUGIN_HOOKS['reports']['example'] = ['report.php' => 'New Report', - 'report.php?other' => 'New Report 2']; + // Add specific tags to the header into anonymous page + $PLUGIN_HOOKS[Hooks::ADD_HEADER_TAG_ANONYMOUS_PAGE]['example'] = [ + [ + 'tag' => 'meta', + 'properties' => [ + 'name' => 'robots', + 'content' => 'noindex, nofollow', + ], + ], + [ + 'tag' => 'link', + 'properties' => [ + 'rel' => 'alternate', + 'type' => 'application/rss+xml', + 'title' => 'The company RSS feed', + 'href' => 'https://example.org/feed.xml', + ], + ], + ]; - // Stats - $PLUGIN_HOOKS['stats']['example'] = ['stat.php' => 'New stat', - 'stat.php?other' => 'New stats 2',]; + // request more attributes from ldap + //$PLUGIN_HOOKS['retrieve_more_field_from_ldap']['example']="plugin_retrieve_more_field_from_ldap_example"; - $PLUGIN_HOOKS[Hooks::POST_INIT]['example'] = 'plugin_example_postinit'; + // Retrieve others datas from LDAP + //$PLUGIN_HOOKS['retrieve_more_data_from_ldap']['example']="plugin_retrieve_more_data_from_ldap_example"; - $PLUGIN_HOOKS['status']['example'] = 'plugin_example_Status'; + // Reports + $PLUGIN_HOOKS['reports']['example'] = ['report.php' => 'New Report', + 'report.php?other' => 'New Report 2']; - // CSRF compliance : All actions must be done via POST and forms closed by Html::closeForm(); - $PLUGIN_HOOKS[Hooks::CSRF_COMPLIANT]['example'] = true; + // Stats + $PLUGIN_HOOKS['stats']['example'] = ['stat.php' => 'New stat', + 'stat.php?other' => 'New stats 2',]; - $PLUGIN_HOOKS[Hooks::DISPLAY_CENTRAL]['example'] = "plugin_example_display_central"; - $PLUGIN_HOOKS[Hooks::DISPLAY_LOGIN]['example'] = "plugin_example_display_login"; - $PLUGIN_HOOKS[Hooks::INFOCOM]['example'] = "plugin_example_infocom_hook"; + $PLUGIN_HOOKS[Hooks::POST_INIT]['example'] = 'plugin_example_postinit'; - // pre_show and post_show for tabs and items, - // see GlpiPlugin\Example\Showtabitem class for implementation explanations - $PLUGIN_HOOKS[Hooks::PRE_SHOW_TAB]['example'] = [Showtabitem::class, 'pre_show_tab']; - $PLUGIN_HOOKS[Hooks::POST_SHOW_TAB]['example'] = [Showtabitem::class, 'post_show_tab']; - $PLUGIN_HOOKS[Hooks::PRE_SHOW_ITEM]['example'] = [Showtabitem::class, 'pre_show_item']; - $PLUGIN_HOOKS[Hooks::POST_SHOW_ITEM]['example'] = [Showtabitem::class, 'post_show_item']; + $PLUGIN_HOOKS['status']['example'] = 'plugin_example_Status'; - $PLUGIN_HOOKS[Hooks::PRE_ITEM_FORM]['example'] = [ItemForm::class, 'preItemForm']; - $PLUGIN_HOOKS[Hooks::POST_ITEM_FORM]['example'] = [ItemForm::class, 'postItemForm']; + $PLUGIN_HOOKS[Hooks::DISPLAY_CENTRAL]['example'] = "plugin_example_display_central"; + $PLUGIN_HOOKS[Hooks::DISPLAY_LOGIN]['example'] = "plugin_example_display_login"; + $PLUGIN_HOOKS[Hooks::INFOCOM]['example'] = "plugin_example_infocom_hook"; - //TODO: remove check when GLPI 11.0.0 is released - if (version_compare(GLPI_VERSION, '11.0.0', 'ge')) { - $PLUGIN_HOOKS[Hooks::PRE_ITIL_INFO_SECTION]['example'] = [ItemForm::class, 'preSection']; - $PLUGIN_HOOKS[Hooks::POST_ITIL_INFO_SECTION]['example'] = [ItemForm::class, 'postSection']; - } + // pre_show and post_show for tabs and items, + // see GlpiPlugin\Example\Showtabitem class for implementation explanations + $PLUGIN_HOOKS[Hooks::PRE_SHOW_TAB]['example'] = [Showtabitem::class, 'pre_show_tab']; + $PLUGIN_HOOKS[Hooks::POST_SHOW_TAB]['example'] = [Showtabitem::class, 'post_show_tab']; + $PLUGIN_HOOKS[Hooks::PRE_SHOW_ITEM]['example'] = [Showtabitem::class, 'pre_show_item']; + $PLUGIN_HOOKS[Hooks::POST_SHOW_ITEM]['example'] = [Showtabitem::class, 'post_show_item']; - // Add new actions to timeline - $PLUGIN_HOOKS[Hooks::TIMELINE_ACTIONS]['example'] = [ - ItemForm::class, 'timelineActions' - ]; + $PLUGIN_HOOKS[Hooks::PRE_ITEM_FORM]['example'] = [ItemForm::class, 'preItemForm']; + $PLUGIN_HOOKS[Hooks::POST_ITEM_FORM]['example'] = [ItemForm::class, 'postItemForm']; - // declare this plugin as an import plugin for Computer itemtype - $PLUGIN_HOOKS['import_item']['example'] = [Computer::class => ['Plugin']]; + $PLUGIN_HOOKS[Hooks::PRE_ITIL_INFO_SECTION]['example'] = [ItemForm::class, 'preSection']; + $PLUGIN_HOOKS[Hooks::POST_ITIL_INFO_SECTION]['example'] = [ItemForm::class, 'postSection']; - // add additional informations on Computer::showForm - $PLUGIN_HOOKS[Hooks::AUTOINVENTORY_INFORMATION]['example'] = [ - Computer::class => [Computer::class, 'showInfo'] - ]; + // Add new actions to timeline + $PLUGIN_HOOKS[Hooks::TIMELINE_ACTIONS]['example'] = [ + ItemForm::class, 'timelineActions', + ]; + + // declare this plugin as an import plugin for Computer itemtype + $PLUGIN_HOOKS['import_item']['example'] = [Computer::class => ['Plugin']]; + + // add additional informations on Computer::showForm + $PLUGIN_HOOKS[Hooks::AUTOINVENTORY_INFORMATION]['example'] = [ + Computer::class => [Computer::class, 'showInfo'], + ]; $PLUGIN_HOOKS[Hooks::FILTER_ACTORS]['example'] = "plugin_example_filter_actors"; - // add new cards to dashboard grid - $PLUGIN_HOOKS['dashboard_types']['example'] = [Example::class, 'dashboardTypes']; - $PLUGIN_HOOKS['dashboard_cards']['example'] = [Example::class, 'dashboardCards']; + // add new cards to dashboard grid + $PLUGIN_HOOKS['dashboard_types']['example'] = [Example::class, 'dashboardTypes']; + $PLUGIN_HOOKS['dashboard_cards']['example'] = [Example::class, 'dashboardCards']; - // Dashboard filter - $PLUGIN_HOOKS[Hooks::DASHBOARD_FILTERS]['example'] = [ - ComputerModelFilter::class - ]; + // Dashboard filter + $PLUGIN_HOOKS[Hooks::DASHBOARD_FILTERS]['example'] = [ + ComputerModelFilter::class, + ]; - //TODO: remove check when GLPI 11.0.0 is released - if (version_compare(GLPI_VERSION, '11.0.0', 'ge')) { - // Icon in the impact analysis - $PLUGIN_HOOKS[Hooks::SET_ITEM_IMPACT_ICON]['example'] = 'plugin_example_set_impact_icon'; - } + $PLUGIN_HOOKS[Hooks::SET_ITEM_IMPACT_ICON]['example'] = 'plugin_example_set_impact_icon'; } @@ -304,20 +305,21 @@ function plugin_init_example() { * * @return array */ -function plugin_version_example() { - return [ - 'name' => 'Plugin Example', - 'version' => PLUGIN_EXAMPLE_VERSION, - 'author' => 'Example plugin team', - 'license' => 'GPLv2+', - 'homepage' => 'https://github.com/pluginsGLPI/example', - 'requirements' => [ - 'glpi' => [ - 'min' => PLUGIN_EXAMPLE_MIN_GLPI, - 'max' => PLUGIN_EXAMPLE_MAX_GLPI, - ] - ] - ]; +function plugin_version_example() +{ + return [ + 'name' => 'Plugin Example', + 'version' => PLUGIN_EXAMPLE_VERSION, + 'author' => 'Example plugin team', + 'license' => 'GPLv2+', + 'homepage' => 'https://github.com/pluginsGLPI/example', + 'requirements' => [ + 'glpi' => [ + 'min' => PLUGIN_EXAMPLE_MIN_GLPI, + 'max' => PLUGIN_EXAMPLE_MAX_GLPI, + ], + ], + ]; } @@ -327,11 +329,12 @@ function plugin_version_example() { * * @return boolean */ -function plugin_example_check_prerequisites() { - if (false) { - return false; - } - return true; +function plugin_example_check_prerequisites() +{ + if (false) { + return false; + } + return true; } /** @@ -341,13 +344,14 @@ function plugin_example_check_prerequisites() { * * @return boolean */ -function plugin_example_check_config($verbose = false) { - if (true) { // Your configuration check - return true; - } +function plugin_example_check_config($verbose = false) +{ + if (true) { // Your configuration check + return true; + } - if ($verbose) { - echo __('Installed / not configured', 'example'); - } - return false; + if ($verbose) { + echo __('Installed / not configured', 'example'); + } + return false; } diff --git a/src/Child.php b/src/Child.php index ce2a4ed..5520406 100644 --- a/src/Child.php +++ b/src/Child.php @@ -34,6 +34,7 @@ // ---------------------------------------------------------------------- namespace GlpiPlugin\Example; + use CommonDBChild; use Session; @@ -43,64 +44,68 @@ use Session; // enhancements. // For CommonDBRelation, the variable are quiet equivalent, but they use _1 and _2 for each side // parent -class Child extends CommonDBChild { - - // A child rely on an item. If $itemtype=='itemtype', then that is a variable item. - static public $itemtype = 'itemtype'; - static public $items_id = 'items_id'; +class Child extends CommonDBChild +{ + // A child rely on an item. If $itemtype=='itemtype', then that is a variable item. + public static $itemtype = 'itemtype'; + public static $items_id = 'items_id'; - // With 0.84, you have to specify each right (create, view, update and delete), because - // CommonDBChild(s) and CommonDBRelation(s) mainly depend on the rights on the parent item - // All these methods rely on parent:can*. Two attributs are usefull : - // * $checkParentRights: define what to check regarding the parent : - // - CommonDBConnexity::DONT_CHECK_ITEM_RIGHTS don't eaven relly on parents rights - // - CommonDBConnexity::HAVE_VIEW_RIGHT_ON_ITEM view right on the item is enough - // - CommonDBConnexity::HAVE_SAME_RIGHT_ON_ITEM we must have at least update right - // on the item - // * $mustBeAttached: some CommonDBChild can be free, without any parent. - static function canCreate() { + // With 0.84, you have to specify each right (create, view, update and delete), because + // CommonDBChild(s) and CommonDBRelation(s) mainly depend on the rights on the parent item + // All these methods rely on parent:can*. Two attributs are usefull : + // * $checkParentRights: define what to check regarding the parent : + // - CommonDBConnexity::DONT_CHECK_ITEM_RIGHTS don't eaven relly on parents rights + // - CommonDBConnexity::HAVE_VIEW_RIGHT_ON_ITEM view right on the item is enough + // - CommonDBConnexity::HAVE_SAME_RIGHT_ON_ITEM we must have at least update right + // on the item + // * $mustBeAttached: some CommonDBChild can be free, without any parent. + public static function canCreate(): bool + { - return (Session::haveRight('internet', UPDATE) - && parent::canCreate()); - } + return (Session::haveRight('internet', UPDATE) + && parent::canCreate()); + } - static function canView() { + public static function canView(): bool + { - return (Session::haveRight('internet', READ) - && parent::canView()); - } + return (Session::haveRight('internet', READ) + && parent::canView()); + } - static function canUpdate() { + public static function canUpdate(): bool + { - return (Session::haveRight('internet', UPDATE) - && parent::canUpdate()); - } + return (Session::haveRight('internet', UPDATE) + && parent::canUpdate()); + } - static function canDelete() { + public static function canDelete(): bool + { - return (Session::haveRight('internet', DELETE) - && parent::canDelete()); - } + return (Session::haveRight('internet', DELETE) + && parent::canDelete()); + } - // By default, post_addItem, post_updateItem and post_deleteFromDB are defined. - // They define the history to add to the parents - // This method define the name to set inside the history of the parent. - // All these methods use $log_history_add, $log_history_update and $log_history_delete to - // define the level of log (Log::HISTORY_ADD_DEVICE, Log::HISTORY_UPDATE_DEVICE ...) - function getHistoryName_for_item($case) { - } + // By default, post_addItem, post_updateItem and post_deleteFromDB are defined. + // They define the history to add to the parents + // This method define the name to set inside the history of the parent. + // All these methods use $log_history_add, $log_history_update and $log_history_delete to + // define the level of log (Log::HISTORY_ADD_DEVICE, Log::HISTORY_UPDATE_DEVICE ...) + public function getHistoryName_for_item($case) {} - // CommonDBChild also check if we can add or updatethe item regarding the new item - // ($input[static::$itemtype] and $input[static::$items_id]). - // But don't forget to call parent::prepareInputForAdd() - function prepareInputForAdd($input) { - // My preparation on $input - return parent::prepareInputForAdd($input); - } + // CommonDBChild also check if we can add or updatethe item regarding the new item + // ($input[static::$itemtype] and $input[static::$items_id]). + // But don't forget to call parent::prepareInputForAdd() + public function prepareInputForAdd($input) + { + // My preparation on $input + return parent::prepareInputForAdd($input); + } } diff --git a/src/Computer.php b/src/Computer.php index 1834155..ea75fe5 100644 --- a/src/Computer.php +++ b/src/Computer.php @@ -34,50 +34,48 @@ // ---------------------------------------------------------------------- namespace GlpiPlugin\Example; + use CommonDBTM; -// Class of the defined type +class Computer extends CommonDBTM +{ + public static function showInfo() + { -if (!defined('GLPI_ROOT')) { - die("Sorry. You can't access directly to this file"); -} - -class Computer extends CommonDBTM { - - static function showInfo() { - - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo '
'.__('More information').'
'; - echo __('Test successful'); - echo '
'; - } + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo '
' . __('More information') . '
'; + echo __('Test successful'); + echo '
'; + } - static function item_can($item) { + public static function item_can($item) + { - if (($item->getType() == 'Computer') - && ($item->right == READ) - && ($item->fields['groups_id'] > 0) - && !in_array($item->fields['groups_id'], $_SESSION["glpigroups"])) { - $item->right = 0; // unknown, so denied. - } - } + if (($item->getType() == 'Computer') + && ($item->right == READ) + && ($item->fields['groups_id'] > 0) + && !in_array($item->fields['groups_id'], $_SESSION["glpigroups"])) { + $item->right = 0; // unknown, so denied. + } + } - static function add_default_where($in) { + public static function add_default_where($in) + { - list($itemtype, $condition) = $in; - if ($itemtype == 'Computer') { - $table = getTableForItemType($itemtype); - $condition .= " (".$table.".groups_id NOT IN (".implode(',', $_SESSION["glpigroups"])."))"; - } - return [$itemtype, $condition]; - } + list($itemtype, $condition) = $in; + if ($itemtype == 'Computer') { + $table = getTableForItemType($itemtype); + $condition .= " (" . $table . ".groups_id NOT IN (" . implode(',', $_SESSION["glpigroups"]) . "))"; + } + return [$itemtype, $condition]; + } } diff --git a/src/Config.php b/src/Config.php index e22b906..014d8f9 100644 --- a/src/Config.php +++ b/src/Config.php @@ -29,6 +29,7 @@ */ namespace GlpiPlugin\Example; + use CommonDBTM; use CommonGLPI; use Config as GlpiConfig; @@ -37,60 +38,65 @@ use Html; use Session; use Toolbox; -class Config extends CommonDBTM { +class Config extends CommonDBTM +{ + protected static $notable = true; - static protected $notable = true; + public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) + { - function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { + if (!$withtemplate) { + if ($item->getType() == 'Config') { + return __('Example plugin'); + } + } + return ''; + } - if (!$withtemplate) { - if ($item->getType() == 'Config') { - return __('Example plugin'); - } - } - return ''; - } + public static function configUpdate($input) + { + $input['configuration'] = 1 - $input['configuration']; + return $input; + } - static function configUpdate($input) { - $input['configuration'] = 1 - $input['configuration']; - return $input; - } + public function showFormExample() + { + /** @var array $CFG_GLPI */ + global $CFG_GLPI; - function showFormExample() { - global $CFG_GLPI; + if (!Session::haveRight("config", UPDATE)) { + return false; + } - if (!Session::haveRight("config", UPDATE)) { - return false; - } + $my_config = GlpiConfig::getConfigurationValues('plugin:Example'); - $my_config = GlpiConfig::getConfigurationValues('plugin:Example'); + echo "
"; + echo "
"; + echo ""; + echo ""; + echo ""; + echo ""; - echo ""; - echo "
"; - echo "
" . __('Example setup') . "
" . __('My boolean choice :') . ""; + echo ""; + echo ""; + Dropdown::showYesNo("configuration", $my_config['configuration']); + echo "
"; - echo ""; - echo ""; - echo ""; + echo ""; + echo ""; - echo ""; - echo ""; + echo "
" . __('Example setup') . "
" . __('My boolean choice :') . ""; - echo ""; - echo ""; - Dropdown::showYesNo("configuration", $my_config['configuration']); - echo "
"; + echo ""; + echo "
"; - echo ""; - echo "
"; + Html::closeForm(); + } - echo ""; - Html::closeForm(); - } - - static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { - - if ($item->getType() == 'Config') { - $config = new self(); - $config->showFormExample(); - } - } + public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) + { + if ($item->getType() == Config::class) { + $config = new self(); + $config->showFormExample(); + } + return true; + } } diff --git a/src/DeviceCamera.php b/src/DeviceCamera.php index 64b52d2..eaf15e9 100644 --- a/src/DeviceCamera.php +++ b/src/DeviceCamera.php @@ -34,19 +34,15 @@ // ---------------------------------------------------------------------- namespace GlpiPlugin\Example; + use CommonDevice; -// Class of the defined type - -if (!defined('GLPI_ROOT')) { - die("Sorry. You can't access directly to this file"); -} - /// Class DeviceCamera -class DeviceCamera extends CommonDevice { - - static function getTypeName($nb = 0) { - return _n('Camera', 'Cameras', $nb); - } +class DeviceCamera extends CommonDevice +{ + public static function getTypeName($nb = 0) + { + return _n('Camera', 'Cameras', $nb); + } } diff --git a/src/Document.php b/src/Document.php index a306c0a..3aec520 100644 --- a/src/Document.php +++ b/src/Document.php @@ -1,30 +1,31 @@ . --------------------------------------------------------------------------- +/** + * ------------------------------------------------------------------------- + * Example plugin for GLPI + * ------------------------------------------------------------------------- + * + * LICENSE + * + * This file is part of Example. + * + * Example is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Example is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Example. If not, see . + * ------------------------------------------------------------------------- + * @copyright Copyright (C) 2006-2022 by Example plugin team. + * @license GPLv2 https://www.gnu.org/licenses/gpl-2.0.html + * @link https://github.com/pluginsGLPI/example + * ------------------------------------------------------------------------- */ /** @@ -55,14 +56,14 @@ along with GLPI. If not, see . */ namespace GlpiPlugin\Example; + use Document as GlpiDocument; +use Exception; +use Glpi\Exception\Http\NotFoundHttpException; +use Sabre\DAV\Exception\BadRequest; -if (!defined('GLPI_ROOT')) { - die("Sorry. You can't access this file directly"); -} - -class Document extends GlpiDocument { - +class Document extends GlpiDocument +{ /** * Return the table used to store this object. Overloads the implementation in CommonDBTM * @@ -70,155 +71,160 @@ class Document extends GlpiDocument { * * @return string **/ - public static function getTable($classname = null) { - if ($classname === null) { - $classname = get_called_class(); - } - if ($classname == get_called_class()) { - return parent::getTable(Document::class); - } + public static function getTable($classname = null) + { + if ($classname === null) { + $classname = get_called_class(); + } + if ($classname == get_called_class()) { + return parent::getTable(Document::class); + } - return parent::getTable($classname); - } + return parent::getTable($classname); + } - /** - * Prepare creation of an item - * - * @param array $input - * @return array|false - */ - public function prepareInputForAdd($input) { - $input['_only_if_upload_succeed'] = true; - if (!isset($_FILES['file'])) { - return false; - } + /** + * Prepare creation of an item + * + * @param array $input + * @return array|false + */ + public function prepareInputForAdd($input) + { + $input['_only_if_upload_succeed'] = true; + if (!isset($_FILES['file'])) { + return false; + } - // Move the uploaded file to GLPi's tmp dir - while (count($_FILES['file']['name']) > 0) { - $source = array_pop($_FILES['file']['name']); - $destination = GLPI_TMP_DIR . '/' . $source; - move_uploaded_file($source, $destination); - $input['_filename'][] = $source; - } + // Move the uploaded file to GLPi's tmp dir + while (count($_FILES['file']['name']) > 0) { + $source = array_pop($_FILES['file']['name']); + $destination = GLPI_TMP_DIR . '/' . $source; + move_uploaded_file($source, $destination); + $input['_filename'][] = $source; + } - return parent::prepareInputForAdd($input); - } + return parent::prepareInputForAdd($input); + } - /** - * Prepare update of an item - * - * @param array $input - * @return array|false - */ - public function prepareInputForUpdate($input) { - // Do not allow update of document - return false; - } + /** + * Prepare update of an item + * + * @param array $input + * @return array|false + */ + public function prepareInputForUpdate($input) + { + // Do not allow update of document + return false; + } - /** - * Process required after loading an object from DB - * In this example, a file is sent as a byte strem then stops execution. - * - * @return void - */ - public function post_getFromDB() { - // Check the user can view this itemtype and can view this item - if ($this->canView() && $this->canViewItem()) { - if (isset($_SERVER['HTTP_ACCEPT']) && $_SERVER['HTTP_ACCEPT'] == 'application/octet-stream' - || isset($_GET['alt']) && $_GET['alt'] == 'media') { - $this->sendFile(); // and terminate script - } - } - } - - /** - * Send a byte stream to the HTTP client and stops execution - * - * @return void - */ - protected function sendFile() { - $streamSource = GLPI_DOC_DIR . '/' . $this->fields['filepath']; - - // Ensure the file exists - if (!file_exists($streamSource) || !is_file($streamSource)) { - header("HTTP/1.0 404 Not Found"); - exit(0); - } - - // Download range defaults to the full file - // get file metadata - $size = filesize($streamSource); - $begin = 0; - $end = $size - 1; - $mimeType = 'application/octet-stream'; - $time = date('r', filemtime($streamSource)); - - // Open the file - $fileHandle = @fopen($streamSource, 'rb'); - if (!$fileHandle) { - header ("HTTP/1.0 500 Internal Server Error"); - exit(0); - } - - // set range if specified by the client - if (isset($_SERVER['HTTP_RANGE'])) { - if (preg_match('/bytes=\h*(\d+)?-(\d*)[\D.*]?/i', $_SERVER['HTTP_RANGE'], $matches)) { - if (!empty($matches[1])) { - $begin = intval($matches[1]); + /** + * Process required after loading an object from DB + * In this example, a file is sent as a byte strem then stops execution. + * + * @return void + */ + public function post_getFromDB() + { + // Check the user can view this itemtype and can view this item + if ($this->canView() && $this->canViewItem()) { + if (isset($_SERVER['HTTP_ACCEPT']) && $_SERVER['HTTP_ACCEPT'] == 'application/octet-stream' + || isset($_GET['alt']) && $_GET['alt'] == 'media') { + $this->sendFile(); // and terminate script } - if (!empty($matches[2])) { - $end = min(intval($matches[2]), $end); + } + } + + /** + * Send a byte stream to the HTTP client and stops execution + * + * @return void + */ + protected function sendFile() + { + $streamSource = GLPI_DOC_DIR . '/' . $this->fields['filepath']; + + // Ensure the file exists + if (!file_exists($streamSource) || !is_file($streamSource)) { + header("HTTP/1.0 404 Not Found"); + throw new NotFoundHttpException(); + } + + // Download range defaults to the full file + // get file metadata + $size = filesize($streamSource); + $begin = 0; + $end = $size - 1; + $mimeType = 'application/octet-stream'; + $time = date('r', filemtime($streamSource)); + + // Open the file + $fileHandle = @fopen($streamSource, 'rb'); + if (!$fileHandle) { + header("HTTP/1.0 500 Internal Server Error"); + throw new Exception(); + } + + // set range if specified by the client + if (isset($_SERVER['HTTP_RANGE'])) { + if (preg_match('/bytes=\h*(\d+)?-(\d*)[\D.*]?/i', $_SERVER['HTTP_RANGE'], $matches)) { + if (!empty($matches[1])) { + $begin = intval($matches[1]); + } + if (!empty($matches[2])) { + $end = min(intval($matches[2]), $end); + } } - } - } + } - // seek to the begining of the range - $currentPosition = $begin; - if (fseek($fileHandle, $begin, SEEK_SET) < 0) { - header("HTTP/1.0 500 Internal Server Error"); - exit(0); - } + // seek to the begining of the range + $currentPosition = $begin; + if (fseek($fileHandle, $begin, SEEK_SET) < 0) { + header("HTTP/1.0 500 Internal Server Error"); + throw new Exception(); + } - // send headers to ensure the client is able to detect a corrupted download - // example : less bytes than the expected range - // send meta data - // setup client's cache behavior - header("Expires: Mon, 26 Nov 1962 00:00:00 GMT"); - header('Pragma: private'); /// IE BUG + SSL - header('Cache-control: private, must-revalidate'); /// IE BUG + SSL - header("Content-disposition: attachment; filename=\"" . $this->fields['filename'] . "\""); - header("Content-type: $mimeType"); - header("Last-Modified: $time"); - header('Accept-Ranges: bytes'); - header('Content-Length:' . ($end - $begin + 1)); - header("Content-Range: bytes $begin-$end/$size"); - header("Content-Transfer-Encoding: binary\n"); - header('Connection: close'); + // send headers to ensure the client is able to detect a corrupted download + // example : less bytes than the expected range + // send meta data + // setup client's cache behavior + header("Expires: Mon, 26 Nov 1962 00:00:00 GMT"); + header('Pragma: private'); /// IE BUG + SSL + header('Cache-control: private, must-revalidate'); /// IE BUG + SSL + header("Content-disposition: attachment; filename=\"" . $this->fields['filename'] . "\""); + header("Content-type: $mimeType"); + header("Last-Modified: $time"); + header('Accept-Ranges: bytes'); + header('Content-Length:' . ($end - $begin + 1)); + header("Content-Range: bytes $begin-$end/$size"); + header("Content-Transfer-Encoding: binary\n"); + header('Connection: close'); - // Prepare HTTP response - if ($begin > 0 || $end < $size - 1) { - header('HTTP/1.0 206 Partial Content'); - } else { - header('HTTP/1.0 200 OK'); - } + // Prepare HTTP response + if ($begin > 0 || $end < $size - 1) { + header('HTTP/1.0 206 Partial Content'); + } else { + header('HTTP/1.0 200 OK'); + } - // Sends bytes until the end of the range or connection closed - while (!feof($fileHandle) && $currentPosition < $end && (connection_status() == 0)) { - // allow a few seconds to send a few KB. - set_time_limit(10); - $content = fread($fileHandle, min(1024 * 16, $end - $currentPosition + 1)); - if ($content === false) { - header("HTTP/1.0 500 Internal Server Error", true); // Replace previously sent headers - exit(0); - } else { - print $content; - } - flush(); - $currentPosition += 1024 * 16; - } + // Sends bytes until the end of the range or connection closed + while (!feof($fileHandle) && $currentPosition < $end && (connection_status() == 0)) { + // allow a few seconds to send a few KB. + set_time_limit(10); + $content = fread($fileHandle, min(1024 * 16, $end - $currentPosition + 1)); + if ($content === false) { + header("HTTP/1.0 500 Internal Server Error", true); // Replace previously sent headers + throw new Exception(); + } else { + print $content; + } + flush(); + $currentPosition += 1024 * 16; + } - // End now to prevent any unwanted bytes - exit(0); - } + // End now to prevent any unwanted bytes + return; + } } diff --git a/src/Dropdown.php b/src/Dropdown.php index 463324d..b91926d 100644 --- a/src/Dropdown.php +++ b/src/Dropdown.php @@ -32,18 +32,20 @@ // Original Author of file: // Purpose of file: // ---------------------------------------------------------------------- + namespace GlpiPlugin\Example; + use CommonDropdown; // Class for a Dropdown -class Dropdown extends CommonDropdown { +class Dropdown extends CommonDropdown +{ + public static function getTypeName($nb = 0) + { - - static function getTypeName($nb = 0) { - - if ($nb > 0) { - return __('Plugin Example Dropdowns', 'example'); - } - return __('Plugin Example Dropdowns', 'example'); - } + if ($nb > 0) { + return __('Plugin Example Dropdowns', 'example'); + } + return __('Plugin Example Dropdowns', 'example'); + } } diff --git a/src/Example.php b/src/Example.php index de4482a..b75da1b 100644 --- a/src/Example.php +++ b/src/Example.php @@ -34,560 +34,592 @@ // ---------------------------------------------------------------------- namespace GlpiPlugin\Example; + use CommonDBTM; use CommonGLPI; use Computer; +use DBmysql; use Html; use Log; use MassiveAction; use Session; // Class of the defined type -class Example extends CommonDBTM { +class Example extends CommonDBTM +{ + public static $tags = '[EXAMPLE_ID]'; + public static $rightname = 'plugin_example'; - static $tags = '[EXAMPLE_ID]'; - public static $rightname = 'plugin_example'; + // Should return the localized name of the type + public static function getTypeName($nb = 0) + { + return 'Example Type'; + } - // Should return the localized name of the type - static function getTypeName($nb = 0) { - return 'Example Type'; - } + public static function getMenuName() + { + return __('Example plugin'); + } - static function getMenuName() { - return __('Example plugin'); - } + public static function getAdditionalMenuLinks() + { + /** @var array $CFG_GLPI */ + global $CFG_GLPI; + $links = []; - static function getAdditionalMenuLinks() { - global $CFG_GLPI; - $links = []; + $links['config'] = '/plugins/example/index.php'; + $links["" . __s("] = '/plugins/example/index.php'; + $links[__s('Test link', 'example')] = '/plugins/example/index.php'; - $links['config'] = '/plugins/example/index.php'; - $links["".__s("] = '/plugins/example/index.php'; - $links[__s('Test link', 'example')] = '/plugins/example/index.php'; + return $links; + } - return $links; - } + public function defineTabs($options = []) + { - function defineTabs($options = []) { + $ong = []; + $this->addDefaultFormTab($ong); + $this->addStandardTab('Link', $ong, $options); - $ong = []; - $this->addDefaultFormTab($ong); - $this->addStandardTab('Link', $ong, $options); + return $ong; + } - return $ong; - } + public function showForm($ID, array $options = []) + { + $this->initForm($ID, $options); + $this->showFormHeader($options); - function showForm($ID, array $options = []) { - global $CFG_GLPI; + echo ""; - $this->initForm($ID, $options); - $this->showFormHeader($options); + echo "" . __('ID') . ""; + echo ""; + echo $ID; + echo ""; - echo ""; + $this->showFormButtons($options); - echo "" . __('ID') . ""; - echo ""; - echo $ID; - echo ""; + return true; + } - $this->showFormButtons($options); + public function rawSearchOptions() + { - return true; - } + $tab = []; - function rawSearchOptions() { + $tab[] = [ + 'id' => 'common', + 'name' => __('Header Needed'), + ]; - $tab = []; + $tab[] = [ + 'id' => '1', + 'table' => 'glpi_plugin_example_examples', + 'field' => 'name', + 'name' => __('Name'), + ]; - $tab[] = [ - 'id' => 'common', - 'name' => __('Header Needed') - ]; + $tab[] = [ + 'id' => '2', + 'table' => 'glpi_plugin_example_dropdowns', + 'field' => 'name', + 'name' => __('Dropdown'), + ]; - $tab[] = [ - 'id' => '1', - 'table' => 'glpi_plugin_example_examples', - 'field' => 'name', - 'name' => __('Name'), - ]; + $tab[] = [ + 'id' => '3', + 'table' => 'glpi_plugin_example_examples', + 'field' => 'serial', + 'name' => __('Serial number'), + 'usehaving' => true, + 'searchtype' => 'equals', + ]; - $tab[] = [ - 'id' => '2', - 'table' => 'glpi_plugin_example_dropdowns', - 'field' => 'name', - 'name' => __('Dropdown'), - ]; + $tab[] = [ + 'id' => '30', + 'table' => 'glpi_plugin_example_examples', + 'field' => 'id', + 'name' => __('ID'), + 'usehaving' => true, + 'searchtype' => 'equals', + ]; - $tab[] = [ - 'id' => '3', - 'table' => 'glpi_plugin_example_examples', - 'field' => 'serial', - 'name' => __('Serial number'), - 'usehaving' => true, - 'searchtype' => 'equals', - ]; - - $tab[] = [ - 'id' => '30', - 'table' => 'glpi_plugin_example_examples', - 'field' => 'id', - 'name' => __('ID'), - 'usehaving' => true, - 'searchtype' => 'equals', - ]; - - return $tab; - } + return $tab; + } - /** - * Give localized information about 1 task - * - * @param $name of the task - * - * @return array of strings - */ - static function cronInfo($name) { + /** + * Give localized information about 1 task + * + * @param $name of the task + * + * @return array of strings + */ + public static function cronInfo($name) + { - switch ($name) { - case 'Sample' : - return ['description' => __('Cron description for example', 'example'), + switch ($name) { + case 'Sample': + return ['description' => __('Cron description for example', 'example'), 'parameter' => __('Cron parameter for example', 'example')]; - } - return []; - } + } + return []; + } - /** - * Execute 1 task manage by the plugin - * - * @param $task Object of CronTask class for log / stat - * - * @return interger - * >0 : done - * <0 : to be run again (not finished) - * 0 : nothing to do - */ - static function cronSample($task) { + /** + * Execute 1 task manage by the plugin + * + * @param $task Object of CronTask class for log / stat + * + * @return int + * >0 : done + * <0 : to be run again (not finished) + * 0 : nothing to do + */ + public static function cronSample($task) + { + $task->log("Example log message from class"); + $r = mt_rand(0, $task->fields['param']); + usleep(1000000 + $r * 1000); + $task->setVolume($r); - $task->log("Example log message from class"); - $r = mt_rand(0, $task->fields['param']); - usleep(1000000+$r*1000); - $task->setVolume($r); - - return 1; - } + return 1; + } - // Hook done on before add item case (data from form, not altered) - static function pre_item_add_computer(Computer $item) { - if (isset($item->input['name']) && empty($item->input['name'])) { - Session::addMessageAfterRedirect("Pre Add Computer Hook KO (name empty)", true); - return $item->input = false; - } else { - Session::addMessageAfterRedirect("Pre Add Computer Hook OK", true); - } - } + // Hook done on before add item case (data from form, not altered) + public static function pre_item_add_computer(Computer $item) + { + if (isset($item->input['name']) && empty($item->input['name'])) { + Session::addMessageAfterRedirect("Pre Add Computer Hook KO (name empty)", true); + return $item->input = false; + } else { + Session::addMessageAfterRedirect("Pre Add Computer Hook OK", true); + } + } - // Hook done on before add item case (data altered by object prepareInputForAdd) - static function post_prepareadd_computer(Computer $item) { - Session::addMessageAfterRedirect("Post prepareAdd Computer Hook", true); - } + // Hook done on before add item case (data altered by object prepareInputForAdd) + public static function post_prepareadd_computer(Computer $item) + { + Session::addMessageAfterRedirect("Post prepareAdd Computer Hook", true); + } - // Hook done on add item case - static function item_add_computer(Computer $item) { + // Hook done on add item case + public static function item_add_computer(Computer $item) + { - Session::addMessageAfterRedirect("Add Computer Hook, ID=".$item->getID(), true); - return true; - } + Session::addMessageAfterRedirect("Add Computer Hook, ID=" . $item->getID(), true); + return true; + } - function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { + public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) + { + if (!$withtemplate) { + if ($item instanceof \Profile) { + if ($item->getField('central')) { + return __('Example', 'example'); + } - if (!$withtemplate) { - switch ($item->getType()) { - case 'Profile' : - if ($item->getField('central')) { - return __('Example', 'example'); - } - break; + } elseif ($item instanceof \Phone) { + if ($_SESSION['glpishow_count_on_tabs']) { + return self::createTabEntry( + __('Example', 'example'), + countElementsInTable($this->getTable()), + ); + } + return __('Example', 'example'); - case 'Phone' : - if ($_SESSION['glpishow_count_on_tabs']) { - return self::createTabEntry(__('Example', 'example'), - countElementsInTable($this->getTable())); - } - return __('Example', 'example'); + } elseif ($item instanceof \Item_Disk || $item instanceof \Supplier) { + return [ + 1 => __("Test Plugin", 'example'), + 2 => __("Test Plugin 2", 'example'), + ]; - case 'ComputerDisk' : - case 'Supplier' : - return [1 => __("Test Plugin", 'example'), - 2 => __("Test Plugin 2", 'example')]; + } elseif ( + $item instanceof \Computer || + $item instanceof \Central || + $item instanceof \Preference || + $item instanceof \Notification + ) { + return [1 => __("Test Plugin", 'example')]; + } + } - case 'Computer' : - case 'Central' : - case 'Preference': - case 'Notification': - return [1 => __("Test Plugin", 'example')]; + return ''; + } - } - } - return ''; - } - - - static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { - - switch ($item->getType()) { - case 'Phone' : + public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) + { + if ($item instanceof \Phone) { echo __("Plugin Example on Phone", 'example'); - break; - case 'Central' : + } elseif ($item instanceof \Central) { echo __("Plugin central action", 'example'); - break; - case 'Preference' : + } elseif ($item instanceof \Preference) { // Complete form display $data = plugin_version_example(); echo ""; echo ""; - echo ""; echo ""; echo ""; - echo ""; echo ""; echo "
".$data['name']." - ".$data['version']; + echo "
" . $data['name'] . " - " . $data['version']; echo "
Name of the prefInput to set the pref
"; echo ""; - break; - case 'Notification' : + } elseif ($item instanceof \Notification) { echo __("Plugin mailing action", 'example'); - break; - case 'ComputerDisk' : - case 'Supplier' : - if ($tabnum==1) { - echo __('First tab of Plugin example', 'example'); + } elseif ($item instanceof \Item_Disk || $item instanceof \Supplier) { + if ($tabnum == 1) { + echo __('First tab of Plugin example', 'example'); } else { - echo __('Second tab of Plugin example', 'example'); + echo __('Second tab of Plugin example', 'example'); } - break; - default : + } else { //TRANS: %1$s is a class name, %2$d is an item ID - printf(__('Plugin example CLASS=%1$s id=%2$d', 'example'), $item->getType(), $item->getField('id')); - break; - } - return true; - } + printf(__('Plugin example CLASS=%1$s', 'example'), get_class($item)); + } - static function getSpecificValueToDisplay($field, $values, array $options = []) { + return true; + } - if (!is_array($values)) { - $values = [$field => $values]; - } - switch ($field) { - case 'serial' : - return "S/N: ".$values[$field]; - } - return ''; - } - // Parm contains begin, end and who - // Create data to be displayed in the planning of $parm["who"] or $parm["who_group"] between $parm["begin"] and $parm["end"] - static function populatePlanning($parm) { + public static function getSpecificValueToDisplay($field, $values, array $options = []) + { - // Add items in the output array - // Items need to have an unique index beginning by the begin date of the item to display - // needed to be correcly displayed - $output = []; - $key = $parm["begin"]."$$$"."plugin_example1"; - $output[$key]["begin"] = date("Y-m-d 17:00:00"); - $output[$key]["end"] = date("Y-m-d 18:00:00"); - $output[$key]["name"] = __("test planning example 1", 'example'); - // Specify the itemtype to be able to use specific display system - $output[$key]["itemtype"] = Example::class; - // Set the ID using the ID of the item in the database to have unique ID - $output[$key][getForeignKeyFieldForItemType(Example::class)] = 1; - return $output; - } + if (!is_array($values)) { + $values = [$field => $values]; + } + switch ($field) { + case 'serial': + return "S/N: " . $values[$field]; + } + return ''; + } - /** - * Display a Planning Item - * - * @param $val Array of the item to display - * @param $who ID of the user (0 if all) - * @param $type position of the item in the time block (in, through, begin or end) - * @param $complete complete display (more details) - * - * @return Nothing (display function) + // Parm contains begin, end and who + // Create data to be displayed in the planning of $parm["who"] or $parm["who_group"] between $parm["begin"] and $parm["end"] + public static function populatePlanning($parm) + { + + // Add items in the output array + // Items need to have an unique index beginning by the begin date of the item to display + // needed to be correcly displayed + $output = []; + $key = $parm["begin"] . "$$$" . "plugin_example1"; + $output[$key]["begin"] = date("Y-m-d 17:00:00"); + $output[$key]["end"] = date("Y-m-d 18:00:00"); + $output[$key]["name"] = __("test planning example 1", 'example'); + // Specify the itemtype to be able to use specific display system + $output[$key]["itemtype"] = Example::class; + // Set the ID using the ID of the item in the database to have unique ID + $output[$key][getForeignKeyFieldForItemType(Example::class)] = 1; + return $output; + } + + /** + * Display a Planning Item + * + * @param array $val array of the item to display + * @param integer $who ID of the user (0 if all) + * @param string $type position of the item in the time block (in, through, begin or end) + * @param integer|boolean $complete complete display (more details) + * + * @return string + */ + public static function displayPlanningItem(array $val, $who, $type = "", $complete = 0) + { + + // $parm["type"] say begin end in or from type + // Add items in the items fields of the parm array + $out = ''; + switch ($type) { + case "in": + //TRANS: %1$s is the start time of a planned item, %2$s is the end + $out .= sprintf( + __('From %1$s to %2$s :'), + date("H:i", strtotime($val["begin"])), + date("H:i", strtotime($val["end"])), + ); + break; + + case "through": + $out .= Html::resume_text($val["name"], 80); + break; + + case "begin": + //TRANS: %s is the start time of a planned item + $out .= sprintf(__('Start at %s:'), date("H:i", strtotime($val["begin"]))); + break; + + case "end": + //TRANS: %s is the end time of a planned item + $out .= sprintf(__('End at %s:'), date("H:i", strtotime($val["end"]))); + break; + } + $out .= "
"; + $out .= Html::resume_text($val["name"], 80); + + return $out; + } + + /** + * Get an history entry message + * + * @param $data Array from glpi_logs table + * + * @since GLPI version 0.84 + * + * @return string **/ - static function displayPlanningItem(array $val, $who, $type = "", $complete = 0) { + public static function getHistoryEntry($data) + { - // $parm["type"] say begin end in or from type - // Add items in the items fields of the parm array - switch ($type) { - case "in" : - //TRANS: %1$s is the start time of a planned item, %2$s is the end - printf(__('From %1$s to %2$s :'), - date("H:i", strtotime($val["begin"])), date("H:i", strtotime($val["end"]))); - break; + switch ($data['linked_action'] - Log::HISTORY_PLUGIN) { + case 0: + return __('History from plugin example', 'example'); + } - case "through" : - echo Html::resume_text($val["name"], 80); - break; - - case "begin" : - //TRANS: %s is the start time of a planned item - printf(__('Start at %s:'), date("H:i", strtotime($val["begin"]))); - break; - - case "end" : - //TRANS: %s is the end time of a planned item - printf(__('End at %s:'), date("H:i", strtotime($val["end"]))); - break; - } - echo "
"; - echo Html::resume_text($val["name"], 80); - } - - /** - * Get an history entry message - * - * @param $data Array from glpi_logs table - * - * @since GLPI version 0.84 - * - * @return string - **/ - static function getHistoryEntry($data) { - - switch ($data['linked_action'] - Log::HISTORY_PLUGIN) { - case 0: - return __('History from plugin example', 'example'); - } - - return ''; - } + return ''; + } - ////////////////////////////// - ////// SPECIFIC MODIF MASSIVE FUNCTIONS /////// - function getSpecificMassiveActions($checkitem = null) { + ////////////////////////////// + ////// SPECIFIC MODIF MASSIVE FUNCTIONS /////// + public function getSpecificMassiveActions($checkitem = null) + { - $actions = parent::getSpecificMassiveActions($checkitem); + $actions = parent::getSpecificMassiveActions($checkitem); - $actions['Document_Item'.MassiveAction::CLASS_ACTION_SEPARATOR.'add'] = - _x('button', 'Add a document'); // GLPI core one - $actions[__CLASS__.MassiveAction::CLASS_ACTION_SEPARATOR.'do_nothing'] = - __('Do Nothing - just for fun', 'example'); // Specific one + $actions['Document_Item' . MassiveAction::CLASS_ACTION_SEPARATOR . 'add'] = + _x('button', 'Add a document'); // GLPI core one + $actions[__CLASS__ . MassiveAction::CLASS_ACTION_SEPARATOR . 'do_nothing'] = + __('Do Nothing - just for fun', 'example'); // Specific one - return $actions; - } + return $actions; + } - static function showMassiveActionsSubForm(MassiveAction $ma) { + public static function showMassiveActionsSubForm(MassiveAction $ma) + { - switch ($ma->getAction()) { - case 'DoIt': - echo " ". - Html::submit(_x('button', 'Post'), ['name' => 'massiveaction']). - " ".__('Write in item history', 'example'); - return true; - case 'do_nothing' : - echo " ".Html::submit(_x('button', 'Post'), ['name' => 'massiveaction']). - " ".__('but do nothing :)', 'example'); - return true; - } - return parent::showMassiveActionsSubForm($ma); - } + switch ($ma->getAction()) { + case 'DoIt': + echo " " . + Html::submit(_x('button', 'Post'), ['name' => 'massiveaction']) . + " " . __('Write in item history', 'example'); + return true; + case 'do_nothing': + echo " " . Html::submit(_x('button', 'Post'), ['name' => 'massiveaction']) . + " " . __('but do nothing :)', 'example'); + return true; + } + return parent::showMassiveActionsSubForm($ma); + } - /** - * @since version 0.85 - * - * @see CommonDBTM::processMassiveActionsForOneItemtype() - **/ - static function processMassiveActionsForOneItemtype(MassiveAction $ma, CommonDBTM $item, - array $ids) { - global $DB; + /** + * @since version 0.85 + * + * @see CommonDBTM::processMassiveActionsForOneItemtype() + **/ + public static function processMassiveActionsForOneItemtype( + MassiveAction $ma, + CommonDBTM $item, + array $ids + ) { + switch ($ma->getAction()) { + case 'DoIt': + if ($item->getType() == 'Computer') { + Session::addMessageAfterRedirect(__("Right it is the type I want...", 'example')); + Session::addMessageAfterRedirect(__('Write in item history', 'example')); + $changes = [0, 'old value', 'new value']; + foreach ($ids as $id) { + if ($item->getFromDB($id)) { + Session::addMessageAfterRedirect("- " . $item->getField("name")); + Log::history( + $id, + 'Computer', + $changes, + Example::class, + Log::HISTORY_PLUGIN, + ); + $ma->itemDone($item->getType(), $id, MassiveAction::ACTION_OK); + } else { + // Example of ko count + $ma->itemDone($item->getType(), $id, MassiveAction::ACTION_KO); + } + } + } else { + // When nothing is possible ... + $ma->itemDone($item->getType(), $ids, MassiveAction::ACTION_KO); + } + return; - switch ($ma->getAction()) { - case 'DoIt' : - if ($item->getType() == 'Computer') { - Session::addMessageAfterRedirect(__("Right it is the type I want...", 'example')); - Session::addMessageAfterRedirect(__('Write in item history', 'example')); - $changes = [0, 'old value', 'new value']; - foreach ($ids as $id) { - if ($item->getFromDB($id)) { - Session::addMessageAfterRedirect("- ".$item->getField("name")); - Log::history($id, 'Computer', $changes, Example::class, - Log::HISTORY_PLUGIN); - $ma->itemDone($item->getType(), $id, MassiveAction::ACTION_OK); - } else { - // Example of ko count - $ma->itemDone($item->getType(), $id, MassiveAction::ACTION_KO); - } - } - } else { - // When nothing is possible ... - $ma->itemDone($item->getType(), $ids, MassiveAction::ACTION_KO); - } - return; + case 'do_nothing': + if ($item->getType() == Example::class) { + Session::addMessageAfterRedirect(__("Right it is the type I want...", 'example')); + Session::addMessageAfterRedirect(__( + "But... I say I will do nothing for:", + 'example', + )); + foreach ($ids as $id) { + if ($item->getFromDB($id)) { + Session::addMessageAfterRedirect("- " . $item->getField("name")); + $ma->itemDone($item->getType(), $id, MassiveAction::ACTION_OK); + } else { + // Example for noright / Maybe do it with can function is better + $ma->itemDone($item->getType(), $id, MassiveAction::ACTION_KO); + } + } + } else { + $ma->itemDone($item->getType(), $ids, MassiveAction::ACTION_KO); + } + return; + } + parent::processMassiveActionsForOneItemtype($ma, $item, $ids); + } - case 'do_nothing' : - If ($item->getType() == Example::class) { - Session::addMessageAfterRedirect(__("Right it is the type I want...", 'example')); - Session::addMessageAfterRedirect(__("But... I say I will do nothing for:", - 'example')); - foreach ($ids as $id) { - if ($item->getFromDB($id)) { - Session::addMessageAfterRedirect("- ".$item->getField("name")); - $ma->itemDone($item->getType(), $id, MassiveAction::ACTION_OK); - } else { - // Example for noright / Maybe do it with can function is better - $ma->itemDone($item->getType(), $id, MassiveAction::ACTION_KO); - } - } - } else { - $ma->itemDone($item->getType(), $ids, MassiveAction::ACTION_KO); - } - Return; - } - parent::processMassiveActionsForOneItemtype($ma, $item, $ids); - } + public static function generateLinkContents($link, CommonDBTM $item, bool $safe_url = true) + { + if (strstr($link, "[EXAMPLE_ID]")) { + $link = str_replace("[EXAMPLE_ID]", (string) $item->getID(), $link); + return [$link]; + } - static function generateLinkContents($link, CommonDBTM $item) { - - if (strstr($link, "[EXAMPLE_ID]")) { - $link = str_replace("[EXAMPLE_ID]", $item->getID(), $link); - return [$link]; - } - - return parent::generateLinkContents($link, $item); - } + return parent::generateLinkContents($link, $item, $safe_url); + } - static function dashboardTypes() { - return [ - 'example' => [ - 'label' => __("Plugin Example", 'example'), - 'function' => Example::class . "::cardWidget", - 'image' => "https://via.placeholder.com/100x86?text=example", - ], - 'example_static' => [ - 'label' => __("Plugin Example (static)", 'example'), - 'function' => Example::class . "::cardWidgetWithoutProvider", - 'image' => "https://via.placeholder.com/100x86?text=example+static", - ], - ]; - } + public static function dashboardTypes() + { + return [ + 'example' => [ + 'label' => __("Plugin Example", 'example'), + 'function' => Example::class . "::cardWidget", + 'image' => "https://via.placeholder.com/100x86?text=example", + ], + 'example_static' => [ + 'label' => __("Plugin Example (static)", 'example'), + 'function' => Example::class . "::cardWidgetWithoutProvider", + 'image' => "https://via.placeholder.com/100x86?text=example+static", + ], + ]; + } - static function dashboardCards($cards = []) { - if (is_null($cards)) { - $cards = []; - } - $new_cards = [ - 'plugin_example_card' => [ - 'widgettype' => ["example"], - 'label' => __("Plugin Example card"), - 'provider' => Example::class . "::cardDataProvider", - ], - 'plugin_example_card_without_provider' => [ - 'widgettype' => ["example_static"], - 'label' => __("Plugin Example card without provider"), - ], - 'plugin_example_card_with_core_widget' => [ - 'widgettype' => ["bigNumber"], - 'label' => __("Plugin Example card with core provider"), - 'provider' => Example::class . "::cardBigNumberProvider", - ], - ]; + public static function dashboardCards($cards = []) + { + if (is_null($cards)) { + $cards = []; + } + $new_cards = [ + 'plugin_example_card' => [ + 'widgettype' => ["example"], + 'label' => __("Plugin Example card"), + 'provider' => Example::class . "::cardDataProvider", + ], + 'plugin_example_card_without_provider' => [ + 'widgettype' => ["example_static"], + 'label' => __("Plugin Example card without provider"), + ], + 'plugin_example_card_with_core_widget' => [ + 'widgettype' => ["bigNumber"], + 'label' => __("Plugin Example card with core provider"), + 'provider' => Example::class . "::cardBigNumberProvider", + ], + ]; - return array_merge($cards, $new_cards); - } + return array_merge($cards, $new_cards); + } - static function cardWidget(array $params = []) { - $default = [ - 'data' => [], - 'title' => '', - // this property is "pretty" mandatory, - // as it contains the colors selected when adding widget on the grid send - // without it, your card will be transparent - 'color' => '', - ]; - $p = array_merge($default, $params); + public static function cardWidget(array $params = []) + { + $default = [ + 'data' => [], + 'title' => '', + // this property is "pretty" mandatory, + // as it contains the colors selected when adding widget on the grid send + // without it, your card will be transparent + 'color' => '', + ]; + $p = array_merge($default, $params); - // you need to encapsulate your html in div.card to benefit core style - $html = "
"; - $html.= "

{$p['title']}

"; - $html.= "
    "; - foreach ($p['data'] as $line) { - $html.= "
  • $line
  • "; - } - $html.= "
"; - $html.= "
"; + // you need to encapsulate your html in div.card to benefit core style + $html = "
"; + $html .= "

{$p['title']}

"; + $html .= "
    "; + foreach ($p['data'] as $line) { + $html .= "
  • $line
  • "; + } + $html .= "
"; + $html .= "
"; - return $html; - } + return $html; + } - static function cardDataProvider(array $params = []) { - $default_params = [ - 'label' => null, - 'icon' => "fas fa-smile-wink", - ]; - $params = array_merge($default_params, $params); + public static function cardDataProvider(array $params = []) + { + $default_params = [ + 'label' => null, + 'icon' => "fas fa-smile-wink", + ]; + $params = array_merge($default_params, $params); - return [ - 'title' => $params['label'], - 'icon' => $params['icon'], - 'data' => [ - 'test1', - 'test2', - 'test3', - ] - ]; - } + return [ + 'title' => $params['label'], + 'icon' => $params['icon'], + 'data' => [ + 'test1', + 'test2', + 'test3', + ], + ]; + } - static function cardWidgetWithoutProvider(array $params = []) { - $default = [ - // this property is "pretty" mandatory, - // as it contains the colors selected when adding widget on the grid send - // without it, your card will be transparent - 'color' => '', - ]; - $p = array_merge($default, $params); + public static function cardWidgetWithoutProvider(array $params = []) + { + $default = [ + // this property is "pretty" mandatory, + // as it contains the colors selected when adding widget on the grid send + // without it, your card will be transparent + 'color' => '', + ]; + $p = array_merge($default, $params); - // you need to encapsulate your html in div.card to benefit core style - $html = "
+ // you need to encapsulate your html in div.card to benefit core style + $html = "
static html (+optional javascript) as card is not matched with a data provider
"; - return $html; - } + return $html; + } - static function cardBigNumberProvider(array $params = []) { - $default_params = [ - 'label' => null, - 'icon' => null, - ]; - $params = array_merge($default_params, $params); + public static function cardBigNumberProvider(array $params = []) + { + $default_params = [ + 'label' => null, + 'icon' => null, + ]; + $params = array_merge($default_params, $params); - return [ - 'number' => rand(), - 'url' => "https://www.linux.org/", - 'label' => "plugin example - some text", - 'icon' => "fab fa-linux", // font awesome icon - ]; - } + return [ + 'number' => rand(), + 'url' => "https://www.linux.org/", + 'label' => "plugin example - some text", + 'icon' => "fab fa-linux", // font awesome icon + ]; + } } diff --git a/src/Filters/ComputerModelFilter.php b/src/Filters/ComputerModelFilter.php index e1ea1c1..62a4a88 100644 --- a/src/Filters/ComputerModelFilter.php +++ b/src/Filters/ComputerModelFilter.php @@ -48,6 +48,7 @@ class ComputerModelFilter extends AbstractFilter public static function canBeApplied(string $table): bool { + /** @var DBmysql $DB */ global $DB; return $DB->fieldExists($table, ComputerModel::getForeignKeyField()); @@ -59,7 +60,7 @@ class ComputerModelFilter extends AbstractFilter self::getName(), is_string($value) ? $value : "", self::getId(), - ComputerModel::class + ComputerModel::class, ); } @@ -69,8 +70,8 @@ class ComputerModelFilter extends AbstractFilter $field = ComputerModel::getForeignKeyField(); return [ "WHERE" => [ - "$table.$field" => (int) $value - ] + "$table.$field" => (int) $value, + ], ]; } @@ -88,9 +89,9 @@ class ComputerModelFilter extends AbstractFilter 'field' => self::getSearchOptionID( $table, ComputerModel::getForeignKeyField(), - ComputerModel::getTable() + ComputerModel::getTable(), ), - ] + ], ]; } diff --git a/src/ItemForm.php b/src/ItemForm.php index a6b882f..d33bf57 100644 --- a/src/ItemForm.php +++ b/src/ItemForm.php @@ -39,21 +39,21 @@ use Ticket; * Example of *_item_form implementation * @see http://glpi-developer-documentation.rtfd.io/en/master/plugins/hooks.html#items-display-related * */ -class ItemForm { +class ItemForm +{ + /** + * Display contents at the begining of ITILObject section (right panel). + * + * @param array $params Array with "item" and "options" keys + * + * @return void + */ + public static function preSection($params) + { + $item = $params['item']; + $options = $params['options']; - - /** - * Display contents at the begining of ITILObject section (right panel). - * - * @param array $params Array with "item" and "options" keys - * - * @return void - */ - static public function preSection($params) { - $item = $params['item']; - $options = $params['options']; - - echo TemplateRenderer::getInstance()->renderFromStringTemplate(<<renderFromStringTemplate(<<

TWIG, []); - } + } - /** - * Display contents at the begining of item forms. - * - * @param array $params Array with "item" and "options" keys - * - * @return void - */ - static public function preItemForm($params) { - $item = $params['item']; - $options = $params['options']; + /** + * Display contents at the begining of item forms. + * + * @param array $params Array with "item" and "options" keys + * + * @return void + */ + public static function preItemForm($params) + { + $item = $params['item']; + $options = $params['options']; - $firstelt = ($item::getType() == Ticket::class ? 'th' : 'td'); + $firstelt = ($item::getType() == Ticket::class ? 'th' : 'td'); - $out = ''; - $out .= sprintf( - __('Start %1$s hook call for %2$s type'), - 'pre_item_form', - $item::getType() - ); - $out .= ''; + $out = ''; + $out .= sprintf( + __('Start %1$s hook call for %2$s type'), + 'pre_item_form', + $item::getType(), + ); + $out .= ''; - $out .= "<$firstelt>"; - $out .= ''; - $out .= ""; - $out .= ''; - $out .= "<$firstelt>"; - $out .= ''; - $out .= ""; - $out .= ''; - $out .= ''; + $out .= "<$firstelt>"; + $out .= ''; + $out .= ""; + $out .= ''; + $out .= "<$firstelt>"; + $out .= ''; + $out .= ""; + $out .= ''; + $out .= ''; - $out .= ''; - $out .= sprintf( - __('End %1$s hook call for %2$s type'), - 'pre_item_form', - $item::getType() - ); - $out .= ''; + $out .= ''; + $out .= sprintf( + __('End %1$s hook call for %2$s type'), + 'pre_item_form', + $item::getType(), + ); + $out .= ''; - echo $out; - } + echo $out; + } - /** - * Display contents at the begining of item forms. - * - * @param array $params Array with "item" and "options" keys - * - * @return void - */ - static public function postItemForm($params) { - $item = $params['item']; - $options = $params['options']; + /** + * Display contents at the begining of item forms. + * + * @param array $params Array with "item" and "options" keys + * + * @return void + */ + public static function postItemForm($params) + { + $item = $params['item']; + $options = $params['options']; - $firstelt = ($item::getType() == Ticket::class ? 'th' : 'td'); + $firstelt = ($item::getType() == Ticket::class ? 'th' : 'td'); - $out = ''; - $out .= sprintf( - __('Start %1$s hook call for %2$s type'), - 'post_item_form', - $item::getType() - ); - $out .= ''; + $out = ''; + $out .= sprintf( + __('Start %1$s hook call for %2$s type'), + 'post_item_form', + $item::getType(), + ); + $out .= ''; - $out .= "<$firstelt>"; - $out .= ''; - $out .= ""; - $out .= ''; - $out .= "<$firstelt>"; - $out .= ''; - $out .= ""; - $out .= ''; - $out .= ''; + $out .= "<$firstelt>"; + $out .= ''; + $out .= ""; + $out .= ''; + $out .= "<$firstelt>"; + $out .= ''; + $out .= ""; + $out .= ''; + $out .= ''; - $out .= ''; - $out .= sprintf( - __('End %1$s hook call for %2$s type'), - 'post_item_form', - $item::getType() - ); - $out .= ''; + $out .= ''; + $out .= sprintf( + __('End %1$s hook call for %2$s type'), + 'post_item_form', + $item::getType(), + ); + $out .= ''; - echo $out; - } + echo $out; + } - static public function timelineActions($params = []) { - $rand = $params['rand']; - $ticket = $params['item']; + public static function timelineActions($params = []) + { + $rand = $params['rand']; + $ticket = $params['item']; - if (get_class($ticket) !== "Ticket") { - return false; - } + if (get_class($ticket) !== "Ticket") { + return false; + } - $edit_panel = "viewitem".$ticket->fields['id'].$rand; - $JS = <<fields['id'] . $rand; + $JS = << - ". - __("Send a notification"). - Html::scriptBlock($JS)." + echo "
  • + " . + __("Send a notification") . + Html::scriptBlock($JS) . "
  • "; - } + } } diff --git a/src/Item_DeviceCamera.php b/src/Item_DeviceCamera.php index a2aa88d..52e1106 100644 --- a/src/Item_DeviceCamera.php +++ b/src/Item_DeviceCamera.php @@ -36,21 +36,18 @@ // Class of the defined type namespace GlpiPlugin\Example; + use GlpiPlugin\Example\DeviceCamera; use Item_Devices; -if (!defined('GLPI_ROOT')) { - die("Sorry. You can't access directly to this file"); -} - /** * Relation between item and devices **/ -class Item_DeviceCamera extends Item_Devices { +class Item_DeviceCamera extends Item_Devices +{ + public static $itemtype_2 = DeviceCamera::class; + public static $items_id_2 = 'plugin_example_devicecameras_id'; - static public $itemtype_2 = DeviceCamera::class; - static public $items_id_2 = 'plugin_example_devicecameras_id'; - - static protected $notable = false; + protected static $notable = false; } diff --git a/src/NotificationTargetExample.php b/src/NotificationTargetExample.php index a197049..d4bc300 100644 --- a/src/NotificationTargetExample.php +++ b/src/NotificationTargetExample.php @@ -29,22 +29,19 @@ */ namespace GlpiPlugin\Example; + use NotificationTarget; -if (!defined('GLPI_ROOT')) { - die("Sorry. You can't access directly to this file"); -} - // Class NotificationTarget -class NotificationTargetExample extends NotificationTarget { +class NotificationTargetExample extends NotificationTarget +{ + public function getEvents() + { + return ['alert' => 'alert example']; + } - function getEvents() { - return ['alert' => 'alert example']; - } - - function addDataForTemplate($event, $options = []) { - global $DB, $CFG_GLPI; - - $this->data['##example.name##'] = __('Example', 'example'); - } + public function addDataForTemplate($event, $options = []) + { + $this->data['##example.name##'] = __('Example', 'example'); + } } diff --git a/src/Profile.php b/src/Profile.php index 48a6d69..ee3b256 100644 --- a/src/Profile.php +++ b/src/Profile.php @@ -34,17 +34,27 @@ use CommonGLPI; use Html; use Session; -final class Profile extends \Profile +class Profile extends \Profile { public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { - return __('Example plugin'); + if ( + $item instanceof \Profile + && $item->getField('id') + ) { + return self::createTabEntry(__('Example plugin')); + } + + return ''; } public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { - $profile = new self(); - $profile->showFormExample($item->getID()); + if ($item instanceof self) { + $profile = new self(); + $profile->showFormExample($item->getID()); + } + return true; } public function showFormExample(int $profiles_id): void @@ -67,8 +77,8 @@ final class Profile extends \Profile [ 'itemtype' => Example::class, 'label' => Example::getTypeName(Session::getPluralNumber()), - 'field' => Example::$rightname - ] + 'field' => Example::$rightname, + ], ]; $matrix_options['title'] = self::getTypeName(1); $this->displayRightsChoiceMatrix($rights, $matrix_options); diff --git a/src/RuleTest.php b/src/RuleTest.php index 25a018b..8c7b380 100644 --- a/src/RuleTest.php +++ b/src/RuleTest.php @@ -34,13 +34,9 @@ // ---------------------------------------------------------------------- namespace GlpiPlugin\Example; + use Rule; -if (!defined('GLPI_ROOT')) { - die("Sorry. You can't access directly to this file"); -} - - /** * Rule class store all informations about a GLPI rule : * - description @@ -48,40 +44,44 @@ if (!defined('GLPI_ROOT')) { * - actions * **/ -class RuleTest extends Rule { - - // From Rule - public static $rightname = 'rule_import'; - public $can_sort = true; +class RuleTest extends Rule +{ + // From Rule + public static $rightname = 'rule_import'; + public $can_sort = true; - function getTitle() { - return 'test'; - } + public function getTitle() + { + return 'test'; + } - function maxActionsCount() { - return 1; - } + public function maxActionsCount() + { + return 1; + } - function getCriterias() { + public function getCriterias() + { - $criterias = []; - $criterias['name']['field'] = 'name'; - $criterias['name']['name'] = __('Software'); - $criterias['name']['table'] = 'glpi_softwares'; + $criterias = []; + $criterias['name']['field'] = 'name'; + $criterias['name']['name'] = __('Software'); + $criterias['name']['table'] = 'glpi_softwares'; - return $criterias; - } + return $criterias; + } - function getActions() { + public function getActions() + { - $actions = []; - $actions['softwarecategories_id']['name'] = __('Category (class)', 'example'); - $actions['softwarecategories_id']['type'] = 'dropdown'; - $actions['softwarecategories_id']['table'] = 'glpi_softwarecategories'; - return $actions; - } + $actions = []; + $actions['softwarecategories_id']['name'] = __('Category (class)', 'example'); + $actions['softwarecategories_id']['type'] = 'dropdown'; + $actions['softwarecategories_id']['table'] = 'glpi_softwarecategories'; + return $actions; + } } diff --git a/src/RuleTestCollection.php b/src/RuleTestCollection.php index 58a4d18..031ca5f 100644 --- a/src/RuleTestCollection.php +++ b/src/RuleTestCollection.php @@ -34,21 +34,18 @@ // ---------------------------------------------------------------------- namespace GlpiPlugin\Example; + use RuleCollection; -if (!defined('GLPI_ROOT')) { - die("Sorry. You can't access directly to this file"); -} - - -class RuleTestCollection extends RuleCollection { - - // From RuleCollection - public $stop_on_first_match = true; - public static $rightname = 'rule_import'; - public $menu_option = 'test'; - - function getTitle() { - return 'Rulesengine test'; - } +class RuleTestCollection extends RuleCollection +{ + // From RuleCollection + public $stop_on_first_match = true; + public static $rightname = 'rule_import'; + public $menu_option = 'test'; + + public function getTitle() + { + return 'Rulesengine test'; + } } diff --git a/src/Showtabitem.php b/src/Showtabitem.php index 021f9e3..8a1ac68 100644 --- a/src/Showtabitem.php +++ b/src/Showtabitem.php @@ -51,45 +51,47 @@ namespace GlpiPlugin\Example; * post_show_tab will be fired after the tab show * * */ -class Showtabitem { +class Showtabitem +{ + /** + * Summary of pre_show_tab + * @param array $params is an array like following + * array( 'item', 'options') + * where 'item' is the parent object (like 'Ticket'), + * and 'options' are options like following + * array( 'tabnum', 'itemtype') + * where 'tabnum' is the internal name of the tab that will be shown + * and 'itemtype' is the type of the tab (ex: 'ITILFollowup' when showing followup tab in a ticket) + * Note: you may pass datas to post_show_tab using the $param['options'] array (see example below) + */ + public static function pre_show_tab($params) + { + switch ($params['item']->getType()) { + case 'Ticket': + if ($params['options']['itemtype'] == 'TicketValidation' && $params['options']['tabnum'] == 2) { + // if tasks are not all done + // then prevent solution div to show + // this is an example to prevent solving of ticket + if (true) { // here you should test if some tasks are in todo status. + $params['options']['prevent_solution'] = true; // this will be passed to the post_show hook + echo "