diff --git a/.harness.json b/.harness.json index 8a2893a5..30298095 100644 --- a/.harness.json +++ b/.harness.json @@ -3,6 +3,7 @@ "mode": "enforce", "ratchet": { "phpstan_level": 5, - "phpstan_baseline": 58 + "phpstan_baseline": 58, + "coverage": 53 } } diff --git a/CHANGELOG.md b/CHANGELOG.md index 35691cb2..a8451c40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,12 @@ All notable changes to the Pollora framework will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased](https://github.com/Pollora/framework/compare/v13.39.3...develop) +## [Unreleased](https://github.com/Pollora/framework/compare/v13.40.0...develop) + +## [v13.40.0](https://github.com/Pollora/framework/compare/v13.39.3...v13.40.0) - 2026-11-04 + +### Changed +- The framework requires Laravel 13.40 (`illuminate/*` `^13.40`) ## [v13.39.3](https://github.com/Pollora/framework/compare/v13.39.2...v13.39.3) - 2026-11-02 diff --git a/CLAUDE.md b/CLAUDE.md index 40026a2a..8d9db881 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -14,7 +14,7 @@ Pollora is a Laravel & WordPress integration framework that creates a "sweet ble ddev exec --dir /var/www/html/vendor/pollora/framework composer test # Individual test commands -ddev exec --dir /var/www/html/vendor/pollora/framework composer test:unit # Run PHPUnit tests with coverage (requires 100% coverage) +ddev exec --dir /var/www/html/vendor/pollora/framework composer test:unit # Run the Pest tests ddev exec --dir /var/www/html/vendor/pollora/framework composer test:types # Run PHPStan static analysis ddev exec --dir /var/www/html/vendor/pollora/framework composer test:lint # Test code formatting with Pint ddev exec --dir /var/www/html/vendor/pollora/framework composer test:refacto # Test refactoring rules with Rector (dry-run) @@ -25,7 +25,8 @@ ddev exec --dir /var/www/html/vendor/pollora/framework composer refacto ``` ### Key Quality Standards -- **Test Coverage**: 100% test coverage is required (`--min=100`) +- **Type Coverage**: at least 98% (`composer test:type-coverage`, enforced by the CI) +- **Line Coverage**: tracked, not a fixed target. The Harness ratchet (`coverage` in `.harness.json`) fails a change that lowers it, so a pull request that adds code adds the tests that keep the figure up - **Static Analysis**: PHPStan level 5 with WordPress and Laravel extensions - **Code Style**: Laravel Pint for PHP formatting, Prettier for JS/MD/YAML - **Refactoring**: Rector with Laravel-specific rules diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c00ef609..6e09579e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -36,8 +36,8 @@ outlines our guidelines and conventions. composer test ``` This executes Rector, Pint, PHPStan and the unit tests. -- Pull requests must pass the CI pipeline. Aim for 100% coverage as enforced by - the test configuration. +- Pull requests must pass the CI pipeline. A pull request must not lower + the line coverage recorded in `.harness.json`, and the type coverage stays at 98% or more. ## Commit Messages diff --git a/README.md b/README.md index 5bc825e7..8e2a5306 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ **Pollora is the Laravel framework for WordPress.** WordPress runs inside a Laravel application: the front end uses Laravel routing, controllers, Blade and Eloquent, while the WordPress admin, database, editors' workflow and plugins keep working as usual. Hooks, post types, taxonomies and REST routes are declared with PHP 8 attributes and registered by auto-discovery, so `functions.php` stops being the place where everything piles up. -[Website](https://pollora.dev) · [Documentation](https://pollora.dev/getting-started/installation/) · [Why Pollora](https://pollora.dev/why/) · [How Pollora compares with Acorn, Sage, Radicle and Corcel](https://pollora.dev/compare/) · [1-minute tour](https://www.youtube.com/watch?v=Wk1VzPapqM8) +[Website](https://pollora.dev) · [Documentation](https://pollora.dev/getting-started/installation/) · [Why Pollora](https://pollora.dev/why/) · [How Pollora compares with Acorn, Sage, Radicle and Corcel](https://pollora.dev/compare/) · [1-minute tour](https://www.youtube.com/watch?v=Wk1VzPapqM8) · [Featured in Laravel News](https://laravel-news.com/pollora-wordpress-laravel) ## Installation @@ -30,7 +30,7 @@ composer create-project pollora/pollora my-project Requirements: - PHP 8.4+ for a new project (the skeleton's lock file ships Symfony 8; this package alone accepts PHP 8.3) -- Laravel 13.39 (Pollora's version numbers follow the Laravel release it is built on) +- Laravel 13.40 (Pollora's version numbers follow the Laravel release it is built on) - WordPress 7.1+ ## Quick start @@ -82,7 +82,7 @@ Learn more: ```bash composer test # Run all checks (Rector, Pint, PHPStan, Pest, type coverage) -composer test:unit # Run Pest tests with 100% coverage requirement +composer test:unit # Run the Pest tests composer test:types # Run PHPStan static analysis composer test:lint # Check code style with Pint composer test:refacto # Check refactoring rules with Rector @@ -97,6 +97,10 @@ All notable changes are documented in [CHANGELOG.md](CHANGELOG.md). Pollora builds on the work of [Roots](https://roots.io), a constant source of inspiration: themes, blocks and plugins are built with `@roots/vite-plugin`, the project follows the Bedrock layout with `roots/bedrock-autoloader`, and Blade ships [Sage Directives](https://github.com/Log1x/sage-directives). The WordPress models are built on [Colt](https://github.com/Pollora/colt), a fork of [Corcel](https://github.com/corcel/corcel). +## Support the project + +If Pollora is useful to you, **[star the skeleton](https://github.com/Pollora/pollora)**, the repository you install from: it helps other WordPress developers find it. Questions and ideas are welcome in [GitHub Discussions](https://github.com/Pollora/pollora/discussions). + ## Contributing Contributions are welcome: see the [contributing guide](CONTRIBUTING.md). Report security issues privately, as described in the [security policy](SECURITY.md). diff --git a/composer.json b/composer.json index 72f0cf3f..ff3f58f6 100644 --- a/composer.json +++ b/composer.json @@ -24,11 +24,11 @@ "require": { "php": "^8.3", "pollora/helper-overrider": "^1.2", - "illuminate/auth": "^13.39", - "illuminate/support": "^13.39", - "illuminate/database": "^13.39", - "illuminate/routing": "^13.39", - "illuminate/console": "^13.39", + "illuminate/auth": "^13.40", + "illuminate/support": "^13.40", + "illuminate/database": "^13.40", + "illuminate/routing": "^13.40", + "illuminate/console": "^13.40", "pollora/abilities": "^1.0", "pollora/ajax": "^1.1", "pollora/assets": "^0.1", @@ -54,7 +54,7 @@ "coduo/php-humanizer": "5.0.3", "nwidart/laravel-modules": "^13.2", "symfony/process": "^7.4 || ^8.0", - "illuminate/config": "^13.39", + "illuminate/config": "^13.40", "laravel/prompts": "^0.3.26" }, "autoload": { @@ -149,7 +149,7 @@ "test:refacto": "rector --dry-run", "test:lint": "pint --test", "test:types": "phpstan analyse --ansi", - "test:unit": "pest --colors=always --min=100", + "test:unit": "pest --colors=always", "test:type-coverage": "pest --type-coverage --min=98", "test": [ "@test:refacto", diff --git a/tests/Feature/Doctor/InstallChecksTest.php b/tests/Feature/Doctor/InstallChecksTest.php index b7b018d8..b596fcf2 100644 --- a/tests/Feature/Doctor/InstallChecksTest.php +++ b/tests/Feature/Doctor/InstallChecksTest.php @@ -201,7 +201,7 @@ function writeLock(string $project, array $patches): void it('is skipped when the site cannot request itself', function (): void { config(['app.url' => 'http://pollora.test']); - Http::fake(fn () => throw new RuntimeException('timeout')); + Http::fake(fn (): never => throw new RuntimeException('timeout')); expect((new PublicRootCheck)->run(RunContext::Http)->status->value)->toBe('skipped'); }); diff --git a/tests/Unit/Discovery/Infrastructure/Services/DiscoveryRegistrarTest.php b/tests/Unit/Discovery/Infrastructure/Services/DiscoveryRegistrarTest.php index b3c9e069..5e4ac434 100644 --- a/tests/Unit/Discovery/Infrastructure/Services/DiscoveryRegistrarTest.php +++ b/tests/Unit/Discovery/Infrastructure/Services/DiscoveryRegistrarTest.php @@ -102,7 +102,7 @@ function createMockRegistrarEngine(): DiscoveryEngineInterface }); it('gracefully handles unresolvable bindings', function (): void { - $this->container->singleton('App\\BrokenDiscovery', fn () => throw new RuntimeException('Cannot resolve')); + $this->container->singleton('App\\BrokenDiscovery', fn (): never => throw new RuntimeException('Cannot resolve')); $engine = createMockRegistrarEngine(); $engine->shouldNotReceive('addDiscovery'); diff --git a/tests/Unit/Proxy/WordPressDatabaseTest.php b/tests/Unit/Proxy/WordPressDatabaseTest.php index 12db0105..a2c7cb6a 100644 --- a/tests/Unit/Proxy/WordPressDatabaseTest.php +++ b/tests/Unit/Proxy/WordPressDatabaseTest.php @@ -143,7 +143,7 @@ public function __construct(public string $dbuser, public string $dbpassword, pu it('throws RuntimeException on mysql_connect', function (): void { $proxy = new WordPressDatabase; - expect(fn () => $proxy->mysql_connect()) + expect(fn (): never => $proxy->mysql_connect()) ->toThrow(RuntimeException::class, 'Using mysql_connect is deprecated'); }); });