diff --git a/tests/php-static-analysis/README.md b/tests/php-static-analysis/README.md new file mode 100644 index 0000000000..492f0b7b3f --- /dev/null +++ b/tests/php-static-analysis/README.md @@ -0,0 +1,120 @@ +# PHP static analysis + +- [Installation](#installation) +- [Usages](#usages) + - [Analysing a package](#analysing-a-package) + - [Analysing a module](#analysing-a-module) +- [Configuration](#configuration) + - [Adjust local configuration to your needs](#adjust-local-configuration-to-your-needs) + - [Adjust configuration for a particular CI repository / job](#adjust-configuration-for-a-particular-ci-repository--job) + +## Installation +- Install dependencies by running `composer install` in this folder +- You should be all set! 🚀 + +## Usages +### Analysing a package +_Do this if you want to analyse the whole iTop package (iTop core, extensions, third-party libs, ...)_ + +- Make sure you ran a setup on your iTop as it will analyse the `env-production` folder +- Open a prompt in your iTop folder +- Run the following command + ```bash + tests/php-static-analysis/vendor/bin/phpstan analyse \ + --configuration ./tests/php-static-analysis/config/for-package.dist.neon \ + --error-format raw + ``` + +You will then have an output like this listing all errors: +```bash +tests/php-static-analysis/vendor/bin/phpstan analyse \ + --configuration ./tests/php-static-analysis/config/for-package.dist.neon \ + --error-format raw + + 1049/1049 [============================] 100% + +\addons\userrights\userrightsprofile.class.inc.php:552:Call to static method InitSharedClassProperties() on an unknown class SharedObject. +\addons\userrights\userrightsprofile.db.class.inc.php:927:Call to static method GetSharedClassProperties() on an unknown class SharedObject. +\addons\userrights\userrightsprojection.class.inc.php:722:Access to an undefined property UserRightsProjection::$m_aClassProjs. +\application\applicationextension.inc.php:295:Method AbstractPreferencesExtension::ApplyPreferences() should return bool but return statement is missing. +\application\cmdbabstract.class.inc.php:1010:Class utils referenced with incorrect case: Utils. +[...] +``` + +### Analysing a module +_Do this if you only want to analyse one or more modules within this iTop but not the whole package_ + +- Make sure you ran a setup on your iTop as it will analyse the `env-production` folder +- Open a prompt in your iTop folder +- Run the following command + ``` + tests/php-static-analysis/vendor/bin/phpstan analyse \ + --configuration ./tests/php-static-analysis/config/for-package.dist.neon \ + --error-format raw \ + env-production/ [env-production/ ...] + ``` + +You will then have an output like this listing all errors: +``` + tests/php-static-analysis/vendor/bin/phpstan analyse \ + --configuration ./tests/php-static-analysis/config/for-module.dist.neon \ + --error-format raw \ + env-production/authent-ldap env-production/itop-oauth-client + + 49/49 [============================] 100% + +\env-production\authent-ldap\model.authent-ldap.php:79:Undefined variable: $hDS +\env-production\authent-ldap\model.authent-ldap.php:80:Undefined variable: $name +\env-production\authent-ldap\model.authent-ldap.php:80:Undefined variable: $value +\env-production\itop-oauth-client\vendor\composer\InstalledVersions.php:105:Parameter $parser of method Composer\InstalledVersions::satisfies() has invalid type Composer\Semver\VersionParser. +[...] +``` + +## Configuration +### Adjust local configuration to your needs +#### Change some parameters for a local run +If you want to change some particular settings (eg. the memory limit, the rules level, the PHP version to check, ...) for a local run of the analysis you have 2 choices. + +##### Method 1: CLI parameter +For most parameters there is a good chance you can just add the parameter and its value in your command, which will override the one defined in the configuration file. \ +Below are some example, but your can find the complete reference [here](https://phpstan.org/user-guide/command-line-usage). + +```bash +--memory-limit 1G +--level 5 +--error-format raw +[...] +``` + +**Pros** Quick and easy to try different parameters \ +**Cons** Parameters aren't saved, so you'll have to remember them and put them again next time + +##### Method 2: Configuration file +Crafting your own configuration file gives you the ability to fine tune any parameters, it's way more powerful but can also quickly lead to crashes if you mess with the symbols discovery (classes, ...). \ +But mostly it can be saved, shared, re-used; which is it's main purpose. + +It is recommended that you create your configuration file from scratch and that you include the `base.dist.neon` so you are bootstrapped for the symbols discovery. Then you can override any parameter. \ +Check [the documentation](https://phpstan.org/config-reference#multiple-files) for more information. + +```neon +includes: + - base.dist.neon + +parameters: + # Override parameters here +``` + +#### Analyse only one (or some) folder(s) quicker +It's pretty easy and good news you don't need to create a new configuration file or change an existing one. \ +Just adapt and use command lines from the [usages section](#usages) and add the folders you want to analyse at the end of the command, exactly like when analysing modules. + +For example if you want to analyse just `/setup` and `/sources`, use something like: +``` +tests/php-static-analysis/vendor/bin/phpstan analyse \ + --configuration ./tests/php-static-analysis/config/for-package.dist.neon \ + --error-format raw \ + setup sources +``` + +### Adjust configuration for a particular CI repository / job +TODO \ No newline at end of file diff --git a/tests/php-static-analysis/composer.json b/tests/php-static-analysis/composer.json new file mode 100644 index 0000000000..79097c0b3e --- /dev/null +++ b/tests/php-static-analysis/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "phpstan/phpstan": "^1.10" + } +} diff --git a/tests/php-static-analysis/composer.lock b/tests/php-static-analysis/composer.lock new file mode 100644 index 0000000000..4e52e3fb3e --- /dev/null +++ b/tests/php-static-analysis/composer.lock @@ -0,0 +1,81 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "14812c2a05a5972f00f9d67abbd710a9", + "packages": [ + { + "name": "phpstan/phpstan", + "version": "1.10.26", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "5d660cbb7e1b89253a47147ae44044f49832351f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/5d660cbb7e1b89253a47147ae44044f49832351f", + "reference": "5d660cbb7e1b89253a47147ae44044f49832351f", + "shasum": "" + }, + "require": { + "php": "^7.2|^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" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", + "type": "tidelift" + } + ], + "time": "2023-07-19T12:44:37+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [], + "plugin-api-version": "2.3.0" +} diff --git a/tests/php-static-analysis/config/README.md b/tests/php-static-analysis/config/README.md new file mode 100644 index 0000000000..2ef0858892 --- /dev/null +++ b/tests/php-static-analysis/config/README.md @@ -0,0 +1,29 @@ +## Disclaimer +DON'T modify the following files without knowledge and discussing with the team: +- base.dist.neon +- for-package.dist.neon +- for-module.dist.neon + +## Purpose of these files +### base.dist.neon +This configuration file contains the common parameters for all analysis, whereas it is a package, a module or something specific. Among others: +- Rules level for analysis +- PHP version to compare +- Necessary files for autoloaders discovery and such +- ... + +This file should not be modified for your specific needs, you should always include it and override the desired parameters. \ +See how it is done in `for-package.dist.neon` and `for-module.dist.neon` or on the documentation [here](https://phpstan.org/config-reference#multiple-files). + +### for-package.dist.neon +This configuration file contains the parameters to analyse a package (iTop core, modules, third-party libs). + +### for-module.dist.neon +This configuration file contains the parameters to analyse one or more modules only. + +## How / when can I modify these files? +**You CAN'T!** \ +Well, unless there is a good reason and you talked about it with the team. But you should never modify them for a specific need on your local environment. + +- If you have a particular need for your local environment (eg. increase memory limit, change rules levels, analyse only a specific folder), check the [Configuration section](../#configuration) of the main README.md. +- If you feel like there is need for an adjustment in the default configurations, discuss it with th team and make a PR. \ No newline at end of file diff --git a/tests/php-static-analysis/config/base.dist.neon b/tests/php-static-analysis/config/base.dist.neon new file mode 100644 index 0000000000..85b0071f25 --- /dev/null +++ b/tests/php-static-analysis/config/base.dist.neon @@ -0,0 +1,29 @@ +includes: + - php-includes/set-php-version-from-process.php # Workaround to set PHP version to the on running the CLI + +parameters: + level: 0 + #phpVersion: null # Explicitly commented as we rather use the detected version from the above include (`php-includes/target-php-version.php`) + editorUrl: 'phpstorm://open?file=%%file%%&line=%%line%%' # Open in PHPStorm asit is Combodo's default IDE + bootstrapFiles: + - ../../../approot.inc.php + - ../../../bootstrap.inc.php + scanFiles: + # Files necessary as they contain some declarations (constants, classes, functions, ...) + - ../../../approot.inc.php + - ../../../bootstrap.inc.php + excludePaths: + analyse: + # For third-party libs we should analyse them in a dedicated configuration as we can't improve / clean them which would + # prevent us from raising the rules level as we improve / clean our codebase + - ../../../lib # Irrelevant as we only want to analyze our codebase + - ../../../node_modules # Irrelevant as we only want to analyze our codebase + analyseAndScan: + #- ../../../data # Left and commented on purpose to show that we want to analyse the generated cache files + # Note 1: We can analyse these folders as if a PHP file requires another PHP element declared in an XML file, it won't find it. So we rely only on `env-production` + # Note 2: Only the options selected during the setup will be analysed correctly in `env-production`. For unselected options, we still want to ignore them during the analysis as they would only give a false sentiment of security as their XML PHP classes / snippets / etc would not be tested. + - ../../../data/production-modules # Irrelevent as it will already be in `env-production` (for local run only, not useful in the CI) + - ../../../datamodels # Irrelevent as it will already be in `env-production` + - ../../../extensions # Irrelevent as it will already be in `env-production` (for local run only, not useful in the CI) + - ../../../tests # Exclude tests for now + - ../../../toolkit # Exlclude toolkit for now \ No newline at end of file diff --git a/tests/php-static-analysis/config/for-module.dist.neon b/tests/php-static-analysis/config/for-module.dist.neon new file mode 100644 index 0000000000..586be18012 --- /dev/null +++ b/tests/php-static-analysis/config/for-module.dist.neon @@ -0,0 +1,15 @@ +includes: + - base.dist.neon + +parameters: + paths: + # We just want to analyse the module folder(s), either: + # - Create your own `for-module.neon` file, include this one and override this parameter (see https://phpstan.org/config-reference#multiple-files) + # - Pass the module folder(s) in the commande line (see https://phpstan.org/config-reference#analysed-files) + scanDirectories: + # Unlike for `for-package.dist.neon`, here we need to scan all the folders to discover symbols, but we only want to analyse the module folder. + # We initially thought of doing it through the `excludePaths` param. by excluding everything but the module folder, but it doesn't seem to be possible, because it uses the `fnmatch()` function. + # As a workaround, we list here all the folders to scan. + # + # Scan the whole project and rely on the `excludePaths` param. to filter the unnecessary + - ../../.. diff --git a/tests/php-static-analysis/config/for-package.dist.neon b/tests/php-static-analysis/config/for-package.dist.neon new file mode 100644 index 0000000000..ff0d190ebf --- /dev/null +++ b/tests/php-static-analysis/config/for-package.dist.neon @@ -0,0 +1,7 @@ +includes: + - base.dist.neon + +parameters: + paths: + # We want to analyse almost the whole project, so we do a negative selection between the `paths` and `excludePaths` (see base.dist.neon) parameters + - ../../../ diff --git a/tests/php-static-analysis/config/php-includes/set-php-version-from-process.php b/tests/php-static-analysis/config/php-includes/set-php-version-from-process.php new file mode 100644 index 0000000000..4a618628a5 --- /dev/null +++ b/tests/php-static-analysis/config/php-includes/set-php-version-from-process.php @@ -0,0 +1,24 @@ +