diff --git a/.gitattributes b/.gitattributes index f2b996686..6fa043c47 100644 --- a/.gitattributes +++ b/.gitattributes @@ -7,14 +7,17 @@ /tests/ export-ignore /docs/ export-ignore -/Makefile export-ignore -/.editorconfig export-ignore -/.gitattributes export-ignore -/.gitignore export-ignore -/.php-censor.yml export-ignore -/phpunit.xml.dist export-ignore -/phpmd.xml.dist export-ignore -/.php_cs.dist export-ignore -/codecov.yml export-ignore -/infection.json.dist export-ignore -/psalm.xml.dist export-ignore +/Makefile export-ignore +/.editorconfig export-ignore +/.gitattributes export-ignore +/.gitignore export-ignore +/.php-censor.yml export-ignore +/phpunit.xml.dist export-ignore +/phpmd.xml.dist export-ignore +/.php_cs.dist export-ignore +/codecov.yml export-ignore +/infection.json.dist export-ignore +/psalm.xml.dist export-ignore +/.php-cs-fixer.dist.php export-ignore +/rector.php export-ignore +/composer.lock export-ignore diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 3636f9d4a..fbdefea04 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -8,7 +8,7 @@ jobs: strategy: fail-fast: false matrix: - php-version: ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4'] + php-version: ['8.1', '8.2', '8.3', '8.4'] steps: - name: Setup MySQL latest @@ -63,12 +63,12 @@ jobs: export POSTGRESQL_PASSWORD='postgres'; export MYSQL_USER='root'; export MYSQL_PASSWORD='root'; - if [[ ${{ matrix.php-version }} == '7.4' ]]; then + if [[ ${{ matrix.php-version }} == '8.1' ]]; then export CODECOVERAGE=1 && vendor/bin/phpunit --verbose --coverage-clover=coverage.xml else vendor/bin/phpunit --verbose fi - name: Submit code coverage - if: matrix.php-version == '7.4' + if: matrix.php-version == '8.1' uses: codecov/codecov-action@v1 diff --git a/.php-censor.yml b/.php-censor.yml index d111b9e00..557ff4252 100644 --- a/.php-censor.yml +++ b/.php-censor.yml @@ -53,10 +53,3 @@ complete: commands: - "cd ~ && ./drop_test_ci_mysql_db.sh %BUILD_ID%" - "cd ~ && ./drop_test_ci_postgres_db.sh %BUILD_ID%" - email_notify: - default_mailto_address: poisoncorpsee@gmail.com - telegram_notify: - auth_token: "%SECRET:telegram_auth_token%" - recipients: - - "%SECRET:telegram_chat_id%" - send_log: false diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index bc368207a..a1624df72 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -32,7 +32,7 @@ 'allow_mixed' => true, 'allow_unused_params' => true, ], - 'no_unneeded_curly_braces' => [ + 'no_unneeded_braces' => [ 'namespaces' => true, ], 'phpdoc_types_order' => [ diff --git a/CHANGELOG.md b/CHANGELOG.md index dc1b566bc..21d8ddebe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,121 +1,37 @@ -Changelog 2.1 +Changelog 3.0 ============= The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## [2.1.6 (Mr. Meeseeks)](https://github.com/php-censor/php-censor/tree/2.1.6) (2025-03-15) +## [3.0.0](https://github.com/php-censor/php-censor/tree/3.0.0) (2025-03-30) -[Full Changelog](https://github.com/php-censor/php-censor/compare/2.1.5...2.1.6) +[Full Changelog](https://github.com/php-censor/php-censor/compare/2.1.6...3.0.0) -### Fixed - -- Security issue with remember me key in auth. See: https://chmod744.super.site/redacted-vulnerability. -- Security issue CVE-2024-50345: CVE-2024-50345: Open redirect via browser-sanitized URLs. See: https://symfony.com/cve-2024-50345. - - -## [2.1.5 (Mr. Meeseeks)](https://github.com/php-censor/php-censor/tree/2.1.5) (2024-05-04) - -[Full Changelog](https://github.com/php-censor/php-censor/compare/2.1.4...2.1.5) - -### Added - -- Support of PHP 8.2 and 8.3 in GitHub Actions. - -### Fixed - -- Security issue with remember me key in auth. See: https://chmod744.super.site/redacted-vulnerability. - - -## [2.1.4 (Mr. Meeseeks)](https://github.com/php-censor/php-censor/tree/2.1.4) (2024-01-11) - -[Full Changelog](https://github.com/php-censor/php-censor/compare/2.1.3...2.1.4) - -### Fixed - -- Updated dependencies. Fixed: - - `guzzlehttp/psr7` (1.9.0) | CVE-2023-29197: Improper header validation | https://github.com/guzzle/psr7/security/advisories/GHSA-wxmh-65f7-jcvw. - - -## [2.1.3 (Mr. Meeseeks)](https://github.com/php-censor/php-censor/tree/2.1.3) (2023-01-11) - -[Full Changelog](https://github.com/php-censor/php-censor/compare/2.1.2...2.1.3) - -### Fixed - -- PHP 8.1 deprecation while searching for composer binary. Pull request [#434](https://github.com/php-censor/php-censor/pull/434). - Thanks to [@StudioMaX](https://github.com/StudioMaX). -- PHP 8.1 error with return type of `php_user_filter::filter` function. - - -## [2.1.2 (Mr. Meeseeks)](https://github.com/php-censor/php-censor/tree/2.1.2) (2022-09-01) - -[Full Changelog](https://github.com/php-censor/php-censor/compare/2.1.1...2.1.2) - -### Fixed - -- Build logger expression. Pull requests [#431](https://github.com/php-censor/php-censor/pull/431). Thanks to [@StudioMaX](https://github.com/StudioMaX). -- Type of GET param `commitId` in WebhookController. Issue [#432](https://github.com/php-censor/php-censor/pull/432). -- Webhook response type. Issue [#432](https://github.com/php-censor/php-censor/pull/432). -- Secrets security: denied to using secrets in notify plugins content. - - -## [2.1.1 (Mr. Meeseeks)](https://github.com/php-censor/php-censor/tree/2.1.1) (2022-08-30) - -[Full Changelog](https://github.com/php-censor/php-censor/compare/2.1.0...2.1.1) - -### Fixed - -- `php-censor/common` package version. -- Logging with secret variables (Now secrets hides from log). -- Secrets validation. - - -## [2.1.0 (Mr. Meeseeks)](https://github.com/php-censor/php-censor/tree/2.1.0) (2022-08-18) - -[Full Changelog](https://github.com/php-censor/php-censor/compare/2.0.10...2.1.0) +### [How tp upgrade from v1 to v2](/docs/en/upgrades/UPGRADE_2.0.md) +### [How tp upgrade from v2 to v3](/docs/en/upgrades/UPGRADE_3.0.md) ### Added -- Secrets storage with UI and secret variables in build interpolation (you can use it like `%SECRET:secret_name%`. See [documentation](https://github.com/php-censor/php-censor/blob/master/docs/en/interpolation.md)). Issue [#14](https://github.com/php-censor/php-censor/issues/#14). -- Optional logging into database webhook requests payloads (option `php-censor.webhook.log_requests`). Issue [#384](https://github.com/php-censor/php-censor/issues/#384). -- Steps inside stages (`test`, `deploy` etc.) which allow to have several same plugins into one stage. Issue [#91](https://github.com/php-censor/php-censor/issues/#91). Pull request [#417](https://github.com/php-censor/php-censor/pull/417). Thanks to [@KieranFYI](https://github.com/KieranFYI). Usage example: - ```yml - setup: # <--- stage - setup_env: # <--- step 1 - plugin: shell # <--- step 1 plugin name - commands: - - "php -r \"copy('.env.ci', '.env');\"" - - "php artisan key:generate" - - "chmod -R 777 storage bootstrap/cache" - migrate: # <--- step 2 - plugin: shell # <--- step 2 same plugin name - commands: - - "php artisan migrate" - ``` -- `GET`-parameter `environment` for Git webhook. Issue [#407](https://github.com/php-censor/php-censor/issues/#407). -- Cloning/coping projects ability. -- **[PHP Unit]** Coverage trand for builds in the timeline on dashboard. +- CLI commands for secrets. +- PHP executable path in "build_settings" config. +- **[TelegramNotify]** Notifications in telegram group topics. Pull request [#440](https://github.com/php-censor/php-censor/pull/440). Thanks to [@yugeon](https://github.com/yugeon). ### Changed -- Massive refactoring: added types, dependency injection, new tests, documentation, fixed code style etc. Issue [#413](https://github.com/php-censor/php-censor/issues/#413). Pull requests [#412](https://github.com/php-censor/php-censor/pull/412), [#424](https://github.com/php-censor/php-censor/pull/424) and [#425](https://github.com/php-censor/php-censor/pull/425). Thanks to [@KieranFYI](https://github.com/KieranFYI) and [@Ooypunk](https://github.com/Ooypunk). -- Integrated `symfony/http-foundation` library as a new HTTP part of project. -- Integrate some features from `php-censor/common` library. -- Improved UI: fixed colors and ratio for `Chart.js` charts, added ability to disable AJAX UI reloading (option `php-censor.realtime_ui`), improved error trends view. Pull request [#426](https://github.com/php-censor/php-censor/pull/426). Thanks to [@KieranFYI](https://github.com/KieranFYI). -- Improved Ukrainian localization. Pull request [#419](https://github.com/php-censor/php-censor/pull/419). Thanks to [@oshka](https://github.com/oshka). +- **Minimal PHP version increased to 8.1 (from 7.4)**. -### Fixed +### Removed -- Install command return code. -- **[PHPUnit]** Xdebug settings for coverage option. Pull request [#427](https://github.com/php-censor/php-censor/pull/427). Thanks to [@KieranFYI](https://github.com/KieranFYI). +- **[HipchatNotify]** HipChat notification plugin (It was shut down in 2019). Pull request [#433](https://github.com/php-censor/php-censor/pull/433). Thanks to [@StudioMaX](https://github.com/StudioMaX). ## Other versions -- [0.x Changelog](/docs/CHANGELOG_0.x.md) -- [1.0 Changelog](/docs/CHANGELOG_1.0.md) -- [1.1 Changelog](/docs/CHANGELOG_1.1.md) -- [1.2 Changelog](/docs/CHANGELOG_1.2.md) -- [1.3 Changelog](/docs/CHANGELOG_1.3.md) -- [2.0 Changelog](/docs/CHANGELOG_2.0.md) +- [0.x Changelog](/docs/en/changelogs/CHANGELOG_0.x.md) +- [1.0 Changelog](/docs/en/changelogs/CHANGELOG_1.0.md) +- [1.1 Changelog](/docs/en/changelogs/CHANGELOG_1.1.md) +- [1.2 Changelog](/docs/en/changelogs/CHANGELOG_1.2.md) +- [1.3 Changelog](/docs/en/changelogs/CHANGELOG_1.3.md) +- [2.0 Changelog](/docs/en/changelogs/CHANGELOG_2.0.md) +- [2.1 Changelog](/docs/en/changelogs/CHANGELOG_2.1.md) diff --git a/Makefile b/Makefile index ebbb9b0b9..cca309316 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -PHP?=php7.4 +PHP?=php8.1 COMPOSER=/usr/local/bin/composer php-info: diff --git a/README.md b/README.md index 89079768f..7ab90aa4d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Minimum PHP version: 7.4.0](https://img.shields.io/badge/php-7.4.0%2B-blue.svg?label=PHP)](https://packagist.org/packages/php-censor/php-censor) +[![Minimum PHP version: 8.1.0](https://img.shields.io/badge/php-8.1.0%2B-blue.svg?label=PHP)](https://packagist.org/packages/php-censor/php-censor) [![Actions](https://github.com/php-censor/php-censor/actions/workflows/ci.yaml/badge.svg)](https://github.com/php-censor/php-censor/actions) [![PHP Censor](http://ci.php-censor.info/build-status/image/2?branch=master&label=PHP%20Censor)](http://ci.php-censor.info/build-status/view/2?branch=master) [![Codecov](https://codecov.io/gh/php-censor/php-censor/branch/master/graph/badge.svg)](https://codecov.io/gh/php-censor/php-censor) @@ -11,19 +11,14 @@

**PHP Censor** is an open source, self-hosted, continuous integration server for PHP projects -([PHPCI](https://github.com/dancryer/PHPCI) fork). [Official twitter @php_censor](https://twitter.com/php_censor). +([PHPCI](https://github.com/dancryer/PHPCI) fork). -PHP Censor versions: +PHP Censor has two stable release versions: -| Version | Latest | Branch | Status | Minimal PHP Version | -|:---------------------:|:--------:|:-------------:|:------------------------------------------------------------------:| :-----------------: | -| `1.0` (Morty Smith) | `1.0.16` | `release-1.0` | Old version (**UNSUPPORTED**) | `>=5.6, <8.0` | -| `1.1` (Birdperson) | `1.1.6` | `release-1.1` | Old version (**UNSUPPORTED**) | `>=5.6, <8.0` | -| `1.2` (Summer Smith) | `1.2.4` | `release-1.2` | Old version (**UNSUPPORTED**) | `>=5.6, <8.0` | -| `1.3` (Jerry Smith) | `1.3.7` | `release-1.3` | Old version (**UNSUPPORTED**) | `>=5.6, <8.0` | -| `2.0` (Rick Sanchez) | `2.0.14` | `release-2.0` | Last stable version ([Upgrade from v1 to v2](docs/UPGRADE_2.0.md)) | `>=7.4` | -| `2.1` (Mr. Meeseeks) | `2.1.6` | `release-2.1` | Current stable version | `>=7.4` | -| `2.2` | WIP | `master` | Feature minor version (WIP) | `>=7.4` | +- **Latest stable version: 3.0 (PHP >= 8.1)** +- Previous stable version: 2.1 (PHP >= 7.4) + +You can learn more about PHP Censor releases at the [release page](/docs/en/releases.md). [![Dashboard](docs/screenshots/dashboard.png)](docs/screenshots/dashboard.png) @@ -32,7 +27,6 @@ More [screenshots](docs/en/screenshots.md). * [System requirements](#system-requirements) * [Features](#features) * [Changelog](#changelog) -* [Roadmap](#roadmap) * [Installing](#installing) * [Updating](#updating) * [Configuring project](#configuring-project) @@ -46,7 +40,7 @@ More [screenshots](docs/en/screenshots.md). * Unix-like OS (**Windows isn't supported**); -* PHP 7.4+ (with OpenSSL support and enabled functions: `exec()`, `shell_exec()` and `proc_open()`); +* PHP 8.1+ (with OpenSSL support and enabled functions: `exec()`, `shell_exec()` and `proc_open()`); * Web-server (Nginx or Apache2); @@ -82,10 +76,6 @@ CleanBuild, CopyBuild, Deployer, Env, Git, Grunt, Gulp, PackageBuild, Phar, Phin [Versions changelog](CHANGELOG.md). -## Roadmap - -See [milestones](https://github.com/php-censor/php-censor/milestones). - ## Installing See [Installing](docs/en/installing.md) section in documentation; diff --git a/VERSION.md b/VERSION.md index a74d18b8d..4a36342fc 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -2.2.0-alpha +3.0.0 diff --git a/composer.json b/composer.json index fee2d97b0..dbbfab508 100644 --- a/composer.json +++ b/composer.json @@ -14,19 +14,19 @@ "ci", "continuous integration" ], - "homepage": "http://php-censor.info", + "homepage": "https://php-censor.info", "license": "BSD-2-Clause", "authors": [ { "name": "Dmitry Khomutov", "email": "poisoncorpsee@gmail.com", - "homepage": "http://corpsee.com", + "homepage": "https://corpsee.com", "role": "PHP Censor developer" }, { "name": "Dan Cryer", "email": "dan.cryer@block8.co.uk", - "homepage": "http://www.block8.co.uk", + "homepage": "https://www.block8.co.uk", "role": "PHPCI developer" } ], @@ -45,7 +45,7 @@ } }, "require": { - "php": ">=7.4.0", + "php": ">=8.1.0", "ext-openssl": "*", "ext-PDO": "*", "ext-json": "*", @@ -101,7 +101,7 @@ }, "extra": { "platform": { - "php": "7.4.*" + "php": "8.1" } }, "config": { diff --git a/composer.lock b/composer.lock index 09fe3ffdb..4ab7ca55d 100644 --- a/composer.lock +++ b/composer.lock @@ -4,11 +4,11 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b021933c25e0840d8c885e184593250d", + "content-hash": "f932746a4a6f7264724683be82ddf292", "packages": [ { "name": "cakephp/core", - "version": "4.5.9", + "version": "4.6.0", "source": { "type": "git", "url": "https://github.com/cakephp/core.git", @@ -68,7 +68,7 @@ }, { "name": "cakephp/database", - "version": "4.5.9", + "version": "4.6.0", "source": { "type": "git", "url": "https://github.com/cakephp/database.git", @@ -124,7 +124,7 @@ }, { "name": "cakephp/datasource", - "version": "4.5.9", + "version": "4.6.0", "source": { "type": "git", "url": "https://github.com/cakephp/datasource.git", @@ -182,7 +182,7 @@ }, { "name": "cakephp/utility", - "version": "4.5.9", + "version": "4.6.0", "source": { "type": "git", "url": "https://github.com/cakephp/utility.git", @@ -1176,20 +1176,20 @@ }, { "name": "psr/cache", - "version": "1.0.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/php-fig/cache.git", - "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" + "reference": "213f9dbc5b9bfbc4f8db86d2838dc968752ce13b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", - "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", + "url": "https://api.github.com/repos/php-fig/cache/zipball/213f9dbc5b9bfbc4f8db86d2838dc968752ce13b", + "reference": "213f9dbc5b9bfbc4f8db86d2838dc968752ce13b", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=8.0.0" }, "type": "library", "extra": { @@ -1209,7 +1209,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for caching libraries", @@ -1219,9 +1219,9 @@ "psr-6" ], "support": { - "source": "https://github.com/php-fig/cache/tree/master" + "source": "https://github.com/php-fig/cache/tree/2.0.0" }, - "time": "2016-08-06T20:24:11+00:00" + "time": "2021-02-03T23:23:37+00:00" }, { "name": "psr/container", @@ -1426,25 +1426,25 @@ }, { "name": "psr/simple-cache", - "version": "1.0.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/php-fig/simple-cache.git", - "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" + "reference": "8707bf3cea6f710bf6ef05491234e3ab06f6432a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", - "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/8707bf3cea6f710bf6ef05491234e3ab06f6432a", + "reference": "8707bf3cea6f710bf6ef05491234e3ab06f6432a", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=8.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -1459,7 +1459,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interfaces for simple caching", @@ -1471,9 +1471,9 @@ "simple-cache" ], "support": { - "source": "https://github.com/php-fig/simple-cache/tree/master" + "source": "https://github.com/php-fig/simple-cache/tree/2.0.0" }, - "time": "2017-10-23T01:57:42+00:00" + "time": "2021-10-29T13:22:09+00:00" }, { "name": "ralouphie/getallheaders", @@ -2046,38 +2046,34 @@ }, { "name": "symfony/config", - "version": "v5.4.46", + "version": "v6.4.14", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "977c88a02d7d3f16904a81907531b19666a08e78" + "reference": "4e55e7e4ffddd343671ea972216d4509f46c22ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/977c88a02d7d3f16904a81907531b19666a08e78", - "reference": "977c88a02d7d3f16904a81907531b19666a08e78", + "url": "https://api.github.com/repos/symfony/config/zipball/4e55e7e4ffddd343671ea972216d4509f46c22ef", + "reference": "4e55e7e4ffddd343671ea972216d4509f46c22ef", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/filesystem": "^4.4|^5.0|^6.0", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-php80": "^1.16", - "symfony/polyfill-php81": "^1.22" + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/filesystem": "^5.4|^6.0|^7.0", + "symfony/polyfill-ctype": "~1.8" }, "conflict": { - "symfony/finder": "<4.4" + "symfony/finder": "<5.4", + "symfony/service-contracts": "<2.5" }, "require-dev": { - "symfony/event-dispatcher": "^4.4|^5.0|^6.0", - "symfony/finder": "^4.4|^5.0|^6.0", - "symfony/messenger": "^4.4|^5.0|^6.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/yaml": "^4.4|^5.0|^6.0" - }, - "suggest": { - "symfony/yaml": "To use the yaml reference dumper" + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/finder": "^5.4|^6.0|^7.0", + "symfony/messenger": "^5.4|^6.0|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/yaml": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -2105,7 +2101,7 @@ "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/config/tree/v5.4.46" + "source": "https://github.com/symfony/config/tree/v6.4.14" }, "funding": [ { @@ -2121,7 +2117,7 @@ "type": "tidelift" } ], - "time": "2024-10-30T07:58:02+00:00" + "time": "2024-11-04T11:33:53+00:00" }, { "name": "symfony/console", @@ -2379,20 +2375,20 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v2.5.4", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "605389f2a7e5625f273b53960dc46aeaf9c62918" + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/605389f2a7e5625f273b53960dc46aeaf9c62918", - "reference": "605389f2a7e5625f273b53960dc46aeaf9c62918", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.1" }, "type": "library", "extra": { @@ -2401,7 +2397,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "3.5-dev" } }, "autoload": { @@ -2426,7 +2422,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.4" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" }, "funding": [ { @@ -2442,7 +2438,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:11:13+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/dom-crawler", @@ -2606,25 +2602,22 @@ }, { "name": "symfony/event-dispatcher-contracts", - "version": "v2.5.4", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "e0fe3d79b516eb75126ac6fa4cbf19b79b08c99f" + "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/e0fe3d79b516eb75126ac6fa4cbf19b79b08c99f", - "reference": "e0fe3d79b516eb75126ac6fa4cbf19b79b08c99f", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7642f5e970b672283b7823222ae8ef8bbc160b9f", + "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.1", "psr/event-dispatcher": "^1" }, - "suggest": { - "symfony/event-dispatcher-implementation": "" - }, "type": "library", "extra": { "thanks": { @@ -2632,7 +2625,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "3.5-dev" } }, "autoload": { @@ -2665,7 +2658,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.4" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.1" }, "funding": [ { @@ -2681,7 +2674,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:11:13+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/filesystem", @@ -2967,40 +2960,40 @@ }, { "name": "symfony/mime", - "version": "v5.4.45", + "version": "v6.4.19", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "8c1b9b3e5b52981551fc6044539af1d974e39064" + "reference": "ac537b6c55ccc2c749f3c979edfa9ec14aaed4f3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/8c1b9b3e5b52981551fc6044539af1d974e39064", - "reference": "8c1b9b3e5b52981551fc6044539af1d974e39064", + "url": "https://api.github.com/repos/symfony/mime/zipball/ac537b6c55ccc2c749f3c979edfa9ec14aaed4f3", + "reference": "ac537b6c55ccc2c749f3c979edfa9ec14aaed4f3", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-intl-idn": "^1.10", - "symfony/polyfill-mbstring": "^1.0", - "symfony/polyfill-php80": "^1.16" + "symfony/polyfill-mbstring": "^1.0" }, "conflict": { "egulias/email-validator": "~3.0.0", "phpdocumentor/reflection-docblock": "<3.2.2", "phpdocumentor/type-resolver": "<1.4.0", - "symfony/mailer": "<4.4", - "symfony/serializer": "<5.4.35|>=6,<6.3.12|>=6.4,<6.4.3" + "symfony/mailer": "<5.4", + "symfony/serializer": "<6.4.3|>7.0,<7.0.3" }, "require-dev": { "egulias/email-validator": "^2.1.10|^3.1|^4", + "league/html-to-markdown": "^5.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/process": "^5.4|^6.4", - "symfony/property-access": "^4.4|^5.1|^6.0", - "symfony/property-info": "^4.4|^5.1|^6.0", - "symfony/serializer": "^5.4.35|~6.3.12|^6.4.3" + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.4|^7.0", + "symfony/property-access": "^5.4|^6.0|^7.0", + "symfony/property-info": "^5.4|^6.0|^7.0", + "symfony/serializer": "^6.4.3|^7.0.3" }, "type": "library", "autoload": { @@ -3032,7 +3025,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v5.4.45" + "source": "https://github.com/symfony/mime/tree/v6.4.19" }, "funding": [ { @@ -3048,7 +3041,7 @@ "type": "tidelift" } ], - "time": "2024-10-23T20:18:32+00:00" + "time": "2025-02-17T21:23:52+00:00" }, { "name": "symfony/polyfill-ctype", @@ -3975,34 +3968,34 @@ }, { "name": "symfony/string", - "version": "v5.4.47", + "version": "v6.4.15", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "136ca7d72f72b599f2631aca474a4f8e26719799" + "reference": "73a5e66ea2e1677c98d4449177c5a9cf9d8b4c6f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/136ca7d72f72b599f2631aca474a4f8e26719799", - "reference": "136ca7d72f72b599f2631aca474a4f8e26719799", + "url": "https://api.github.com/repos/symfony/string/zipball/73a5e66ea2e1677c98d4449177c5a9cf9d8b4c6f", + "reference": "73a5e66ea2e1677c98d4449177c5a9cf9d8b4c6f", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.1", "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/error-handler": "^5.4|^6.0|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/intl": "^6.2|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -4041,7 +4034,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.4.47" + "source": "https://github.com/symfony/string/tree/v6.4.15" }, "funding": [ { @@ -4057,28 +4050,30 @@ "type": "tidelift" } ], - "time": "2024-11-10T20:33:58+00:00" + "time": "2024-11-13T13:31:12+00:00" }, { "name": "symfony/var-exporter", - "version": "v5.4.45", + "version": "v6.4.20", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "862700068db0ddfd8c5b850671e029a90246ec75" + "reference": "998df255e9e6a15a36ae35e9c6cd818c17cf92a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/862700068db0ddfd8c5b850671e029a90246ec75", - "reference": "862700068db0ddfd8c5b850671e029a90246ec75", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/998df255e9e6a15a36ae35e9c6cd818c17cf92a2", + "reference": "998df255e9e6a15a36ae35e9c6cd818c17cf92a2", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3" }, "require-dev": { - "symfony/var-dumper": "^4.4.9|^5.0.9|^6.0" + "symfony/property-access": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -4111,10 +4106,12 @@ "export", "hydrate", "instantiate", + "lazy-loading", + "proxy", "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v5.4.45" + "source": "https://github.com/symfony/var-exporter/tree/v6.4.20" }, "funding": [ { @@ -4130,7 +4127,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:11:13+00:00" + "time": "2025-03-13T09:55:08+00:00" }, { "name": "symfony/yaml", @@ -5035,30 +5032,30 @@ }, { "name": "doctrine/instantiator", - "version": "1.5.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^9 || ^11", + "doctrine/coding-standard": "^11", "ext-pdo": "*", "ext-phar": "*", - "phpbench/phpbench": "^0.16 || ^1", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-phpunit": "^1", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.30 || ^5.4" + "phpbench/phpbench": "^1.2", + "phpstan/phpstan": "^1.9.4", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5.27", + "vimeo/psalm": "^5.4" }, "type": "library", "autoload": { @@ -5085,7 +5082,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.5.0" + "source": "https://github.com/doctrine/instantiator/tree/2.0.0" }, "funding": [ { @@ -5101,7 +5098,7 @@ "type": "tidelift" } ], - "time": "2022-12-30T00:15:36+00:00" + "time": "2022-12-30T00:23:10+00:00" }, { "name": "felixfbecker/advanced-json-rpc", @@ -6817,16 +6814,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.12.21", + "version": "1.12.23", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "14276fdef70575106a3392a4ed553c06a984df28" + "reference": "29201e7a743a6ab36f91394eab51889a82631428" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/14276fdef70575106a3392a4ed553c06a984df28", - "reference": "14276fdef70575106a3392a4ed553c06a984df28", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/29201e7a743a6ab36f91394eab51889a82631428", + "reference": "29201e7a743a6ab36f91394eab51889a82631428", "shasum": "" }, "require": { @@ -6871,7 +6868,7 @@ "type": "github" } ], - "time": "2025-03-09T09:24:50+00:00" + "time": "2025-03-23T14:57:32+00:00" }, { "name": "phpunit/php-code-coverage", @@ -8506,16 +8503,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "3.11.3", + "version": "3.12.0", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "ba05f990e79cbe69b9f35c8c1ac8dca7eecc3a10" + "reference": "2d1b63db139c3c6ea0c927698e5160f8b3b8d630" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/ba05f990e79cbe69b9f35c8c1ac8dca7eecc3a10", - "reference": "ba05f990e79cbe69b9f35c8c1ac8dca7eecc3a10", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/2d1b63db139c3c6ea0c927698e5160f8b3b8d630", + "reference": "2d1b63db139c3c6ea0c927698e5160f8b3b8d630", "shasum": "" }, "require": { @@ -8582,31 +8579,29 @@ "type": "open_collective" }, { - "url": "https://thanks.dev/phpcsstandards", + "url": "https://thanks.dev/u/gh/phpcsstandards", "type": "thanks_dev" } ], - "time": "2025-01-23T17:04:15+00:00" + "time": "2025-03-18T05:04:51+00:00" }, { "name": "symfony/options-resolver", - "version": "v5.4.45", + "version": "v6.4.16", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "74e5b6f0db3e8589e6cfd5efb317a1fc2bb52fb6" + "reference": "368128ad168f20e22c32159b9f761e456cec0c78" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/74e5b6f0db3e8589e6cfd5efb317a1fc2bb52fb6", - "reference": "74e5b6f0db3e8589e6cfd5efb317a1fc2bb52fb6", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/368128ad168f20e22c32159b9f761e456cec0c78", + "reference": "368128ad168f20e22c32159b9f761e456cec0c78", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php73": "~1.0", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3" }, "type": "library", "autoload": { @@ -8639,7 +8634,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v5.4.45" + "source": "https://github.com/symfony/options-resolver/tree/v6.4.16" }, "funding": [ { @@ -8655,25 +8650,25 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:11:13+00:00" + "time": "2024-11-20T10:57:02+00:00" }, { "name": "symfony/stopwatch", - "version": "v5.4.45", + "version": "v6.4.19", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "fb2c199cf302eb207f8c23e7ee174c1c31a5c004" + "reference": "dfe1481c12c06266d0c3d58c0cb4b09bd497ab9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/fb2c199cf302eb207f8c23e7ee174c1c31a5c004", - "reference": "fb2c199cf302eb207f8c23e7ee174c1c31a5c004", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/dfe1481c12c06266d0c3d58c0cb4b09bd497ab9c", + "reference": "dfe1481c12c06266d0c3d58c0cb4b09bd497ab9c", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/service-contracts": "^1|^2|^3" + "php": ">=8.1", + "symfony/service-contracts": "^2.5|^3" }, "type": "library", "autoload": { @@ -8701,7 +8696,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v5.4.45" + "source": "https://github.com/symfony/stopwatch/tree/v6.4.19" }, "funding": [ { @@ -8717,7 +8712,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:11:13+00:00" + "time": "2025-02-21T10:06:30+00:00" }, { "name": "symfony/var-dumper", @@ -9221,7 +9216,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=7.4.0", + "php": ">=8.1.0", "ext-openssl": "*", "ext-pdo": "*", "ext-json": "*", diff --git a/docs/CHANGELOG_0.x.md b/docs/en/changelogs/CHANGELOG_0.x.md similarity index 100% rename from docs/CHANGELOG_0.x.md rename to docs/en/changelogs/CHANGELOG_0.x.md diff --git a/docs/CHANGELOG_1.0.md b/docs/en/changelogs/CHANGELOG_1.0.md similarity index 99% rename from docs/CHANGELOG_1.0.md rename to docs/en/changelogs/CHANGELOG_1.0.md index fa8b965d1..db21da3eb 100644 --- a/docs/CHANGELOG_1.0.md +++ b/docs/en/changelogs/CHANGELOG_1.0.md @@ -274,4 +274,4 @@ the another branch). Issue [#270](https://github.com/php-censor/php-censor/issue ## Other versions -- [0.x change log](/docs/CHANGELOG_0.x.md) +- [0.x change log](/docs/en/changelogs/CHANGELOG_0.x.mdANGELOG_0.x.md) diff --git a/docs/CHANGELOG_1.1.md b/docs/en/changelogs/CHANGELOG_1.1.md similarity index 97% rename from docs/CHANGELOG_1.1.md rename to docs/en/changelogs/CHANGELOG_1.1.md index ad77f1830..4531b7317 100644 --- a/docs/CHANGELOG_1.1.md +++ b/docs/en/changelogs/CHANGELOG_1.1.md @@ -153,5 +153,5 @@ Thanks to [@jwmwalrus](https://github.com/jwmwalrus). ## Other versions -- [0.x Changelog](/docs/CHANGELOG_0.x.md) -- [1.0 Changelog](/docs/CHANGELOG_1.0.md) +- [0.x Changelog](/docs/en/changelogs/CHANGELOG_0.x.mdANGELOG_0.x.md) +- [1.0 Changelog](/docs/en/changelogs/CHANGELOG_1.0.mdANGELOG_1.0.md) diff --git a/docs/CHANGELOG_1.2.md b/docs/en/changelogs/CHANGELOG_1.2.md similarity index 97% rename from docs/CHANGELOG_1.2.md rename to docs/en/changelogs/CHANGELOG_1.2.md index 0e4332535..c45d3be1a 100644 --- a/docs/CHANGELOG_1.2.md +++ b/docs/en/changelogs/CHANGELOG_1.2.md @@ -137,6 +137,6 @@ and [@SimonHeimberg](https://github.com/SimonHeimberg). ## Other versions -- [0.x Changelog](/docs/CHANGELOG_0.x.md) -- [1.0 Changelog](/docs/CHANGELOG_1.0.md) -- [1.1 Changelog](/docs/CHANGELOG_1.1.md) +- [0.x Changelog](/docs/en/changelogs/CHANGELOG_0.x.mdANGELOG_0.x.md) +- [1.0 Changelog](/docs/en/changelogs/CHANGELOG_1.0.mdANGELOG_1.0.md) +- [1.1 Changelog](/docs/en/changelogs/CHANGELOG_1.1.mdANGELOG_1.1.md) diff --git a/docs/CHANGELOG_1.3.md b/docs/en/changelogs/CHANGELOG_1.3.md similarity index 95% rename from docs/CHANGELOG_1.3.md rename to docs/en/changelogs/CHANGELOG_1.3.md index f45adaa47..a9ebe09f4 100644 --- a/docs/CHANGELOG_1.3.md +++ b/docs/en/changelogs/CHANGELOG_1.3.md @@ -144,7 +144,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a ## Other versions -- [0.x Changelog](/docs/CHANGELOG_0.x.md) -- [1.0 Changelog](/docs/CHANGELOG_1.0.md) -- [1.1 Changelog](/docs/CHANGELOG_1.1.md) -- [1.2 Changelog](/docs/CHANGELOG_1.2.md) +- [0.x Changelog](/docs/en/changelogs/CHANGELOG_0.x.mdANGELOG_0.x.md) +- [1.0 Changelog](/docs/en/changelogs/CHANGELOG_1.0.mdANGELOG_1.0.md) +- [1.1 Changelog](/docs/en/changelogs/CHANGELOG_1.1.mdANGELOG_1.1.md) +- [1.2 Changelog](/docs/en/changelogs/CHANGELOG_1.2.mdANGELOG_1.2.md) diff --git a/docs/CHANGELOG_2.0.md b/docs/en/changelogs/CHANGELOG_2.0.md similarity index 96% rename from docs/CHANGELOG_2.0.md rename to docs/en/changelogs/CHANGELOG_2.0.md index 069f1291e..ddd35f691 100644 --- a/docs/CHANGELOG_2.0.md +++ b/docs/en/changelogs/CHANGELOG_2.0.md @@ -198,7 +198,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a [Full Changelog](https://github.com/php-censor/php-censor/compare/1.3.0...2.0.0) -### [How tp upgrade from v1 to v2](/docs/UPGRADE_2.0.md) +### [How tp upgrade from v1 to v2](/docs/en/upgrades/UPGRADE_2.0.md) ### Changed @@ -235,8 +235,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a ## Other versions -- [0.x Changelog](/docs/CHANGELOG_0.x.md) -- [1.0 Changelog](/docs/CHANGELOG_1.0.md) -- [1.1 Changelog](/docs/CHANGELOG_1.1.md) -- [1.2 Changelog](/docs/CHANGELOG_1.2.md) -- [1.3 Changelog](/docs/CHANGELOG_1.3.md) +- [0.x Changelog](/docs/en/changelogs/CHANGELOG_0.x.mdANGELOG_0.x.md) +- [1.0 Changelog](/docs/en/changelogs/CHANGELOG_1.0.mdANGELOG_1.0.md) +- [1.1 Changelog](/docs/en/changelogs/CHANGELOG_1.1.mdANGELOG_1.1.md) +- [1.2 Changelog](/docs/en/changelogs/CHANGELOG_1.2.mdANGELOG_1.2.md) +- [1.3 Changelog](/docs/en/changelogs/CHANGELOG_1.3.mdANGELOG_1.3.md) diff --git a/docs/en/changelogs/CHANGELOG_2.1.md b/docs/en/changelogs/CHANGELOG_2.1.md new file mode 100644 index 000000000..d5099c512 --- /dev/null +++ b/docs/en/changelogs/CHANGELOG_2.1.md @@ -0,0 +1,121 @@ +Changelog 2.1 +============= + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to +[Semantic Versioning](http://semver.org/spec/v2.0.0.html). + + +## [2.1.6 (Mr. Meeseeks)](https://github.com/php-censor/php-censor/tree/2.1.6) (2025-03-15) + +[Full Changelog](https://github.com/php-censor/php-censor/compare/2.1.5...2.1.6) + +### Fixed + +- Security issue with remember me key in auth. See: https://chmod744.super.site/redacted-vulnerability. +- Security issue CVE-2024-50345: CVE-2024-50345: Open redirect via browser-sanitized URLs. See: https://symfony.com/cve-2024-50345. + + +## [2.1.5 (Mr. Meeseeks)](https://github.com/php-censor/php-censor/tree/2.1.5) (2024-05-04) + +[Full Changelog](https://github.com/php-censor/php-censor/compare/2.1.4...2.1.5) + +### Added + +- Support of PHP 8.2 and 8.3 in GitHub Actions. + +### Fixed + +- Security issue with remember me key in auth. See: https://chmod744.super.site/redacted-vulnerability. + + +## [2.1.4 (Mr. Meeseeks)](https://github.com/php-censor/php-censor/tree/2.1.4) (2024-01-11) + +[Full Changelog](https://github.com/php-censor/php-censor/compare/2.1.3...2.1.4) + +### Fixed + +- Updated dependencies. Fixed: + - `guzzlehttp/psr7` (1.9.0) | CVE-2023-29197: Improper header validation | https://github.com/guzzle/psr7/security/advisories/GHSA-wxmh-65f7-jcvw. + + +## [2.1.3 (Mr. Meeseeks)](https://github.com/php-censor/php-censor/tree/2.1.3) (2023-01-11) + +[Full Changelog](https://github.com/php-censor/php-censor/compare/2.1.2...2.1.3) + +### Fixed + +- PHP 8.1 deprecation while searching for composer binary. Pull request [#434](https://github.com/php-censor/php-censor/pull/434). + Thanks to [@StudioMaX](https://github.com/StudioMaX). +- PHP 8.1 error with return type of `php_user_filter::filter` function. + + +## [2.1.2 (Mr. Meeseeks)](https://github.com/php-censor/php-censor/tree/2.1.2) (2022-09-01) + +[Full Changelog](https://github.com/php-censor/php-censor/compare/2.1.1...2.1.2) + +### Fixed + +- Build logger expression. Pull requests [#431](https://github.com/php-censor/php-censor/pull/431). Thanks to [@StudioMaX](https://github.com/StudioMaX). +- Type of GET param `commitId` in WebhookController. Issue [#432](https://github.com/php-censor/php-censor/pull/432). +- Webhook response type. Issue [#432](https://github.com/php-censor/php-censor/pull/432). +- Secrets security: denied to using secrets in notify plugins content. + + +## [2.1.1 (Mr. Meeseeks)](https://github.com/php-censor/php-censor/tree/2.1.1) (2022-08-30) + +[Full Changelog](https://github.com/php-censor/php-censor/compare/2.1.0...2.1.1) + +### Fixed + +- `php-censor/common` package version. +- Logging with secret variables (Now secrets hides from log). +- Secrets validation. + + +## [2.1.0 (Mr. Meeseeks)](https://github.com/php-censor/php-censor/tree/2.1.0) (2022-08-18) + +[Full Changelog](https://github.com/php-censor/php-censor/compare/2.0.10...2.1.0) + +### Added + +- Secrets storage with UI and secret variables in build interpolation (you can use it like `%SECRET:secret_name%`. See [documentation](https://github.com/php-censor/php-censor/blob/master/docs/en/interpolation.md)). Issue [#14](https://github.com/php-censor/php-censor/issues/#14). +- Optional logging into database webhook requests payloads (option `php-censor.webhook.log_requests`). Issue [#384](https://github.com/php-censor/php-censor/issues/#384). +- Steps inside stages (`test`, `deploy` etc.) which allow to have several same plugins into one stage. Issue [#91](https://github.com/php-censor/php-censor/issues/#91). Pull request [#417](https://github.com/php-censor/php-censor/pull/417). Thanks to [@KieranFYI](https://github.com/KieranFYI). Usage example: + ```yml + setup: # <--- stage + setup_env: # <--- step 1 + plugin: shell # <--- step 1 plugin name + commands: + - "php -r \"copy('.env.ci', '.env');\"" + - "php artisan key:generate" + - "chmod -R 777 storage bootstrap/cache" + migrate: # <--- step 2 + plugin: shell # <--- step 2 same plugin name + commands: + - "php artisan migrate" + ``` +- `GET`-parameter `environment` for Git webhook. Issue [#407](https://github.com/php-censor/php-censor/issues/#407). +- Cloning/coping projects ability. +- **[PHP Unit]** Coverage trand for builds in the timeline on dashboard. + +### Changed + +- Massive refactoring: added types, dependency injection, new tests, documentation, fixed code style etc. Issue [#413](https://github.com/php-censor/php-censor/issues/#413). Pull requests [#412](https://github.com/php-censor/php-censor/pull/412), [#424](https://github.com/php-censor/php-censor/pull/424) and [#425](https://github.com/php-censor/php-censor/pull/425). Thanks to [@KieranFYI](https://github.com/KieranFYI) and [@Ooypunk](https://github.com/Ooypunk). +- Integrated `symfony/http-foundation` library as a new HTTP part of project. +- Integrate some features from `php-censor/common` library. +- Improved UI: fixed colors and ratio for `Chart.js` charts, added ability to disable AJAX UI reloading (option `php-censor.realtime_ui`), improved error trends view. Pull request [#426](https://github.com/php-censor/php-censor/pull/426). Thanks to [@KieranFYI](https://github.com/KieranFYI). +- Improved Ukrainian localization. Pull request [#419](https://github.com/php-censor/php-censor/pull/419). Thanks to [@oshka](https://github.com/oshka). + +### Fixed + +- Install command return code. +- **[PHPUnit]** Xdebug settings for coverage option. Pull request [#427](https://github.com/php-censor/php-censor/pull/427). Thanks to [@KieranFYI](https://github.com/KieranFYI). + +## Other versions + +- [0.x Changelog](/docs/en/changelogs/CHANGELOG_0.x.mdANGELOG_0.x.md) +- [1.0 Changelog](/docs/en/changelogs/CHANGELOG_1.0.mdANGELOG_1.0.md) +- [1.1 Changelog](/docs/en/changelogs/CHANGELOG_1.1.mdANGELOG_1.1.md) +- [1.2 Changelog](/docs/en/changelogs/CHANGELOG_1.2.mdANGELOG_1.2.md) +- [1.3 Changelog](/docs/en/changelogs/CHANGELOG_1.3.mdANGELOG_1.3.md) +- [2.0 Changelog](/docs/en/changelogs/CHANGELOG_2.0.mdANGELOG_2.0.md) diff --git a/docs/en/configuring_project.md b/docs/en/configuring_project.md index 2a291d0ea..6760b8ff5 100644 --- a/docs/en/configuring_project.md +++ b/docs/en/configuring_project.md @@ -156,6 +156,8 @@ branch-dev: Section `build_settings` contents common build settings: +* Option `php` set php executable path (For example: `php: php7.4` or `php: /usr/local/bin/php`. Default value: `php: php`). + * Option `verbose` enable/disable verbosity of plugins output (Default value: `verbose: true`). * Option `clone_depth: N` allows cloning repository with partial history (Git clone option `--depth=N`). Option diff --git a/docs/en/releases.md b/docs/en/releases.md new file mode 100644 index 000000000..c154d9ce9 --- /dev/null +++ b/docs/en/releases.md @@ -0,0 +1,14 @@ +Releases +======== + +PHP Censor release versions: + +| Version | Latest | Branch | Status | Minimal PHP Version | +|:--------------------:|:--------:|:-------------:|:-------------------------------------------------------------:|:-------------------:| +| `1.0` (Morty Smith) | `1.0.16` | `release-1.0` | Old version (**UNSUPPORTED**) | `>=5.6, <8.0` | +| `1.1` (Birdperson) | `1.1.6` | `release-1.1` | Old version (**UNSUPPORTED**) | `>=5.6, <8.0` | +| `1.2` (Summer Smith) | `1.2.4` | `release-1.2` | Old version (**UNSUPPORTED**) | `>=5.6, <8.0` | +| `1.3` (Jerry Smith) | `1.3.7` | `release-1.3` | Old version (**UNSUPPORTED**) | `>=5.6, <8.0` | +| `2.0` (Rick Sanchez) | `2.0.14` | `release-2.0` | Old version ([Upgrade from v1 to v2](docs/en/upgrades/UPGRADE_2.0.md)) (**UNSUPPORTED**) | `>=7.4` | +| `2.1` (Mr. Meeseeks) | `2.1.6` | `release-2.1` | Last stable version | `>=7.4` | +| `3.0` | `3.0.0` | `master` | Current stable version | `>=8.1` | diff --git a/docs/UPGRADE_2.0.md b/docs/en/upgrades/UPGRADE_2.0.md similarity index 84% rename from docs/UPGRADE_2.0.md rename to docs/en/upgrades/UPGRADE_2.0.md index 71145c55d..f15d982a1 100644 --- a/docs/UPGRADE_2.0.md +++ b/docs/en/upgrades/UPGRADE_2.0.md @@ -4,11 +4,11 @@ Upgrade from v1 to v2 1. [Upgrade your PHP Censor installation to latest v1 release](https://github.com/php-censor/php-censor/blob/release-1.3/README.md#updating) (`1.3.*`). 2. If you use [cronjob worker](https://github.com/php-censor/php-censor/blob/release-1.3/docs/en/workers/cron.md), you -should migrate to [daemon worker](en/workers/worker.md). +should migrate to [daemon worker](../workers/worker.md). 3. Fix all deprecations from v1 on your installation: * You should rename `phpci.yml` or `.phpci.yml` project configs to `.php-censor.yml`. * You should rename `PHPCI_*` variables to `PHP_CENSOR_*`. * You should rename `b8.database` section of application config to `php-censor.database`. * Etc... ([See v2.0.0 changelog](https://github.com/php-censor/php-censor/releases/tag/2.0.0)). -4. [Upgrade your PHP Censor installation to v2](../README.md#updating) (`2.0.0`). +4. [Upgrade your PHP Censor installation to v2](../../../README.md#updating) (`2.0.0`). 5. (Optional) You may remove manually DB table `migration` (In v2 uses new table `migrations`). diff --git a/docs/en/upgrades/UPGRADE_3.0.md b/docs/en/upgrades/UPGRADE_3.0.md new file mode 100644 index 000000000..93f70dce1 --- /dev/null +++ b/docs/en/upgrades/UPGRADE_3.0.md @@ -0,0 +1,6 @@ +Upgrade from v2 to v3 +===================== + +1. [Upgrade your PHP Censor installation to latest v2 release](https://github.com/php-censor/php-censor/blob/release-2.1/README.md#updating) +(`2.1.*`). +2. [Upgrade your PHP Censor installation to v3](../../../README.md#updating) (`3.0.0`). diff --git a/rector.php b/rector.php index a5d4ab021..58e5ca886 100644 --- a/rector.php +++ b/rector.php @@ -15,9 +15,9 @@ $rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class); $rectorConfig->sets([ - SetList::PHP_74, + SetList::PHP_81, + SetList::DEAD_CODE, //SetList::CODE_QUALITY, //SetList::TYPE_DECLARATION_STRICT, - //SetList::DEAD_CODE, ]); }; diff --git a/src/Application.php b/src/Application.php index a02659c55..5dfcef991 100644 --- a/src/Application.php +++ b/src/Application.php @@ -29,27 +29,14 @@ class Application private Controller $controller; - private Request $request; - - private Session $session; - - private ConfigurationInterface $configuration; - - private StoreRegistry $storeRegistry; - - private Router $router; + private readonly Router $router; public function __construct( - ConfigurationInterface $configuration, - StoreRegistry $storeRegistry, - Request $request, - Session $session + private readonly ConfigurationInterface $configuration, + private readonly StoreRegistry $storeRegistry, + private readonly Request $request, + private readonly Session $session ) { - $this->configuration = $configuration; - $this->storeRegistry = $storeRegistry; - $this->request = $request; - $this->session = $session; - $this->router = new Router($this, $this->request); $this->init(); @@ -80,7 +67,7 @@ public function init(): void return false; }; - $skipAuth = [$this, 'shouldSkipAuth']; + $skipAuth = $this->shouldSkipAuth(...); // Handler for the route we're about to register, checks for a valid session where necessary: $routeHandler = function ($route, Response &$response) use (&$request, $validateSession, $skipAuth, $session) { diff --git a/src/ArrayConfiguration.php b/src/ArrayConfiguration.php index 78b77d223..c0c6d56d6 100644 --- a/src/ArrayConfiguration.php +++ b/src/ArrayConfiguration.php @@ -17,6 +17,5 @@ class ArrayConfiguration extends ParameterBag implements ConfigurationInterface { public function load(): void { - return; } } diff --git a/src/BuildFactory.php b/src/BuildFactory.php index c79bcdd57..6d101ad34 100644 --- a/src/BuildFactory.php +++ b/src/BuildFactory.php @@ -19,16 +19,10 @@ */ class BuildFactory { - private ConfigurationInterface $configuration; - - private StoreRegistry $storeRegistry; - public function __construct( - ConfigurationInterface $configuration, - StoreRegistry $storeRegistry + private readonly ConfigurationInterface $configuration, + private readonly StoreRegistry $storeRegistry ) { - $this->configuration = $configuration; - $this->storeRegistry = $storeRegistry; } /** diff --git a/src/Builder.php b/src/Builder.php index 075b78095..9554fecd3 100644 --- a/src/Builder.php +++ b/src/Builder.php @@ -31,6 +31,10 @@ */ class Builder { + final public const PHP_CLI_TAG = '%PHP%'; + + protected string $phpExecutable = 'php'; + public string $buildPath = ''; /** @@ -48,8 +52,6 @@ class Builder protected bool $verbose = true; - protected Build $build; - protected LoggerInterface $logger; protected array $config = []; @@ -62,30 +64,15 @@ class Builder protected CommandExecutorInterface $commandExecutor; - protected BuildLogger $buildLogger; - protected BuildErrorWriter $buildErrorWriter; - protected ConfigurationInterface $configuration; - - protected DatabaseManager $databaseManager; - - protected StoreRegistry $storeRegistry; - public function __construct( - ConfigurationInterface $configuration, - DatabaseManager $databaseManager, - StoreRegistry $storeRegistry, - Build $build, - BuildLogger $buildLogger + protected ConfigurationInterface $configuration, + protected DatabaseManager $databaseManager, + protected StoreRegistry $storeRegistry, + protected Build $build, + protected BuildLogger $buildLogger ) { - $this->configuration = $configuration; - $this->databaseManager = $databaseManager; - $this->storeRegistry = $storeRegistry; - $this->buildLogger = $buildLogger; - - $this->build = $build; - /** @var BuildStore $buildStore */ $buildStore = $this->storeRegistry->get('Build'); /** @var SecretStore $secretStore */ @@ -144,6 +131,11 @@ public function setConfig(array $config): void $this->config = $config; } + public function setPhpExecutable(string $phpExecutable): void + { + $this->phpExecutable = $phpExecutable; + } + /** * Access a variable from the .php-censor.yml file. * @@ -289,7 +281,7 @@ protected function setTestCoverageTrend(): void ); if (!empty($trend[0]) && !empty($trend[0]['coverage'])) { - $coverage = \json_decode($trend[0]['coverage'], true); + $coverage = \json_decode((string) $trend[0]['coverage'], true); if (isset($coverage['lines'])) { $this->build->setTestCoveragePrevious($coverage['lines']); } @@ -303,6 +295,10 @@ protected function setTestCoverageTrend(): void */ public function executeCommand(...$params): bool { + if (!empty($params[0])) { + $params[0] = \str_replace(self::PHP_CLI_TAG, $this->phpExecutable, (string) $params[0]); + } + return $this->commandExecutor->executeCommand($params); } @@ -325,12 +321,11 @@ public function logExecOutput(bool $enableLog = true): void /** * Find a binary required by a plugin. * - * @param array|string $binary * * @throws Exception when no binary has been found. */ public function findBinary( - $binary, + array|string $binary, string $priorityPath = 'local', string $binaryPath = '', array $binaryName = [] @@ -368,7 +363,7 @@ protected function setupBuild(): bool \chdir($this->buildPath); - $version = (string)\trim(\file_get_contents(ROOT_DIR . 'VERSION.md')); + $version = \trim(\file_get_contents(ROOT_DIR . 'VERSION.md')); $version = !empty($version) ? $version : '0.0.0 (UNKNOWN)'; $this->interpolator->setupInterpolationVars( diff --git a/src/Command/Action/CreateAdmin.php b/src/Command/Action/CreateAdmin.php index 73ad63b47..2becd37fb 100644 --- a/src/Command/Action/CreateAdmin.php +++ b/src/Command/Action/CreateAdmin.php @@ -22,28 +22,13 @@ */ class CreateAdmin { - private QuestionHelper $questionHelper; - - private InputInterface $input; - - private OutputInterface $output; - - private StoreRegistry $storeRegistry; - - private UserStore $userStore; - public function __construct( - QuestionHelper $questionHelper, - InputInterface $input, - OutputInterface $output, - StoreRegistry $storeRegistry, - UserStore $userStore + private readonly QuestionHelper $questionHelper, + private readonly InputInterface $input, + private readonly OutputInterface $output, + private readonly StoreRegistry $storeRegistry, + private readonly UserStore $userStore ) { - $this->questionHelper = $questionHelper; - $this->input = $input; - $this->output = $output; - $this->userStore = $userStore; - $this->storeRegistry = $storeRegistry; } /** diff --git a/src/Command/AddSecretCommand.php b/src/Command/AddSecretCommand.php index 754b3fa7c..03eafaa61 100644 --- a/src/Command/AddSecretCommand.php +++ b/src/Command/AddSecretCommand.php @@ -23,19 +23,15 @@ */ class AddSecretCommand extends Command { - private SecretStore $secretStore; - public function __construct( ConfigurationInterface $configuration, DatabaseManager $databaseManager, StoreRegistry $storeRegistry, LoggerInterface $logger, - SecretStore $secretStore, + private readonly SecretStore $secretStore, ?string $name = null ) { parent::__construct($configuration, $databaseManager, $storeRegistry, $logger, $name); - - $this->secretStore = $secretStore; } /** diff --git a/src/Command/CheckLocalizationsCommand.php b/src/Command/CheckLocalizationsCommand.php index e655fa2e3..877ddc701 100644 --- a/src/Command/CheckLocalizationsCommand.php +++ b/src/Command/CheckLocalizationsCommand.php @@ -38,7 +38,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $sameThanEnglish = (bool)$input->getOption('same'); $languages = $input->getOption('languages') - ? \explode(',', $input->getOption('languages')) + ? \explode(',', (string) $input->getOption('languages')) : []; // Get English version diff --git a/src/Command/Command.php b/src/Command/Command.php index a45558853..b43be74c1 100644 --- a/src/Command/Command.php +++ b/src/Command/Command.php @@ -24,27 +24,14 @@ */ abstract class Command extends BaseCommand { - protected ConfigurationInterface $configuration; - - protected DatabaseManager $databaseManager; - - protected StoreRegistry $storeRegistry; - - protected LoggerInterface $logger; - public function __construct( - ConfigurationInterface $configuration, - DatabaseManager $databaseManager, - StoreRegistry $storeRegistry, - LoggerInterface $logger, + protected ConfigurationInterface $configuration, + protected DatabaseManager $databaseManager, + protected StoreRegistry $storeRegistry, + protected LoggerInterface $logger, ?string $name = null ) { parent::__construct($name); - - $this->configuration = $configuration; - $this->databaseManager = $databaseManager; - $this->storeRegistry = $storeRegistry; - $this->logger = $logger; } protected function configureLogging(OutputInterface $output): void diff --git a/src/Command/CreateAdminCommand.php b/src/Command/CreateAdminCommand.php index 78ba1067f..fdcbfe7ce 100644 --- a/src/Command/CreateAdminCommand.php +++ b/src/Command/CreateAdminCommand.php @@ -25,19 +25,15 @@ */ class CreateAdminCommand extends Command { - protected UserStore $userStore; - public function __construct( ConfigurationInterface $configuration, DatabaseManager $databaseManager, StoreRegistry $storeRegistry, LoggerInterface $logger, - UserStore $userStore, + protected UserStore $userStore, ?string $name = null ) { parent::__construct($configuration, $databaseManager, $storeRegistry, $logger, $name); - - $this->userStore = $userStore; } protected function configure(): void diff --git a/src/Command/CreateBuildCommand.php b/src/Command/CreateBuildCommand.php index b7422cf00..5bf624137 100644 --- a/src/Command/CreateBuildCommand.php +++ b/src/Command/CreateBuildCommand.php @@ -30,23 +30,16 @@ */ class CreateBuildCommand extends Command { - protected ProjectStore $projectStore; - - protected BuildService $buildService; - public function __construct( ConfigurationInterface $configuration, DatabaseManager $databaseManager, StoreRegistry $storeRegistry, LoggerInterface $logger, - ProjectStore $projectStore, - BuildService $buildService, + protected ProjectStore $projectStore, + protected BuildService $buildService, ?string $name = null ) { parent::__construct($configuration, $databaseManager, $storeRegistry, $logger, $name); - - $this->projectStore = $projectStore; - $this->buildService = $buildService; } protected function configure(): void diff --git a/src/Command/InstallCommand.php b/src/Command/InstallCommand.php index f6bc9b360..2425a4053 100644 --- a/src/Command/InstallCommand.php +++ b/src/Command/InstallCommand.php @@ -177,9 +177,9 @@ private function checkRequirements(OutputInterface $output): void $output->writeln('Checking requirements...'); $errors = false; - if (!(\version_compare(PHP_VERSION, '7.4.0') >= 0)) { + if (!(\version_compare(PHP_VERSION, '8.1.0') >= 0)) { $output->writeln(''); - $output->writeln('PHP Censor requires at least PHP 7.4.0! Installed PHP ' . PHP_VERSION . ''); + $output->writeln('PHP Censor requires at least PHP 8.1! Installed PHP ' . PHP_VERSION . ''); $errors = true; } @@ -374,7 +374,7 @@ private function getDatabaseInformation(InputInterface $input, OutputInterface $ if (!$dbType = $input->getOption('db-type')) { $questionType = new Question('Enter your database type ("mysql" or "pgsql"): '); - $dbType = \trim(\strtolower($helper->ask($input, $output, $questionType))); + $dbType = \trim(\strtolower((string) $helper->ask($input, $output, $questionType))); } if (!$dbHost = $input->getOption('db-host')) { @@ -382,7 +382,7 @@ private function getDatabaseInformation(InputInterface $input, OutputInterface $ 'Enter your database host (default: "localhost"): ', 'localhost' ); - $dbHost = \trim($helper->ask($input, $output, $questionHost)); + $dbHost = \trim((string) $helper->ask($input, $output, $questionHost)); } $defaultPort = 3306; @@ -417,7 +417,7 @@ private function getDatabaseInformation(InputInterface $input, OutputInterface $ 'Enter your database name (default: "php-censor-db"): ', 'php-censor-db' ); - $dbName = \trim($helper->ask($input, $output, $questionDb)); + $dbName = \trim((string) $helper->ask($input, $output, $questionDb)); } if (!$dbUser = $input->getOption('db-user')) { @@ -425,7 +425,7 @@ private function getDatabaseInformation(InputInterface $input, OutputInterface $ 'Enter your database user (default: "php-censor-user"): ', 'php-censor-user' ); - $dbUser = \trim($helper->ask($input, $output, $questionUser)); + $dbUser = \trim((string) $helper->ask($input, $output, $questionUser)); } if (!$dbPass = $input->getOption('db-password')) { diff --git a/src/Command/RemoveOldBuildsCommand.php b/src/Command/RemoveOldBuildsCommand.php index 512828a4d..57c997197 100644 --- a/src/Command/RemoveOldBuildsCommand.php +++ b/src/Command/RemoveOldBuildsCommand.php @@ -23,23 +23,16 @@ */ class RemoveOldBuildsCommand extends Command { - protected ProjectStore $projectStore; - - protected BuildService $buildService; - public function __construct( ConfigurationInterface $configuration, DatabaseManager $databaseManager, StoreRegistry $storeRegistry, LoggerInterface $logger, - ProjectStore $projectStore, - BuildService $buildService, + protected ProjectStore $projectStore, + protected BuildService $buildService, ?string $name = null ) { parent::__construct($configuration, $databaseManager, $storeRegistry, $logger, $name); - - $this->projectStore = $projectStore; - $this->buildService = $buildService; } /** diff --git a/src/Command/WorkerCommand.php b/src/Command/WorkerCommand.php index 7d70be3b0..2c58abc88 100644 --- a/src/Command/WorkerCommand.php +++ b/src/Command/WorkerCommand.php @@ -31,23 +31,16 @@ class WorkerCommand extends Command private const MIN_QUEUE_PRIORITY = 24; private const MAX_QUEUE_PRIORITY = 2025; - protected BuildService $buildService; - - protected BuildFactory $buildFactory; - public function __construct( ConfigurationInterface $configuration, DatabaseManager $databaseManager, StoreRegistry $storeRegistry, LoggerInterface $logger, - BuildService $buildService, - BuildFactory $buildFactory, + protected BuildService $buildService, + protected BuildFactory $buildFactory, ?string $name = null ) { parent::__construct($configuration, $databaseManager, $storeRegistry, $logger, $name); - - $this->buildService = $buildService; - $this->buildFactory = $buildFactory; } protected function configure(): void diff --git a/src/Configuration.php b/src/Configuration.php index a8712cefb..81ae28398 100644 --- a/src/Configuration.php +++ b/src/Configuration.php @@ -16,14 +16,10 @@ */ class Configuration extends ParameterBag implements ConfigurationInterface { - private string $configurationPath; - - public function __construct(string $configurationPath) + public function __construct(private readonly string $configurationPath) { parent::__construct([]); - $this->configurationPath = $configurationPath; - $this->load(); } diff --git a/src/Console/Application.php b/src/Console/Application.php index d4d6098a8..5db8bd6fb 100644 --- a/src/Console/Application.php +++ b/src/Console/Application.php @@ -54,12 +54,6 @@ class Application extends BaseApplication LOGO; - private ConfigurationInterface $configuration; - - private DatabaseManager $databaseManager; - - private StoreRegistry $storeRegistry; - /** * @throws Exception */ @@ -85,9 +79,9 @@ protected function initLogger(ConfigurationInterface $applicationConfig): Logger } public function __construct( - ConfigurationInterface $configuration, - DatabaseManager $databaseManager, - StoreRegistry $storeRegistry, + private readonly ConfigurationInterface $configuration, + private readonly DatabaseManager $databaseManager, + private readonly StoreRegistry $storeRegistry, string $name = 'PHP Censor', string $version = 'UNKNOWN' ) { @@ -96,10 +90,6 @@ public function __construct( parent::__construct($name, $version); - $this->configuration = $configuration; - $this->databaseManager = $databaseManager; - $this->storeRegistry = $storeRegistry; - $oldDatabaseSettings = $this->configuration->get('b8.database', []); $databaseSettings = $this->configuration->get('php-censor.database', []); if ($oldDatabaseSettings && !$databaseSettings) { diff --git a/src/Controller.php b/src/Controller.php index a3c7f783b..260bd5b0f 100644 --- a/src/Controller.php +++ b/src/Controller.php @@ -18,24 +18,12 @@ */ abstract class Controller { - protected Request $request; - - protected Session $session; - - protected ConfigurationInterface $configuration; - - protected StoreRegistry $storeRegistry; - public function __construct( - ConfigurationInterface $configuration, - StoreRegistry $storeRegistry, - Request $request, - Session $session + protected ConfigurationInterface $configuration, + protected StoreRegistry $storeRegistry, + protected Request $request, + protected Session $session ) { - $this->configuration = $configuration; - $this->storeRegistry = $storeRegistry; - $this->request = $request; - $this->session = $session; } /** @@ -54,12 +42,15 @@ public function hasAction(string $name): bool /** * Handles an action on this controller and returns a Response object. - * - * @return Response|string */ - public function handleAction(string $action, array $actionParams) + public function handleAction(string $action, array $actionParams): Response|string { - return \call_user_func_array([$this, $action], $actionParams); + $result = \call_user_func_array([$this, $action], $actionParams); + if (!$result) { + $result = ''; + } + + return $result; } /** @@ -69,7 +60,7 @@ public function handleAction(string $action, array $actionParams) * * @return mixed */ - public function getParam(string $key, $default = null) + public function getParam(string $key, mixed $default = null) { return $this->request->get($key, $default); } diff --git a/src/Controller/BuildController.php b/src/Controller/BuildController.php index ebc0ca394..869da7fc3 100644 --- a/src/Controller/BuildController.php +++ b/src/Controller/BuildController.php @@ -107,11 +107,11 @@ public function view(int $buildId): void $this->view->data = $data; $this->view->environment = $this->storeRegistry->get('Environment')->getById((int)$build->getEnvironmentId()); - $this->view->plugin = \urldecode($plugin); + $this->view->plugin = \urldecode((string) $plugin); $this->view->plugins = $errorStore->getKnownPlugins($buildId, $severity, $isNew); $this->view->severity = \urldecode(null !== $severity ? (string)$severity : ''); $this->view->severities = $errorStore->getKnownSeverities($buildId, $plugin, $isNew); - $this->view->isNew = \urldecode($isNew); + $this->view->isNew = \urldecode((string) $isNew); $this->view->isNews = ['only_new', 'only_old']; $this->view->page = $page; @@ -186,7 +186,7 @@ protected function getUiPlugins(): array $dir = \opendir($path); while ($item = \readdir($dir)) { - if (\substr($item, 0, 1) === '.' || \substr($item, -3) !== '.js') { + if (\str_starts_with($item, '.') || !\str_ends_with($item, '.js')) { continue; } @@ -274,9 +274,7 @@ protected function getPaginatorHtml( '(:num)', \http_build_query(\array_merge($params, ['page' => '(:num)'])) ) . '#errors'; - $paginator = new Paginator($total, $perPage, $page, $urlPattern); - - $view->paginator = $paginator; + $view->paginator = new Paginator($total, $perPage, $page, $urlPattern); return $view->render(); } diff --git a/src/Controller/BuildStatusController.php b/src/Controller/BuildStatusController.php index 0ccf5d6cc..250920a2d 100644 --- a/src/Controller/BuildStatusController.php +++ b/src/Controller/BuildStatusController.php @@ -64,7 +64,7 @@ protected function getStatus(Project $project, string $branch): string if (isset($build) && $build instanceof Build && $build->getStatus() !== Build::STATUS_SUCCESS) { $status = 'failed'; } - } catch (\Throwable $e) { + } catch (\Throwable) { $status = 'error'; } @@ -101,7 +101,7 @@ protected function getPhpunitCoverage(Project $project, string $branch, string $ $coverage = $coverageMeta[0]['meta_value'][$type]; } } - } catch (\Throwable $e) { + } catch (\Throwable) { } return $coverage; @@ -313,7 +313,7 @@ public function ccxml(int $projectId): Response } } } - } catch (\Throwable $e) { + } catch (\Throwable) { $xml = new SimpleXMLElement(''); } diff --git a/src/Controller/GroupController.php b/src/Controller/GroupController.php index ffa5ea5d6..a5237ee13 100644 --- a/src/Controller/GroupController.php +++ b/src/Controller/GroupController.php @@ -93,9 +93,7 @@ public function edit(?int $groupId = null) $this->groupStore->save($group); - $response = new RedirectResponse(APP_URL . 'group'); - - return $response; + return new RedirectResponse(APP_URL . 'group'); } $form = new Form(); diff --git a/src/Controller/ProjectController.php b/src/Controller/ProjectController.php index ff2342e3e..3a23c9f9f 100644 --- a/src/Controller/ProjectController.php +++ b/src/Controller/ProjectController.php @@ -126,9 +126,9 @@ public function view(int $projectId): string $this->view->builds = $builds[0]; $this->view->total = $builds[1]; $this->view->project = $project; - $this->view->branch = \urldecode($branch); + $this->view->branch = \urldecode((string) $branch); $this->view->branches = $this->projectStore->getKnownBranches($projectId); - $this->view->environment = \urldecode($environment); + $this->view->environment = \urldecode((string) $environment); $this->view->environments = $project->getEnvironmentsNames(); $this->view->page = $page; $this->view->perPage = $perPage; @@ -179,9 +179,7 @@ protected function getPaginatorHtml( '(:num)', \http_build_query(\array_merge($params, ['page' => '(:num)'])) ); - $paginator = new Paginator($total, $perPage, $page, $urlPattern); - - $view->paginator = $paginator; + $view->paginator = new Paginator($total, $perPage, $page, $urlPattern); return $view->render(); } @@ -421,8 +419,8 @@ public function add() $defaultBranch = $this->getParam('default_branch', null); $options = [ - 'ssh_private_key' => \str_replace("\r", "", $this->getParam('ssh_private_key', null)), - 'ssh_public_key' => \str_replace("\r", "", $this->getParam('ssh_public_key', null)), + 'ssh_private_key' => \str_replace("\r", "", (string) $this->getParam('ssh_private_key', null)), + 'ssh_public_key' => \str_replace("\r", "", (string) $this->getParam('ssh_public_key', null)), 'overwrite_build_config' => (bool)$this->getParam('overwrite_build_config', true), 'build_config' => $this->getParam('build_config', null), 'allow_public_status' => (bool)$this->getParam('allow_public_status', false), @@ -469,10 +467,10 @@ public function edit($projectId) $values['reference'] = $accessInfo['origin']; } elseif (isset($accessInfo['domain']) && $accessInfo['domain']) { $reference = $accessInfo['user'] . - '@' . $accessInfo['domain'] . ':' . \ltrim($project->getReference(), '/') . '.git'; + '@' . $accessInfo['domain'] . ':' . \ltrim((string) $project->getReference(), '/') . '.git'; if (isset($accessInfo['port']) && $accessInfo['port']) { $reference = $accessInfo['user'] . '@' . $accessInfo['domain'] . ':' . $accessInfo['port'] . '/' . - \ltrim($project->getReference(), '/') . '.git'; + \ltrim((string) $project->getReference(), '/') . '.git'; } $values['reference'] = $reference; @@ -502,8 +500,8 @@ public function edit($projectId) $formValues = $form->getValues(); $options = [ - 'ssh_private_key' => \str_replace("\r", "", $this->getParam('ssh_private_key', null)), - 'ssh_public_key' => \str_replace("\r", "", $this->getParam('ssh_public_key', null)), + 'ssh_private_key' => \str_replace("\r", "", (string) $this->getParam('ssh_private_key', null)), + 'ssh_public_key' => \str_replace("\r", "", (string) $this->getParam('ssh_public_key', null)), 'overwrite_build_config' => (bool)$this->getParam('overwrite_build_config', false), 'build_config' => isset($formValues['build_config']) ? $formValues['build_config'] : null, 'allow_public_status' => (bool)$this->getParam('allow_public_status', false), diff --git a/src/Controller/SecretController.php b/src/Controller/SecretController.php index 3ed942c6d..c58e2bf75 100644 --- a/src/Controller/SecretController.php +++ b/src/Controller/SecretController.php @@ -84,9 +84,7 @@ public function edit(?int $secretId = null) $this->secretStore->save($secret); - $response = new RedirectResponse(APP_URL . 'secret'); - - return $response; + return new RedirectResponse(APP_URL . 'secret'); } $form = new Form(); diff --git a/src/Controller/SessionController.php b/src/Controller/SessionController.php index 29035b76e..54983f290 100644 --- a/src/Controller/SessionController.php +++ b/src/Controller/SessionController.php @@ -87,12 +87,11 @@ protected function loginForm(array $values): Form /** * Handles user login (form and processing) * - * @return Response|string * * @throws HttpException * @throws \PHPCensor\Common\Exception\InvalidArgumentException */ - public function login() + public function login(): Response|string { $rememberKey = $this->request->cookies->get('remember_key'); if (!empty($rememberKey)) { @@ -234,12 +233,11 @@ public function forgotPassword(): string /** * Allows the user to change their password after a password reset email. * - * @return Response|string * * @throws HttpException * @throws \PHPCensor\Common\Exception\InvalidArgumentException */ - public function resetPassword(int $userId, string $key) + public function resetPassword(int $userId, string $key): Response|string { $user = $this->userStore->getById($userId); $userKey = \md5(\date('Y-m-d') . $user->getHash()); @@ -251,7 +249,7 @@ public function resetPassword(int $userId, string $key) } if ($this->request->getMethod() === 'POST') { - $hash = \password_hash($this->getParam('password'), PASSWORD_DEFAULT); + $hash = \password_hash((string) $this->getParam('password'), PASSWORD_DEFAULT); $user->setHash($hash); $this->userStore->save($user); diff --git a/src/Controller/UserController.php b/src/Controller/UserController.php index a58279489..5a8e47902 100644 --- a/src/Controller/UserController.php +++ b/src/Controller/UserController.php @@ -164,11 +164,10 @@ public function profile(): string /** * Add a user - handles both form and processing. * - * @return Response|string * * @throws \PHPCensor\Exception\HttpException */ - public function add() + public function add(): Response|string { $this->requireAdmin(); @@ -214,14 +213,13 @@ public function add() /** * Edit a user - handles both form and processing. * - * @return Response|string * * @throws ForbiddenException * @throws NotFoundException * @throws \PHPCensor\Common\Exception\RuntimeException * @throws \PHPCensor\Exception\HttpException */ - public function edit(int $userId) + public function edit(int $userId): Response|string { $currentUser = $this->getUser(); diff --git a/src/Controller/WebhookController.php b/src/Controller/WebhookController.php index 0b710ff50..131f4e5dc 100644 --- a/src/Controller/WebhookController.php +++ b/src/Controller/WebhookController.php @@ -163,7 +163,7 @@ protected function createBuild( $tag, $committer, $commitMessage, - (int)$source, + $source, null, $extra ); @@ -211,7 +211,7 @@ protected function createBuild( // If not, create a new build job for it: $build = $this->buildService->createBuild( $project, - (int)$environmentId, + $environmentId, $commitId, $project->getDefaultBranch(), $tag, @@ -269,7 +269,7 @@ protected function createBuild( $tag, $committer, $commitMessage, - (int)$source, + $source, null, $extra ); @@ -324,7 +324,7 @@ protected function logWebhookRequest( $this->webhookRequestStore->save($webhookRequest); } - } catch (\Throwable $e) { + } catch (\Throwable) { } } @@ -473,7 +473,7 @@ public function bitbucket(int $projectId): array $payloadJson ); - return $this->bitbucketService(\json_decode($payloadJson, true), $project); + return $this->bitbucketService(\json_decode((string) $payloadJson, true), $project); } $payloadJson = \file_get_contents("php://input"); @@ -520,9 +520,9 @@ protected function bitbucketCommitRequest(Project $project, array $payload): arr if (!empty($commit['new'])) { try { $email = $commit['new']['target']['author']['raw']; - if (\strpos($email, '>') !== false) { + if (\str_contains((string) $email, '>')) { // In order not to lose email if it is RAW, w/o "<>" symbols - $email = \substr($email, 0, \strpos($email, '>')); + $email = \substr((string) $email, 0, \strpos((string) $email, '>')); $email = \substr($email, \strpos($email, '<') + 1); } @@ -552,7 +552,7 @@ protected function bitbucketCommitRequest(Project $project, array $payload): arr */ protected function bitbucketPullRequest(Project $project, array $payload): array { - $triggerType = \trim($_SERVER['HTTP_X_EVENT_KEY']); + $triggerType = \trim((string) $_SERVER['HTTP_X_EVENT_KEY']); if (!\array_key_exists( $triggerType, @@ -577,7 +577,7 @@ protected function bitbucketPullRequest(Project $project, array $payload): array $commitsResponse = $client->get($commitsUrl, [ 'auth' => [$username, $appPassword], ]); - $httpStatus = (int)$commitsResponse->getStatusCode(); + $httpStatus = $commitsResponse->getStatusCode(); // Check we got a success response: if ($httpStatus < 200 || $httpStatus >= 300) { @@ -590,7 +590,7 @@ protected function bitbucketPullRequest(Project $project, array $payload): array foreach ($commits as $commit) { // Skip all but the current HEAD commit ID: $id = $commit['hash']; - if (\strpos($id, $payload['pullrequest']['source']['commit']['hash']) !== 0) { + if (!\str_starts_with((string) $id, (string) $payload['pullrequest']['source']['commit']['hash'])) { $results[$id] = ['status' => 'ignored', 'message' => 'not branch head']; continue; @@ -599,9 +599,9 @@ protected function bitbucketPullRequest(Project $project, array $payload): array try { $branch = $payload['pullrequest']['destination']['branch']['name']; $committer = $commit['author']['raw']; - if (\strpos($committer, '>') !== false) { + if (\str_contains((string) $committer, '>')) { // In order not to lose email if it is RAW, w/o "<>" symbols - $committer = \substr($committer, 0, \strpos($committer, '>')); + $committer = \substr((string) $committer, 0, \strpos((string) $committer, '>')); $committer = \substr($committer, \strpos($committer, '<') + 1); } $message = $commit['message']; @@ -638,7 +638,7 @@ protected function bitbucketPullRequest(Project $project, array $payload): array */ protected function bitbucketSvrPullRequest(Project $project, array $payload): array { - $triggerType = \trim($_SERVER['HTTP_X_EVENT_KEY']); + $triggerType = \trim((string) $_SERVER['HTTP_X_EVENT_KEY']); if (!\array_key_exists( $triggerType, @@ -692,7 +692,7 @@ protected function bitbucketService(array $payload, Project $project): array foreach ($payload['commits'] as $commit) { try { $email = $commit['raw_author']; - $email = \substr($email, 0, \strpos($email, '>')); + $email = \substr((string) $email, 0, \strpos((string) $email, '>')); $email = \substr($email, \strpos($email, '<') + 1); $results[$commit['raw_node']] = $this->createBuild( @@ -748,7 +748,7 @@ public function github(int $projectId): array ); } - $payload = \json_decode($payloadJson, true); + $payload = \json_decode((string) $payloadJson, true); // Handle Pull Request webhooks: if (\array_key_exists('pull_request', $payload)) { @@ -775,7 +775,7 @@ protected function githubCommitRequest(Project $project, array $payload): array } if (isset($payload['head_commit']) && $payload['head_commit']) { - $isTag = (\substr($payload['ref'], 0, 10) === 'refs/tags/') ? true : false; + $isTag = (\str_starts_with((string) $payload['ref'], 'refs/tags/')) ? true : false; $commit = $payload['head_commit']; $results = []; $status = 'failed'; @@ -786,11 +786,11 @@ protected function githubCommitRequest(Project $project, array $payload): array try { $tag = null; if ($isTag) { - $tag = \str_replace('refs/tags/', '', $payload['ref']); - $branch = \str_replace('refs/heads/', '', $payload['base_ref']); + $tag = \str_replace('refs/tags/', '', (string) $payload['ref']); + $branch = \str_replace('refs/heads/', '', (string) $payload['base_ref']); $committer = $payload['pusher']['email']; } else { - $branch = \str_replace('refs/heads/', '', $payload['ref']); + $branch = \str_replace('refs/heads/', '', (string) $payload['ref']); $committer = $commit['committer']['email']; } @@ -823,7 +823,7 @@ protected function githubCommitRequest(Project $project, array $payload): array */ protected function githubPullRequest(Project $project, array $payload): array { - $triggerType = \trim($payload['action']); + $triggerType = \trim((string) $payload['action']); if (!\array_key_exists( $triggerType, @@ -876,7 +876,7 @@ protected function githubPullRequest(Project $project, array $payload): array } try { - $branch = \str_replace('refs/heads/', '', $payload['pull_request']['base']['ref']); + $branch = \str_replace('refs/heads/', '', (string) $payload['pull_request']['base']['ref']); $committer = $commit['commit']['author']['email']; $message = $commit['commit']['message']; @@ -958,7 +958,7 @@ public function gitlab(int $projectId): array $commit = \end($payload['commits']); try { - $branch = \str_replace('refs/heads/', '', $payload['ref']); + $branch = \str_replace('refs/heads/', '', (string) $payload['ref']); $committer = $commit['author']['email']; $results[$commit['id']] = $this->createBuild( Build::SOURCE_WEBHOOK_PUSH, @@ -981,8 +981,6 @@ public function gitlab(int $projectId): array } /** - * @param string $projectId - * * @throws Exception */ public function gogs(int $projectId): array @@ -996,15 +994,10 @@ public function gogs(int $projectId): array ? $_SERVER['CONTENT_TYPE'] : null; - switch ($contentType) { - case 'application/x-www-form-urlencoded': - $payloadJson = $this->getParam('payload'); - - break; - case 'application/json': - default: - $payloadJson = \file_get_contents('php://input'); - } + $payloadJson = match ($contentType) { + 'application/x-www-form-urlencoded' => $this->getParam('payload'), + default => \file_get_contents('php://input'), + }; if ($payloadJson) { $this->logWebhookRequest( @@ -1014,7 +1007,7 @@ public function gogs(int $projectId): array ); } - $payload = \json_decode($payloadJson, true); + $payload = \json_decode((string) $payloadJson, true); // Handle Push web hooks: if (\array_key_exists('commits', $payload)) { @@ -1039,7 +1032,7 @@ protected function gogsCommitRequest(Project $project, array $payload): array $status = 'failed'; foreach ($payload['commits'] as $commit) { try { - $branch = \str_replace('refs/heads/', '', $payload['ref']); + $branch = \str_replace('refs/heads/', '', (string) $payload['ref']); $committer = $commit['author']['email']; $results[$commit['id']] = $this->createBuild( Build::SOURCE_WEBHOOK_PUSH, @@ -1093,8 +1086,8 @@ protected function gogsPullRequest(Project $project, array $payload): array if (\in_array($action, $activeActions, true) && \in_array($state, $activeStates, true)) { if (isset($pullRequest['labels']) && \is_array($pullRequest['labels'])) { foreach ($pullRequest['labels'] as $label) { - if (\strpos($label['name'], 'env:') === 0) { - $envs[] = \substr($label['name'], 4); + if (\str_starts_with((string) $label['name'], 'env:')) { + $envs[] = \substr((string) $label['name'], 4); } } } diff --git a/src/DatabaseConnection.php b/src/DatabaseConnection.php index 4ae6fd821..b282d6947 100644 --- a/src/DatabaseConnection.php +++ b/src/DatabaseConnection.php @@ -14,29 +14,13 @@ class DatabaseConnection { private ?\PDO $pdoConnection = null; - private string $dsn; - - private ?string $username; - - private ?string $password; - - private ?array $options; - - private string $sequencePattern; - public function __construct( - string $dsn, - ?string $username = null, - ?string $password = null, - ?array $options = null, - string $sequencePattern = '%s_id_seq' + private readonly string $dsn, + private readonly ?string $username = null, + private readonly ?string $password = null, + private readonly ?array $options = null, + private readonly string $sequencePattern = '%s_id_seq' ) { - $this->sequencePattern = $sequencePattern; - - $this->dsn = $dsn; - $this->username = $username; - $this->password = $password; - $this->options = $options; } public function getPdo(): \PDO @@ -77,26 +61,17 @@ public function lastInsertId(string $tableName): int return (int)$this->getPdo()->lastInsertId(); } - /** - * @return false|\PDOStatement - */ - public function prepare(string $query, array $options = []) + public function prepare(string $query, array $options = []): false|\PDOStatement { return $this->getPdo()->prepare($this->quoteNames($query), $options); } - /** - * @return false|int - */ - public function exec(string $statement) + public function exec(string $statement): false|int { return $this->getPdo()->exec($this->quoteNames($statement)); } - /** - * @return false|\PDOStatement - */ - public function query(string $statement) + public function query(string $statement): false|\PDOStatement { return $this->getPdo()->query($this->quoteNames($statement)); } diff --git a/src/DatabaseManager.php b/src/DatabaseManager.php index 5a74b770a..f553418ac 100644 --- a/src/DatabaseManager.php +++ b/src/DatabaseManager.php @@ -16,19 +16,16 @@ */ class DatabaseManager { - public const MYSQL_TYPE = 'mysql'; - public const POSTGRESQL_TYPE = 'pgsql'; - - private ConfigurationInterface $configuration; + final public const MYSQL_TYPE = 'mysql'; + final public const POSTGRESQL_TYPE = 'pgsql'; private array $connections = [ 'read' => null, 'write' => null ]; - public function __construct(ConfigurationInterface $configuration) + public function __construct(private readonly ConfigurationInterface $configuration) { - $this->configuration = $configuration; } /** @@ -77,7 +74,7 @@ public function getConnection(string $type = 'read'): DatabaseConnection $this->configuration->get('php-censor.database.password', ''), $pdoOptions ); - } catch (\PDOException $ex) { + } catch (\PDOException) { $connection = false; } diff --git a/src/Form.php b/src/Form.php index 2e06e03b8..fc0e19a05 100644 --- a/src/Form.php +++ b/src/Form.php @@ -13,7 +13,7 @@ * @author Dan Cryer * @author Dmitry Khomutov */ -class Form extends FieldSet +class Form extends FieldSet implements \Stringable { protected string $action = ''; diff --git a/src/Form/Element/Checkbox.php b/src/Form/Element/Checkbox.php index f6b432029..93c41868c 100644 --- a/src/Form/Element/Checkbox.php +++ b/src/Form/Element/Checkbox.php @@ -31,10 +31,7 @@ public function getCheckedValue() return $this->checkedValue; } - /** - * @param mixed $value - */ - public function setCheckedValue($value): self + public function setCheckedValue(mixed $value): self { $this->checkedValue = $value; diff --git a/src/Form/Element/Csrf.php b/src/Form/Element/Csrf.php index 8e02e1c11..56b2f8411 100644 --- a/src/Form/Element/Csrf.php +++ b/src/Form/Element/Csrf.php @@ -16,13 +16,11 @@ */ class Csrf extends Hidden { - private Session $session; - - public function __construct(Session $session, ?string $name = null) - { + public function __construct( + private readonly Session $session, + ?string $name = null + ) { parent::__construct($name); - - $this->session = $session; } public function validate(): bool diff --git a/src/Form/Input.php b/src/Form/Input.php index 1cd182217..49a83bb35 100644 --- a/src/Form/Input.php +++ b/src/Form/Input.php @@ -5,7 +5,6 @@ namespace PHPCensor\Form; use Closure; -use Exception; use PHPCensor\Form\DataTransformer\DataTransformerInterface; use PHPCensor\View; @@ -136,8 +135,7 @@ public function validate(): bool } $validator = $this->getValidator(); - - if (\is_callable($validator)) { + if ($validator) { try { \call_user_func_array($validator, [$this->getValue()]); } catch (\Throwable $ex) { diff --git a/src/Helper/Bitbucket.php b/src/Helper/Bitbucket.php index 2f8467ed6..82fcd28bb 100644 --- a/src/Helper/Bitbucket.php +++ b/src/Helper/Bitbucket.php @@ -16,11 +16,8 @@ */ class Bitbucket { - private ConfigurationInterface $configuration; - - public function __construct(ConfigurationInterface $configuration) + public function __construct(private readonly ConfigurationInterface $configuration) { - $this->configuration = $configuration; } /** @@ -137,8 +134,7 @@ public function getFileLinkTemplate(Build $build): string $link .= 'src/' . $build->getCommitId() . '/'; $link .= '{FILE}'; - $link .= '#{BASEFILE}-{LINE}'; - return $link; + return $link . '#{BASEFILE}-{LINE}'; } } diff --git a/src/Helper/BuildInterpolator.php b/src/Helper/BuildInterpolator.php index ef8db63e4..e403507ec 100644 --- a/src/Helper/BuildInterpolator.php +++ b/src/Helper/BuildInterpolator.php @@ -29,15 +29,10 @@ class BuildInterpolator */ private array $interpolationVars = []; - private EnvironmentStore $environmentStore; - private SecretStore $secretStore; - public function __construct( - EnvironmentStore $environmentStore, - SecretStore $secretStore + private readonly EnvironmentStore $environmentStore, + private readonly SecretStore $secretStore ) { - $this->environmentStore = $environmentStore; - $this->secretStore = $secretStore; } /** diff --git a/src/Helper/CommandExecutor.php b/src/Helper/CommandExecutor.php index b240a27ef..f870d780c 100644 --- a/src/Helper/CommandExecutor.php +++ b/src/Helper/CommandExecutor.php @@ -16,16 +16,6 @@ */ class CommandExecutor implements CommandExecutorInterface { - /** - * @var BuildLogger - */ - protected $logger; - - /** - * @var bool - */ - protected $verbose; - /** * @var array */ @@ -41,13 +31,6 @@ class CommandExecutor implements CommandExecutorInterface */ public $logExecOutput = true; - /** - * The path which findBinary will look in. - * - * @var string - */ - protected $rootDir; - /** * Current build path * @@ -78,11 +61,11 @@ class CommandExecutor implements CommandExecutorInterface * @param string $rootDir * @param bool $verbose */ - public function __construct(BuildLogger $logger, $rootDir, $verbose = false) - { - $this->logger = $logger; - $this->verbose = $verbose; - $this->rootDir = $rootDir; + public function __construct( + protected BuildLogger $logger, + protected $rootDir, + protected $verbose = false + ) { } /** @@ -104,7 +87,7 @@ public function executeCommand($args = []) $withNoExit = ''; foreach (self::$noExitCommands as $nec) { - if (\preg_match("/\b{$nec}\b/", $command)) { + if (\preg_match("/\b{$nec}\b/", (string) $command)) { $withNoExit = $nec; break; @@ -131,7 +114,7 @@ public function executeCommand($args = []) \exec("ps auxww | grep '{$withNoExit}' | grep -v grep", $response); $response = \array_filter( $response, - fn ($a) => \strpos($a, $this->buildPath) !== false + fn ($a) => \str_contains($a, $this->buildPath) ); } while (!empty($response)); $process->stop(); @@ -206,10 +189,8 @@ public function getLastError() /** * @param string $binaryPath * @param string $binary - * - * @return false|string */ - protected function findBinaryByPath($binaryPath, $binary) + protected function findBinaryByPath($binaryPath, $binary): false|string { if (\is_dir($binaryPath) && \is_file($binaryPath . '/' . $binary)) { $this->logger->logDebug(\sprintf('Found in %s (binary_path): %s', $binaryPath, $binary)); @@ -223,10 +204,8 @@ protected function findBinaryByPath($binaryPath, $binary) /** * @param string $composerBin * @param string $binary - * - * @return false|string */ - protected function findBinaryLocal($composerBin, $binary) + protected function findBinaryLocal($composerBin, $binary): false|string { if (\is_dir($composerBin) && \is_file($composerBin . '/' . $binary)) { $this->logger->logDebug(\sprintf('Found in %s (local): %s', $composerBin, $binary)); @@ -239,10 +218,8 @@ protected function findBinaryLocal($composerBin, $binary) /** * @param string $binary - * - * @return false|string */ - protected function findBinaryGlobal($binary) + protected function findBinaryGlobal($binary): false|string { if (\is_file($this->rootDir . 'vendor/bin/' . $binary)) { $this->logger->logDebug(\sprintf('Found in %s (global): %s', 'vendor/bin', $binary)); @@ -257,13 +234,11 @@ protected function findBinaryGlobal($binary) * Uses 'which' to find a system binary by name * * @param string $binary - * - * @return false|string */ - protected function findBinarySystem($binary) + protected function findBinarySystem($binary): false|string { - $tempBinary = \trim(\shell_exec('which ' . $binary)); - if (\is_file($tempBinary)) { + $tempBinary = \trim((string)\shell_exec('which ' . $binary)); + if ($tempBinary && \is_file($tempBinary)) { $this->logger->logDebug(\sprintf('Found in %s (system): %s', '', $binary)); return $tempBinary; @@ -426,9 +401,7 @@ private function getDefaultEnv() if (\in_array($k, self::$blacklistEnvVars, true)) { continue; } - if (\is_string($v)) { - $env[$k] = $v; - } + $env[$k] = $v; } } else { $output = []; diff --git a/src/Helper/CommandExecutorInterface.php b/src/Helper/CommandExecutorInterface.php index 3f72078cf..494e3169d 100644 --- a/src/Helper/CommandExecutorInterface.php +++ b/src/Helper/CommandExecutorInterface.php @@ -32,15 +32,13 @@ public function getLastOutput(); /** * Find a binary required by a plugin. * - * @param array|string $binary * @param string $priorityPath * @param string $binaryPath * @param array $binaryName * @return string - * * @throws Exception when no binary has been found. */ - public function findBinary($binary, $priorityPath = 'local', $binaryPath = '', $binaryName = []); + public function findBinary(array|string $binary, $priorityPath = 'local', $binaryPath = '', $binaryName = []); /** * Set the buildPath property. diff --git a/src/Helper/Email.php b/src/Helper/Email.php index 2c102248c..fd86eac87 100644 --- a/src/Helper/Email.php +++ b/src/Helper/Email.php @@ -16,18 +16,16 @@ */ class Email { - public const DEFAULT_FROM = 'PHP Censor '; + final public const DEFAULT_FROM = 'PHP Censor '; protected $emailTo = []; protected $emailCc = []; protected $subject = 'Email from PHP Censor'; protected $body = ''; protected $isHtml = false; - protected $config; - public function __construct(ConfigurationInterface $config) + public function __construct(protected ConfigurationInterface $config) { - $this->config = $config; } /** @@ -104,11 +102,11 @@ public function getFrom() self::DEFAULT_FROM ); - if (\strpos($from, '<') === false) { - return [(string)\trim($from) => 'PHP Censor']; + if (!\str_contains((string) $from, '<')) { + return [\trim((string) $from) => 'PHP Censor']; } - \preg_match('#^(.*?)<(.*?)>$#ui', $from, $fromParts); + \preg_match('#^(.*?)<(.*?)>$#ui', (string) $from, $fromParts); return [\trim($fromParts[2]) => \trim($fromParts[1])]; } diff --git a/src/Helper/Github.php b/src/Helper/Github.php index e163e1be9..493e73876 100644 --- a/src/Helper/Github.php +++ b/src/Helper/Github.php @@ -15,11 +15,8 @@ */ class Github { - private ConfigurationInterface $configuration; - - public function __construct(ConfigurationInterface $configuration) + public function __construct(private readonly ConfigurationInterface $configuration) { - $this->configuration = $configuration; } /** @@ -34,7 +31,7 @@ public function createPullRequestComment($repo, $pullId, $commitId, $file, $line return null; } - $url = '/repos/' . \strtolower($repo) . '/pulls/' . $pullId . '/comments'; + $url = '/repos/' . \strtolower((string) $repo) . '/pulls/' . $pullId . '/comments'; $params = [ 'body' => $comment, @@ -65,7 +62,7 @@ public function createCommitComment($repo, $commitId, $file, $line, $comment) return null; } - $url = '/repos/' . \strtolower($repo) . '/commits/' . $commitId . '/comments'; + $url = '/repos/' . \strtolower((string) $repo) . '/commits/' . $commitId . '/comments'; $params = [ 'body' => $comment, diff --git a/src/Helper/Lang.php b/src/Helper/Lang.php index 6dde2631a..c15fbee0a 100644 --- a/src/Helper/Lang.php +++ b/src/Helper/Lang.php @@ -16,12 +16,12 @@ */ class Lang { - public const DEFAULT_LANGUAGE = 'en'; + final public const DEFAULT_LANGUAGE = 'en'; /** * @var string */ - protected static $language = null; + protected static $language; /** * @var array @@ -41,11 +41,10 @@ class Lang /** * Get a specific string from the language file. * - * @param mixed ...$params * * @return string */ - public static function get(...$params) + public static function get(mixed ...$params) { $string = $params[0]; if (\array_key_exists($string, self::$strings)) { @@ -149,9 +148,7 @@ public static function init( // Try the installation default language: $language = $config->get('php-censor.language', self::DEFAULT_LANGUAGE); - if (self::setLanguage($language)) { - return; - } + self::setLanguage($language); } /** @@ -188,7 +185,7 @@ protected static function loadAvailableLanguages() { $matches = []; foreach (\glob(SRC_DIR . 'Languages/lang.*.php') as $file) { - if (\preg_match('/lang\.([a-z]{2}\-?[a-z]*)\.php/', $file, $matches)) { + if (\preg_match('/lang\.([a-z]{2}\-?[a-z]*)\.php/', (string) $file, $matches)) { self::$languages[] = $matches[1]; } } diff --git a/src/Helper/MailerFactory.php b/src/Helper/MailerFactory.php index fdff20a43..32d69abaa 100644 --- a/src/Helper/MailerFactory.php +++ b/src/Helper/MailerFactory.php @@ -73,16 +73,11 @@ public function getMailConfig($configName) if (isset($this->emailConfig[$configName]) && '' !== $this->emailConfig[$configName]) { return $this->emailConfig[$configName]; } else { - switch ($configName) { - case 'default_mailto_address': - case 'smtp_encryption': - return null; - case 'smtp_port': - return '25'; - case 'smtp_address': - default: - return ''; - } + return match ($configName) { + 'default_mailto_address', 'smtp_encryption' => null, + 'smtp_port' => '25', + default => '', + }; } } } diff --git a/src/Helper/SshKey.php b/src/Helper/SshKey.php index 82c812ad4..c3802c174 100644 --- a/src/Helper/SshKey.php +++ b/src/Helper/SshKey.php @@ -14,11 +14,8 @@ */ class SshKey { - protected ConfigurationInterface $configuration; - - public function __construct(ConfigurationInterface $configuration) + public function __construct(protected ConfigurationInterface $configuration) { - $this->configuration = $configuration; } /** diff --git a/src/Helper/Template.php b/src/Helper/Template.php index 1f8c8eba0..e2beb464d 100644 --- a/src/Helper/Template.php +++ b/src/Helper/Template.php @@ -15,7 +15,7 @@ class Template /** * @var AntiXSS */ - protected static $antiXss = null; + protected static $antiXss; /** * @param string $string diff --git a/src/Helper/Xml.php b/src/Helper/Xml.php index 307a3d388..5f8eccf8b 100644 --- a/src/Helper/Xml.php +++ b/src/Helper/Xml.php @@ -26,7 +26,7 @@ public static function loadFromFile($filePath) try { $xml = \simplexml_load_file('php://filter/read=xml_utf8_clean/resource=' . $filePath); - } catch (\Throwable $ex) { + } catch (\Throwable) { $xml = null; } diff --git a/src/Helper/Xml/Utf8CleanFilter.php b/src/Helper/Xml/Utf8CleanFilter.php index e3daafea5..7d65f2892 100644 --- a/src/Helper/Xml/Utf8CleanFilter.php +++ b/src/Helper/Xml/Utf8CleanFilter.php @@ -12,7 +12,7 @@ */ class Utf8CleanFilter extends php_user_filter { - public const PATTERN = '/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u'; + final public const PATTERN = '/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u'; /** * @param resource $in @@ -24,7 +24,7 @@ class Utf8CleanFilter extends php_user_filter public function filter($in, $out, &$consumed, $closing): int { while ($bucket = \stream_bucket_make_writeable($in)) { - $bucket->data = \preg_replace(self::PATTERN, '', $bucket->data); + $bucket->data = \preg_replace(self::PATTERN, '', (string) $bucket->data); $consumed += $bucket->datalen; \stream_bucket_append($out, $bucket); diff --git a/src/Http/Router.php b/src/Http/Router.php index 84b8a2884..877234109 100644 --- a/src/Http/Router.php +++ b/src/Http/Router.php @@ -15,18 +15,14 @@ */ class Router { - protected Request $request; - - protected Application $application; - protected array $routes = [ ['route' => '/:controller/:action', 'callback' => null, 'defaults' => []] ]; - public function __construct(Application $application, Request $request) - { - $this->application = $application; - $this->request = $request; + public function __construct( + protected Application $application, + protected Request $request + ) { } public function clearRoutes() @@ -67,7 +63,7 @@ public function dispatch() $thisAction = $route['defaults']['action']; } - $routeParts = \array_filter(\explode('/', $route['route'])); + $routeParts = \array_filter(\explode('/', (string) $route['route'])); $routeMatches = true; while (\count($routeParts)) { diff --git a/src/Logging/BuildDBLogHandler.php b/src/Logging/BuildDBLogHandler.php index a0cfbd9a9..c5783ee6f 100644 --- a/src/Logging/BuildDBLogHandler.php +++ b/src/Logging/BuildDBLogHandler.php @@ -21,10 +21,6 @@ */ class BuildDBLogHandler extends AbstractProcessingHandler { - protected Build $build; - protected BuildStore $buildStore; - private SecretStore $secretStore; - protected string $logValue; /** @@ -38,18 +34,14 @@ class BuildDBLogHandler extends AbstractProcessingHandler protected int $flushDelay = 1; public function __construct( - SecretStore $secretStore, - BuildStore $buildStore, - Build $build, + private readonly SecretStore $secretStore, + protected BuildStore $buildStore, + protected Build $build, int $level = Logger::INFO, bool $bubble = true ) { parent::__construct($level, $bubble); - $this->secretStore = $secretStore; - $this->build = $build; - $this->buildStore = $buildStore; - // We want to add to any existing saved log information. $this->logValue = (string)$build->getLog(); } @@ -89,14 +81,12 @@ private function sanitizeSecrets(string $message): string { $replace = []; $secrets = $this->secretStore->getAll(); - if (\count($secrets['items']) > 0) { - /** @var Secret $secret */ - foreach ($secrets['items'] as $secret) { - $value = $secret->getValue(); - $name = '%' . \sprintf('SECRET:%s', $secret->getName()) . '%'; - if (\trim($value)) { - $replace[$name] = $secret->getValue(); - } + /** @var Secret $secret */ + foreach ($secrets['items'] as $secret) { + $value = $secret->getValue(); + $name = '%' . \sprintf('SECRET:%s', $secret->getName()) . '%'; + if (\trim($value)) { + $replace[$name] = $secret->getValue(); } } @@ -110,7 +100,7 @@ protected function write(array $record): void { $this->logValue .= $this->sanitize( $this->sanitizeSecrets( - (string)$record['message'] + $record['message'] ) ) . PHP_EOL; diff --git a/src/Logging/BuildLogger.php b/src/Logging/BuildLogger.php index 521831a78..c4538980b 100644 --- a/src/Logging/BuildLogger.php +++ b/src/Logging/BuildLogger.php @@ -16,14 +16,10 @@ */ class BuildLogger { - private LoggerInterface $logger; - - private Build $build; - - public function __construct(LoggerInterface $logger, Build $build) - { - $this->logger = $logger; - $this->build = $build; + public function __construct( + private readonly LoggerInterface $logger, + private readonly Build $build + ) { } public function log($message, string $level = LogLevel::INFO, array $context = []): void diff --git a/src/Logging/Handler.php b/src/Logging/Handler.php index 5ff2a419a..d4a40f934 100644 --- a/src/Logging/Handler.php +++ b/src/Logging/Handler.php @@ -28,21 +28,18 @@ class Handler E_USER_DEPRECATED => 'User Deprecated', ]; - protected ?LoggerInterface $logger; - - public function __construct(?LoggerInterface $logger = null) + public function __construct(protected ?LoggerInterface $logger = null) { - $this->logger = $logger; } public static function register(?LoggerInterface $logger = null): void { $handler = new static($logger); - \set_error_handler([$handler, 'handleError']); + \set_error_handler($handler->handleError(...)); \register_shutdown_function([$handler, 'handleFatalError']); - \set_exception_handler([$handler, 'handleException']); + \set_exception_handler($handler->handleException(...)); } /** @@ -84,7 +81,7 @@ public function handleFatalError(): void ); $this->log($error); } - } catch (\Throwable $e) { + } catch (\Throwable) { $error = new ErrorException( \sprintf( '%s: %s in %s line %d', @@ -112,7 +109,7 @@ protected function log(\Throwable $exception): void if (null !== $this->logger) { $message = \sprintf( '%s: %s (uncaught exception) at %s line %s', - \get_class($exception), + $exception::class, $exception->getMessage(), $exception->getFile(), $exception->getLine() diff --git a/src/Logging/OutputLogHandler.php b/src/Logging/OutputLogHandler.php index 1b4f0a7f4..0d2e12e32 100644 --- a/src/Logging/OutputLogHandler.php +++ b/src/Logging/OutputLogHandler.php @@ -18,16 +18,12 @@ */ class OutputLogHandler extends AbstractProcessingHandler { - protected OutputInterface $output; - public function __construct( - OutputInterface $output, + protected OutputInterface $output, string $level = LogLevel::INFO, bool $bubble = true ) { parent::__construct($level, $bubble); - - $this->output = $output; } /** diff --git a/src/Model.php b/src/Model.php index 61afbb94f..f30fa6c21 100644 --- a/src/Model.php +++ b/src/Model.php @@ -22,10 +22,8 @@ class Model private array $modified = []; - protected StoreRegistry $storeRegistry; - public function __construct( - StoreRegistry $storeRegistry, + protected StoreRegistry $storeRegistry, array $initialData = [] ) { if (!isset($this->dataTypes['id'])) { @@ -35,8 +33,6 @@ public function __construct( foreach ($initialData as $column => $value) { $this->setDataItem($column, $this->castToDataType($this->getDataType($column), $value)); } - - $this->storeRegistry = $storeRegistry; } public function getDataType(string $column): string @@ -93,7 +89,7 @@ private function castToDataType(string $type, $value) return \is_float($value) ? $value : \floatval($value); case 'array': - return \is_array($value) ? $value : \json_decode($value, true); + return \is_array($value) ? $value : \json_decode((string) $value, true); case 'datetime': if (\is_a($value, DateTime::class)) { @@ -101,7 +97,7 @@ private function castToDataType(string $type, $value) } try { return new DateTime($value); - } catch (\Throwable $e) { + } catch (\Throwable) { return null; } diff --git a/src/Model/Base/Build.php b/src/Model/Base/Build.php index 4eb10dd30..94dd52a9f 100644 --- a/src/Model/Base/Build.php +++ b/src/Model/Base/Build.php @@ -261,10 +261,7 @@ public function setExtra(array $value): bool return $this->setDataItem('extra', $value); } - /** - * @param mixed $value - */ - public function addExtraValue(string $name, $value): bool + public function addExtraValue(string $name, mixed $value): bool { $extra = $this->getExtra(); if ($extra === null) { @@ -396,7 +393,7 @@ public function getTestCoveragePrevious(): ?string $trend = $store->getBuildTestCoverageTrend($this->getId(), $this->getProjectId(), $this->getBranch()); if (!empty($trend[0]) && !empty($trend[0]['coverage'])) { - $coverage = \json_decode($trend[0]['coverage'], true); + $coverage = \json_decode((string) $trend[0]['coverage'], true); if (isset($coverage['lines'])) { $this->setTestCoveragePrevious($coverage['lines']); $store->save($this); @@ -418,7 +415,6 @@ public function setTestCoveragePrevious(string $value): bool public function getErrorsNew(): ?int { if ($this->getDataItem('errors_new') === null) { - /** @var BuildStore $errorStore */ $store = $this->storeRegistry->get('Build'); $this->setErrorsNew( diff --git a/src/Model/Base/BuildError.php b/src/Model/Base/BuildError.php index f430511e4..8bd617064 100644 --- a/src/Model/Base/BuildError.php +++ b/src/Model/Base/BuildError.php @@ -18,10 +18,10 @@ class BuildError extends Model { use HasCreateDateTrait; - public const SEVERITY_CRITICAL = 0; - public const SEVERITY_HIGH = 1; - public const SEVERITY_NORMAL = 2; - public const SEVERITY_LOW = 3; + final public const SEVERITY_CRITICAL = 0; + final public const SEVERITY_HIGH = 1; + final public const SEVERITY_NORMAL = 2; + final public const SEVERITY_LOW = 3; protected array $data = [ 'id' => null, diff --git a/src/Model/Base/Project.php b/src/Model/Base/Project.php index e82a759e2..4cbce8f34 100644 --- a/src/Model/Base/Project.php +++ b/src/Model/Base/Project.php @@ -21,21 +21,21 @@ class Project extends Model use HasCreateDateTrait; use HasUserIdTrait; - public const TYPE_LOCAL = 'local'; - public const TYPE_GIT = 'git'; - public const TYPE_GITHUB = 'github'; - public const TYPE_BITBUCKET = 'bitbucket'; - public const TYPE_GITLAB = 'gitlab'; - public const TYPE_GOGS = 'gogs'; - public const TYPE_HG = 'hg'; - public const TYPE_BITBUCKET_HG = 'bitbucket-hg'; - public const TYPE_BITBUCKET_SERVER = 'bitbucket-server'; - public const TYPE_SVN = 'svn'; - - public const MIN_BUILD_PRIORITY = 1; - public const MAX_BUILD_PRIORITY = 2000; - public const DEFAULT_BUILD_PRIORITY = 1000; - public const OFFSET_BETWEEN_BUILD_AND_QUEUE = 24; + final public const TYPE_LOCAL = 'local'; + final public const TYPE_GIT = 'git'; + final public const TYPE_GITHUB = 'github'; + final public const TYPE_BITBUCKET = 'bitbucket'; + final public const TYPE_GITLAB = 'gitlab'; + final public const TYPE_GOGS = 'gogs'; + final public const TYPE_HG = 'hg'; + final public const TYPE_BITBUCKET_HG = 'bitbucket-hg'; + final public const TYPE_BITBUCKET_SERVER = 'bitbucket-server'; + final public const TYPE_SVN = 'svn'; + + final public const MIN_BUILD_PRIORITY = 1; + final public const MAX_BUILD_PRIORITY = 2000; + final public const DEFAULT_BUILD_PRIORITY = 1000; + final public const OFFSET_BETWEEN_BUILD_AND_QUEUE = 24; protected array $data = [ 'id' => null, diff --git a/src/Model/Base/WebhookRequest.php b/src/Model/Base/WebhookRequest.php index 01b4cdb3f..d7b2dc64b 100644 --- a/src/Model/Base/WebhookRequest.php +++ b/src/Model/Base/WebhookRequest.php @@ -17,13 +17,13 @@ class WebhookRequest extends Model { use HasCreateDateTrait; - public const WEBHOOK_TYPE_GIT = 'git'; - public const WEBHOOK_TYPE_GITHUB = 'github'; - public const WEBHOOK_TYPE_BITBUCKET = 'bitbucket'; - public const WEBHOOK_TYPE_GITLAB = 'gitlab'; - public const WEBHOOK_TYPE_GOGS = 'gogs'; - public const WEBHOOK_TYPE_HG = 'hg'; - public const WEBHOOK_TYPE_SVN = 'svn'; + final public const WEBHOOK_TYPE_GIT = 'git'; + final public const WEBHOOK_TYPE_GITHUB = 'github'; + final public const WEBHOOK_TYPE_BITBUCKET = 'bitbucket'; + final public const WEBHOOK_TYPE_GITLAB = 'gitlab'; + final public const WEBHOOK_TYPE_GOGS = 'gogs'; + final public const WEBHOOK_TYPE_HG = 'hg'; + final public const WEBHOOK_TYPE_SVN = 'svn'; protected array $data = [ 'id' => null, diff --git a/src/Model/Build.php b/src/Model/Build.php index 145ae8c52..5d9f63e25 100644 --- a/src/Model/Build.php +++ b/src/Model/Build.php @@ -30,14 +30,14 @@ */ class Build extends BaseBuild { - public const STAGE_SETUP = 'setup'; - public const STAGE_TEST = 'test'; - public const STAGE_DEPLOY = 'deploy'; - public const STAGE_COMPLETE = 'complete'; - public const STAGE_SUCCESS = 'success'; - public const STAGE_FAILURE = 'failure'; - public const STAGE_FIXED = 'fixed'; - public const STAGE_BROKEN = 'broken'; + final public const STAGE_SETUP = 'setup'; + final public const STAGE_TEST = 'test'; + final public const STAGE_DEPLOY = 'deploy'; + final public const STAGE_COMPLETE = 'complete'; + final public const STAGE_SUCCESS = 'success'; + final public const STAGE_FAILURE = 'failure'; + final public const STAGE_FIXED = 'fixed'; + final public const STAGE_BROKEN = 'broken'; public static array $pullRequestSources = [ self::SOURCE_WEBHOOK_PULL_REQUEST_CREATED, @@ -172,9 +172,8 @@ public function getProjectTitle() * Store build metadata * * @param string $key - * @param mixed $value */ - public function storeMeta($key, $value) + public function storeMeta($key, mixed $value) { $value = \json_encode($value); @@ -206,6 +205,9 @@ public function handleConfigBeforeClone(Builder $builder) $builder->logDebug('Config before repository clone (DB): ' . \json_encode($buildConfig)); $builder->setConfig($buildConfig); + if (!empty($buildConfig['build_settings']['php'])) { + $builder->setPhpExecutable($buildConfig['build_settings']['php']); + } } } @@ -258,6 +260,9 @@ protected function handleConfig(Builder $builder, string $buildPath): bool $builder->logDebug('Final config: ' . \json_encode($buildConfig)); $builder->setConfig($buildConfig); + if (!empty($buildConfig['build_settings']['php'])) { + $builder->setPhpExecutable($buildConfig['build_settings']['php']); + } } return true; @@ -439,7 +444,7 @@ public function removeBuildDirectory(bool $withArtifacts = false) $fileSystem->remove(PUBLIC_DIR . 'artifacts/pdepend/' . $buildDirectory); $fileSystem->remove(PUBLIC_DIR . 'artifacts/phpunit/' . $buildDirectory); } - } catch (\Throwable $e) { + } catch (\Throwable) { } } @@ -553,31 +558,19 @@ public function getSourceHumanize() $parentId = $this->getParentId(); $parentLink = '#' . $parentId . ''; - switch ($this->getSource()) { - case Build::SOURCE_WEBHOOK_PUSH: - return Lang::get('source_webhook_push'); - case Build::SOURCE_WEBHOOK_PULL_REQUEST_CREATED: - return Lang::get('source_webhook_pull_request_created'); - case Build::SOURCE_WEBHOOK_PULL_REQUEST_UPDATED: - return Lang::get('source_webhook_pull_request_updated'); - case Build::SOURCE_WEBHOOK_PULL_REQUEST_APPROVED: - return Lang::get('source_webhook_pull_request_approved'); - case Build::SOURCE_WEBHOOK_PULL_REQUEST_MERGED: - return Lang::get('source_webhook_pull_request_merged'); - case Build::SOURCE_MANUAL_WEB: - return Lang::get('source_manual_web'); - case Build::SOURCE_MANUAL_REBUILD_WEB: - return Lang::get('source_manual_rebuild_web', $parentLink); - case Build::SOURCE_MANUAL_CONSOLE: - return Lang::get('source_manual_console'); - case Build::SOURCE_MANUAL_REBUILD_CONSOLE: - return Lang::get('source_manual_rebuild_console', $parentLink); - case Build::SOURCE_PERIODICAL: - return Lang::get('source_periodical'); - case Build::SOURCE_UNKNOWN: - default: - return Lang::get('source_unknown'); - } + return match ($this->getSource()) { + Build::SOURCE_WEBHOOK_PUSH => Lang::get('source_webhook_push'), + Build::SOURCE_WEBHOOK_PULL_REQUEST_CREATED => Lang::get('source_webhook_pull_request_created'), + Build::SOURCE_WEBHOOK_PULL_REQUEST_UPDATED => Lang::get('source_webhook_pull_request_updated'), + Build::SOURCE_WEBHOOK_PULL_REQUEST_APPROVED => Lang::get('source_webhook_pull_request_approved'), + Build::SOURCE_WEBHOOK_PULL_REQUEST_MERGED => Lang::get('source_webhook_pull_request_merged'), + Build::SOURCE_MANUAL_WEB => Lang::get('source_manual_web'), + Build::SOURCE_MANUAL_REBUILD_WEB => Lang::get('source_manual_rebuild_web', $parentLink), + Build::SOURCE_MANUAL_CONSOLE => Lang::get('source_manual_console'), + Build::SOURCE_MANUAL_REBUILD_CONSOLE => Lang::get('source_manual_rebuild_console', $parentLink), + Build::SOURCE_PERIODICAL => Lang::get('source_periodical'), + default => Lang::get('source_unknown'), + }; } /** @@ -606,7 +599,7 @@ public function getTotalErrorsCount($plugin = null, $severity = null, $isNew = n /** @var BuildErrorStore $store */ $store = $this->storeRegistry->get('BuildError'); - $this->totalErrorsCount[$key] = (int)$store->getErrorTotalForBuild( + $this->totalErrorsCount[$key] = $store->getErrorTotalForBuild( $this->getId(), $plugin, $severity, diff --git a/src/Model/Build/BitbucketBuild.php b/src/Model/Build/BitbucketBuild.php index 3a4918be5..1e78f9da6 100644 --- a/src/Model/Build/BitbucketBuild.php +++ b/src/Model/Build/BitbucketBuild.php @@ -216,7 +216,7 @@ protected function postCloneSetup(Builder $builder, $cloneTo, array $extra = nul \unlink($diffFile); $skipGitFinalization = true; } - } catch (\Throwable $ex) { + } catch (\Throwable) { $success = false; } diff --git a/src/Model/Build/BitbucketServerBuild.php b/src/Model/Build/BitbucketServerBuild.php index 2c0707c1d..9700e4faa 100644 --- a/src/Model/Build/BitbucketServerBuild.php +++ b/src/Model/Build/BitbucketServerBuild.php @@ -103,9 +103,8 @@ public function getFileLinkTemplate() $link = $this->getProject()->getReference() . $reference . '/'; $link .= 'src/' . $this->getCommitId() . '/'; $link .= '{FILE}'; - $link .= '#{BASEFILE}-{LINE}'; - return $link; + return $link . '#{BASEFILE}-{LINE}'; } /** @@ -133,7 +132,7 @@ protected function postCloneSetup(Builder $builder, $cloneTo, array $extra = nul $skipGitFinalization = true; } - } catch (\Throwable $ex) { + } catch (\Throwable) { $success = false; } diff --git a/src/Model/Build/GithubBuild.php b/src/Model/Build/GithubBuild.php index 1b537b975..8ead77114 100644 --- a/src/Model/Build/GithubBuild.php +++ b/src/Model/Build/GithubBuild.php @@ -160,7 +160,7 @@ public function sendStatusPostback() ] ]); - $status = (int)$response->getStatusCode(); + $status = $response->getStatusCode(); return ($status >= 200 && $status < 300); } @@ -200,12 +200,14 @@ public function getCommitMessage(): ?string if (!\is_null($project)) { $reference = $project->getReference(); $commitLink = '#$1'; - $message = \preg_replace('/\#([0-9]+)/', $commitLink, $message); - $message = \preg_replace( - '/\@([a-zA-Z0-9_]+)/', - '@$1', - $message - ); + if ($message) { + $message = \preg_replace('/\#([0-9]+)/', $commitLink, $message); + $message = \preg_replace( + '/\@([a-zA-Z0-9_]+)/', + '@$1', + $message + ); + } } return $message; @@ -226,9 +228,8 @@ public function getFileLinkTemplate() $link = '//' . $this->getDomain() . '/' . $reference . '/'; $link .= 'blob/' . $this->getCommitId() . '/'; $link .= '{FILE}'; - $link .= '#L{LINE}-L{LINE_END}'; - return $link; + return $link . '#L{LINE}-L{LINE_END}'; } /** @@ -252,7 +253,7 @@ protected function postCloneSetup(Builder $builder, $cloneTo, array $extra = nul $success = $builder->executeCommand($cmd, $cloneTo, $this->getBranch(), $pullRequestId); } - } catch (\Throwable $ex) { + } catch (\Throwable) { $success = false; } diff --git a/src/Model/Build/HgBuild.php b/src/Model/Build/HgBuild.php index 6ac11e845..b19b3e984 100644 --- a/src/Model/Build/HgBuild.php +++ b/src/Model/Build/HgBuild.php @@ -19,16 +19,12 @@ */ class HgBuild extends Build { - protected ConfigurationInterface $configuration; - public function __construct( - ConfigurationInterface $configuration, + protected ConfigurationInterface $configuration, StoreRegistry $storeRegistry, array $initialData = [] ) { parent::__construct($storeRegistry, $initialData); - - $this->configuration = $configuration; } /** diff --git a/src/Model/Build/LocalBuild.php b/src/Model/Build/LocalBuild.php index a129ec73b..f08ddd73e 100644 --- a/src/Model/Build/LocalBuild.php +++ b/src/Model/Build/LocalBuild.php @@ -29,7 +29,7 @@ class LocalBuild extends TypedBuild public function createWorkingCopy(Builder $builder, $buildPath) { $reference = $this->getProject()->getReference(); - $reference = \substr($reference, -1) === '/' ? \substr($reference, 0, -1) : $reference; + $reference = \str_ends_with($reference, '/') ? \substr($reference, 0, -1) : $reference; $buildPath = \substr($buildPath, 0, -1); // If there's a /config file in the reference directory, it is probably a bare repository diff --git a/src/Model/Build/SvnBuild.php b/src/Model/Build/SvnBuild.php index 97869dcbb..0793dadf9 100644 --- a/src/Model/Build/SvnBuild.php +++ b/src/Model/Build/SvnBuild.php @@ -34,9 +34,9 @@ protected function getCloneUrl() $url .= 'trunk'; // For default branch with standard default branch directory ("branches") like "/branch-1" or "branch-1" // (-> "branches/branch-1") - } elseif (false === \strpos($branch, '/')) { + } elseif (!\str_contains($branch, '/')) { $url .= 'branches/' . $branch; - // For default branch with non-standard branch directory like "/branch/branch-1" or "branch/branch-1" + // For default branch with non-standard branch directory like "/branch/branch-1" or "branch/branch-1" // (-> "branch/branch-1") } else { $url .= $branch; diff --git a/src/Model/Build/TypedBuild.php b/src/Model/Build/TypedBuild.php index 410f3a497..e6fe2d5c2 100644 --- a/src/Model/Build/TypedBuild.php +++ b/src/Model/Build/TypedBuild.php @@ -16,15 +16,11 @@ */ class TypedBuild extends Build { - protected ConfigurationInterface $configuration; - public function __construct( - ConfigurationInterface $configuration, + protected ConfigurationInterface $configuration, StoreRegistry $storeRegistry, array $initialData = [] ) { parent::__construct($storeRegistry, $initialData); - - $this->configuration = $configuration; } } diff --git a/src/Model/Project.php b/src/Model/Project.php index ff377e942..e3c1d645e 100644 --- a/src/Model/Project.php +++ b/src/Model/Project.php @@ -233,15 +233,13 @@ public function setEnvironments($value) } } - if (!empty($environmentsNames)) { - // add - foreach ($environmentsNames as $environmentName) { - $environment = new Environment($this->storeRegistry); - $environment->setProjectId($this->getId()); - $environment->setName($environmentName); - $environment->setBranches(!empty($environmentsConfig[$environment->getName()]) ? $environmentsConfig[$environment->getName()] : []); - $store->save($environment); - } + // add + foreach ($environmentsNames as $environmentName) { + $environment = new Environment($this->storeRegistry); + $environment->setProjectId($this->getId()); + $environment->setName($environmentName); + $environment->setBranches(!empty($environmentsConfig[$environment->getName()]) ? $environmentsConfig[$environment->getName()] : []); + $store->save($environment); } } diff --git a/src/Model/Secret.php b/src/Model/Secret.php index e0e241d46..e54f3aba5 100644 --- a/src/Model/Secret.php +++ b/src/Model/Secret.php @@ -14,5 +14,5 @@ */ class Secret extends BaseSecret { - public const SECRET_NAME_PATTERN = '^[-_\w\d]+$'; + final public const SECRET_NAME_PATTERN = '^[-_\w\d]+$'; } diff --git a/src/Plugin.php b/src/Plugin.php index adc7f278f..d524c2fd3 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -14,34 +14,19 @@ */ abstract class Plugin { - public const STATUS_PENDING = 0; - public const STATUS_RUNNING = 1; - public const STATUS_SUCCESS = 2; - public const STATUS_FAILED = 3; - public const STATUS_FAILED_ALLOWED = 4; + final public const STATUS_PENDING = 0; + final public const STATUS_RUNNING = 1; + final public const STATUS_SUCCESS = 2; + final public const STATUS_FAILED = 3; + final public const STATUS_FAILED_ALLOWED = 4; - public const AVAILABLE_PRIORITY_PATHS = [ + final public const AVAILABLE_PRIORITY_PATHS = [ 'global', 'system', 'local', 'binary_path' ]; - /** - * @var Builder - */ - protected $builder; - - /** - * @var Build - */ - protected $build; - - /** - * @var array - */ - protected $options; - /** * @var string */ @@ -78,12 +63,11 @@ abstract class Plugin protected ?StoreRegistry $storeRegistry = null; - public function __construct(Builder $builder, Build $build, array $options = []) - { - $this->builder = $builder; - $this->build = $build; - $this->options = $options; - + public function __construct( + protected Builder $builder, + protected Build $build, + protected array $options = [] + ) { $this->directory = $this->normalizeDirectory(); $this->binaryPath = $this->normalizeBinaryPath(); $this->ignore = $this->normalizeIgnore(); @@ -116,7 +100,7 @@ protected function normalizePath($rawPath) { $normalizedPath = $this->builder->interpolate($rawPath, true); - if ('/' !== \substr($rawPath, 0, 1)) { + if (!\str_starts_with($rawPath, '/')) { $normalizedPath = $this->build->getBuildPath() . $normalizedPath; } @@ -143,7 +127,7 @@ protected function normalizeBinaryPath() if (!empty($this->options['binary_path'])) { $optionBinaryPath = $this->builder->interpolate($this->options['binary_path'], true); - if ('/' !== \substr($optionBinaryPath, 0, 1)) { + if (!\str_starts_with($optionBinaryPath, '/')) { $binaryPath = $this->build->getBuildPath(); } @@ -179,7 +163,7 @@ protected function normalizeDirectory() if (!empty($this->options['directory'])) { $optionDirectory = $this->builder->interpolate($this->options['directory'], true); - if ('/' !== \substr($optionDirectory, 0, 1)) { + if (!\str_starts_with($optionDirectory, '/')) { $directory = $this->build->getBuildPath(); } @@ -222,7 +206,7 @@ protected function normalizeIgnore() \array_walk($ignore, function (&$value) use ($baseDirectory) { $value = $this->builder->interpolate($value, true); - if ('/' !== \substr($value, 0, 1)) { + if (!\str_starts_with($value, '/')) { $value = $baseDirectory . $value; } @@ -250,13 +234,11 @@ protected function normalizeIgnore() /** * Find a binary required by a plugin. * - * @param array|string $binary * * @return string - * * @throws Exception when no binary has been found. */ - public function findBinary($binary) + public function findBinary(array|string $binary) { return $this->builder->findBinary($binary, $this->priorityPath, $this->binaryPath, $this->binaryName); } diff --git a/src/Plugin/Atoum.php b/src/Plugin/Atoum.php index 571ea265d..2138bf3d3 100644 --- a/src/Plugin/Atoum.php +++ b/src/Plugin/Atoum.php @@ -59,7 +59,7 @@ public function __construct(Builder $builder, Build $build, array $options = []) */ public function execute() { - $cmd = $this->executable; + $cmd = Builder::PHP_CLI_TAG . ' ' . $this->executable; if (null !== $this->args) { $cmd .= " {$this->args}"; @@ -77,7 +77,7 @@ public function execute() $output = $this->builder->getLastOutput(); - if (false === \strpos($output, "Success (")) { + if (!\str_contains($output, "Success (")) { $status = false; $this->builder->log($output); } diff --git a/src/Plugin/Behat.php b/src/Plugin/Behat.php index bfff90a48..0ba73c587 100644 --- a/src/Plugin/Behat.php +++ b/src/Plugin/Behat.php @@ -56,7 +56,7 @@ public function execute() return false; } - $success = $this->builder->executeCommand($this->executable . ' %s', $this->features); + $success = $this->builder->executeCommand(Builder::PHP_CLI_TAG . ' ' . $this->executable . ' %s', $this->features); list($errorCount, $data) = $this->parseBehatOutput(); @@ -94,7 +94,7 @@ public function parseBehatOutput() continue; } - if (\strpos($line, ':') === false) { + if (!\str_contains($line, ':')) { $storeFailures = false; } diff --git a/src/Plugin/BitbucketNotify.php b/src/Plugin/BitbucketNotify.php index 862d53c64..4621ebc76 100644 --- a/src/Plugin/BitbucketNotify.php +++ b/src/Plugin/BitbucketNotify.php @@ -68,7 +68,7 @@ public function __construct(Builder $builder, Build $build, array $options = []) parent::__construct($builder, $build, $options); $this->httpClient = new Client(); - $this->url = \trim($options['url']); + $this->url = \trim((string) $options['url']); $this->message = isset($options['message']) ? $options['message'] : ''; $this->projectKey = $options['project_key']; $this->repositorySlug = $options['repository_slug']; @@ -158,7 +158,7 @@ protected function findPullRequestsByBranch() { $endpoint = \sprintf('/projects/%s/repos/%s/pull-requests', $this->projectKey, $this->repositorySlug); $response = $this->apiRequest($endpoint)->getBody(); - $response = \json_decode($response, true); + $response = \json_decode((string) $response, true); foreach ($response['values'] as $pullRequest) { if ($pullRequest['fromRef']['displayId'] === $this->getBuild()->getBranch()) { @@ -179,7 +179,7 @@ protected function getTargetBranchForPullRequest($pullRequestId) ); $response = $this->apiRequest($endpoint)->getBody(); - $response = \json_decode($response, true); + $response = \json_decode((string) $response, true); return $response['toRef']['displayId']; } @@ -199,7 +199,7 @@ protected function createCommentInPullRequest($pullRequestId, $message) ); $response = $this->apiRequest($endpoint, 'post', ['text' => $message])->getBody(); - $response = \json_decode($response, true); + $response = \json_decode((string) $response, true); return (int)$response['id']; } @@ -227,18 +227,11 @@ protected function updateBuild() $this->getBuild()->getCommitId() ); - switch ($this->getBuild()->getStatus()) { - case Build::STATUS_SUCCESS: - $state = 'SUCCESSFUL'; - - break; - case Build::STATUS_FAILED: - $state = 'FAILED'; - - break; - default: - $state = 'INPROGRESS'; - } + $state = match ($this->getBuild()->getStatus()) { + Build::STATUS_SUCCESS => 'SUCCESSFUL', + Build::STATUS_FAILED => 'FAILED', + default => 'INPROGRESS', + }; $this->buildStatusRequest($endpoint, 'post', [ 'state' => $state, diff --git a/src/Plugin/Codeception.php b/src/Plugin/Codeception.php index 8af65569e..1427eed88 100644 --- a/src/Plugin/Codeception.php +++ b/src/Plugin/Codeception.php @@ -132,7 +132,7 @@ protected function runConfigFile() return false; } - $cmd = 'cd "%s" && ' . $codeception . ' run -c "%s" ' . $this->args . ' --xml'; + $cmd = 'cd "%s" && ' . Builder::PHP_CLI_TAG . ' ' . $codeception . ' run -c "%s" ' . $this->args . ' --xml'; $success = $this->builder->executeCommand($cmd, $this->directory, $this->ymlConfigFile); if (!$success) { @@ -145,12 +145,12 @@ protected function runConfigFile() $trueReportXmlPath = null; if ($config && isset($config['paths']['log'])) { - $trueReportXmlPath = \rtrim($config['paths']['log'], '/\\') . '/'; + $trueReportXmlPath = \rtrim((string) $config['paths']['log'], '/\\') . '/'; } if (!\file_exists($trueReportXmlPath . 'report.xml')) { foreach ($this->outputPath as $outputPath) { - $trueReportXmlPath = \rtrim($outputPath, '/\\') . '/'; + $trueReportXmlPath = \rtrim((string) $outputPath, '/\\') . '/'; if (\file_exists($trueReportXmlPath . 'report.xml')) { break; } diff --git a/src/Plugin/Composer.php b/src/Plugin/Composer.php index 97852eceb..a1bd4b24c 100644 --- a/src/Plugin/Composer.php +++ b/src/Plugin/Composer.php @@ -85,7 +85,7 @@ public function execute() { $composerLocation = $this->executable; - $cmd = $composerLocation . ' --no-ansi --no-interaction '; + $cmd = Builder::PHP_CLI_TAG . ' ' . $composerLocation . ' --no-ansi --no-interaction '; if ($this->preferDist) { $this->builder->log('Using --prefer-dist flag'); diff --git a/src/Plugin/CopyBuild.php b/src/Plugin/CopyBuild.php index 4cedb2bc0..e0cadd985 100644 --- a/src/Plugin/CopyBuild.php +++ b/src/Plugin/CopyBuild.php @@ -36,8 +36,8 @@ public function __construct(Builder $builder, Build $build, array $options = []) { parent::__construct($builder, $build, $options); - $this->wipe = isset($options['wipe']) ? (bool)$options['wipe'] : false; - $this->respectIgnore = isset($options['respect_ignore']) ? (bool)$options['respect_ignore'] : false; + $this->wipe = isset($options['wipe']) && (bool)$options['wipe']; + $this->respectIgnore = isset($options['respect_ignore']) && (bool)$options['respect_ignore']; } /** diff --git a/src/Plugin/Deployer.php b/src/Plugin/Deployer.php index 742ad89fa..7e708e82c 100644 --- a/src/Plugin/Deployer.php +++ b/src/Plugin/Deployer.php @@ -74,7 +74,7 @@ public function execute() ] ); - $status = (int)$response->getStatusCode(); + $status = $response->getStatusCode(); return ( ($status >= 200 && $status < 300) diff --git a/src/Plugin/DeployerOrg.php b/src/Plugin/DeployerOrg.php index c8e3b4b94..9b7615031 100644 --- a/src/Plugin/DeployerOrg.php +++ b/src/Plugin/DeployerOrg.php @@ -53,7 +53,7 @@ public function execute() $branchConfig = $this->options[$this->branch]; $options = $this->getOptions($branchConfig); - $deployerCmd = "$this->executable $options"; + $deployerCmd = Builder::PHP_CLI_TAG . " $this->executable $options"; return $this->builder->executeCommand($deployerCmd); } diff --git a/src/Plugin/EmailNotify.php b/src/Plugin/EmailNotify.php index ee8549780..8c2f236af 100644 --- a/src/Plugin/EmailNotify.php +++ b/src/Plugin/EmailNotify.php @@ -50,7 +50,7 @@ public function execute() try { $view = $this->getMailTemplate(); - } catch (RuntimeException $e) { + } catch (RuntimeException) { $this->builder->log( \sprintf('Unknown mail template "%s", falling back to default.', $this->options['template']), LogLevel::WARNING diff --git a/src/Plugin/FlowdockNotify.php b/src/Plugin/FlowdockNotify.php index fb5e236a5..9a8709276 100644 --- a/src/Plugin/FlowdockNotify.php +++ b/src/Plugin/FlowdockNotify.php @@ -26,7 +26,7 @@ class FlowdockNotify extends Plugin protected $email; protected $message; - public const MESSAGE_DEFAULT = 'Build %BUILD_ID% has finished for commit %SHORT_COMMIT_ID% + final public const MESSAGE_DEFAULT = 'Build %BUILD_ID% has finished for commit %SHORT_COMMIT_ID% (%COMMITTER_EMAIL%)> on branch %BRANCH%'; /** @@ -48,9 +48,7 @@ public function __construct(Builder $builder, Build $build, array $options = []) throw new InvalidArgumentException('Please define the "auth_token" for Flowdock Notify plugin!'); } - if (\array_key_exists('auth_token', $options)) { - $this->authToken = $this->builder->interpolate($options['auth_token'], true); - } + $this->authToken = $this->builder->interpolate($options['auth_token'], true); $this->message = isset($options['message']) ? $options['message'] : self::MESSAGE_DEFAULT; $this->email = isset($options['email']) ? $options['email'] : 'PHP Censor'; diff --git a/src/Plugin/Git.php b/src/Plugin/Git.php index e7d63f3c2..f182987d0 100644 --- a/src/Plugin/Git.php +++ b/src/Plugin/Git.php @@ -68,22 +68,13 @@ public function execute() */ protected function runAction($action, array $options = []) { - switch ($action) { - case 'merge': - return $this->runMergeAction($options); - - case 'tag': - return $this->runTagAction($options); - - case 'pull': - return $this->runPullAction($options); - - case 'push': - return $this->runPushAction($options); - } - - - return false; + return match ($action) { + 'merge' => $this->runMergeAction($options), + 'tag' => $this->runTagAction($options), + 'pull' => $this->runPullAction($options), + 'push' => $this->runPushAction($options), + default => false, + }; } /** diff --git a/src/Plugin/Grunt.php b/src/Plugin/Grunt.php index 0d49bac7d..79dabd211 100644 --- a/src/Plugin/Grunt.php +++ b/src/Plugin/Grunt.php @@ -17,7 +17,7 @@ */ class Grunt extends Plugin { - protected $task = null; + protected $task; protected $gruntfile = 'Gruntfile.js'; /** diff --git a/src/Plugin/Gulp.php b/src/Plugin/Gulp.php index 6aff9411a..5b702095c 100644 --- a/src/Plugin/Gulp.php +++ b/src/Plugin/Gulp.php @@ -17,7 +17,7 @@ */ class Gulp extends Plugin { - protected $task = null; + protected $task; protected $gulpfile = 'gulpfile.js'; /** diff --git a/src/Plugin/Lint.php b/src/Plugin/Lint.php index 9a7eb92bf..5a6ecc777 100644 --- a/src/Plugin/Lint.php +++ b/src/Plugin/Lint.php @@ -3,7 +3,6 @@ namespace PHPCensor\Plugin; use DirectoryIterator; -use PHPCensor; use PHPCensor\Builder; use PHPCensor\Model\Build; use PHPCensor\Plugin; @@ -46,7 +45,7 @@ public function __construct(Builder $builder, Build $build, array $options = []) $relativePath = \preg_replace( '#^(\./|/)?(.*)$#', '$2', - $options['directories'][$index] + (string) $options['directories'][$index] ); $relativePath = \rtrim($relativePath, "\//"); @@ -66,10 +65,8 @@ public function execute() { $success = true; - $php = $this->findBinary('php'); - foreach ($this->directories as $dir) { - if (!$this->lintDirectory($php, $dir)) { + if (!$this->lintDirectory($dir)) { $success = false; } } @@ -81,15 +78,15 @@ public function execute() * Lint an item (file or directory) by calling the appropriate method. * @return bool */ - protected function lintItem($php, $item, $itemPath) + protected function lintItem($item, $itemPath) { $success = true; - if ($item->isFile() && $item->getExtension() === 'php' && !$this->lintFile($php, $itemPath)) { + if ($item->isFile() && $item->getExtension() === 'php' && !$this->lintFile($itemPath)) { $success = false; } elseif ($item->isDir() && $this->recursive && - !$this->lintDirectory($php, ($itemPath . '/'))) { + !$this->lintDirectory($itemPath . '/')) { $success = false; } @@ -100,7 +97,7 @@ protected function lintItem($php, $item, $itemPath) * Run php -l against a directory of files. * @return bool */ - protected function lintDirectory($php, $path) + protected function lintDirectory($path) { $success = true; $directory = new DirectoryIterator($this->builder->buildPath . $path); @@ -116,7 +113,7 @@ protected function lintDirectory($php, $path) continue; } - if (!$this->lintItem($php, $item, $itemPath)) { + if (!$this->lintItem($item, $itemPath)) { $success = false; } } @@ -128,11 +125,11 @@ protected function lintDirectory($php, $path) * Run php -l against a specific file. * @return bool */ - protected function lintFile($php, $path) + protected function lintFile($path) { $success = true; - if (!$this->builder->executeCommand($php . ' -l "%s"', $this->builder->buildPath . $path)) { + if (!$this->builder->executeCommand(Builder::PHP_CLI_TAG . ' -l "%s"', $this->builder->buildPath . $path)) { $this->builder->logFailure($path); $success = false; } diff --git a/src/Plugin/Mage.php b/src/Plugin/Mage.php index c276703b8..dc4ebb7ae 100644 --- a/src/Plugin/Mage.php +++ b/src/Plugin/Mage.php @@ -53,7 +53,7 @@ public function execute() return false; } - $result = $this->builder->executeCommand($this->executable . ' deploy to:' . $this->mageEnv); + $result = $this->builder->executeCommand(Builder::PHP_CLI_TAG . ' ' . $this->executable . ' deploy to:' . $this->mageEnv); try { $this->builder->log('########## MAGE LOG BEGIN ##########'); diff --git a/src/Plugin/Mage3.php b/src/Plugin/Mage3.php index c60ab9f47..da047003f 100644 --- a/src/Plugin/Mage3.php +++ b/src/Plugin/Mage3.php @@ -58,7 +58,7 @@ public function execute() return false; } - $result = $this->builder->executeCommand($this->executable . ' -n deploy ' . $this->mageEnv); + $result = $this->builder->executeCommand(Builder::PHP_CLI_TAG . ' ' . $this->executable . ' -n deploy ' . $this->mageEnv); try { $this->builder->log('########## MAGE LOG BEGIN ##########'); diff --git a/src/Plugin/Mysql.php b/src/Plugin/Mysql.php index 04e469bc5..35b7977c5 100644 --- a/src/Plugin/Mysql.php +++ b/src/Plugin/Mysql.php @@ -35,12 +35,12 @@ class Mysql extends Plugin /** * @var string|null */ - protected $dbName = null; + protected $dbName; /** * @var string|null */ - protected $charset = null; + protected $charset; /** * @var array diff --git a/src/Plugin/Option/PhpUnitOptions.php b/src/Plugin/Option/PhpUnitOptions.php index 4bbe70e42..a56ff8a57 100644 --- a/src/Plugin/Option/PhpUnitOptions.php +++ b/src/Plugin/Option/PhpUnitOptions.php @@ -15,19 +15,13 @@ */ class PhpUnitOptions { - protected array $options; - - protected string $location; - protected array $arguments = []; - protected ConfigurationInterface $configuration; - - public function __construct(ConfigurationInterface $configuration, array $options, string $location) - { - $this->configuration = $configuration; - $this->options = $options; - $this->location = $location; + public function __construct( + protected ConfigurationInterface $configuration, + protected array $options, + protected string $location + ) { } /** @@ -54,9 +48,7 @@ public function buildArgumentString() foreach ($this->getCommandArguments() as $argumentName => $argumentValues) { $prefix = $argumentName[0] === '-' ? '' : '--'; - if (!\is_array($argumentValues)) { - $argumentValues = [$argumentValues]; - } + $argumentValues = [$argumentValues]; foreach ($argumentValues as $argValue) { $postfix = ' '; diff --git a/src/Plugin/PackageBuild.php b/src/Plugin/PackageBuild.php index e69fc7ad2..3fb54fd57 100644 --- a/src/Plugin/PackageBuild.php +++ b/src/Plugin/PackageBuild.php @@ -50,7 +50,7 @@ public function execute() return false; } - $filename = \preg_replace('/([^a-zA-Z0-9_-]+)/', '', $this->filename); + $filename = \preg_replace('/([^a-zA-Z0-9_-]+)/', '', (string) $this->filename); if (!\is_array($this->format)) { $this->format = [$this->format]; diff --git a/src/Plugin/Pahout.php b/src/Plugin/Pahout.php index a997ff785..377b58829 100644 --- a/src/Plugin/Pahout.php +++ b/src/Plugin/Pahout.php @@ -20,7 +20,7 @@ class Pahout extends Plugin { /** @var string */ - public const TAB = "\t"; + final public const TAB = "\t"; /** @var string */ protected $directory; @@ -62,7 +62,7 @@ public function execute() } $this->builder->executeCommand( - 'cd "%s" && ' . $pahout . ' %s --format=json', + 'cd "%s" && ' . Builder::PHP_CLI_TAG . ' ' . $pahout . ' %s --format=json', $this->builder->buildPath, $this->directory ); diff --git a/src/Plugin/Pdepend.php b/src/Plugin/Pdepend.php index 74964c0b9..f00ea6b5e 100644 --- a/src/Plugin/Pdepend.php +++ b/src/Plugin/Pdepend.php @@ -104,7 +104,7 @@ public function execute() } $pdepend = $this->executable; - $cmd = 'cd "%s" && ' . $pdepend . ' --summary-xml="%s" --jdepend-chart="%s" --overview-pyramid="%s" %s "%s"'; + $cmd = 'cd "%s" && ' . Builder::PHP_CLI_TAG . ' ' . $pdepend . ' --summary-xml="%s" --jdepend-chart="%s" --overview-pyramid="%s" %s "%s"'; $ignore = ''; if (\count($this->ignore)) { diff --git a/src/Plugin/Pgsql.php b/src/Plugin/Pgsql.php index 88a6f6e1c..c90b8a984 100644 --- a/src/Plugin/Pgsql.php +++ b/src/Plugin/Pgsql.php @@ -32,7 +32,7 @@ class Pgsql extends Plugin /** * @var string|null */ - protected $dbName = null; + protected $dbName; /** * @var array diff --git a/src/Plugin/Phan.php b/src/Plugin/Phan.php index f3eeefe9c..5cb898bca 100644 --- a/src/Plugin/Phan.php +++ b/src/Plugin/Phan.php @@ -78,7 +78,7 @@ public function execute() $phan = $this->findBinary(['phan', 'phan.phar']); // Launch Phan on PHP files with json output - $cmd = $phan.' -f %s -i -m json -o %s'; + $cmd = Builder::PHP_CLI_TAG . ' ' . $phan . ' -f %s -i -m json -o %s'; $this->builder->executeCommand($cmd, $this->location . '/phan.in', $this->location . '/phan.out'); diff --git a/src/Plugin/Phing.php b/src/Plugin/Phing.php index 231dadbe4..a27bd0cf2 100644 --- a/src/Plugin/Phing.php +++ b/src/Plugin/Phing.php @@ -68,7 +68,7 @@ public function execute() { $phingExecutable = $this->executable; - $cmd[] = $phingExecutable . ' -f ' . $this->getBuildFilePath(); + $cmd[] = Builder::PHP_CLI_TAG . ' ' . $phingExecutable . ' -f ' . $this->getBuildFilePath(); if ($this->getPropertyFile()) { $cmd[] = '-propertyfile ' . $this->getPropertyFile(); @@ -101,11 +101,9 @@ private function targetsToString() } /** - * @param array|string $targets - * * @return $this */ - public function setTargets($targets) + public function setTargets(array|string $targets) { if (\is_string($targets)) { $targets = [$targets]; @@ -123,12 +121,11 @@ public function getBuildFile() } /** - * @param mixed $buildFile * * @return $this * @throws Exception */ - public function setBuildFile($buildFile) + public function setBuildFile(mixed $buildFile) { if (!\file_exists($this->directory . $buildFile)) { throw new RuntimeException('Specified build file does not exist.'); @@ -177,11 +174,9 @@ public function propertiesToString() } /** - * @param array|string $properties - * * @return $this */ - public function setProperties($properties) + public function setProperties(array|string $properties) { if (\is_string($properties)) { $properties = [$properties]; diff --git a/src/Plugin/Phlint.php b/src/Plugin/Phlint.php index 91501e8a0..eb74835d1 100644 --- a/src/Plugin/Phlint.php +++ b/src/Plugin/Phlint.php @@ -47,7 +47,7 @@ public function execute() $this->builder->executeCommand( 'cd "%s" && %s analyze --no-interaction --no-ansi', $this->builder->buildPath, - $this->executable + Builder::PHP_CLI_TAG . ' ' . $this->executable ); // Define that the plugin succeed @@ -95,20 +95,18 @@ protected function processReport($output) $errors = []; - if (0 < \count($data)) { - foreach ($data as $error) { - $error = \explode(PHP_EOL, $error); - $header = \substr(\trim(\array_shift($error)), 3); - $file = \strstr(\substr(\strstr($header, 'in '), 3), ':', true); - $line = \substr(\strrchr($header, ':'), 1); - $message = \ltrim($error[0]) . PHP_EOL . \ltrim($error[1]); - - $errors[] = [ - 'message' => $message, - 'file' => $file, - 'line_from' => $line - ]; - } + foreach ($data as $error) { + $error = \explode(PHP_EOL, $error); + $header = \substr(\trim(\array_shift($error)), 3); + $file = \strstr(\substr(\strstr($header, 'in '), 3), ':', true); + $line = \substr(\strrchr($header, ':'), 1); + $message = \ltrim($error[0]) . PHP_EOL . \ltrim($error[1]); + + $errors[] = [ + 'message' => $message, + 'file' => $file, + 'line_from' => $line + ]; } return $errors; diff --git a/src/Plugin/PhpCodeSniffer.php b/src/Plugin/PhpCodeSniffer.php index 082e221c3..b3b66194b 100644 --- a/src/Plugin/PhpCodeSniffer.php +++ b/src/Plugin/PhpCodeSniffer.php @@ -55,17 +55,17 @@ class PhpCodeSniffer extends Plugin implements ZeroConfigPluginInterface /** * @var int */ - protected $severity = null; + protected $severity; /** * @var int|null */ - protected $errorSeverity = null; + protected $errorSeverity; /** * @var int|null */ - protected $warningSeverity = null; + protected $warningSeverity; /** * @return string @@ -151,7 +151,7 @@ public function execute() $this->builder->logExecOutput(false); } - $cmd = 'cd "%s" && ' . $phpcs . ' --report=json %s %s %s %s %s "%s" %s %s %s'; + $cmd = 'cd "%s" && ' . Builder::PHP_CLI_TAG . ' ' . $phpcs . ' --report=json %s %s %s %s %s "%s" %s %s %s'; $this->builder->executeCommand( $cmd, $this->builder->buildPath, @@ -234,7 +234,7 @@ protected function getFlags() */ protected function processReport($output) { - $data = \json_decode(\trim($output), true); + $data = \json_decode(\trim((string) $output), true); if (!\is_array($data)) { $this->builder->log($output); @@ -246,7 +246,7 @@ protected function processReport($output) $warnings = $data['totals']['warnings']; foreach ($data['files'] as $fileName => $file) { - $fileName = \str_replace($this->builder->buildPath, '', $fileName); + $fileName = \str_replace($this->builder->buildPath, '', (string) $fileName); foreach ($file['messages'] as $message) { $this->build->reportError( diff --git a/src/Plugin/PhpCpd.php b/src/Plugin/PhpCpd.php index 8ea652081..39defbead 100644 --- a/src/Plugin/PhpCpd.php +++ b/src/Plugin/PhpCpd.php @@ -78,16 +78,22 @@ public function execute() } $phpcpd = $this->executable; - $lastLine = \exec( - \sprintf('cd "%s" && ' . $phpcpd . ' %s "%s" --version', $this->builder->buildPath, $ignore, $this->directory) + $this->builder->executeCommand( + 'cd "%s" && ' . Builder::PHP_CLI_TAG . ' ' . $phpcpd . ' %s "%s" --version', + $this->builder->buildPath, + $ignore, + $this->directory, ); - if (false !== \strpos($lastLine, '--names-exclude')) { + $this->builder->logExecOutput(true); + + $lastOutput = $this->builder->getLastOutput(); + if (\str_contains($lastOutput, '--names-exclude')) { $ignore = $ignoreForNewVersion; } $tmpFileName = \tempnam(\sys_get_temp_dir(), (self::pluginName() . '_')); - $cmd = 'cd "%s" && ' . $phpcpd . ' --log-pmd "%s" %s "%s"'; + $cmd = 'cd "%s" && ' . Builder::PHP_CLI_TAG . ' ' . $phpcpd . ' --log-pmd "%s" %s "%s"'; $success = $this->builder->executeCommand($cmd, $this->builder->buildPath, $tmpFileName, $ignore, $this->directory); $errorCount = $this->processReport(\file_get_contents($tmpFileName)); @@ -109,7 +115,7 @@ public function execute() */ protected function processReport($xmlString) { - $xml = \simplexml_load_string($xmlString); + $xml = \simplexml_load_string((string) $xmlString); if (false === $xml) { $this->builder->log($xmlString); diff --git a/src/Plugin/PhpCsFixer.php b/src/Plugin/PhpCsFixer.php index 369368200..67fe07548 100644 --- a/src/Plugin/PhpCsFixer.php +++ b/src/Plugin/PhpCsFixer.php @@ -96,7 +96,7 @@ public function execute() $phpCsFixer = $this->executable; // Determine the version of PHP CS Fixer - $cmd = $phpCsFixer . ' --version'; + $cmd = Builder::PHP_CLI_TAG . ' ' . $phpCsFixer . ' --version'; $success = $this->builder->executeCommand($cmd); $output = $this->builder->getLastOutput(); $matches = []; @@ -132,7 +132,7 @@ public function execute() } } - $cmd = $phpCsFixer . ' fix ' . $directory . ' %s'; + $cmd = Builder::PHP_CLI_TAG . ' ' . $phpCsFixer . ' fix ' . $directory . ' %s'; $success = $this->builder->executeCommand($cmd, $this->args); $this->builder->logExecOutput(true); @@ -191,21 +191,11 @@ protected function processReport($output) } $chunkDiff = []; foreach ($chunk->getLines() as $line) { - /** @var Line $line */ - switch ($line->getType()) { - case Line::ADDED: - $symbol = '+'; - - break; - case Line::REMOVED: - $symbol = '-'; - - break; - default: - $symbol = ' '; - - break; - } + $symbol = match ($line->getType()) { + Line::ADDED => '+', + Line::REMOVED => '-', + default => ' ', + }; $chunkDiff[] = $symbol . $line->getContent(); if ($foundChanges) { continue; diff --git a/src/Plugin/PhpDocblockChecker.php b/src/Plugin/PhpDocblockChecker.php index 516a75d2c..f9805be33 100644 --- a/src/Plugin/PhpDocblockChecker.php +++ b/src/Plugin/PhpDocblockChecker.php @@ -110,7 +110,7 @@ public function execute() } // Build command string: - $cmd = $checkerCmd . ' --json --directory="%s"%s%s'; + $cmd = Builder::PHP_CLI_TAG . ' ' . $checkerCmd . ' --json --directory="%s"%s%s'; if (!$this->build->isDebug()) { $this->builder->logExecOutput(false); diff --git a/src/Plugin/PhpLoc.php b/src/Plugin/PhpLoc.php index 0529cc3bf..6da188b87 100644 --- a/src/Plugin/PhpLoc.php +++ b/src/Plugin/PhpLoc.php @@ -65,7 +65,7 @@ public function execute() $phploc = $this->executable; - $success = $this->builder->executeCommand('cd "%s" && php -d xdebug.mode=off -d error_reporting=0 ' . $phploc . ' %s %s', $this->builder->buildPath, $ignore, $this->directory); + $success = $this->builder->executeCommand('cd "%s" && ' . Builder::PHP_CLI_TAG . ' -d xdebug.mode=off -d error_reporting=0 ' . Builder::PHP_CLI_TAG . ' ' . $phploc . ' %s %s', $this->builder->buildPath, $ignore, $this->directory); $output = $this->builder->getLastOutput(); if (\preg_match_all('/\((LOC|CLOC|NCLOC|LLOC)\)\s+([0-9]+)/', $output, $matches)) { diff --git a/src/Plugin/PhpMessDetector.php b/src/Plugin/PhpMessDetector.php index afa99af93..dc354f547 100644 --- a/src/Plugin/PhpMessDetector.php +++ b/src/Plugin/PhpMessDetector.php @@ -115,7 +115,7 @@ protected function overrideSetting($options, $key) */ protected function processReport($xmlString) { - $xml = \simplexml_load_string($xmlString); + $xml = \simplexml_load_string((string) $xmlString); if (false === $xml) { $this->builder->log($xmlString); @@ -160,7 +160,7 @@ protected function tryAndProcessRules() } foreach ($this->rules as &$rule) { - if (\strpos($rule, '/') !== false) { + if (\str_contains((string) $rule, '/')) { $rule = $this->builder->buildPath . $rule; } } @@ -173,7 +173,7 @@ protected function tryAndProcessRules() */ protected function executePhpMd($binaryPath) { - $cmd = 'cd "%s" && ' . $binaryPath . ' "%s" xml %s %s %s'; + $cmd = 'cd "%s" && ' . Builder::PHP_CLI_TAG . ' ' . $binaryPath . ' "%s" xml %s %s %s'; $ignore = ''; if (\is_array($this->ignore) && \count($this->ignore) > 0) { diff --git a/src/Plugin/PhpParallelLint.php b/src/Plugin/PhpParallelLint.php index 4ec480d77..3a98e2ba2 100644 --- a/src/Plugin/PhpParallelLint.php +++ b/src/Plugin/PhpParallelLint.php @@ -57,8 +57,8 @@ public function __construct(Builder $builder, Build $build, array $options = []) // Only use if this is a comma delimited list $pattern = '/^([a-z]+)(,\ *[a-z]*)*$/'; - if (\preg_match($pattern, $options['extensions'])) { - $this->extensions = \str_replace(' ', '', $options['extensions']); + if (\preg_match($pattern, (string) $options['extensions'])) { + $this->extensions = \str_replace(' ', '', (string) $options['extensions']); } } } @@ -84,7 +84,7 @@ public function execute() $phplint = $this->executable; - $cmd = $phplint . ' -e %s' . '%s %s "%s"'; + $cmd = Builder::PHP_CLI_TAG . ' ' . $phplint . ' -e %s' . '%s %s "%s"'; $success = $this->builder->executeCommand( $cmd, $this->extensions, diff --git a/src/Plugin/PhpSpec.php b/src/Plugin/PhpSpec.php index c285dcdbe..ddd916edf 100644 --- a/src/Plugin/PhpSpec.php +++ b/src/Plugin/PhpSpec.php @@ -40,7 +40,7 @@ public function execute() { $phpspec = $this->executable; - $success = $this->builder->executeCommand($phpspec . ' --format=junit --no-code-generation run'); + $success = $this->builder->executeCommand(Builder::PHP_CLI_TAG . ' ' . $phpspec . ' --format=junit --no-code-generation run'); $output = $this->builder->getLastOutput(); /* diff --git a/src/Plugin/PhpStan.php b/src/Plugin/PhpStan.php index 270efe20e..a6f1e982e 100644 --- a/src/Plugin/PhpStan.php +++ b/src/Plugin/PhpStan.php @@ -65,7 +65,7 @@ public function execute() } $this->builder->executeCommand( - 'cd "%s" && ' . $phpStan . ' analyze --error-format=json %s', + 'cd "%s" && ' . Builder::PHP_CLI_TAG . ' ' . $phpStan . ' analyze --error-format=json %s', $this->builder->buildPath, \implode(' ', $this->directories) ); @@ -83,18 +83,18 @@ public function execute() foreach ($files as $file => $payload) { if (0 < $payload['errors']) { - $file = \str_replace($this->build->getBuildPath(), '', $file); + $file = \str_replace($this->build->getBuildPath(), '', (string) $file); $len = \strlen($file); $out = ''; - $filename = (false !== \strpos($file, ' (')) ? \strstr($file, ' (', true) : $file; + $filename = (\str_contains($file, ' (')) ? \strstr($file, ' (', true) : $file; foreach ($payload['messages'] as $message) { - if (\strlen($message['message']) > $len) { - $len = \strlen($message['message']); + if (\strlen((string) $message['message']) > $len) { + $len = \strlen((string) $message['message']); } $out .= \vsprintf(' %d%s %s' . PHP_EOL, [ $message['line'], - \str_repeat(' ', 6 - \strlen($message['line'])), + \str_repeat(' ', 6 - \strlen((string) $message['line'])), $message['message'] ]); diff --git a/src/Plugin/PhpTalLint.php b/src/Plugin/PhpTalLint.php index 61e549fdd..720c20f31 100644 --- a/src/Plugin/PhpTalLint.php +++ b/src/Plugin/PhpTalLint.php @@ -109,7 +109,7 @@ protected function lintItem($item, $itemPath) { $success = true; - if ($item->isFile() && \in_array(\strtolower($item->getExtension()), $this->suffixes, true)) { + if ($item->isFile() && \in_array(\strtolower((string) $item->getExtension()), $this->suffixes, true)) { if (!$this->lintFile($itemPath)) { $success = false; } @@ -160,7 +160,7 @@ protected function lintFile($path) $lint = __DIR__ . '/'; $lint .= 'vendor/phptal/phptal/'; $lint .= 'tools/phptal_lint.php'; - $cmd = 'php ' . $lint . ' %s "%s"'; + $cmd = Builder::PHP_CLI_TAG . ' ' . $lint . ' %s "%s"'; $this->builder->executeCommand($cmd, $suffixes, $this->builder->buildPath . $path); @@ -175,7 +175,7 @@ protected function lintFile($path) unset($rows[3]); foreach ($rows as $row) { - $name = \basename($path); + $name = \basename((string) $path); $row = \str_replace('(use -i to include your custom modifier functions)', '', $row); $message = \str_replace($name . ': ', '', $row); diff --git a/src/Plugin/PhpUnit.php b/src/Plugin/PhpUnit.php index aa8aad285..2afd30ce1 100644 --- a/src/Plugin/PhpUnit.php +++ b/src/Plugin/PhpUnit.php @@ -3,7 +3,6 @@ namespace PHPCensor\Plugin; use Exception; -use PHPCensor; use PHPCensor\Builder; use PHPCensor\Model\Build; use PHPCensor\Model\BuildError; @@ -47,10 +46,7 @@ class PhpUnit extends Plugin implements ZeroConfigPluginInterface */ protected $buildBranchLocation; - /** - * @var PhpUnitOptions - */ - protected $options; + protected PhpUnitOptions $phpunitOptions; /** * @return string @@ -83,7 +79,7 @@ public function __construct(Builder $builder, Build $build, array $options = []) $this->buildLocation = PUBLIC_DIR . 'artifacts/phpunit/' . $this->buildDirectory; $this->buildBranchLocation = PUBLIC_DIR . 'artifacts/phpunit/' . $this->buildBranchDirectory; - $this->options = new PhpUnitOptions($this->builder->getConfiguration(), $options, $this->buildLocation); + $this->phpunitOptions = new PhpUnitOptions($this->builder->getConfiguration(), $options, $this->buildLocation); $this->executable = $this->findBinary(['phpunit', 'phpunit.phar']); } @@ -107,17 +103,23 @@ public static function canExecuteOnStage($stage, Build $build) */ public function execute() { - $xmlConfigFiles = $this->options->getConfigFiles($this->build->getBuildPath()); - $directories = $this->options->getDirectories(); + $xmlConfigFiles = $this->phpunitOptions->getConfigFiles($this->build->getBuildPath()); + $directories = $this->phpunitOptions->getDirectories(); if (empty($xmlConfigFiles) && empty($directories)) { $this->builder->logFailure('Neither a configuration file nor a test directory found.'); return false; } - $cmd = $this->executable; - $lastLine = \exec($cmd . ' --log-json . --version'); - if (false !== \strpos($lastLine, '--log-json')) { + $cmd = $this->executable; + + $this->builder->executeCommand( + Builder::PHP_CLI_TAG . ' ' . $cmd . ' --log-json . --version', + ); + $this->builder->logExecOutput(true); + + $lastOutput = $this->builder->getLastOutput(); + if (\str_contains($lastOutput, '--log-json')) { $logFormat = 'junit'; // --log-json is not supported } else { $logFormat = 'json'; @@ -131,11 +133,8 @@ public function execute() $success[] = $this->runConfig($directory, null, $logFormat); } } else { - // Run any config files - if (!empty($xmlConfigFiles)) { - foreach ($xmlConfigFiles as $configFile) { - $success[] = $this->runConfig($this->options->getTestsPath(), $configFile, $logFormat); - } + foreach ($xmlConfigFiles as $configFile) { + $success[] = $this->runConfig($this->phpunitOptions->getTestsPath(), $configFile, $logFormat); } } @@ -162,7 +161,7 @@ protected function runConfig($directory, $configFile, $logFormat) $fileSystem = new Filesystem(); - $options = clone $this->options; + $options = clone $this->phpunitOptions; $buildPath = $this->build->getBuildPath(); // Save the results into a log file @@ -190,7 +189,7 @@ protected function runConfig($directory, $configFile, $logFormat) } $arguments = $this->builder->interpolate($options->buildArgumentString(), true); - $cmd = $this->executable . ' %s %s'; + $cmd = Builder::PHP_CLI_TAG . ' ' . $this->executable . ' %s %s'; if ($options->getOption('coverage')) { $cmd = 'XDEBUG_MODE=coverage ' . $cmd; @@ -283,8 +282,8 @@ protected function executePhpUnitCommand($cmd, $arguments, $directory) protected function checkRequiredCoverage($coverage) { foreach ($coverage as $key => $currentValue) { - if ($requiredValue = $this->options->getOption(\implode('_', ['required', $key, 'coverage']))) { - if (\bccomp($requiredValue, $currentValue) === 1) { + if ($requiredValue = $this->phpunitOptions->getOption(\implode('_', ['required', $key, 'coverage']))) { + if (\bccomp($requiredValue, (string) $currentValue) === 1) { return false; } } diff --git a/src/Plugin/Psalm.php b/src/Plugin/Psalm.php index 257add7d7..d5582f3b6 100644 --- a/src/Plugin/Psalm.php +++ b/src/Plugin/Psalm.php @@ -58,7 +58,7 @@ public function execute() $this->builder->logExecOutput(false); } - $this->builder->executeCommand('cd "%s" && ' . $psalm . ' --output-format=json', $this->builder->buildPath); + $this->builder->executeCommand('cd "%s" && ' . Builder::PHP_CLI_TAG . ' ' . $psalm . ' --output-format=json', $this->builder->buildPath); $this->builder->logExecOutput(true); // Define that the plugin succeed diff --git a/src/Plugin/SecurityChecker.php b/src/Plugin/SecurityChecker.php index 53bfeebe2..e67d5844b 100644 --- a/src/Plugin/SecurityChecker.php +++ b/src/Plugin/SecurityChecker.php @@ -91,10 +91,10 @@ public function execute() } if ('symfony' === $this->binaryType) { - $cmd = '%s check:security --format=json --dir=%s'; + $cmd = Builder::PHP_CLI_TAG . ' %s check:security --format=json --dir=%s'; $executable = $this->findBinary('symfony'); } else { - $cmd = '%s --format=json --path="%s"'; + $cmd = Builder::PHP_CLI_TAG . ' %s --format=json --path="%s"'; $executable = $this->findBinary('local-php-security-checker'); } diff --git a/src/Plugin/SensiolabsInsight.php b/src/Plugin/SensiolabsInsight.php index 4bd7790c0..2c9a84bfd 100644 --- a/src/Plugin/SensiolabsInsight.php +++ b/src/Plugin/SensiolabsInsight.php @@ -100,7 +100,7 @@ public function execute() */ protected function processReport($xmlString) { - $xml = \simplexml_load_string($xmlString); + $xml = \simplexml_load_string((string) $xmlString); if ($xml === false) { $this->builder->log($xmlString); @@ -137,7 +137,7 @@ protected function processReport($xmlString) */ protected function executeSensiolabsInsight($binaryPath) { - $cmd = $binaryPath . ' -n analyze --reference %s %s --api-token %s --user-uuid %s'; + $cmd = Builder::PHP_CLI_TAG . ' ' . $binaryPath . ' -n analyze --reference %s %s --api-token %s --user-uuid %s'; // Run Sensiolabs Insight: $this->builder->executeCommand( @@ -148,7 +148,7 @@ protected function executeSensiolabsInsight($binaryPath) $this->userUuid ); - $cmd = $binaryPath . ' -n analysis --format pmd %s --api-token %s --user-uuid %s'; + $cmd = Builder::PHP_CLI_TAG . ' ' . $binaryPath . ' -n analysis --format pmd %s --api-token %s --user-uuid %s'; // Run Sensiolabs Insight: $this->builder->executeCommand( diff --git a/src/Plugin/Shell.php b/src/Plugin/Shell.php index debc07193..cc1bc8da2 100644 --- a/src/Plugin/Shell.php +++ b/src/Plugin/Shell.php @@ -45,8 +45,6 @@ public function __construct(Builder $builder, Build $build, array $options = []) if (isset($options['commands']) && \is_array($options['commands'])) { $this->commands = $options['commands']; - - return; } } diff --git a/src/Plugin/SlackNotify.php b/src/Plugin/SlackNotify.php index 0b69bf9ae..89c7228c1 100644 --- a/src/Plugin/SlackNotify.php +++ b/src/Plugin/SlackNotify.php @@ -44,7 +44,7 @@ public function __construct(Builder $builder, Build $build, array $options = []) parent::__construct($builder, $build, $options); if (\is_array($options) && isset($options['webhook_url'])) { - $this->webHook = \trim($options['webhook_url']); + $this->webHook = \trim((string) $options['webhook_url']); if (isset($options['message'])) { $this->message = $options['message']; diff --git a/src/Plugin/TechnicalDebt.php b/src/Plugin/TechnicalDebt.php index 8c19f77ec..bdb0e213c 100644 --- a/src/Plugin/TechnicalDebt.php +++ b/src/Plugin/TechnicalDebt.php @@ -100,14 +100,13 @@ protected function returnResult() $string = ''; $fileNumber = 0; foreach ($this->errorPerFile as $oneLine) { - $fileNumber += \strlen($oneLine); - $string .= \str_pad($oneLine, 60, ' ', STR_PAD_RIGHT); + $fileNumber += \strlen((string) $oneLine); + $string .= \str_pad((string) $oneLine, 60, ' ', STR_PAD_RIGHT); $string .= \str_pad($fileNumber, 4, ' ', STR_PAD_LEFT); $string .= "/" . $this->numberOfAnalysedFile . " (" . \floor($fileNumber * 100 / $this->numberOfAnalysedFile) . " %)\n"; } - $string .= "Checked {$fileNumber} files\n"; - return $string; + return $string . "Checked {$fileNumber} files\n"; } /** @@ -196,7 +195,7 @@ protected function getErrorList() $ignoreAbsolute = $this->builder->buildPath . $ignore; if ('/' === $ignoreAbsolute[0]) { - if (0 === \strpos($filePath, $ignoreAbsolute)) { + if (\str_starts_with($filePath, $ignoreAbsolute)) { $ignored = true; break; @@ -212,7 +211,7 @@ protected function getErrorList() $line = \fgets($handle); foreach ($this->searches as $search) { - if ($technicalDebtLine = \trim(\strstr($line, $search))) { + if ($technicalDebtLine = \trim(\strstr($line, (string) $search))) { $fileName = \str_replace($this->directory, '', $filePath); $this->build->reportError( diff --git a/src/Plugin/TelegramNotify.php b/src/Plugin/TelegramNotify.php index dbbb0bb58..2e7ce5d8d 100644 --- a/src/Plugin/TelegramNotify.php +++ b/src/Plugin/TelegramNotify.php @@ -51,9 +51,7 @@ public function __construct(Builder $builder, Build $build, array $options = []) throw new InvalidArgumentException("Not setting recipients"); } - if (\array_key_exists('auth_token', $options)) { - $this->authToken = $this->builder->interpolate($options['auth_token'], true); - } + $this->authToken = $this->builder->interpolate($options['auth_token'], true); $this->message = '[%ICON_BUILD%] [%PROJECT_TITLE%](%PROJECT_LINK%)' . ' - [Build #%BUILD_ID%](%BUILD_LINK%) has finished ' . @@ -153,16 +151,15 @@ private function buildMessage() $this->buildMsg .= $firstRow === 'composer' ? '' : ('```' . \mb_substr($bm, $pos) . '```'); } - return $this->builder->interpolate(\str_replace(['%ICON_BUILD%'], [$buildIcon], $this->message)); + return $this->builder->interpolate(\str_replace(['%ICON_BUILD%'], [$buildIcon], (string) $this->message)); } /** * Split chat group id to chat id and topic id * - * @param int|string $chatId * @return array{string, string|null} */ - protected function splitChatIdAndTopicId($chatId) + protected function splitChatIdAndTopicId(int|string $chatId) { $parts = \explode('/', \trim((string) $chatId) . '/'); $topicId = $parts[1] !== '' ? $parts[1] : null; diff --git a/src/Plugin/Util/BitbucketNotifyPluginResult.php b/src/Plugin/Util/BitbucketNotifyPluginResult.php index 8157dcdb6..65efd2adb 100644 --- a/src/Plugin/Util/BitbucketNotifyPluginResult.php +++ b/src/Plugin/Util/BitbucketNotifyPluginResult.php @@ -8,27 +8,23 @@ * * @author Dmitry Khomutov */ -class BitbucketNotifyPluginResult +class BitbucketNotifyPluginResult implements \Stringable { public const DEFAULT_PLUGIN_OUTPUT_FORMAT = "%s | %d\t=> %d\t%s"; - /** @var string $plugin */ - protected $plugin; - - /** @var int $left */ - protected $left; - - /** @var int $right */ - protected $right; - /** @var string $outputFormat */ protected $outputFormat = self::DEFAULT_PLUGIN_OUTPUT_FORMAT; - public function __construct($plugin, $left, $right) - { - $this->plugin = $plugin; - $this->left = $left; - $this->right = $right; + /** + * @param string $plugin + * @param int $left + * @param int $right + */ + public function __construct( + protected $plugin, + protected $left, + protected $right + ) { } public function getPlugin() @@ -112,7 +108,7 @@ protected function getTaskDescriptionMessage() return 'pls fix %s because it has increased from %d to %d errors'; } - public function __toString() + public function __toString(): string { return $this->plugin; } diff --git a/src/Plugin/Util/Executor.php b/src/Plugin/Util/Executor.php index e4ff1b2ba..ac23be639 100644 --- a/src/Plugin/Util/Executor.php +++ b/src/Plugin/Util/Executor.php @@ -21,33 +21,12 @@ */ class Executor { - /** - * @var BuildLogger - */ - protected $logger; - - /** - * @var Factory - */ - protected $pluginFactory; - - /** - * @var BuildStore - */ - protected $store; - - protected StoreRegistry $storeRegistry; - public function __construct( - StoreRegistry $storeRegistry, - Factory $pluginFactory, - BuildLogger $logger, - BuildStore $store = null + protected StoreRegistry $storeRegistry, + protected Factory $pluginFactory, + protected BuildLogger $logger, + protected ?BuildStore $store = null ) { - $this->storeRegistry = $storeRegistry; - $this->pluginFactory = $pluginFactory; - $this->logger = $logger; - $this->store = $store; } /** @@ -82,20 +61,18 @@ public function executePlugins($config, $stage) /** * @param array $config * @param string $branch - * - * @return array|bool */ - public function getBranchSpecificConfig($config, $branch) + public function getBranchSpecificConfig($config, $branch): array|bool { $configSections = \array_keys($config); foreach ($configSections as $configSection) { - if (0 === \strpos($configSection, 'branch-')) { + if (\str_starts_with($configSection, 'branch-')) { if ($configSection === ('branch-' . $branch)) { return $config[$configSection]; } - if (0 === \strpos($configSection, 'branch-regex:')) { + if (\str_starts_with($configSection, 'branch-regex:')) { $pattern = '#' . \substr($configSection, 13) . '#u'; \preg_match($pattern, $branch, $matches); if (!empty($matches[0])) { @@ -174,7 +151,7 @@ protected function doExecutePlugins($plugins, $stage) $this->logger->log(''); $this->logger->logSuccess( - \sprintf('RUNNING PLUGIN: %s (Step: %s) (Stage: %s)', Lang::get($plugin), $step, \ucfirst($stage)) + \sprintf('RUNNING PLUGIN: %s (Step: %s) (Stage: %s)', Lang::get($plugin), $step, \ucfirst((string) $stage)) ); $this->setPluginStatus($stage, $step, $plugin, Plugin::STATUS_RUNNING); @@ -224,7 +201,7 @@ public function executePlugin($plugin, $options) { $class = $plugin; if (!\class_exists($class)) { - $class = \str_replace('_', ' ', $plugin); + $class = \str_replace('_', ' ', (string) $plugin); $class = \ucwords($class); $class = 'PHPCensor\Plugin\\' . \str_replace(' ', '', $class); diff --git a/src/Plugin/Util/Factory.php b/src/Plugin/Util/Factory.php index e04210e0c..4d948dbb9 100644 --- a/src/Plugin/Util/Factory.php +++ b/src/Plugin/Util/Factory.php @@ -16,16 +16,10 @@ */ class Factory { - private Builder $builder; - - private Build $build; - public function __construct( - Builder $builder, - Build $build + private readonly Builder $builder, + private readonly Build $build ) { - $this->builder = $builder; - $this->build = $build; } public function buildPlugin(string $className, array $options = []): Plugin diff --git a/src/Plugin/Util/PhpUnitResult.php b/src/Plugin/Util/PhpUnitResult.php index e90788cb8..ba4f0c811 100644 --- a/src/Plugin/Util/PhpUnitResult.php +++ b/src/Plugin/Util/PhpUnitResult.php @@ -15,23 +15,20 @@ */ abstract class PhpUnitResult { - public const SEVERITY_PASS = 'success'; - public const SEVERITY_FAIL = 'fail'; - public const SEVERITY_ERROR = 'error'; - public const SEVERITY_SKIPPED = 'skipped'; - public const SEVERITY_WARN = self::SEVERITY_PASS; - public const SEVERITY_RISKY = self::SEVERITY_PASS; - - protected $outputFile; - protected $buildPath; + final public const SEVERITY_PASS = 'success'; + final public const SEVERITY_FAIL = 'fail'; + final public const SEVERITY_ERROR = 'error'; + final public const SEVERITY_SKIPPED = 'skipped'; + final public const SEVERITY_WARN = self::SEVERITY_PASS; + final public const SEVERITY_RISKY = self::SEVERITY_PASS; protected $results; protected $failures = 0; protected $errors = []; - public function __construct($outputFile, $buildPath = '') - { - $this->outputFile = $outputFile; - $this->buildPath = $buildPath; + public function __construct( + protected $outputFile, + protected $buildPath = '' + ) { } /** diff --git a/src/Plugin/Util/PhpUnitResultJson.php b/src/Plugin/Util/PhpUnitResultJson.php index da47d4088..6f4cafd2e 100644 --- a/src/Plugin/Util/PhpUnitResultJson.php +++ b/src/Plugin/Util/PhpUnitResultJson.php @@ -16,9 +16,9 @@ */ class PhpUnitResultJson extends PhpUnitResult { - public const EVENT_TEST = 'test'; - public const EVENT_TEST_START = 'testStart'; - public const EVENT_SUITE_START = 'suiteStart'; + final public const EVENT_TEST = 'test'; + final public const EVENT_TEST_START = 'testStart'; + final public const EVENT_SUITE_START = 'suiteStart'; protected $options; protected $arguments = []; @@ -86,7 +86,7 @@ protected function getSeverity($testCase) break; case 'error': - if (\strpos($testCase['message'], 'Skipped') === 0 || \strpos($testCase['message'], 'Incomplete') === 0) { + if (\str_starts_with((string) $testCase['message'], 'Skipped') || \str_starts_with((string) $testCase['message'], 'Incomplete')) { $severity = self::SEVERITY_SKIPPED; } else { $severity = self::SEVERITY_ERROR; @@ -136,7 +136,7 @@ protected function buildTrace($testCase) if (!empty($testCase['trace'])) { foreach ($testCase['trace'] as $step) { - $line = \str_replace($this->buildPath, '', $step['file']) . ':' . $step['line']; + $line = \str_replace($this->buildPath, '', (string) $step['file']) . ':' . $step['line']; $formattedTrace[] = $line; } } @@ -163,7 +163,7 @@ protected function getFileAndLine($testCase) \reset($testCase['trace']); return [ - 'file' => \str_replace($this->buildPath, '', $firstTrace['file']), + 'file' => \str_replace($this->buildPath, '', (string) $firstTrace['file']), 'line' => $firstTrace['line'] ]; } diff --git a/src/Plugin/Util/PhpUnitResultJunit.php b/src/Plugin/Util/PhpUnitResultJunit.php index 003ad5874..8ae6a896c 100644 --- a/src/Plugin/Util/PhpUnitResultJunit.php +++ b/src/Plugin/Util/PhpUnitResultJunit.php @@ -88,10 +88,10 @@ protected function buildMessage($testCase) $msg = $this->getMessageTrace($testCase); if ('' !== $msg) { //strip trace - $trPos = \strrpos($msg, "\n\n"); + $trPos = \strrpos((string) $msg, "\n\n"); if (false !== $trPos) { $tracePos = $trPos; - $msg = \substr($msg, 0, $trPos); + $msg = \substr((string) $msg, 0, $trPos); } } if ('' === $msg) { @@ -114,7 +114,7 @@ protected function buildTrace($testCase) } if ($testCase['_tracePos'] >= 0) { - $stackStr = \substr($this->getMessageTrace($testCase), (int)$testCase['_tracePos'] + 2, -1); + $stackStr = \substr((string) $this->getMessageTrace($testCase), (int)$testCase['_tracePos'] + 2, -1); $trace = \explode("\n", \str_replace($this->buildPath, '.', $stackStr)); } else { $trace = []; @@ -162,7 +162,7 @@ private function loadResultFile() /** * @param string $description */ - private function internalProblem($description) + private function internalProblem($description): never { throw new RuntimeException($description); } @@ -172,7 +172,7 @@ protected function getFileAndLine($testCase) $attributes = $testCase->attributes(); return [ - 'file' => \str_replace($this->buildPath, '', $attributes['file']), + 'file' => \str_replace($this->buildPath, '', (string) $attributes['file']), 'line' => (int) $attributes['line'] ]; } diff --git a/src/Plugin/Util/TestResultParsers/Codeception.php b/src/Plugin/Util/TestResultParsers/Codeception.php index b64c57cb5..5e9e0ce7e 100644 --- a/src/Plugin/Util/TestResultParsers/Codeception.php +++ b/src/Plugin/Util/TestResultParsers/Codeception.php @@ -16,16 +16,6 @@ */ class Codeception implements ParserInterface { - /** - * @var Builder - */ - protected $builder; - - /** - * @var string - */ - protected $xmlPath; - /** * @var array */ @@ -54,10 +44,10 @@ class Codeception implements ParserInterface /** * @param string $xmlPath */ - public function __construct(Builder $builder, $xmlPath) - { - $this->builder = $builder; - $this->xmlPath = $xmlPath; + public function __construct( + protected Builder $builder, + protected $xmlPath + ) { } /** diff --git a/src/Plugin/WebhookNotify.php b/src/Plugin/WebhookNotify.php index eb0e7a0fe..271536c8a 100644 --- a/src/Plugin/WebhookNotify.php +++ b/src/Plugin/WebhookNotify.php @@ -25,7 +25,7 @@ class WebhookNotify extends Plugin /** * @var string The URL to send the webhook to. */ - private string $url; + private readonly string $url; /** * @return string @@ -51,7 +51,7 @@ public function __construct(Builder $builder, Build $build, array $options = []) if (!isset($options['url'])) { throw new InvalidArgumentException('Please define the url for webhook_notify plugin!'); } - $this->url = \trim($options['url']); + $this->url = \trim((string) $options['url']); } /** @@ -93,7 +93,7 @@ public function execute() $this->url, ['json' => $payload] ); - } catch (GuzzleException $e) { + } catch (GuzzleException) { return false; } @@ -102,25 +102,12 @@ public function execute() private function getReadableStatus($statusId) { - switch ($statusId) { - case self::STATUS_PENDING: - return 'Pending'; - - break; - case self::STATUS_RUNNING: - return 'Running'; - - break; - case self::STATUS_SUCCESS: - return 'Successful'; - - break; - case self::STATUS_FAILED: - return 'Failed'; - - break; - } - - return \sprintf('Unknown (%d)', $statusId); + return match ($statusId) { + self::STATUS_PENDING => 'Pending', + self::STATUS_RUNNING => 'Running', + self::STATUS_SUCCESS => 'Successful', + self::STATUS_FAILED => 'Failed', + default => \sprintf('Unknown (%d)', $statusId), + }; } } diff --git a/src/Plugin/Wipe.php b/src/Plugin/Wipe.php index 590f2f025..455329455 100644 --- a/src/Plugin/Wipe.php +++ b/src/Plugin/Wipe.php @@ -25,14 +25,6 @@ public static function pluginName() return 'wipe'; } - /** - * {@inheritDoc} - */ - public function __construct(Builder $builder, Build $build, array $options = []) - { - parent::__construct($builder, $build, $options); - } - /** * Wipes a directory's contents */ diff --git a/src/Security/Authentication/Service.php b/src/Security/Authentication/Service.php index 58b7ff901..86976184c 100644 --- a/src/Security/Authentication/Service.php +++ b/src/Security/Authentication/Service.php @@ -19,7 +19,7 @@ class Service /** * The table of providers. */ - private array $providers; + private readonly array $providers; public function __construct( ConfigurationInterface $configuration, @@ -47,7 +47,7 @@ public function __construct( public static function buildProvider(StoreRegistry $storeRegistry, string $key, array $config): UserProviderInterface { - $class = \ucfirst($config['type']); + $class = \ucfirst((string) $config['type']); if (\class_exists('\\PHPCensor\\Security\\Authentication\\UserProvider\\' . $class)) { $class = '\\PHPCensor\\Security\\Authentication\\UserProvider\\' . $class; } diff --git a/src/Security/Authentication/UserProvider/AbstractProvider.php b/src/Security/Authentication/UserProvider/AbstractProvider.php index 683a49663..4d0b9ed72 100644 --- a/src/Security/Authentication/UserProvider/AbstractProvider.php +++ b/src/Security/Authentication/UserProvider/AbstractProvider.php @@ -16,20 +16,11 @@ */ abstract class AbstractProvider implements UserProviderInterface { - protected string $key; - - protected array $config; - - protected StoreRegistry $storeRegistry; - public function __construct( - StoreRegistry $storeRegistry, - string $key, - array $config + protected StoreRegistry $storeRegistry, + protected string $key, + protected array $config ) { - $this->key = $key; - $this->config = $config; - $this->storeRegistry = $storeRegistry; } public function getKey(): string diff --git a/src/Service/BuildService.php b/src/Service/BuildService.php index ac12d10a1..c93a8f1b9 100644 --- a/src/Service/BuildService.php +++ b/src/Service/BuildService.php @@ -35,30 +35,15 @@ */ class BuildService { - private BuildStore $buildStore; - - private ProjectStore $projectStore; - - private ConfigurationInterface $configuration; - - private StoreRegistry $storeRegistry; - - private BuildFactory $buildFactory; - public bool $queueError = false; public function __construct( - ConfigurationInterface $configuration, - StoreRegistry $storeRegistry, - BuildFactory $buildFactory, - BuildStore $buildStore, - ProjectStore $projectStore + private readonly ConfigurationInterface $configuration, + private readonly StoreRegistry $storeRegistry, + private readonly BuildFactory $buildFactory, + private readonly BuildStore $buildStore, + private readonly ProjectStore $projectStore ) { - $this->configuration = $configuration; - $this->storeRegistry = $storeRegistry; - $this->buildStore = $buildStore; - $this->projectStore = $projectStore; - $this->buildFactory = $buildFactory; } public function createBuild( @@ -280,7 +265,7 @@ public function createDuplicateBuild(Build $originalBuild, int $source): Build public function deleteOldByProject(int $projectId): void { $keepBuilds = (int)$this->configuration->get('php-censor.build.keep_builds', 100); - $builds = $this->buildStore->getOldByProject((int)$projectId, $keepBuilds); + $builds = $this->buildStore->getOldByProject($projectId, $keepBuilds); /** @var Build $build */ foreach ($builds['items'] as $build) { @@ -291,7 +276,7 @@ public function deleteOldByProject(int $projectId): void public function deleteAllByProject(int $projectId): void { - $this->buildStore->deleteAllByProject((int)$projectId); + $this->buildStore->deleteAllByProject($projectId); try { $projectPaths = [ @@ -310,7 +295,7 @@ public function deleteAllByProject(int $projectId): void $fileSystem->remove($projectPath); } } - } catch (\Throwable $e) { + } catch (\Throwable) { } } @@ -366,7 +351,7 @@ public function addJobToQueue(string $jobType, array $jobData, int $queuePriorit PheanstalkInterface::DEFAULT_DELAY, $this->configuration->get('php-censor.queue.lifetime', 600) ); - } catch (\Throwable $ex) { + } catch (\Throwable) { $this->queueError = true; } } diff --git a/src/Service/BuildStatusService.php b/src/Service/BuildStatusService.php index 12230e076..dceb3cd1f 100644 --- a/src/Service/BuildStatusService.php +++ b/src/Service/BuildStatusService.php @@ -20,12 +20,6 @@ class BuildStatusService { private ?BuildStatusService $prevService = null; - private Project $project; - - private string $branch; - - private ?Build $build; - private string $url; private array $finishedStatusIds = [ @@ -34,14 +28,11 @@ class BuildStatusService ]; public function __construct( - string $branch, - Project $project, - ?Build $build = null, + private readonly string $branch, + private readonly Project $project, + private readonly ?Build $build = null, bool $isParent = false ) { - $this->project = $project; - $this->branch = $branch; - $this->build = $build; if ($this->build) { $this->loadParentBuild($isParent); } diff --git a/src/Service/ProjectService.php b/src/Service/ProjectService.php index d90f5de20..f094108a7 100644 --- a/src/Service/ProjectService.php +++ b/src/Service/ProjectService.php @@ -22,16 +22,10 @@ */ class ProjectService { - private ProjectStore $projectStore; - - private StoreRegistry $storeRegistry; - public function __construct( - StoreRegistry $storeRegistry, - ProjectStore $projectStore + private readonly StoreRegistry $storeRegistry, + private readonly ProjectStore $projectStore ) { - $this->storeRegistry = $storeRegistry; - $this->projectStore = $projectStore; } /** @@ -42,7 +36,7 @@ public function createProject(string $title, string $type, string $reference, in // Create base project and use updateProject() to set its properties: $project = new Project($this->storeRegistry); $project->setCreateDate(new DateTime()); - $project->setUserId((int)$userId); + $project->setUserId($userId); return $this->updateProject($project, $title, $type, $reference, $options); } diff --git a/src/Service/UserService.php b/src/Service/UserService.php index 49b1a19f0..cb91d31ba 100644 --- a/src/Service/UserService.php +++ b/src/Service/UserService.php @@ -19,20 +19,20 @@ */ class UserService { - private UserStore $store; - - private StoreRegistry $storeRegistry; - public function __construct( - StoreRegistry $storeRegistry, - UserStore $store + private readonly StoreRegistry $storeRegistry, + private readonly UserStore $store ) { - $this->storeRegistry = $storeRegistry; - $this->store = $store; } - public function createUser(string $name, string $email, string $providerKey, array $providerData, string $password, bool $isAdmin = false): ?User - { + public function createUser( + string $name, + string $email, + string $providerKey, + array $providerData, + string $password, + bool $isAdmin = false + ): ?User { $user = new User($this->storeRegistry); $user->setName($name); $user->setEmail($email); diff --git a/src/Store.php b/src/Store.php index 02949dabf..ba3ca7b70 100644 --- a/src/Store.php +++ b/src/Store.php @@ -23,16 +23,10 @@ abstract class Store protected string $primaryKey = 'id'; - protected DatabaseManager $databaseManager; - - protected StoreRegistry $storeRegistry; - public function __construct( - DatabaseManager $databaseManager, - StoreRegistry $storeRegistry + protected DatabaseManager $databaseManager, + protected StoreRegistry $storeRegistry ) { - $this->databaseManager = $databaseManager; - $this->storeRegistry = $storeRegistry; } public function getById(int $id, string $useConnection = 'read'): ?Model @@ -146,7 +140,7 @@ public function getWhere( public function save(Model $model): ?Model { if (!($model instanceof $this->modelName)) { - throw new InvalidArgumentException(\get_class($model) . ' is an invalid model type for this store.'); + throw new InvalidArgumentException($model::class . ' is an invalid model type for this store.'); } $data = $this->getData($model); @@ -242,7 +236,7 @@ protected function saveByInsert(Model $model, array $data): ?Model public function delete(Model $model): bool { if (!($model instanceof $this->modelName)) { - throw new InvalidArgumentException(\get_class($model) . ' is an invalid model type for this store.'); + throw new InvalidArgumentException($model::class . ' is an invalid model type for this store.'); } $query = $this->databaseManager->getConnection('write') @@ -268,7 +262,7 @@ protected function fieldCheck(string $field): string throw new InvalidArgumentException('You cannot have an empty field name.'); } - if (\strpos($field, '.') === false) { + if (!\str_contains($field, '.')) { return '{{' . $this->tableName . '}}.{{' . $field . '}}'; } diff --git a/src/Store/BuildErrorStore.php b/src/Store/BuildErrorStore.php index b40894faf..13d05dd61 100644 --- a/src/Store/BuildErrorStore.php +++ b/src/Store/BuildErrorStore.php @@ -62,10 +62,10 @@ public function getByBuildId(int $buildId, ?int $limit = null, int $offset = 0, $stmt->bindValue(':plugin', $plugin, PDO::PARAM_STR); } if (null !== $severity) { - $stmt->bindValue(':severity', (int)$severity, PDO::PARAM_INT); + $stmt->bindValue(':severity', $severity, PDO::PARAM_INT); } if (null !== $limit) { - $stmt->bindValue(':limit', (int)$limit, PDO::PARAM_INT); + $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); } if ($offset) { $stmt->bindValue(':offset', (int)$offset, PDO::PARAM_INT); @@ -117,7 +117,7 @@ public function getErrorTotalForBuild(int $buildId, ?string $plugin = null, ?int } if (null !== $severity) { - $stmt->bindValue(':severity', (int)$severity, PDO::PARAM_INT); + $stmt->bindValue(':severity', $severity, PDO::PARAM_INT); } if ($stmt->execute()) { @@ -146,7 +146,7 @@ public function getKnownPlugins(int $buildId, ?int $severity = null, ?string $is $stmt = $this->databaseManager->getConnection('read')->prepare($query); $stmt->bindValue(':build', $buildId); if (null !== $severity) { - $stmt->bindValue(':severity', (int)$severity, PDO::PARAM_INT); + $stmt->bindValue(':severity', $severity, PDO::PARAM_INT); } if ($stmt->execute()) { diff --git a/src/Store/BuildErrorWriter.php b/src/Store/BuildErrorWriter.php index fdee2ed59..92f3f0f41 100644 --- a/src/Store/BuildErrorWriter.php +++ b/src/Store/BuildErrorWriter.php @@ -19,35 +19,21 @@ */ class BuildErrorWriter { - private int $buildId; - - private int $projectId; - private array $errors = []; - private DatabaseManager $databaseManager; - - private StoreRegistry $storeRegistry; - /** * @see https://stackoverflow.com/questions/40361164/pdoexception-sqlstatehy000-general-error-7-number-of-parameters-must-be-bet */ - private int $bufferSize; + private readonly int $bufferSize; public function __construct( ConfigurationInterface $configuration, - DatabaseManager $databaseManager, - StoreRegistry $storeRegistry, - int $projectId, - int $buildId + private readonly DatabaseManager $databaseManager, + private readonly StoreRegistry $storeRegistry, + private readonly int $projectId, + private readonly int $buildId ) { $this->bufferSize = (int)$configuration->get('php-censor.build.writer_buffer_size', 500); - - $this->projectId = $projectId; - $this->buildId = $buildId; - - $this->databaseManager = $databaseManager; - $this->storeRegistry = $storeRegistry; } public function __destruct() diff --git a/src/Store/BuildMetaStore.php b/src/Store/BuildMetaStore.php index ff358c705..6ce89bc2d 100644 --- a/src/Store/BuildMetaStore.php +++ b/src/Store/BuildMetaStore.php @@ -65,7 +65,7 @@ public function getByBuildId(int $buildId, int $limit = 1000, string $useConnect $query = 'SELECT * FROM {{' . $this->tableName . '}} WHERE {{build_id}} = :build_id LIMIT :limit'; $stmt = $this->databaseManager->getConnection($useConnection)->prepare($query); $stmt->bindValue(':build_id', $buildId); - $stmt->bindValue(':limit', (int)$limit, PDO::PARAM_INT); + $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); if ($stmt->execute()) { $res = $stmt->fetchAll(PDO::FETCH_ASSOC); diff --git a/src/Store/BuildStore.php b/src/Store/BuildStore.php index 98fd7b814..f0f24bf86 100644 --- a/src/Store/BuildStore.php +++ b/src/Store/BuildStore.php @@ -39,7 +39,7 @@ public function getByProjectId(int $projectId, int $limit = 1000, string $useCon $query = 'SELECT * FROM {{' . $this->tableName . '}} WHERE {{project_id}} = :project_id LIMIT :limit'; $stmt = $this->databaseManager->getConnection($useConnection)->prepare($query); $stmt->bindValue(':project_id', $projectId); - $stmt->bindValue(':limit', (int)$limit, PDO::PARAM_INT); + $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); if ($stmt->execute()) { $res = $stmt->fetchAll(PDO::FETCH_ASSOC); @@ -69,7 +69,7 @@ public function getByStatus(int $status, int $limit = 1000, string $useConnectio $query = 'SELECT * FROM {{' . $this->tableName . '}} WHERE {{status}} = :status ORDER BY {{create_date}} ASC LIMIT :limit'; $stmt = $this->databaseManager->getConnection($useConnection)->prepare($query); $stmt->bindValue(':status', $status); - $stmt->bindValue(':limit', (int)$limit, PDO::PARAM_INT); + $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); if ($stmt->execute()) { $res = $stmt->fetchAll(PDO::FETCH_ASSOC); @@ -338,7 +338,7 @@ public function getMeta(string $key, ?int $projectId, ?int $buildId = null, ?str $rtn = \array_reverse($rtn); $rtn = \array_map(function ($item) use ($key, $errorStore, $buildId) { - $item['meta_value'] = \json_decode($item['meta_value'], true); + $item['meta_value'] = \json_decode((string) $item['meta_value'], true); if ('plugin-summary' === $key) { foreach ($item['meta_value'] as $stage => $stageData) { foreach ($stageData as $plugin => $pluginData) { @@ -405,7 +405,7 @@ public function getOldByProject(int $projectId, int $keep = 100): array $query = 'SELECT * FROM {{' . $this->tableName . '}} WHERE {{project_id}} = :project_id ORDER BY {{create_date}} DESC LIMIT 1000000 OFFSET :keep'; $stmt = $this->databaseManager->getConnection('read')->prepare($query); $stmt->bindValue(':project_id', $projectId); - $stmt->bindValue(':keep', (int)$keep, PDO::PARAM_INT); + $stmt->bindValue(':keep', $keep, PDO::PARAM_INT); if ($stmt->execute()) { $res = $stmt->fetchAll(PDO::FETCH_ASSOC); @@ -485,7 +485,7 @@ public function getTestCoverage(int $buildId): string $coverage = $coverageMeta[0]['meta_value'][$type]; } } - } catch (\Throwable $e) { + } catch (\Throwable) { } return $coverage; diff --git a/src/Store/ProjectStore.php b/src/Store/ProjectStore.php index f9151207d..59230b326 100644 --- a/src/Store/ProjectStore.php +++ b/src/Store/ProjectStore.php @@ -66,7 +66,7 @@ public function getByTitle(string $title, int $limit = 1000, string $useConnecti $query = 'SELECT * FROM {{' . $this->tableName . '}} WHERE {{title}} = :title LIMIT :limit'; $stmt = $this->databaseManager->getConnection($useConnection)->prepare($query); $stmt->bindValue(':title', $title); - $stmt->bindValue(':limit', (int)$limit, PDO::PARAM_INT); + $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); if ($stmt->execute()) { $res = $stmt->fetchAll(PDO::FETCH_ASSOC); @@ -148,7 +148,7 @@ public function getByGroupId(int $groupId, bool $archived = false, int $limit = $stmt->bindValue(':group_id', $groupId); $stmt->bindValue(':archived', $archived); - $stmt->bindValue(':limit', (int)$limit, PDO::PARAM_INT); + $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); if ($stmt->execute()) { $res = $stmt->fetchAll(PDO::FETCH_ASSOC); diff --git a/src/Store/UserStore.php b/src/Store/UserStore.php index fb0ad4a33..28163dced 100644 --- a/src/Store/UserStore.php +++ b/src/Store/UserStore.php @@ -109,7 +109,7 @@ public function getByName(string $name, int $limit = 1000, string $useConnection $query = 'SELECT * FROM {{' . $this->tableName . '}} WHERE {{name}} = :name LIMIT :limit'; $stmt = $this->databaseManager->getConnection($useConnection)->prepare($query); $stmt->bindValue(':name', $name); - $stmt->bindValue(':limit', (int)$limit, PDO::PARAM_INT); + $stmt->bindValue(':limit', $limit, PDO::PARAM_INT); if ($stmt->execute()) { $res = $stmt->fetchAll(PDO::FETCH_ASSOC); diff --git a/src/StoreRegistry.php b/src/StoreRegistry.php index 4b8eb968a..f87670bc3 100644 --- a/src/StoreRegistry.php +++ b/src/StoreRegistry.php @@ -14,8 +14,6 @@ */ class StoreRegistry { - private DatabaseManager $databaseManager; - /** * A collection of the stores currently loaded by the factory. * @@ -23,9 +21,8 @@ class StoreRegistry */ private array $loadedStores = []; - public function __construct(DatabaseManager $databaseManager) + public function __construct(private readonly DatabaseManager $databaseManager) { - $this->databaseManager = $databaseManager; } /** diff --git a/src/Traits/Model/Build/GitGetDiffLineNumberTrait.php b/src/Traits/Model/Build/GitGetDiffLineNumberTrait.php index 8dfde96fb..5ba91dbc9 100644 --- a/src/Traits/Model/Build/GitGetDiffLineNumberTrait.php +++ b/src/Traits/Model/Build/GitGetDiffLineNumberTrait.php @@ -63,7 +63,7 @@ private function getLinePositions(string $diff): ?array while (\count($diffLines)) { $line = \array_shift($diffLines); - if (\substr($line, 0, 2) === '@@') { + if (\str_starts_with($line, '@@')) { \array_unshift($diffLines, $line); break; diff --git a/src/View.php b/src/View.php index 8e76aa75c..ed603297b 100644 --- a/src/View.php +++ b/src/View.php @@ -62,10 +62,7 @@ public function __get(string $key) return $this->data[$key]; } - /** - * @param mixed $value - */ - public function __set(string $key, $value): void + public function __set(string $key, mixed $value): void { $this->data[$key] = $value; } diff --git a/src/View/Build/errors.phtml b/src/View/Build/errors.phtml index bff36390d..fc9450ebd 100644 --- a/src/View/Build/errors.phtml +++ b/src/View/Build/errors.phtml @@ -14,9 +14,9 @@ $linkTemplate = $build->getFileLinkTemplate(); foreach ($errors as $error): - $link = \str_replace('{BASEFILE}', \basename($error->getFile()), $linkTemplate); - $link = \str_replace('{FILE}', $error->getFile(), $link); - $link = \str_replace('{LINE}', $error->getLineStart(), $link); + $link = \str_replace('{BASEFILE}', \basename((string)$error->getFile()), $linkTemplate); + $link = \str_replace('{FILE}', (string)$error->getFile(), $link); + $link = \str_replace('{LINE}', (string)$error->getLineStart(), $link); if ($error->getLineStart() == $error->getLineEnd() || !$error->getLineEnd()) { # For Github diff --git a/src/WebController.php b/src/WebController.php index 42aa0d9ca..750c7f775 100644 --- a/src/WebController.php +++ b/src/WebController.php @@ -37,7 +37,7 @@ public function __construct( ) { parent::__construct($configuration, $storeRegistry, $request, $session); - $class = \explode('\\', \get_class($this)); + $class = \explode('\\', $this::class); $this->className = \substr(\array_pop($class), 0, -10); } @@ -49,7 +49,7 @@ public function init(): void $this->layout->title = 'PHP Censor'; $this->layout->breadcrumb = []; - $version = (string)\trim(\file_get_contents(ROOT_DIR . 'VERSION.md')); + $version = \trim(\file_get_contents(ROOT_DIR . 'VERSION.md')); $version = !empty($version) ? $version : '0.0.0 (UNKNOWN)'; $this->layout->version = $version; diff --git a/src/Worker/BuildWorker.php b/src/Worker/BuildWorker.php index 21c11b91b..dda121f87 100644 --- a/src/Worker/BuildWorker.php +++ b/src/Worker/BuildWorker.php @@ -31,63 +31,37 @@ */ class BuildWorker { - public const JOB_TYPE_BUILD = 'php-censor.build'; - public const JOB_TYPE_STOP_FLAG = 'php-censor.stop-flag'; + final public const JOB_TYPE_BUILD = 'php-censor.build'; + final public const JOB_TYPE_STOP_FLAG = 'php-censor.stop-flag'; /** * If this variable changes to false, the worker will stop after the current build. */ private bool $canRun = true; - private bool $canPeriodicalWork; - - /** - * The logger for builds to use. - */ - private LoggerInterface $logger; - - private BuildService $buildService; - - private ConfigurationInterface $configuration; - - private DatabaseManager $databaseManager; - - private StoreRegistry $storeRegistry; - - private BuildFactory $buildFactory; - - /** - * beanstalkd queue to watch - */ - private string $queueTube; - - private Pheanstalk $pheanstalk; + private readonly Pheanstalk $pheanstalk; private int $lastPeriodical = 0; public function __construct( - ConfigurationInterface $configuration, - DatabaseManager $databaseManager, - StoreRegistry $storeRegistry, - LoggerInterface $logger, - BuildService $buildService, - BuildFactory $buildFactory, + private readonly ConfigurationInterface $configuration, + private readonly DatabaseManager $databaseManager, + private readonly StoreRegistry $storeRegistry, + /** + * The logger for builds to use. + */ + private readonly LoggerInterface $logger, + private readonly BuildService $buildService, + private readonly BuildFactory $buildFactory, string $queueHost, int $queuePort, - string $queueTube, - bool $canPeriodicalWork + /** + * beanstalkd queue to watch + */ + private readonly string $queueTube, + private readonly bool $canPeriodicalWork ) { - $this->logger = $logger; - $this->buildService = $buildService; - $this->configuration = $configuration; - $this->databaseManager = $databaseManager; - $this->storeRegistry = $storeRegistry; - $this->buildFactory = $buildFactory; - - $this->queueTube = $queueTube; $this->pheanstalk = Pheanstalk::create($queueHost, $queuePort); - - $this->canPeriodicalWork = $canPeriodicalWork; } public function stopWorker(): void @@ -229,7 +203,7 @@ protected function canForceRewindLoop(): bool { try { $this->pheanstalk->peekReady(); - } catch (\Throwable $e) { + } catch (\Throwable) { return true; } diff --git a/tests/src/FormTest.php b/tests/src/FormTest.php index 677d6bf9f..c3248a451 100644 --- a/tests/src/FormTest.php +++ b/tests/src/FormTest.php @@ -77,7 +77,7 @@ public function testInputValidation(): void self::assertFalse($f->validate()); $f->setRequired(false); - $f->setPattern('input\-value'); + $f->setPattern('input-value'); self::assertFalse($f->validate()); diff --git a/tests/src/Plugin/Util/Fake/ExamplePluginFull.php b/tests/src/Plugin/Util/Fake/ExamplePluginFull.php index ea7738f25..dc9f09a11 100644 --- a/tests/src/Plugin/Util/Fake/ExamplePluginFull.php +++ b/tests/src/Plugin/Util/Fake/ExamplePluginFull.php @@ -10,15 +10,18 @@ class ExamplePluginFull extends Plugin { - public $options; + public array $options; public static function pluginName(): string { return 'example_plugin_full'; } - public function __construct(Builder $builder, Build $build, array $options = []) - { + public function __construct( + Builder $builder, + Build $build, + array $options = [] + ) { $this->options = $options; } diff --git a/tests/src/PluginTest.php b/tests/src/PluginTest.php index 0c928c382..cd5e862e5 100644 --- a/tests/src/PluginTest.php +++ b/tests/src/PluginTest.php @@ -21,8 +21,11 @@ class TestPlugin extends Plugin /** * {@inheritDoc} */ - public function __construct(Builder $builder, Build $build, array $options = []) - { + public function __construct( + Builder $builder, + Build $build, + array $options = [] + ) { parent::__construct($builder, $build, $options); }