diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e40164b..44dfabf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,8 @@ jobs: strategy: fail-fast: false matrix: - php: ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4'] + # Keep in sync with the tests below and "Requires PHP" (7.4) + php: ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5'] steps: - uses: actions/checkout@v4 - uses: shivammathur/setup-php@v2 @@ -39,11 +40,13 @@ jobs: - uses: actions/checkout@v4 - uses: shivammathur/setup-php@v2 with: - php-version: '8.3' + php-version: '8.5' coverage: none tools: composer - name: Install dependencies run: composer install --no-interaction --no-progress + # PHPCompatibility 10 knows the changes up to PHP 8.5; testVersion + # "7.4-" in phpcs.xml.dist checks all of them - name: Run PHPCS (PHPCompatibilityWP) run: composer phpcs @@ -53,7 +56,7 @@ jobs: strategy: fail-fast: false matrix: - php: ['7.4', '8.3'] + php: ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5'] services: mariadb: image: mariadb:10.11 diff --git a/.wordpress-org/banner-1544x500.png b/.wordpress-org/banner-1544x500.png index 8a65b06..cf923b5 100644 Binary files a/.wordpress-org/banner-1544x500.png and b/.wordpress-org/banner-1544x500.png differ diff --git a/.wordpress-org/banner-772x250.png b/.wordpress-org/banner-772x250.png index 1d44db4..57163e3 100644 Binary files a/.wordpress-org/banner-772x250.png and b/.wordpress-org/banner-772x250.png differ diff --git a/.wordpress-org/icon-128x128.png b/.wordpress-org/icon-128x128.png index 26c6db4..fa90d00 100644 Binary files a/.wordpress-org/icon-128x128.png and b/.wordpress-org/icon-128x128.png differ diff --git a/.wordpress-org/icon-256x256.png b/.wordpress-org/icon-256x256.png index 8c4b5a9..640a1d0 100644 Binary files a/.wordpress-org/icon-256x256.png and b/.wordpress-org/icon-256x256.png differ diff --git a/CLAUDE.md b/CLAUDE.md index 4546e19..cb730e0 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,7 +8,7 @@ WordPress plugin, published on wordpress.org (slug `wirecore-rest-control`) and - Prefix everything global: functions/options/hooks/nonces `wirecore_rc_`, constants `WIRECORE_RC_`, CSS classes/IDs `wirecore-rc-`, text domain `wirecore-rest-control`, WP-CLI command `wp wirecore-rest`. - Admin pages in plain PHP with `admin-post.php` forms, nonces, `wp_safe_redirect()` plus a notice query arg. No build step for JS; the only CSS build is `npm run build:css` (below). - UI in the WireLayer corporate design: the markup uses the `.wc-*` classes of `@wirecore/wirelayer-css` (class reference: `node_modules/@wirecore/wirelayer-css/llms-full.txt`). `npm run build:css` writes the used components, scoped to `#wirecore-rc`, to `assets/wirelayer/` – committed, CI checks it is up to date. Add a component to the list in `package.json` before using its classes, and run the command again after updating the package. `wirecore-rc-*` classes are hooks for `admin.js` and page layout in `assets/admin.css` (scoped to `#wirecore-rc`, colors and spacing from WireLayer variables). Icons are inline Lucide SVGs (`WireCore_RC_Admin::icon()`). -- Minimum versions: WordPress 5.8, PHP 7.4 (verified with PHPCompatibility and a WP 5.8/PHP 7.4 instance) – do not use newer functions without raising them. +- Supported versions: WordPress 5.8+, PHP 7.4 – 8.5 (verified with PHPCompatibility 10, a WP 5.8/PHP 7.4 instance and the tests on every PHP version) – do not use newer functions without raising the minimum, and avoid anything deprecated up to PHP 8.5 (e.g. `ReflectionProperty::setAccessible()` only below PHP 8.1). The Docker environment runs PHP 8.5. - Formatting with Prettier (tabs, single quotes). Plugin Check must stay free of errors and warnings; justified exceptions are marked with `phpcs:ignore`/`phpcs:disable` plus a comment explaining why. ## Architecture @@ -43,7 +43,7 @@ Only `wirecore-rest-control.php`, `uninstall.php`, `index.php`, `readme.txt`, `L ## Checks -CI (`.github/workflows/ci.yml`) must stay green: PHP lint 7.4–8.4, `composer phpcs` (PHPCompatibilityWP, `phpcs.xml.dist`), PHPUnit on PHP 7.4 and 8.3, `npm run format:check`, `assets/wirelayer/` up to date with `npm run build:css`, Plugin Check in strict mode on the package built from `.distignore`. +CI (`.github/workflows/ci.yml`) must stay green: PHP lint 7.4–8.5, `composer phpcs` (PHPCompatibilityWP, `phpcs.xml.dist`), PHPUnit on PHP 7.4–8.5 (see README for the loop over all versions in Docker), `npm run format:check`, `assets/wirelayer/` up to date with `npm run build:css`, Plugin Check in strict mode on the package built from `.distignore`. Tests live in `tests/` (`test-*.php`, base class `WireCore_RC_TestCase`). They are integration tests against the WordPress test suite: dispatch requests through `rest_get_server()->dispatch()` (the bootstrap defines `REST_REQUEST`), and register fixture routes in `tests/bootstrap.php` – the route list is cached, so routes must exist before the first REST server is created. Run them inside the Docker container (see README) against the separate database `wordpress_test`. diff --git a/Dockerfile b/Dockerfile index 61c5116..d46a14f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM wordpress:php8.2-apache +FROM wordpress:php8.5-apache # install some needed packages RUN apt update && apt install mariadb-client -y diff --git a/README.md b/README.md index 7885c8b..9336d48 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,8 @@ docker compose up -d # WordPress on http://localhost:8092, phpMyAdmin on :8093 npm install # Prettier with the PHP plugin, @wirecore/wirelayer-css ``` +The container runs the newest supported PHP version (8.5, see `Dockerfile`), so deprecations show up during development. + The settings page uses the [WireLayer](https://github.com/WireCore/WireLayer) components (`.wc-*` classes). `npm run build:css` writes the components listed in `package.json`, scoped to `#wirecore-rc`, with their fonts to `assets/wirelayer/`. The output is committed, so the plugin needs no build step; run the command again after adding a component or updating `@wirecore/wirelayer-css`. WP-CLI is available in the container: @@ -105,6 +107,17 @@ docker compose exec -w /var/www/html/wp-content/plugins/wirecore-rest-control wo The database settings in [`tests/wp-tests-config.php`](tests/wp-tests-config.php) default to the Docker environment and can be overridden with `WP_TESTS_DB_HOST`, `WP_TESTS_DB_USER`, `WP_TESTS_DB_PASSWORD` and `WP_TESTS_DB_NAME`. +The plugin supports PHP 7.4 – 8.5. To run the syntax check and the tests on every version like the CI does, use the official PHP images in the network of the Docker environment: + +```bash +for v in 7.4 8.0 8.1 8.2 8.3 8.4 8.5; do + docker run --rm --network "$(basename "$PWD" | tr '[:upper:]' '[:lower:]')_default" -v "$PWD":/app -w /app -e WP_TESTS_DB_PASSWORD=password php:$v-cli \ + sh -c "docker-php-ext-install mysqli >/dev/null && find . -name '*.php' -not -path './vendor/*' -not -path './node_modules/*' -exec php -l {} \; | grep -v 'No syntax errors'; vendor/bin/phpunit" +done +``` + +Composer installs the dependencies for PHP 7.4 (`config.platform` in `composer.json`), so the same `vendor/` works on every version. + ### Translations All UI strings are English in the code (text domain `wirecore-rest-control`) and translated in `languages/`. After changing strings (`P=wp-content/plugins/wirecore-rest-control`): @@ -125,9 +138,9 @@ Only the files needed by the plugin are shipped. Development files are excluded [`.github/workflows/ci.yml`](.github/workflows/ci.yml) runs on every push to `main` and on pull requests: -- PHP syntax check on PHP 7.4 – 8.4 -- PHP compatibility for the minimum PHP version (`composer phpcs`, see [`phpcs.xml.dist`](phpcs.xml.dist)) -- PHPUnit on PHP 7.4 and 8.3 (`composer test`) +- PHP syntax check on PHP 7.4 – 8.5 +- PHP compatibility from PHP 7.4 up to 8.5 with PHPCompatibility 10 (`composer phpcs`, see [`phpcs.xml.dist`](phpcs.xml.dist)) +- PHPUnit on PHP 7.4 – 8.5 (`composer test`); deprecations fail the tests - Prettier (`npm run format:check`) - Plugin Check on the built package, warnings included diff --git a/composer.json b/composer.json index f33c3b7..6d49670 100644 --- a/composer.json +++ b/composer.json @@ -21,12 +21,14 @@ }, "require-dev": { "squizlabs/php_codesniffer": "^3.10", - "phpcompatibility/phpcompatibility-wp": "^2.1", + "phpcompatibility/phpcompatibility-wp": "^3.0@alpha", "dealerdirect/phpcodesniffer-composer-installer": "^1.0", "phpunit/phpunit": "^9.6", "yoast/phpunit-polyfills": "*", "wp-phpunit/wp-phpunit": "*", - "roots/wordpress-no-content": "*" + "roots/wordpress-no-content": "*", + "phpcompatibility/php-compatibility": "^10.0@alpha", + "phpcompatibility/phpcompatibility-paragonie": "^2.0@alpha" }, "config": { "allow-plugins": { diff --git a/composer.lock b/composer.lock index 5eb3355..f6452b9 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "48baa1e48caf7c18bd4b1d29ad14aabb", + "content-hash": "9d42159df904c3b8b0cdaf88e3759775", "packages": [], "packages-dev": [ { @@ -410,33 +410,41 @@ }, { "name": "phpcompatibility/php-compatibility", - "version": "9.3.5", + "version": "10.0.0-alpha2", "source": { "type": "git", "url": "https://github.com/PHPCompatibility/PHPCompatibility.git", - "reference": "9fb324479acf6f39452e0655d2429cc0d3914243" + "reference": "e0f0e5a3dc819a4a0f8d679a0f2453d941976e18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/9fb324479acf6f39452e0655d2429cc0d3914243", - "reference": "9fb324479acf6f39452e0655d2429cc0d3914243", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/e0f0e5a3dc819a4a0f8d679a0f2453d941976e18", + "reference": "e0f0e5a3dc819a4a0f8d679a0f2453d941976e18", "shasum": "" }, "require": { - "php": ">=5.3", - "squizlabs/php_codesniffer": "^2.3 || ^3.0.2" + "php": ">=5.4", + "phpcsstandards/phpcsutils": "^1.1.2", + "squizlabs/php_codesniffer": "^3.13.3 || ^4.0" }, - "conflict": { - "squizlabs/php_codesniffer": "2.6.2" + "replace": { + "wimg/php-compatibility": "*" }, "require-dev": { - "phpunit/phpunit": "~4.5 || ^5.0 || ^6.0 || ^7.0" - }, - "suggest": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically.", - "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." + "php-parallel-lint/php-console-highlighter": "^1.0.0", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpcsstandards/phpcsdevcs": "^1.2.0", + "phpcsstandards/phpcsdevtools": "^1.2.3", + "phpunit/phpunit": "^4.8.36 || ^5.7.21 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4 || ^10.5.32 || ^11.3.3", + "yoast/phpunit-polyfills": "^1.1.5 || ^2.0.5 || ^3.1.0" }, "type": "phpcodesniffer-standard", + "extra": { + "branch-alias": { + "dev-master": "9.x-dev", + "dev-develop": "10.x-dev" + } + }, "notification-url": "https://packagist.org/downloads/", "license": [ "LGPL-3.0-or-later" @@ -458,44 +466,59 @@ } ], "description": "A set of sniffs for PHP_CodeSniffer that checks for PHP cross-version compatibility.", - "homepage": "http://techblog.wimgodden.be/tag/codesniffer/", + "homepage": "https://techblog.wimgodden.be/tag/codesniffer/", "keywords": [ "compatibility", "phpcs", - "standards" + "standards", + "static analysis" ], "support": { "issues": "https://github.com/PHPCompatibility/PHPCompatibility/issues", + "security": "https://github.com/PHPCompatibility/PHPCompatibility/security/policy", "source": "https://github.com/PHPCompatibility/PHPCompatibility" }, - "time": "2019-12-27T09:44:58+00:00" + "funding": [ + { + "url": "https://github.com/PHPCompatibility", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcompatibility", + "type": "thanks_dev" + } + ], + "time": "2025-11-28T11:36:33+00:00" }, { "name": "phpcompatibility/phpcompatibility-paragonie", - "version": "1.3.4", + "version": "2.0.0-alpha2", "source": { "type": "git", "url": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie.git", - "reference": "244d7b04fc4bc2117c15f5abe23eb933b5f02bbf" + "reference": "7a979711c87d8202b52f56c56bd719d09d8ed7f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/244d7b04fc4bc2117c15f5abe23eb933b5f02bbf", - "reference": "244d7b04fc4bc2117c15f5abe23eb933b5f02bbf", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/7a979711c87d8202b52f56c56bd719d09d8ed7f5", + "reference": "7a979711c87d8202b52f56c56bd719d09d8ed7f5", "shasum": "" }, "require": { - "phpcompatibility/php-compatibility": "^9.0" + "phpcompatibility/php-compatibility": "^10.0@dev" }, "require-dev": { - "dealerdirect/phpcodesniffer-composer-installer": "^1.0", "paragonie/random_compat": "dev-master", "paragonie/sodium_compat": "dev-master" }, - "suggest": { - "dealerdirect/phpcodesniffer-composer-installer": "^1.0 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.", - "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." - }, "type": "phpcodesniffer-standard", "notification-url": "https://packagist.org/downloads/", "license": [ @@ -544,33 +567,25 @@ "type": "thanks_dev" } ], - "time": "2025-09-19T17:43:28+00:00" + "time": "2025-11-29T13:09:49+00:00" }, { "name": "phpcompatibility/phpcompatibility-wp", - "version": "2.1.8", + "version": "3.0.0-alpha2", "source": { "type": "git", "url": "https://github.com/PHPCompatibility/PHPCompatibilityWP.git", - "reference": "7c8d18b4d90dac9e86b0869a608fa09158e168fa" + "reference": "bd53f24e7528422ac51d64dc8d53e8d4c4a877b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/7c8d18b4d90dac9e86b0869a608fa09158e168fa", - "reference": "7c8d18b4d90dac9e86b0869a608fa09158e168fa", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/bd53f24e7528422ac51d64dc8d53e8d4c4a877b3", + "reference": "bd53f24e7528422ac51d64dc8d53e8d4c4a877b3", "shasum": "" }, "require": { - "phpcompatibility/php-compatibility": "^9.0", - "phpcompatibility/phpcompatibility-paragonie": "^1.0", - "squizlabs/php_codesniffer": "^3.3" - }, - "require-dev": { - "dealerdirect/phpcodesniffer-composer-installer": "^1.0" - }, - "suggest": { - "dealerdirect/phpcodesniffer-composer-installer": "^1.0 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.", - "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." + "phpcompatibility/php-compatibility": "^10.0@dev", + "phpcompatibility/phpcompatibility-paragonie": "^2.0@dev" }, "type": "phpcodesniffer-standard", "notification-url": "https://packagist.org/downloads/", @@ -619,7 +634,100 @@ "type": "thanks_dev" } ], - "time": "2025-10-18T00:05:59+00:00" + "time": "2025-12-16T13:35:20+00:00" + }, + { + "name": "phpcsstandards/phpcsutils", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/PHPCSStandards/PHPCSUtils.git", + "reference": "5f35d9408c54d7b529501f3c688b6eae562aea1f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCSStandards/PHPCSUtils/zipball/5f35d9408c54d7b529501f3c688b6eae562aea1f", + "reference": "5f35d9408c54d7b529501f3c688b6eae562aea1f", + "shasum": "" + }, + "require": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.1 || ^0.5 || ^0.6.2 || ^0.7 || ^1.0", + "php": ">=5.4", + "squizlabs/php_codesniffer": "^3.13.5 || ^4.0.1" + }, + "require-dev": { + "ext-filter": "*", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpcsstandards/phpcsdevcs": "^1.2.0", + "yoast/phpunit-polyfills": "^1.1.0 || ^2.0.0 || ^3.0.0" + }, + "type": "phpcodesniffer-standard", + "extra": { + "branch-alias": { + "dev-stable": "1.x-dev", + "dev-develop": "1.x-dev" + } + }, + "autoload": { + "classmap": [ + "PHPCSUtils/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Juliette Reinders Folmer", + "homepage": "https://github.com/jrfnl", + "role": "lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHPCSUtils/graphs/contributors" + } + ], + "description": "A suite of utility functions for use with PHP_CodeSniffer", + "homepage": "https://phpcsutils.com/", + "keywords": [ + "PHP_CodeSniffer", + "phpcbf", + "phpcodesniffer-standard", + "phpcs", + "phpcs3", + "phpcs4", + "standards", + "static analysis", + "tokens", + "utility" + ], + "support": { + "docs": "https://phpcsutils.com/", + "issues": "https://github.com/PHPCSStandards/PHPCSUtils/issues", + "security": "https://github.com/PHPCSStandards/PHPCSUtils/security/policy", + "source": "https://github.com/PHPCSStandards/PHPCSUtils" + }, + "funding": [ + { + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" + } + ], + "time": "2026-07-27T10:28:41+00:00" }, { "name": "phpunit/php-code-coverage", @@ -2360,7 +2468,11 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": { + "phpcompatibility/php-compatibility": 15, + "phpcompatibility/phpcompatibility-paragonie": 15, + "phpcompatibility/phpcompatibility-wp": 15 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/tests/class-wirecore-rc-testcase.php b/tests/class-wirecore-rc-testcase.php index 543fc4b..01f4f93 100644 --- a/tests/class-wirecore-rc-testcase.php +++ b/tests/class-wirecore-rc-testcase.php @@ -35,7 +35,10 @@ protected static function reset_settings_cache() WireCore_RC_Settings::class, 'cache' ); - $property->setAccessible(true); + // Needed before PHP 8.1, deprecated since PHP 8.5 + if (PHP_VERSION_ID < 80100) { + $property->setAccessible(true); + } $property->setValue(null, null); }