Author: Markus Staab (staabm)
Committer: Derick Rethans (derickr)
Date: 2026-06-17T12:10:29+01:00
Commit: Setup PHPStan · php/web-php@aaf3693 · GitHub
Raw diff: https://github.com/php/web-php/commit/aaf36935fbe31ff603a537fb9ecd87f864ff5c8f.diff
Setup PHPStan
Changed paths:
A phpstan-baseline.neon
A phpstan.neon.dist
M .github/CONTRIBUTING.md
M .github/workflows/integrate.yaml
M Makefile
Diff:
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index c00267ff51..28456451f9 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -74,6 +74,19 @@ about what you're working on, you can contact us via the
```
to automatically fix coding standard issues.
+- Run
+
+ ```shell
+ make static-analysis
+ ```
+
+ to run a static analysis or, if applicable, run
+
+ ```shell
+ make static-analysis-baseline
+ ```
+
+ to regenerate the baseline.
- Review the change once more just before submitting it.
## What happens after submitting contribution?
@@ -134,6 +147,20 @@ Having said that, here are the organizational rules:
make coding-standards
```
-6. Use reasonable commit messages.
+6. Run
+
+ ```shell
+ make static-analysis
+ ```
+
+to run a static analysis or, if applicable, run
+
+ ```shell
+ make static-analysis-baseline
+ ```
+
+to regenerate the baseline.
+
+7. Use reasonable commit messages.
Thank you for contributing to https://www.php.net!
diff --git a/.github/workflows/integrate.yaml b/.github/workflows/integrate.yaml
index 14a7a72a1c..16fd55c1f9 100644
--- a/.github/workflows/integrate.yaml
+++ b/.github/workflows/integrate.yaml
@@ -107,6 +107,49 @@ jobs:
- name: "Validate XML files"
run: "for a in $(find . -name '*.xml'); do xmllint --quiet --noout $a; done"
+ static-analysis:
+ name: "Static Analysis"
+
+ runs-on: "ubuntu-latest"
+
+ strategy:
+ matrix:
+ php-version:
+ - "8.2"
+
+ dependencies:
+ - "locked"
+
+ steps:
+ - name: "Checkout"
+ uses: "actions/checkout@v3"
+
+ - name: "Set up PHP"
+ uses: "shivammathur/setup-php@v2"
+ with:
+ coverage: "none"
+ extensions: "none, curl, dom, json, mbstring, tokenizer, xml, xmlwriter, iconv"
+ php-version: "${{ matrix.php-version }}"
+
+ - name: "Set up problem matchers for PHP"
+ run: "echo \"::add-matcher::${{ runner.tool_cache }}/php.json\""
+
+ - name: "Determine composer cache directory"
+ run: "echo \"COMPOSER_CACHE_DIR=$(composer config cache-dir)\" >> $GITHUB_ENV"
+
+ - name: "Cache dependencies installed with composer"
+ uses: "actions/cache@v3"
+ with:
+ path: "${{ env.COMPOSER_CACHE_DIR }}"
+ key: "php-${{ matrix.php-version }}-composer-${{ hashFiles('composer.lock') }}"
+ restore-keys: "php-${{ matrix.php-version }}-composer-"
+
+ - name: "Install dependencies with composer"
+ run: "composer install --ansi --no-interaction --no-progress"
+
+ - name: "Run static analysis"
+ run: "vendor/bin/phpstan"
+
tests:
name: "Tests"
diff --git a/Makefile b/Makefile
index 12de398fe1..724f253731 100644
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,7 @@ HTTP_HOST:=localhost:8080
CORES?=$(shell (nproc || sysctl -n hw.ncpu) 2> /dev/null)
.PHONY: it
-it: coding-standards tests ## Runs all the targets
+it: coding-standards static-analysis tests ## Runs all the targets
.PHONY: code-coverage
code-coverage: vendor ## Collects code coverage from running unit tests with phpunit/phpunit
@@ -18,6 +18,14 @@ coding-standards: vendor ## Fixes code style issues with friendsofphp/php-cs-fix
help: ## Displays this list of targets with descriptions
@grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[32m%-30s\033[0m %s\n", $$1, $$2}'
+.PHONY: static-analysis
+static-analysis: vendor ## Runs a static code analysis
+ vendor/bin/phpstan
+
+.PHONY: static-analysis-baseline
+static-analysis-baseline: vendor ## Generates a baseline for static analysis
+ vendor/bin/phpstan --generate-baseline
+
.PHONY: tests
tests: vendor ## Runs unit and end-to-end tests with phpunit/phpunit
vendor/bin/phpunit --configuration=tests/phpunit.xml --testsuite=unit
diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
new file mode 100644
index 0000000000..e9ed039c3a
--- /dev/null
+++ b/phpstan-baseline.neon
@@ -0,0 +1,295 @@
+parameters:
+ ignoreErrors:
+ -
+ message: '#^Variable \$version might not be defined\.$#'
+ identifier: variable.undefined
+ count: 1
+ path: include/download-instructions/linux-debian-cli-community.php
+
+ -
+ message: '#^Variable \$version might not be defined\.$#'
+ identifier: variable.undefined
+ count: 1
+ path: include/download-instructions/linux-debian-web-community.php
+
+ -
+ message: '#^Variable \$version might not be defined\.$#'
+ identifier: variable.undefined
+ count: 2
+ path: include/download-instructions/linux-docker-cli-community.php
+
+ -
+ message: '#^Variable \$version might not be defined\.$#'
+ identifier: variable.undefined
+ count: 2
+ path: include/download-instructions/linux-docker-web-community.php
+
+ -
+ message: '#^Variable \$multiversion might not be defined\.$#'
+ identifier: variable.undefined
+ count: 1
+ path: include/download-instructions/linux-fedora-cli-community.php
+
+ -
+ message: '#^Variable \$version might not be defined\.$#'
+ identifier: variable.undefined
+ count: 1
+ path: include/download-instructions/linux-fedora-cli-community.php
+
+ -
+ message: '#^Variable \$versionNoDot might not be defined\.$#'
+ identifier: variable.undefined
+ count: 1
+ path: include/download-instructions/linux-fedora-cli-community.php
+
+ -
+ message: '#^Variable \$multiversion might not be defined\.$#'
+ identifier: variable.undefined
+ count: 1
+ path: include/download-instructions/linux-fedora-web-community.php
+
+ -
+ message: '#^Variable \$version might not be defined\.$#'
+ identifier: variable.undefined
+ count: 1
+ path: include/download-instructions/linux-fedora-web-community.php
+
+ -
+ message: '#^Variable \$versionNoDot might not be defined\.$#'
+ identifier: variable.undefined
+ count: 1
+ path: include/download-instructions/linux-fedora-web-community.php
+
+ -
+ message: '#^Variable \$multiversion might not be defined\.$#'
+ identifier: variable.undefined
+ count: 1
+ path: include/download-instructions/linux-redhat-cli-community.php
+
+ -
+ message: '#^Variable \$version might not be defined\.$#'
+ identifier: variable.undefined
+ count: 1
+ path: include/download-instructions/linux-redhat-cli-community.php
+
+ -
+ message: '#^Variable \$versionNoDot might not be defined\.$#'
+ identifier: variable.undefined
+ count: 1
+ path: include/download-instructions/linux-redhat-cli-community.php
+
+ -
+ message: '#^Variable \$multiversion might not be defined\.$#'
+ identifier: variable.undefined
+ count: 1
+ path: include/download-instructions/linux-redhat-web-community.php
+
+ -
+ message: '#^Variable \$version might not be defined\.$#'
+ identifier: variable.undefined
+ count: 1
+ path: include/download-instructions/linux-redhat-web-community.php
+
+ -
+ message: '#^Variable \$versionNoDot might not be defined\.$#'
+ identifier: variable.undefined
+ count: 1
+ path: include/download-instructions/linux-redhat-web-community.php
+
+ -
+ message: '#^Variable \$version might not be defined\.$#'
+ identifier: variable.undefined
+ count: 1
+ path: include/download-instructions/linux-ubuntu-cli-community.php
+
+ -
+ message: '#^Variable \$version might not be defined\.$#'
+ identifier: variable.undefined
+ count: 1
+ path: include/download-instructions/linux-ubuntu-web-community.php
+
+ -
+ message: '#^Variable \$version might not be defined\.$#'
+ identifier: variable.undefined
+ count: 2
+ path: include/download-instructions/osx-docker-cli.php
+
+ -
+ message: '#^Variable \$version might not be defined\.$#'
+ identifier: variable.undefined
+ count: 2
+ path: include/download-instructions/osx-docker-web.php
+
+ -
+ message: '#^Variable \$version might not be defined\.$#'
+ identifier: variable.undefined
+ count: 2
+ path: include/download-instructions/osx-homebrew-php.php
+
+ -
+ message: '#^Variable \$version might not be defined\.$#'
+ identifier: variable.undefined
+ count: 2
+ path: include/download-instructions/osx-homebrew.php
+
+ -
+ message: '#^Variable \$version might not be defined\.$#'
+ identifier: variable.undefined
+ count: 2
+ path: include/download-instructions/osx-macports.php
+
+ -
+ message: '#^Variable \$versionNoDot might not be defined\.$#'
+ identifier: variable.undefined
+ count: 2
+ path: include/download-instructions/osx-macports.php
+
+ -
+ message: '#^Variable \$version might not be defined\.$#'
+ identifier: variable.undefined
+ count: 1
+ path: include/download-instructions/windows-chocolatey.php
+
+ -
+ message: '#^Variable \$version might not be defined\.$#'
+ identifier: variable.undefined
+ count: 2
+ path: include/download-instructions/windows-docker-cli.php
+
+ -
+ message: '#^Variable \$version might not be defined\.$#'
+ identifier: variable.undefined
+ count: 2
+ path: include/download-instructions/windows-docker-web.php
+
+ -
+ message: '#^Variable \$version might not be defined\.$#'
+ identifier: variable.undefined
+ count: 1
+ path: include/download-instructions/windows-downloads.php
+
+ -
+ message: '#^Variable \$version might not be defined\.$#'
+ identifier: variable.undefined
+ count: 1
+ path: include/download-instructions/windows-native.php
+
+ -
+ message: '#^Variable \$versionNoDot might not be defined\.$#'
+ identifier: variable.undefined
+ count: 1
+ path: include/download-instructions/windows-scoop-versions.php
+
+ -
+ message: '#^Variable \$version might not be defined\.$#'
+ identifier: variable.undefined
+ count: 4
+ path: include/download-instructions/windows-winget.php
+
+ -
+ message: '#^Variable \$MYSITE might not be defined\.$#'
+ identifier: variable.undefined
+ count: 1
+ path: include/get-download.inc
+
+ -
+ message: '#^Variable \$CSS might not be defined\.$#'
+ identifier: variable.undefined
+ count: 1
+ path: include/header.inc
+
+ -
+ message: '#^Variable \$MYSITE might not be defined\.$#'
+ identifier: variable.undefined
+ count: 9
+ path: include/header.inc
+
+ -
+ message: '#^Variable \$classes might not be defined\.$#'
+ identifier: variable.undefined
+ count: 1
+ path: include/header.inc
+
+ -
+ message: '#^Variable \$config might not be defined\.$#'
+ identifier: variable.undefined
+ count: 3
+ path: include/header.inc
+
+ -
+ message: '#^Variable \$curr might not be defined\.$#'
+ identifier: variable.undefined
+ count: 2
+ path: include/header.inc
+
+ -
+ message: '#^Variable \$lang might not be defined\.$#'
+ identifier: variable.undefined
+ count: 1
+ path: include/header.inc
+
+ -
+ message: '#^Variable \$shorturl might not be defined\.$#'
+ identifier: variable.undefined
+ count: 3
+ path: include/header.inc
+
+ -
+ message: '#^Variable \$title might not be defined\.$#'
+ identifier: variable.undefined
+ count: 1
+ path: include/header.inc
+
+ -
+ message: '#^Variable \$userPreferences might not be defined\.$#'
+ identifier: variable.undefined
+ count: 1
+ path: include/langchooser.inc
+
+ -
+ message: '#^Variable \$MYSITE might not be defined\.$#'
+ identifier: variable.undefined
+ count: 2
+ path: include/layout.inc
+
+ -
+ message: '#^Variable \$TOC might not be defined\.$#'
+ identifier: variable.undefined
+ count: 6
+ path: include/layout.inc
+
+ -
+ message: '#^Variable \$link might not be defined\.$#'
+ identifier: variable.undefined
+ count: 1
+ path: include/layout.inc
+
+ -
+ message: '#^Variable \$title might not be defined\.$#'
+ identifier: variable.undefined
+ count: 1
+ path: include/layout.inc
+
+ -
+ message: '#^Variable \$MYSITE might not be defined\.$#'
+ identifier: variable.undefined
+ count: 2
+ path: include/mozopensearch.inc
+
+ -
+ message: '#^Variable \$MYSITE might not be defined\.$#'
+ identifier: variable.undefined
+ count: 5
+ path: include/mozsearch.inc
+
+ -
+ message: '#^Variable \$LANG might not be defined\.$#'
+ identifier: variable.undefined
+ count: 1
+ path: manual/index.php
+
+ -
+ message: '#^Variable \$N might not be defined\.$#'
+ identifier: variable.undefined
+ count: 1
+ path: manual/vote-note.php
diff --git a/phpstan.neon.dist b/phpstan.neon.dist
new file mode 100644
index 0000000000..e81fcf4243
--- /dev/null
+++ b/phpstan.neon.dist
@@ -0,0 +1,13 @@
+includes:
+ - phpstan-baseline.neon
+
+parameters:
+ level: 3
+ paths:
+ - src
+ - tests
+ - manual
+ - include
+ fileExtensions:
+ - php
+ - inc