From 2e0217ead0f446410c74c94ff5621c0302e73a35 Mon Sep 17 00:00:00 2001 From: Stanislas Date: Wed, 16 Jul 2025 10:58:25 +0200 Subject: [PATCH] phpstan --- composer.json | 5 +- composer.lock | 155 +++++++++++++++++++++++++++++++++++++++++++++++- front/popup.php | 5 -- hook.php | 3 +- phpstan.neon | 18 ++++++ setup.php | 17 ++---- src/Config.php | 1 + src/Example.php | 126 +++++++++++++++++++-------------------- 8 files changed, 246 insertions(+), 84 deletions(-) create mode 100644 phpstan.neon diff --git a/composer.json b/composer.json index 54fed37..c721d10 100644 --- a/composer.json +++ b/composer.json @@ -5,8 +5,11 @@ "require-dev": { "friendsofphp/php-cs-fixer": "^3.75", "friendsoftwig/twigcs": "^6.1", + "glpi-project/phpstan-glpi": "^1.0", "glpi-project/tools": "^0.7.5", - "php-parallel-lint/php-parallel-lint": "^1.4" + "php-parallel-lint/php-parallel-lint": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-deprecation-rules": "^2.0" }, "config": { "optimize-autoloader": true, diff --git a/composer.lock b/composer.lock index 7757887..6d41a2f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "981190cd221bfc071af80a355f4b0b57", + "content-hash": "0b8145569965029789c21a725b504a22", "packages": [], "packages-dev": [ { @@ -565,6 +565,54 @@ }, "time": "2024-11-27T21:59:24+00:00" }, + { + "name": "glpi-project/phpstan-glpi", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/glpi-project/phpstan-glpi.git", + "reference": "432f7a10d221f60abdbd4ab4676dbd846a485df1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/glpi-project/phpstan-glpi/zipball/432f7a10d221f60abdbd4ab4676dbd846a485df1", + "reference": "432f7a10d221f60abdbd4ab4676dbd846a485df1", + "shasum": "" + }, + "require": { + "php": ">=7.4", + "phpstan/phpstan": "^2.1" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.75", + "php-parallel-lint/php-parallel-lint": "^1.4", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^9.6" + }, + "type": "phpstan-extension", + "extra": { + "phpstan": { + "includes": [ + "rules.neon" + ] + } + }, + "autoload": { + "psr-4": { + "PHPStanGlpi\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan rules for GLPI.", + "support": { + "issues": "https://github.com/glpi-project/phpstan-glpi/issues", + "source": "https://github.com/glpi-project/phpstan-glpi/tree/1.0.0" + }, + "time": "2025-06-24T11:45:31+00:00" + }, { "name": "glpi-project/tools", "version": "0.7.5", @@ -682,6 +730,111 @@ }, "time": "2024-03-27T12:14:49+00:00" }, + { + "name": "phpstan/phpstan", + "version": "2.1.17", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "89b5ef665716fa2a52ecd2633f21007a6a349053" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/89b5ef665716fa2a52ecd2633f21007a6a349053", + "reference": "89b5ef665716fa2a52ecd2633f21007a6a349053", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + } + ], + "time": "2025-05-21T20:55:28+00:00" + }, + { + "name": "phpstan/phpstan-deprecation-rules", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan-deprecation-rules.git", + "reference": "468e02c9176891cc901143da118f09dc9505fc2f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/468e02c9176891cc901143da118f09dc9505fc2f", + "reference": "468e02c9176891cc901143da118f09dc9505fc2f", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0", + "phpstan/phpstan": "^2.1.15" + }, + "require-dev": { + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^9.6" + }, + "type": "phpstan-extension", + "extra": { + "phpstan": { + "includes": [ + "rules.neon" + ] + } + }, + "autoload": { + "psr-4": { + "PHPStan\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan rules for detecting usage of deprecated classes, methods, properties, constants and traits.", + "support": { + "issues": "https://github.com/phpstan/phpstan-deprecation-rules/issues", + "source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/2.0.3" + }, + "time": "2025-05-14T10:56:57+00:00" + }, { "name": "psr/container", "version": "2.0.2", diff --git a/front/popup.php b/front/popup.php index a75896b..c5753bb 100644 --- a/front/popup.php +++ b/front/popup.php @@ -47,11 +47,6 @@ if (isset($_SESSION['glpipopup']['name'])) { 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 '
'; diff --git a/hook.php b/hook.php index 7f3259a..0944f5c 100644 --- a/hook.php +++ b/hook.php @@ -350,7 +350,7 @@ function plugin_example_searchOptionsValues($options = []) switch ($table . '.' . $field) { case 'glpi_plugin_example_examples.serial': echo __('Not really specific - Use your own dropdown - Just for example', 'example'); - GlpiDropdown::show( + Dropdown::show( getItemTypeForTable($options['searchoption']['table']), ['value' => $options['value'], 'name' => $options['name'], @@ -729,6 +729,7 @@ function plugin_example_Status($param) // Do checks (no check for example) $ok = true; echo 'example plugin: example'; + if ($ok) { echo '_OK'; } else { diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..2006aa0 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,18 @@ +parameters: + parallel: + maximumNumberOfProcesses: 2 + level: 5 + paths: + - front + - src + - hook.php + - setup.php + - report.php + scanDirectories: + - ../../inc + - ../../src + - ../../front + bootstrapFiles: + - ../../stubs/glpi_constants.php + - ../../vendor/autoload.php + diff --git a/setup.php b/setup.php index 553e8d4..1217545 100644 --- a/setup.php +++ b/setup.php @@ -250,9 +250,6 @@ function plugin_init_example() $PLUGIN_HOOKS['status']['example'] = 'plugin_example_Status'; - // CSRF compliance : All actions must be done via POST and forms closed by Html::closeForm(); - $PLUGIN_HOOKS[Hooks::CSRF_COMPLIANT]['example'] = true; - $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'; @@ -267,11 +264,8 @@ function plugin_init_example() $PLUGIN_HOOKS[Hooks::PRE_ITEM_FORM]['example'] = [ItemForm::class, 'preItemForm']; $PLUGIN_HOOKS[Hooks::POST_ITEM_FORM]['example'] = [ItemForm::class, 'postItemForm']; - //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']; - } + $PLUGIN_HOOKS[Hooks::PRE_ITIL_INFO_SECTION]['example'] = [ItemForm::class, 'preSection']; + $PLUGIN_HOOKS[Hooks::POST_ITIL_INFO_SECTION]['example'] = [ItemForm::class, 'postSection']; // Add new actions to timeline $PLUGIN_HOOKS[Hooks::TIMELINE_ACTIONS]['example'] = [ @@ -297,11 +291,8 @@ function plugin_init_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'; - } + // Icon in the impact analysis + $PLUGIN_HOOKS[Hooks::SET_ITEM_IMPACT_ICON]['example'] = 'plugin_example_set_impact_icon'; } diff --git a/src/Config.php b/src/Config.php index baf00b3..c6804d7 100644 --- a/src/Config.php +++ b/src/Config.php @@ -96,5 +96,6 @@ class Config extends CommonDBTM $config = new self(); $config->showFormExample(); } + return true; } } diff --git a/src/Example.php b/src/Example.php index f87efc3..eb2d8b0 100644 --- a/src/Example.php +++ b/src/Example.php @@ -35,14 +35,20 @@ namespace GlpiPlugin\Example; +use Central; use CommonDBTM; use CommonGLPI; use Computer; use DBmysql; use Html; +use Item_Disk; use Log; use MassiveAction; +use Notification; +use Phone; +use Preference; use Session; +use Supplier; // Class of the defined type class Example extends CommonDBTM @@ -168,7 +174,7 @@ class Example extends CommonDBTM * * @param $task Object of CronTask class for log / stat * - * @return interger + * @return int * >0 : done * <0 : to be run again (not finished) * 0 : nothing to do @@ -212,33 +218,34 @@ class Example extends CommonDBTM public function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { if (!$withtemplate) { - switch ($item->getType()) { - case 'Profile': - if ($item->getField('central')) { - return __('Example', 'example'); - } - break; - - case 'Phone': - if ($_SESSION['glpishow_count_on_tabs']) { - return self::createTabEntry( - __('Example', 'example'), - countElementsInTable($this->getTable()), - ); - } - + if ($item instanceof Profile) { + if ($item->getField('central')) { return __('Example', 'example'); + } - case 'ComputerDisk': - case 'Supplier': - return [1 => __('Test Plugin', 'example'), - 2 => __('Test Plugin 2', 'example')]; + } elseif ($item instanceof Phone) { + if ($_SESSION['glpishow_count_on_tabs']) { + return self::createTabEntry( + __('Example', 'example'), + countElementsInTable($this->getTable()), + ); + } - case 'Computer': - case 'Central': - case 'Preference': - case 'Notification': - return [1 => __('Test Plugin', 'example')]; + return __('Example', 'example'); + + } elseif ($item instanceof Item_Disk || $item instanceof 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'), + ]; } } @@ -247,53 +254,46 @@ class Example extends CommonDBTM public static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { - switch ($item->getType()) { - case 'Phone': - echo __('Plugin Example on Phone', 'example'); - break; + if ($item instanceof Phone) { + echo __('Plugin Example on Phone', 'example'); - case 'Central': - echo __('Plugin central action', 'example'); - break; + } elseif ($item instanceof Central) { + echo __('Plugin central action', 'example'); - case 'Preference': - // Complete form display - $data = plugin_version_example(); + } elseif ($item instanceof Preference) { + // Complete form display + $data = plugin_version_example(); - echo "
"; - echo ""; - echo "'; + echo ""; + echo "
" . $data['name'] . ' - ' . $data['version']; - echo '
"; + echo "'; - echo ""; - echo ''; + echo ""; + echo ''; - echo ""; - echo ''; + echo ""; + echo ''; - echo '
" . $data['name'] . ' - ' . $data['version']; + echo '
Name of the prefInput to set the pref
Name of the prefInput to set the pref
'; - echo '
'; - break; + echo ''; + echo ''; - case 'Notification': - echo __('Plugin mailing action', 'example'); - break; + } elseif ($item instanceof Notification) { + echo __('Plugin mailing action', 'example'); - case 'ComputerDisk': - case 'Supplier': - if ($tabnum == 1) { - echo __('First tab of Plugin example', 'example'); - } else { - echo __('Second tab of Plugin example', 'example'); - } - break; + } 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'); + } - default: - //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; + } else { + //TRANS: %1$s is a class name, %2$d is an item ID + printf(__('Plugin example CLASS=%1$s', 'example'), get_class($item)); } + return true; } @@ -338,7 +338,7 @@ class Example extends CommonDBTM * @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) + * @return void (display function) **/ public static function displayPlanningItem(array $val, $who, $type = '', $complete = 0) { @@ -491,7 +491,7 @@ class Example extends CommonDBTM public static function generateLinkContents($link, CommonDBTM $item, bool $safe_url = true) { if (strstr($link, '[EXAMPLE_ID]')) { - $link = str_replace('[EXAMPLE_ID]', $item->getID(), $link); + $link = str_replace('[EXAMPLE_ID]', (string) $item->getID(), $link); return [$link]; }