From 3d1100cbdca6e31efa24a5df0a735cbf61cbaead Mon Sep 17 00:00:00 2001 From: Tom Mitchelmore Date: Mon, 8 Sep 2025 09:35:32 +0100 Subject: [PATCH 01/19] Upgrade to php 8.4 --- .github/workflows/ci.yml | 83 +++++++++---------- composer.json | 43 ++++++---- rector.php | 16 ++++ src/Application.php | 16 ++-- .../RegisterExceptionHandler.php | 6 +- src/Config.php | 2 +- src/Contracts/QueryBuilder.php | 2 +- src/Encrypter.php | 5 +- src/Exceptions/Handler.php | 2 +- src/Facades/Config.php | 1 + src/Facades/Log.php | 1 + src/Facades/MiddlewareAliases.php | 1 + src/Facades/Router.php | 1 + src/Facades/Session.php | 1 + src/Http/Lumberjack.php | 5 +- src/Http/Middleware/PasswordProtected.php | 2 +- src/Http/MiddlewareAliasStore.php | 6 +- src/Http/Router.php | 5 +- src/Page.php | 1 + src/Post.php | 9 +- src/Providers/SessionServiceProvider.php | 8 +- .../WordPressControllersServiceProvider.php | 16 ++-- src/QueryBuilder.php | 4 +- src/ScopedQueryBuilder.php | 16 ++-- src/Session/EncryptedStore.php | 4 +- src/Session/FileSessionHandler.php | 9 +- src/Session/Store.php | 2 +- src/ViewModel.php | 32 +++---- src/functions.php | 20 ++--- tests/Unit/ApplicationTest.php | 20 +---- .../RegisterExceptionHandlerTest.php | 16 +--- tests/Unit/GlobalFunctionsTest.php | 4 +- tests/Unit/HelpersTest.php | 15 +--- .../Http/Middleware/PasswordProtectTest.php | 8 +- tests/Unit/Http/MiddlewareAliasStoreTest.php | 11 +-- tests/Unit/Http/RouterTest.php | 10 +-- tests/Unit/PostQueryBuilderTest.php | 3 +- tests/Unit/PostTest.php | 16 ++-- .../CustomPostTypesServiceProviderTest.php | 2 + .../Providers/RouterServiceProviderTest.php | 11 +-- ...ordPressControllersServiceProviderTest.php | 27 +++--- tests/Unit/QueryBuilderTest.php | 1 + tests/Unit/ScopedQueryBuilderTest.php | 3 +- tests/Unit/Session/FileSessionHandlerTest.php | 2 +- tests/Unit/Session/SessionManagerTest.php | 4 +- 45 files changed, 202 insertions(+), 270 deletions(-) create mode 100644 rector.php diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f54dc58..2dd86fc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,45 +3,44 @@ name: CI on: [push, pull_request] jobs: - build-test: - runs-on: ubuntu-latest - strategy: - matrix: - php_version: [8.1, 8.2, 8.3] - composer_flags: ['', '--prefer-lowest'] - - steps: - - uses: actions/checkout@v2 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php_version }} - extensions: xdebug - - - name: Install dependencies - uses: php-actions/composer@v5 - with: - php_version: ${{ matrix.php_version }} - args: ${{ matrix.composer_flags }} - command: update - - - name: Run tests - run: ./vendor/bin/phpunit --coverage-clover ./tests/logs/clover.xml - env: - XDEBUG_MODE: coverage - - - name: Run Codesniffer - run: vendor/bin/phpcs --standard=PSR2 ./src - - # - name: Submit coverage to Coveralls - # # We use php-coveralls library for this, as the official Coveralls GitHub Action lacks support for clover reports: - # # https://github.com/coverallsapp/github-action/issues/15 - # env: - # COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # COVERALLS_PARALLEL: true - # COVERALLS_FLAG_NAME: ${{ github.job }}-PHP-${{ matrix.php_version }} ${{ matrix.composer_flags }} - # run: | - # composer global require php-coveralls/php-coveralls - # ~/.composer/vendor/bin/php-coveralls -v - + build-test: + runs-on: ubuntu-latest + strategy: + matrix: + php_version: [8.4] + composer_flags: ["", "--prefer-lowest"] + + steps: + - uses: actions/checkout@v2 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php_version }} + extensions: xdebug + + - name: Install dependencies + uses: php-actions/composer@v5 + with: + php_version: ${{ matrix.php_version }} + args: ${{ matrix.composer_flags }} + command: update + + - name: Run tests + run: ./vendor/bin/phpunit --coverage-clover ./tests/logs/clover.xml + env: + XDEBUG_MODE: coverage + + - name: Run Codesniffer + run: vendor/bin/phpcs --standard=PSR2 ./src + + # - name: Submit coverage to Coveralls + # # We use php-coveralls library for this, as the official Coveralls GitHub Action lacks support for clover reports: + # # https://github.com/coverallsapp/github-action/issues/15 + # env: + # COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # COVERALLS_PARALLEL: true + # COVERALLS_FLAG_NAME: ${{ github.job }}-PHP-${{ matrix.php_version }} ${{ matrix.composer_flags }} + # run: | + # composer global require php-coveralls/php-coveralls + # ~/.composer/vendor/bin/php-coveralls -v diff --git a/composer.json b/composer.json index 0cf2c1c..6f118cb 100644 --- a/composer.json +++ b/composer.json @@ -3,26 +3,24 @@ "description": "A powerful MVC framework for the modern WordPress developer. Write better, more expressive and easier to maintain code", "license": "MIT", "require": { - "php": ">=8.1", - "php-di/php-di": "^6.4.0", - "rareloop/router": "^6.0.2", - "psr/container": "^1.1.2", - "psr/http-message": "^1.1", + "php": ">=8.4", + "php-di/php-di": "^7", + "rareloop/router": "dev-feature/upgrade-dependencies as 6.0.2", + "psr/container": "^2", + "psr/http-message": "^2", "psr/http-server-middleware": "^1.0.2", "blast/facades": "^1.0", "timber/timber": "^2.3.0", - "monolog/monolog": "^2.9.1", - "http-interop/response-sender": "^1.0", + "monolog/monolog": "^3.9", "symfony/debug": "^4.4.44", - "illuminate/collections": "^8.53.1||^9.52.16", + "illuminate/collections": "^12", "statamic/stringy": "^3.1.3", - "laminas/laminas-diactoros": "^2.25.2", - "rareloop/psr7-server-request-extension": "^2.1.0", + "laminas/laminas-diactoros": "^3.6.0", + "rareloop/psr7-server-request-extension": "dev-master as 3.0", "mmeyer2k/dcrypt": "^8.3.1", "spatie/macroable": "^1.0.1", - "mindplay/middleman": "^3.1.0", - "psr/log": "^1.1.4", - "laminas/laminas-zendframework-bridge": "^1.7", + "mindplay/middleman": "^4.0.4", + "psr/log": "^2.0.0", "symfony/var-dumper": "^5.0||^6.3.6" }, "require-dev": { @@ -31,9 +29,10 @@ "mockery/mockery": "^1.6.6", "brain/monkey": "^2.6.1", "squizlabs/php_codesniffer": "^3.7.2", - "php-mock/php-mock": "^2.4.1", + "php-mock/php-mock": "^2.6.2", "mikey179/vfsstream": "1.6.11", - "dms/phpunit-arraysubset-asserts": "^0.3.1" + "dms/phpunit-arraysubset-asserts": "^0.3.1", + "rector/rector": "^2.1" }, "autoload": { "psr-4": { @@ -49,5 +48,15 @@ "allow-plugins": { "composer/installers": true } - } -} \ No newline at end of file + }, + "repositories": [ + { + "type": "vcs", + "url": "https://github.com/rareloop/router" + }, + { + "type": "vcs", + "url": "https://github.com/tommitchelmore/psr7-server-request-extension" + } + ] +} diff --git a/rector.php b/rector.php new file mode 100644 index 0000000..91bcf48 --- /dev/null +++ b/rector.php @@ -0,0 +1,16 @@ +withPaths([ + __DIR__ . '/src', + __DIR__ . '/tests', + ]) + // uncomment to reach your current PHP version + ->withPhpSets(php84: true); + // ->withTypeCoverageLevel(0) + // ->withDeadCodeLevel(0) + // ->withCodeQualityLevel(0); diff --git a/src/Application.php b/src/Application.php index 22f7443..61f2666 100644 --- a/src/Application.php +++ b/src/Application.php @@ -182,11 +182,9 @@ public function register($provider) public function getProvider($provider) { - $providerClass = is_string($provider) ? $provider : get_class($provider); + $providerClass = is_string($provider) ? $provider : $provider::class; - return (new Collection($this->loadedProviders))->first(function ($provider) use ($providerClass) { - return get_class($provider) === $providerClass; - }); + return new Collection($this->loadedProviders)->first(fn($provider) => $provider::class === $providerClass); } public function getLoadedProviders() @@ -275,7 +273,7 @@ public function detectWhenRequestHasNotBeenHandled() }); } - public function shutdown(ResponseInterface $response = null) + public function shutdown(?ResponseInterface $response = null) { if ($response) { global $wp; @@ -300,16 +298,12 @@ protected function removeSentHeadersAndMoveIntoResponse(ResponseInterface $respo header_remove($parts[0]); return $parts; - })->filter(function ($header) { - return !in_array(strtolower($header[0]), ['content-type']); - }); + })->filter(fn($header) => !in_array(strtolower((string) $header[0]), ['content-type'])); // Add the previously sent headers into the response // Note: You can't mutate a response so we need to use the reduce to end up with a response // object with all the correct headers - $responseToSend = collect($headersToAdd)->reduce(function ($newResponse, $header) { - return $newResponse->withAddedHeader($header[0], $header[1]); - }, $response); + $responseToSend = collect($headersToAdd)->reduce(fn($newResponse, $header) => $newResponse->withAddedHeader($header[0], $header[1]), $response); return $responseToSend; } diff --git a/src/Bootstrappers/RegisterExceptionHandler.php b/src/Bootstrappers/RegisterExceptionHandler.php index b4ff838..14de197 100644 --- a/src/Bootstrappers/RegisterExceptionHandler.php +++ b/src/Bootstrappers/RegisterExceptionHandler.php @@ -34,8 +34,8 @@ public function bootstrap(Application $app) } error_reporting(-1); - set_error_handler([$this, 'handleError']); - set_exception_handler([$this, 'handleException']); + set_error_handler($this->handleError(...)); + set_exception_handler($this->handleException(...)); register_shutdown_function([$this, 'handleShutdown']); } @@ -50,7 +50,7 @@ public function handleException($e) try { $request = $this->app->get('request'); - } catch (NotFoundException $notFoundException) { + } catch (NotFoundException) { $request = ServerRequestFactory::fromGlobals( $_SERVER, $_GET, diff --git a/src/Config.php b/src/Config.php index 86b0ea3..9ea2e60 100644 --- a/src/Config.php +++ b/src/Config.php @@ -9,7 +9,7 @@ class Config { private $data = []; - public function __construct(string $path = null) + public function __construct(?string $path = null) { if ($path) { $this->load($path); diff --git a/src/Contracts/QueryBuilder.php b/src/Contracts/QueryBuilder.php index 848720d..8797b6f 100644 --- a/src/Contracts/QueryBuilder.php +++ b/src/Contracts/QueryBuilder.php @@ -16,7 +16,7 @@ public function offset($offset): QueryBuilder; public function orderBy($orderBy, string $order = QueryBuilder::ASC): QueryBuilder; - public function orderByMeta($metaKey, string $order = QueryBuilder::ASC, string $type = null): QueryBuilder; + public function orderByMeta($metaKey, string $order = QueryBuilder::ASC, ?string $type = null): QueryBuilder; public function whereIdIn(array $ids): QueryBuilder; diff --git a/src/Encrypter.php b/src/Encrypter.php index 12e3049..cc912d8 100644 --- a/src/Encrypter.php +++ b/src/Encrypter.php @@ -7,11 +7,8 @@ class Encrypter implements EncrypterContract { - protected $key; - - public function __construct($key) + public function __construct(protected $key) { - $this->key = $key; } public function encrypt($data) diff --git a/src/Exceptions/Handler.php b/src/Exceptions/Handler.php index 045b6f1..7d59ef8 100644 --- a/src/Exceptions/Handler.php +++ b/src/Exceptions/Handler.php @@ -45,6 +45,6 @@ public function render(ServerRequestInterface $request, Exception $e) : Response protected function shouldNotReport(Exception $e) { - return in_array(get_class($e), $this->dontReport); + return in_array($e::class, $this->dontReport); } } diff --git a/src/Facades/Config.php b/src/Facades/Config.php index 174a692..41b7be7 100644 --- a/src/Facades/Config.php +++ b/src/Facades/Config.php @@ -6,6 +6,7 @@ class Config extends AbstractFacade { + #[\Override] protected static function accessor() { return 'config'; diff --git a/src/Facades/Log.php b/src/Facades/Log.php index 324c66b..fe0a8c3 100644 --- a/src/Facades/Log.php +++ b/src/Facades/Log.php @@ -6,6 +6,7 @@ class Log extends AbstractFacade { + #[\Override] protected static function accessor() { return 'logger'; diff --git a/src/Facades/MiddlewareAliases.php b/src/Facades/MiddlewareAliases.php index cf8bf7d..340128b 100644 --- a/src/Facades/MiddlewareAliases.php +++ b/src/Facades/MiddlewareAliases.php @@ -6,6 +6,7 @@ class MiddlewareAliases extends AbstractFacade { + #[\Override] protected static function accessor() { return 'middleware-alias-store'; diff --git a/src/Facades/Router.php b/src/Facades/Router.php index 6859dec..5db20d4 100644 --- a/src/Facades/Router.php +++ b/src/Facades/Router.php @@ -6,6 +6,7 @@ class Router extends AbstractFacade { + #[\Override] protected static function accessor() { return 'router'; diff --git a/src/Facades/Session.php b/src/Facades/Session.php index cf9b053..036aad0 100644 --- a/src/Facades/Session.php +++ b/src/Facades/Session.php @@ -6,6 +6,7 @@ class Session extends AbstractFacade { + #[\Override] protected static function accessor() { return 'session'; diff --git a/src/Http/Lumberjack.php b/src/Http/Lumberjack.php index df31f57..8225b1b 100644 --- a/src/Http/Lumberjack.php +++ b/src/Http/Lumberjack.php @@ -13,8 +13,6 @@ class Lumberjack { - private $app; - protected $bootstrappers = [ LoadConfiguration::class, RegisterExceptionHandler::class, @@ -25,9 +23,8 @@ class Lumberjack RegisterRequestHandler::class, ]; - public function __construct(Application $app) + public function __construct(private readonly Application $app) { - $this->app = $app; } public function bootstrap() diff --git a/src/Http/Middleware/PasswordProtected.php b/src/Http/Middleware/PasswordProtected.php index 23e886d..ef1bd96 100644 --- a/src/Http/Middleware/PasswordProtected.php +++ b/src/Http/Middleware/PasswordProtected.php @@ -37,7 +37,7 @@ protected function handlePasswordProtected(): ?ResponseInterface try { return new TimberResponse($template, $context); - } catch (TwigTemplateNotFoundException $e) { + } catch (TwigTemplateNotFoundException) { return null; } } diff --git a/src/Http/MiddlewareAliasStore.php b/src/Http/MiddlewareAliasStore.php index c9c2682..b86eb5b 100644 --- a/src/Http/MiddlewareAliasStore.php +++ b/src/Http/MiddlewareAliasStore.php @@ -17,7 +17,7 @@ public function set(string $name, $middleware) public function get(string $name) { - list($name, $params) = $this->parseName($name); + [$name, $params] = $this->parseName($name); $middleware = $this->aliases[$name]; @@ -34,7 +34,7 @@ public function get(string $name) protected function parseName($name) : array { - list($name, $params) = array_pad(explode(':', $name), 2, ''); + [$name, $params] = array_pad(explode(':', (string) $name), 2, ''); $params = explode(',', $params); @@ -43,7 +43,7 @@ protected function parseName($name) : array public function has(string $name) : bool { - list($name, $params) = $this->parseName($name); + [$name, $params] = $this->parseName($name); return isset($this->aliases[$name]); } diff --git a/src/Http/Router.php b/src/Http/Router.php index 7753b07..3eb1d25 100644 --- a/src/Http/Router.php +++ b/src/Http/Router.php @@ -17,6 +17,7 @@ class Router extends RareRouter * @param callable|string $callback * @return \Rareloop\Router\Route */ + #[\Override] public function map(array $verbs, string $uri, $callback): Route { if ($this->isControllerString($callback)) { @@ -34,7 +35,7 @@ public function map(array $verbs, string $uri, $callback): Route */ private function isControllerString($callback) : bool { - return is_string($callback) && strpos($callback, '@') !== false; + return is_string($callback) && str_contains($callback, '@'); } /** @@ -45,7 +46,7 @@ private function isControllerString($callback) : bool */ private function normaliseCallbackString(string $callback) : string { - @list($controller, $method) = explode('@', $callback); + @[$controller, $method] = explode('@', $callback); if (class_exists($this->defaultControllerNamespace . $controller)) { return $this->defaultControllerNamespace . $callback; diff --git a/src/Page.php b/src/Page.php index 8398eea..edaee2b 100644 --- a/src/Page.php +++ b/src/Page.php @@ -11,6 +11,7 @@ class Page extends Post * * @return string */ + #[\Override] public static function getPostType() { return 'page'; diff --git a/src/Post.php b/src/Post.php index 38f4258..62fc2d3 100644 --- a/src/Post.php +++ b/src/Post.php @@ -26,6 +26,7 @@ public function __construct(mixed $wpPost = null, $preventTimberInit = false) } } + #[\Override] public function __call($name, $arguments) { if (static::hasMacro($name)) { @@ -46,7 +47,7 @@ public static function __callStatic($name, $arguments) return call_user_func_array([$builder, $name], $arguments); } - trigger_error('Call to undefined method ' . __CLASS__ . '::' . $name . '()', E_USER_ERROR); + trigger_error('Call to undefined method ' . self::class . '::' . $name . '()', E_USER_ERROR); } /** @@ -101,7 +102,7 @@ public static function register() throw new PostTypeRegistrationException('Config not set'); } - add_filter('timber/post/classmap', [static::class, 'filterTimberPostClassMap']); + add_filter('timber/post/classmap', static::filterTimberPostClassMap(...)); register_post_type($postType, $config); } @@ -119,7 +120,7 @@ public static function filterTimberPostClassMap(array $classMap): array */ public static function all($perPage = -1, $orderby = 'menu_order', $order = 'ASC') { - $order = strtoupper($order); + $order = strtoupper((string) $order); $args = [ 'posts_per_page' => $perPage, @@ -161,6 +162,6 @@ public static function query($args = null) */ private static function posts($args = null) { - return collect(Timber::get_posts($args, get_called_class())); + return collect(Timber::get_posts($args, static::class)); } } diff --git a/src/Providers/SessionServiceProvider.php b/src/Providers/SessionServiceProvider.php index 8ca5715..d7dca2d 100644 --- a/src/Providers/SessionServiceProvider.php +++ b/src/Providers/SessionServiceProvider.php @@ -43,12 +43,8 @@ public function boot() setcookie( $this->session->getName(), - $this->session->getId(), - time() + ($cookieOptions['lifetime'] * 60), - $cookieOptions['path'], - $cookieOptions['domain'], - $cookieOptions['secure'], - $cookieOptions['httpOnly'] + (string) $this->session->getId(), + ['expires' => time() + ($cookieOptions['lifetime'] * 60), 'path' => $cookieOptions['path'], 'domain' => $cookieOptions['domain'], 'secure' => $cookieOptions['secure'], 'httponly' => $cookieOptions['httpOnly']] ); $cookieSet = true; diff --git a/src/Providers/WordPressControllersServiceProvider.php b/src/Providers/WordPressControllersServiceProvider.php index 29170f5..94a8716 100644 --- a/src/Providers/WordPressControllersServiceProvider.php +++ b/src/Providers/WordPressControllersServiceProvider.php @@ -16,7 +16,7 @@ class WordPressControllersServiceProvider extends ServiceProvider { public function boot() { - add_filter('template_include', [$this, 'handleTemplateInclude']); + add_filter('template_include', $this->handleTemplateInclude(...)); } public function handleTemplateInclude($template) @@ -38,14 +38,14 @@ public function handleTemplateInclude($template) if ($response) { $this->app->shutdown($response); } else { - $this->app->bind('__wp-controller-miss-template', basename($template)); + $this->app->bind('__wp-controller-miss-template', basename((string) $template)); $this->app->bind('__wp-controller-miss-controller', $controller); } } public function getControllerClassFromTemplate($template) { - $controllerName = Stringy::create(basename($template, '.php'))->upperCamelize() . 'Controller'; + $controllerName = Stringy::create(basename((string) $template, '.php'))->upperCamelize() . 'Controller'; // Classes can't start with a number so we have to special case the behaviour here if ($controllerName === '404Controller') { @@ -76,11 +76,7 @@ public function handleRequest(RequestInterface $request, $controllerName, $metho if ($controller instanceof ProvidesControllerMiddleware) { $controllerMiddleware = new Collection($controller->getControllerMiddleware()); - $middlewares = $controllerMiddleware->reject(function ($cm) use ($methodName) { - return $cm->excludedForMethod($methodName); - })->map(function ($cm) { - return $cm->middleware(); - })->all(); + $middlewares = $controllerMiddleware->reject(fn($cm) => $cm->excludedForMethod($methodName))->map(fn($cm) => $cm->middleware())->all(); } $middlewares = [ @@ -102,9 +98,7 @@ private function createDispatcher(array $middlewares): Dispatcher $resolver = null; if ($this->app->has('middleware-resolver')) { - $resolver = function ($name) { - return $this->app->get('middleware-resolver')->resolve($name); - }; + $resolver = (fn($name) => $this->app->get('middleware-resolver')->resolve($name)); } return new Dispatcher($middlewares, $resolver); diff --git a/src/QueryBuilder.php b/src/QueryBuilder.php index 384fee6..004f019 100644 --- a/src/QueryBuilder.php +++ b/src/QueryBuilder.php @@ -82,7 +82,7 @@ public function orderBy($orderBy, string $order = QueryBuilder::ASC): QueryBuild return $this; } - public function orderByMeta($metaKey, string $order = QueryBuilder::ASC, string $type = null): QueryBuilderContract + public function orderByMeta($metaKey, string $order = QueryBuilder::ASC, ?string $type = null): QueryBuilderContract { $order = strtoupper($order); @@ -122,7 +122,7 @@ public function whereStatus(): QueryBuilderContract protected function initialiseMetaQuery() { - $this->params['meta_query'] = $this->params['meta_query'] ?? []; + $this->params['meta_query'] ??= []; } public function whereMeta($key, $value, $compare = '=', $type = null): QueryBuilderContract diff --git a/src/ScopedQueryBuilder.php b/src/ScopedQueryBuilder.php index f6089c1..70ba909 100644 --- a/src/ScopedQueryBuilder.php +++ b/src/ScopedQueryBuilder.php @@ -12,14 +12,10 @@ class ScopedQueryBuilder { - protected $postClass; - protected $queryBuilder; - public function __construct($postClass) + public function __construct(protected $postClass) { - $this->postClass = $postClass; - $this->queryBuilder = Helpers::app(QueryBuilderContract::class); $this->queryBuilder @@ -38,12 +34,10 @@ public function __call($name, $arguments) } // See if this is a scope function that needs calling - $scopeFunctionName = 'scope' . ucfirst($name); + $scopeFunctionName = 'scope' . ucfirst((string) $name); $reflection = new ReflectionClass($this->postClass); - $publicMethods = collect($reflection->getMethods(ReflectionMethod::IS_PUBLIC))->map(function ($method) { - return $method->getName(); - })->toArray(); + $publicMethods = collect($reflection->getMethods(ReflectionMethod::IS_PUBLIC))->map(fn($method) => $method->getName())->toArray(); if (!in_array($scopeFunctionName, $publicMethods)) { trigger_error( @@ -54,7 +48,7 @@ public function __call($name, $arguments) array_unshift($arguments, $this); - return (new $this->postClass(false, true))->{$scopeFunctionName}(...$arguments); + return new $this->postClass(false, true)->{$scopeFunctionName}(...$arguments); } /** @@ -77,7 +71,7 @@ protected function hasQueryBuilderMethod(string $name): bool return false; } - public function wherePostType($postType) + public function wherePostType($postType): never { throw new CannotRedeclarePostTypeOnQueryException; } diff --git a/src/Session/EncryptedStore.php b/src/Session/EncryptedStore.php index 856b7c1..3992cf4 100644 --- a/src/Session/EncryptedStore.php +++ b/src/Session/EncryptedStore.php @@ -17,7 +17,7 @@ public function __construct( SessionHandlerInterface $handler, Encrypter $encrypter, $id = null, - HandlerInterface $exceptionHandler = null + ?HandlerInterface $exceptionHandler = null ) { $this->encrypter = $encrypter; $this->exceptionHandler = $exceptionHandler; @@ -25,11 +25,13 @@ public function __construct( parent::__construct($name, $handler, $id); } + #[\Override] protected function prepareForStorage($data) { return $this->encrypter->encrypt($data); } + #[\Override] protected function prepareForUnserialize($data) { try { diff --git a/src/Session/FileSessionHandler.php b/src/Session/FileSessionHandler.php index 80d5a48..9efa24b 100644 --- a/src/Session/FileSessionHandler.php +++ b/src/Session/FileSessionHandler.php @@ -8,13 +8,8 @@ class FileSessionHandler implements SessionHandlerInterface { - protected $path; - protected $prefix; - - public function __construct($path, $prefix = 'lumberjack_session_') + public function __construct(protected $path, protected $prefix = 'lumberjack_session_') { - $this->path = $path; - $this->prefix = $prefix; } #[\ReturnTypeWillChange] @@ -46,7 +41,7 @@ public function write($sessionId, $data) { try { file_put_contents($this->getFilepath($sessionId), $data); - } catch (Exception $e) { + } catch (Exception) { Log::error('Failed to create session on disk'); } diff --git a/src/Session/Store.php b/src/Session/Store.php index 9c58b64..62cbbbc 100644 --- a/src/Session/Store.php +++ b/src/Session/Store.php @@ -194,7 +194,7 @@ public function getId() public function setId($id = null) { - $id = $id ?? static::random(40); + $id ??= static::random(40); $this->id = $id; } diff --git a/src/ViewModel.php b/src/ViewModel.php index a7a9a31..724cede 100644 --- a/src/ViewModel.php +++ b/src/ViewModel.php @@ -12,20 +12,16 @@ abstract class ViewModel implements Arrayable public function toArray() : array { $propertyKeyValues = collect($this->validPropertyNames()) - ->mapWithKeys(function ($method) { - return [ - $method => $this->{$method}, - ]; - }) + ->mapWithKeys(fn($method) => [ + $method => $this->{$method}, + ]) ->toArray(); $methodKeyValues = collect($this->validMethodNames()) ->whereNotIn(null, $this->ignoredMethods()) - ->mapWithKeys(function ($method) { - return [ - $method => call_user_func([$this, $method]), - ]; - }) + ->mapWithKeys(fn($method) => [ + $method => call_user_func([$this, $method]), + ]) ->toArray(); return array_merge($propertyKeyValues, $methodKeyValues); @@ -35,12 +31,8 @@ protected function validMethodNames() : array { $class = new ReflectionClass(static::class); return collect($class->getMethods(ReflectionMethod::IS_PUBLIC)) - ->reject(function ($method) { - return $method->isStatic() || $method->getNumberOfParameters() > 0; - }) - ->map(function ($method) { - return $method->getName(); - }) + ->reject(fn($method) => $method->isStatic() || $method->getNumberOfParameters() > 0) + ->map(fn($method) => $method->getName()) ->all(); } @@ -49,12 +41,8 @@ protected function validPropertyNames() : array $class = new ReflectionClass(static::class); return collect($class->getProperties(ReflectionProperty::IS_PUBLIC)) - ->reject(function ($property) { - return $property->isStatic(); - }) - ->map(function ($property) { - return $property->getName(); - }) + ->reject(fn($property) => $property->isStatic()) + ->map(fn($property) => $property->getName()) ->all(); } diff --git a/src/functions.php b/src/functions.php index 92043dd..20acd20 100644 --- a/src/functions.php +++ b/src/functions.php @@ -5,69 +5,69 @@ if (!function_exists('app')) { function app() { - return call_user_func_array([Helpers::class, 'app'], func_get_args()); + return call_user_func_array(Helpers::app(...), func_get_args()); } } if (!function_exists('config')) { function config() { - return call_user_func_array([Helpers::class, 'config'], func_get_args()); + return call_user_func_array(Helpers::config(...), func_get_args()); } } if (!function_exists('view')) { function view() { - return call_user_func_array([Helpers::class, 'view'], func_get_args()); + return call_user_func_array(Helpers::view(...), func_get_args()); } } if (!function_exists('route')) { function route() { - return call_user_func_array([Helpers::class, 'route'], func_get_args()); + return call_user_func_array(Helpers::route(...), func_get_args()); } } if (!function_exists('redirect')) { function redirect() { - return call_user_func_array([Helpers::class, 'redirect'], func_get_args()); + return call_user_func_array(Helpers::redirect(...), func_get_args()); } } if (!function_exists('report')) { function report() { - return call_user_func_array([Helpers::class, 'report'], func_get_args()); + return call_user_func_array(Helpers::report(...), func_get_args()); } } if (!function_exists('session')) { function session() { - return call_user_func_array([Helpers::class, 'session'], func_get_args()); + return call_user_func_array(Helpers::session(...), func_get_args()); } } if (!function_exists('back')) { function back() { - return call_user_func_array([Helpers::class, 'back'], func_get_args()); + return call_user_func_array(Helpers::back(...), func_get_args()); } } if (!function_exists('request')) { function request() { - return call_user_func_array([Helpers::class, 'request'], func_get_args()); + return call_user_func_array(Helpers::request(...), func_get_args()); } } if (!function_exists('logger')) { function logger() { - return call_user_func_array([Helpers::class, 'logger'], func_get_args()); + return call_user_func_array(Helpers::logger(...), func_get_args()); } } diff --git a/tests/Unit/ApplicationTest.php b/tests/Unit/ApplicationTest.php index cc5f13c..2e6bee6 100644 --- a/tests/Unit/ApplicationTest.php +++ b/tests/Unit/ApplicationTest.php @@ -498,9 +498,7 @@ private function createPhpSapiNameMock($value, $namespace) $builder->setNamespace($namespace) ->setName('php_sapi_name') ->setFunction( - function () use ($value) { - return $value; - } + fn() => $value ); return $builder->build(); @@ -552,21 +550,15 @@ public function calling_detectWhenRequestHasNotBeenHandled_adds_actions() class BootstrapperBootstrapTester { - public $callback; - - public function __construct($callback) + public function __construct(public $callback) { - $this->callback = $callback; } } abstract class TestBootstrapperBase { - private BootstrapperBootstrapTester $tester; - - public function __construct(BootstrapperBootstrapTester $tester) + public function __construct(private readonly BootstrapperBootstrapTester $tester) { - $this->tester = $tester; } public function bootstrap(Application $app) @@ -654,13 +646,9 @@ public function __construct(TestInterface $test) class RequiresAdditionalConstructorParams { public $param; - public $param1; - public $param2; - public function __construct(TestInterface $test, $param1, $param2) + public function __construct(TestInterface $test, public $param1, public $param2) { $this->param = $test; - $this->param1 = $param1; - $this->param2 = $param2; } } diff --git a/tests/Unit/Bootstrappers/RegisterExceptionHandlerTest.php b/tests/Unit/Bootstrappers/RegisterExceptionHandlerTest.php index c19f006..403b4ec 100644 --- a/tests/Unit/Bootstrappers/RegisterExceptionHandlerTest.php +++ b/tests/Unit/Bootstrappers/RegisterExceptionHandlerTest.php @@ -57,9 +57,7 @@ public function E_USER_NOTICE_errors_are_not_converted_to_exceptions() $app->bind('config', $config); $app->bind(Config::class, $config); - $handler->shouldReceive('report')->once()->with(Mockery::on(function ($e) { - return $e->getSeverity() === E_USER_NOTICE && $e->getMessage() === 'Test Error'; - })); + $handler->shouldReceive('report')->once()->with(Mockery::on(fn($e) => $e->getSeverity() === E_USER_NOTICE && $e->getMessage() === 'Test Error')); $bootstrapper = new RegisterExceptionHandler(); $bootstrapper->bootstrap($app); @@ -80,9 +78,7 @@ public function E_USER_DEPRECATED_errors_are_not_converted_to_exceptions() $app->bind('config', $config); $app->bind(Config::class, $config); - $handler->shouldReceive('report')->once()->with(Mockery::on(function ($e) { - return $e->getSeverity() === E_USER_DEPRECATED && $e->getMessage() === 'Test Error'; - })); + $handler->shouldReceive('report')->once()->with(Mockery::on(fn($e) => $e->getSeverity() === E_USER_DEPRECATED && $e->getMessage() === 'Test Error')); $bootstrapper = new RegisterExceptionHandler(); $bootstrapper->bootstrap($app); @@ -103,9 +99,7 @@ public function E_DEPRECATED_errors_are_not_converted_to_exceptions() $app->bind('config', $config); $app->bind(Config::class, $config); - $handler->shouldReceive('report')->once()->with(Mockery::on(function ($e) { - return $e->getSeverity() === E_DEPRECATED && $e->getMessage() === 'Test Error'; - })); + $handler->shouldReceive('report')->once()->with(Mockery::on(fn($e) => $e->getSeverity() === E_DEPRECATED && $e->getMessage() === 'Test Error')); $bootstrapper = new RegisterExceptionHandler(); $bootstrapper->bootstrap($app); @@ -128,9 +122,7 @@ public function custom_error_level_can_be_set_for_report_only() $app->bind('config', $config); $app->bind(Config::class, $config); - $handler->shouldReceive('report')->once()->with(Mockery::on(function ($e) { - return $e->getSeverity() === E_USER_ERROR && $e->getMessage() === 'Test Error'; - })); + $handler->shouldReceive('report')->once()->with(Mockery::on(fn($e) => $e->getSeverity() === E_USER_ERROR && $e->getMessage() === 'Test Error')); $bootstrapper = new RegisterExceptionHandler(); $bootstrapper->bootstrap($app); diff --git a/tests/Unit/GlobalFunctionsTest.php b/tests/Unit/GlobalFunctionsTest.php index bc0d1d6..a0e7a5d 100644 --- a/tests/Unit/GlobalFunctionsTest.php +++ b/tests/Unit/GlobalFunctionsTest.php @@ -46,8 +46,6 @@ public static function globalHelperFunctions() { $reflection = new \ReflectionClass(Helpers::class); - return collect($reflection->getMethods(\ReflectionMethod::IS_STATIC))->map(function ($function) { - return [$function->name]; - })->toArray(); + return collect($reflection->getMethods(\ReflectionMethod::IS_STATIC))->map(fn($function) => [$function->name])->toArray(); } } diff --git a/tests/Unit/HelpersTest.php b/tests/Unit/HelpersTest.php index 11505cd..a4d1c7c 100644 --- a/tests/Unit/HelpersTest.php +++ b/tests/Unit/HelpersTest.php @@ -147,7 +147,7 @@ public function can_get_a_url_for_a_named_route() $url = Helpers::route('test.route'); - $this->assertSame('test/route', trim($url, '/')); + $this->assertSame('test/route', trim((string) $url, '/')); } /** @test */ @@ -164,7 +164,7 @@ public function can_get_a_url_for_a_named_route_with_params() 'name' => 'route', ]); - $this->assertSame('test/route', trim($url, '/')); + $this->assertSame('test/route', trim((string) $url, '/')); } /** @test */ @@ -207,9 +207,7 @@ public function can_report_an_exception() $handler = \Mockery::mock(TestExceptionHandler::class . '[report]', [$app]); $handler->shouldReceive('report')->with($exception)->once(); - $app->bind(HandlerInterface::class, function () use ($handler) { - return $handler; - }); + $app->bind(HandlerInterface::class, fn() => $handler); Helpers::report($exception); } @@ -375,12 +373,7 @@ class TestExceptionHandler extends Handler class RequiresConstructorParams { - public $param1; - public $param2; - - public function __construct($param1, $param2) + public function __construct(public $param1, public $param2) { - $this->param1 = $param1; - $this->param2 = $param2; } } diff --git a/tests/Unit/Http/Middleware/PasswordProtectTest.php b/tests/Unit/Http/Middleware/PasswordProtectTest.php index a21fc20..523e1b4 100644 --- a/tests/Unit/Http/Middleware/PasswordProtectTest.php +++ b/tests/Unit/Http/Middleware/PasswordProtectTest.php @@ -52,9 +52,7 @@ public function it_does_nothing_when_the_password_twig_file_is_not_found() $timber = \Mockery::mock('alias:' . Timber::class); $timber->shouldReceive('get_post')->once(); $timber->shouldReceive('compile') - ->withArgs(function ($template) { - return $template === 'single-password.twig'; - }) + ->withArgs(fn($template) => $template === 'single-password.twig') ->once() ->andReturn(false); @@ -84,9 +82,7 @@ public function it_renders_the_password_template_when_needed() $timber = \Mockery::mock('alias:' . Timber::class); $timber->shouldReceive('get_post')->once(); $timber->shouldReceive('compile') - ->withArgs(function ($template) { - return $template === 'single-password.twig'; - }) + ->withArgs(fn($template) => $template === 'single-password.twig') ->once() ->andReturn('testing123'); diff --git a/tests/Unit/Http/MiddlewareAliasStoreTest.php b/tests/Unit/Http/MiddlewareAliasStoreTest.php index 6d97f28..6818104 100644 --- a/tests/Unit/Http/MiddlewareAliasStoreTest.php +++ b/tests/Unit/Http/MiddlewareAliasStoreTest.php @@ -29,9 +29,7 @@ public function can_register_an_alias_for_a_middleware_closure_factory() $store = new MiddlewareAliasStore; $middleware = Mockery::mock(MiddlewareInterface::class); - $store->set('middlewarekey', function () use ($middleware) { - return $middleware; - }); + $store->set('middlewarekey', fn() => $middleware); $this->assertSame($middleware, $store->get('middlewarekey')); } @@ -108,12 +106,7 @@ class MASTestClass class MASTestClassWithConstructorParams { - public $param1; - public $param2; - - public function __construct($param1, $param2) + public function __construct(public $param1, public $param2) { - $this->param1 = $param1; - $this->param2 = $param2; } } diff --git a/tests/Unit/Http/RouterTest.php b/tests/Unit/Http/RouterTest.php index 9447e00..1422145 100644 --- a/tests/Unit/Http/RouterTest.php +++ b/tests/Unit/Http/RouterTest.php @@ -42,7 +42,7 @@ public function controller_does_not_have_namespace_added_when_it_is_callable() $router = new Router; $controller = new RouterTestController; - $route = $router->get('/test/123', [$controller, 'test']); + $route = $router->get('/test/123', $controller->test(...)); $this->assertSame(RouterTestController::class . '@test', $route->getActionName()); } @@ -63,9 +63,7 @@ public function controller_does_not_have_namespace_added_when_it_is_closure() */ public function can_extend_post_behaviour_with_macros() { - Router::macro('testFunctionAddedByMacro', function () { - return 'abc123'; - }); + Router::macro('testFunctionAddedByMacro', fn() => 'abc123'); $queryBuilder = new Router(); @@ -90,9 +88,7 @@ class RouterMixin { function testFunctionAddedByMixin() { - return function() { - return 'abc123'; - }; + return fn() => 'abc123'; } } diff --git a/tests/Unit/PostQueryBuilderTest.php b/tests/Unit/PostQueryBuilderTest.php index 8cb501d..0ad0fea 100644 --- a/tests/Unit/PostQueryBuilderTest.php +++ b/tests/Unit/PostQueryBuilderTest.php @@ -55,7 +55,7 @@ public function throw_error_on_missing_static_function() try { Post::missingStaticFunction(); - } catch (Throwable $e) { + } catch (Throwable) { $errorThrown = true; } @@ -84,6 +84,7 @@ public static function setCreateBuilderResponse($builder) static::$injectedBuilder = $builder; } + #[\Override] public static function builder(): ScopedQueryBuilder { return static::$injectedBuilder; diff --git a/tests/Unit/PostTest.php b/tests/Unit/PostTest.php index 4aabdc7..e57e3d9 100644 --- a/tests/Unit/PostTest.php +++ b/tests/Unit/PostTest.php @@ -30,7 +30,7 @@ public function register_function_calls_register_post_type_when_post_type_and_co RegisterablePostType::register(); - $this->assertNotFalse(has_filter('timber/post/classmap', [RegisterablePostType::class, 'filterTimberPostClassMap'])); + $this->assertNotFalse(has_filter('timber/post/classmap', RegisterablePostType::filterTimberPostClassMap(...))); } /** @test */ @@ -213,9 +213,7 @@ public function all_can_have_order_set() */ public function can_extend_post_behaviour_with_macros() { - Post::macro('testFunctionAddedByMacro', function () { - return 'abc123'; - }); + Post::macro('testFunctionAddedByMacro', fn() => 'abc123'); $post = new Post(null, true); @@ -228,9 +226,7 @@ public function can_extend_post_behaviour_with_macros() */ public function macros_set_correct_this_context_on_instances() { - PostWithPrivateData::macro('testFunctionAddedByMacro', function () { - return $this->dummyData; - }); + PostWithPrivateData::macro('testFunctionAddedByMacro', fn() => $this->dummyData); $post = new PostWithPrivateData(null, true); @@ -254,9 +250,7 @@ class PostMixin { function testFunctionAddedByMixin() { - return function () { - return 'abc123'; - }; + return fn() => 'abc123'; } } @@ -267,6 +261,7 @@ class PostWithPrivateData extends Post class RegisterablePostType extends Post { + #[\Override] public static function getPostType(): string { return 'registerable_post_type'; @@ -317,6 +312,7 @@ protected static function getPostTypeConfig(): array class UnregisterablePostTypeWithoutConfig extends Post { + #[\Override] public static function getPostType(): string { return 'post_type'; diff --git a/tests/Unit/Providers/CustomPostTypesServiceProviderTest.php b/tests/Unit/Providers/CustomPostTypesServiceProviderTest.php index ae58e05..ac2aa05 100644 --- a/tests/Unit/Providers/CustomPostTypesServiceProviderTest.php +++ b/tests/Unit/Providers/CustomPostTypesServiceProviderTest.php @@ -37,6 +37,7 @@ public function should_call_register_post_type_for_each_configured_post_type() class CustomPost1 extends Post { + #[\Override] public static function getPostType() { return 'custom_post_1'; @@ -52,6 +53,7 @@ protected static function getPostTypeConfig() class CustomPost2 extends Post { + #[\Override] public static function getPostType() { return 'custom_post_1'; diff --git a/tests/Unit/Providers/RouterServiceProviderTest.php b/tests/Unit/Providers/RouterServiceProviderTest.php index 780f363..b8f0ca2 100644 --- a/tests/Unit/Providers/RouterServiceProviderTest.php +++ b/tests/Unit/Providers/RouterServiceProviderTest.php @@ -102,9 +102,7 @@ public function basedir_is_set_from_wordpress_config() $lumberjack->bootstrap(); $router = $app->get('router'); - $router->get('/test/123', function () { - return 'abc123'; - }); + $router->get('/test/123', fn() => 'abc123'); $response = $router->match($request); $this->assertSame(200, $response->getStatusCode()); @@ -287,13 +285,8 @@ private function setSiteUrl($url) class RSPAddHeaderMiddleware implements MiddlewareInterface { - private $key; - private $value; - - public function __construct($key, $value) + public function __construct(private $key, private $value) { - $this->key = $key; - $this->value = $value; } public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface diff --git a/tests/Unit/Providers/WordPressControllersServiceProviderTest.php b/tests/Unit/Providers/WordPressControllersServiceProviderTest.php index f588181..90fc6f2 100644 --- a/tests/Unit/Providers/WordPressControllersServiceProviderTest.php +++ b/tests/Unit/Providers/WordPressControllersServiceProviderTest.php @@ -40,7 +40,7 @@ public function template_include_filter_is_applied_on_boot() $app->register($provider); $app->boot(); - $this->assertNotFalse(has_filter('template_include', [$provider, 'handleTemplateInclude'])); + $this->assertNotFalse(has_filter('template_include', $provider->handleTemplateInclude(...))); } /** @test */ @@ -195,7 +195,7 @@ public function handle_request_returns_response_when_controller_does_exist() $app = new Application(__DIR__ . '/../'); $provider = new WordPressControllersServiceProvider($app); - $provider->boot($app); + $provider->boot(); $response = $provider->handleRequest(new ServerRequest, TestController::class, 'handle'); @@ -212,7 +212,7 @@ public function handle_request_returns_response_when_controller_returns_a_respon $app = new Application(__DIR__ . '/../'); $provider = new WordPressControllersServiceProvider($app); - $provider->boot($app); + $provider->boot(); $response = $provider->handleRequest(new ServerRequest, TestControllerReturningAResponsable::class, 'handle'); @@ -230,7 +230,7 @@ public function handle_request_resolves_constructor_params_from_container() $app = new Application(__DIR__ . '/../'); $provider = new WordPressControllersServiceProvider($app); - $provider->boot($app); + $provider->boot(); $response = $provider->handleRequest(new ServerRequest, TestControllerWithConstructorParams::class, 'handle'); @@ -247,7 +247,7 @@ public function handle_request_resolves_controller_method_params_from_container( $app = new Application(__DIR__ . '/../'); $provider = new WordPressControllersServiceProvider($app); - $provider->boot($app); + $provider->boot(); $response = $provider->handleRequest(new ServerRequest, TestControllerWithHandleParams::class, 'handle'); @@ -267,7 +267,7 @@ public function handle_request_supports_middleware() $app->bind(TestControllerWithMiddleware::class, $controller); $provider = new WordPressControllersServiceProvider($app); - $provider->boot($app); + $provider->boot(); $response = $provider->handleRequest(new ServerRequest, TestControllerWithMiddleware::class, 'handle'); @@ -288,7 +288,7 @@ public function handle_request_adds_password_protect_middleware() $app->bind(TestControllerWithMiddleware::class, $controller); $provider = new WordPressControllersServiceProvider($app); - $provider->boot($app); + $provider->boot(); $response = $provider->handleRequest(new ServerRequest, TestControllerWithMiddleware::class, 'handle'); @@ -308,7 +308,7 @@ public function handle_request_supports_middleware_applied_to_a_specific_method_ $app->bind(TestControllerWithMiddleware::class, $controller); $provider = new WordPressControllersServiceProvider($app); - $provider->boot($app); + $provider->boot(); $response = $provider->handleRequest(new ServerRequest, TestControllerWithMiddleware::class, 'handle'); @@ -328,7 +328,7 @@ public function handle_request_supports_middleware_applied_to_a_specific_method_ $app->bind(TestControllerWithMiddleware::class, $controller); $provider = new WordPressControllersServiceProvider($app); - $provider->boot($app); + $provider->boot(); $response = $provider->handleRequest(new ServerRequest, TestControllerWithMiddleware::class, 'handle'); @@ -358,7 +358,7 @@ public function handle_request_supports_middleware_aliases() $provider = new WordPressControllersServiceProvider($app); $routerProvider->register(); $routerProvider->boot(); - $provider->boot($app); + $provider->boot(); $store = $app->get(MiddlewareAliases::class); $store->set('middleware-key', new AddHeaderMiddleware('X-Header', 'testing123')); @@ -447,13 +447,8 @@ public function handle() class AddHeaderMiddleware implements MiddlewareInterface { - private $key; - private $value; - - public function __construct($key, $value) + public function __construct(private $key, private $value) { - $this->key = $key; - $this->value = $value; } public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface diff --git a/tests/Unit/QueryBuilderTest.php b/tests/Unit/QueryBuilderTest.php index 20a1426..a059f5c 100644 --- a/tests/Unit/QueryBuilderTest.php +++ b/tests/Unit/QueryBuilderTest.php @@ -526,6 +526,7 @@ function testFunctionAddedByMixin() class PostWithCustomPostType extends Post { + #[\Override] public static function getPostType() { return 'post_with_query_scope'; diff --git a/tests/Unit/ScopedQueryBuilderTest.php b/tests/Unit/ScopedQueryBuilderTest.php index 33483b1..9f3ae13 100644 --- a/tests/Unit/ScopedQueryBuilderTest.php +++ b/tests/Unit/ScopedQueryBuilderTest.php @@ -114,7 +114,7 @@ public function missing_query_scope_throws_an_error() try { $builder = new ScopedQueryBuilder(PostWithQueryScope::class); $builder->nonExistentScope(); - } catch (Throwable $e) { + } catch (Throwable) { $errorThrown = true; } @@ -161,6 +161,7 @@ public function nonStandardMethod() class PostWithQueryScope extends Post { + #[\Override] public static function getPostType() { return 'post_with_query_scope'; diff --git a/tests/Unit/Session/FileSessionHandlerTest.php b/tests/Unit/Session/FileSessionHandlerTest.php index c2801e9..2a6ac05 100644 --- a/tests/Unit/Session/FileSessionHandlerTest.php +++ b/tests/Unit/Session/FileSessionHandlerTest.php @@ -32,7 +32,7 @@ public function close_returns_true() { $handler = new FileSessionHandler(vfsStream::url('exampleDir')); - $this->assertTrue($handler->close('save-path', 'session-name')); + $this->assertTrue($handler->close()); } /** @test */ diff --git a/tests/Unit/Session/SessionManagerTest.php b/tests/Unit/Session/SessionManagerTest.php index c46a2c9..f11a012 100644 --- a/tests/Unit/Session/SessionManagerTest.php +++ b/tests/Unit/Session/SessionManagerTest.php @@ -74,9 +74,7 @@ public function can_extend_list_of_drivers() $app = new Application; $manager = new SessionManager($app); - $manager->extend('test', function () { - return new Store('name', new TestSessionHandler); - }); + $manager->extend('test', fn() => new Store('name', new TestSessionHandler)); $this->assertInstanceOf(TestSessionHandler::class, $manager->driver('test')->getHandler()); } From bbaae010c3ddfc3097306bb9ea66105522bdfddc Mon Sep 17 00:00:00 2001 From: Tom Mitchelmore Date: Mon, 8 Sep 2025 09:38:00 +0100 Subject: [PATCH 02/19] Upgrade phpdi --- src/Application.php | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/Application.php b/src/Application.php index 61f2666..81fa4a4 100644 --- a/src/Application.php +++ b/src/Application.php @@ -3,12 +3,11 @@ namespace Rareloop\Lumberjack; use Closure; -use DI\ContainerBuilder; +use DI\Container; use Illuminate\Support\Collection; use Interop\Container\ContainerInterface as InteropContainerInterface; use Psr\Container\ContainerInterface; use Psr\Http\Message\ResponseInterface; -use Rareloop\Router\Invoker; use function Http\Response\send; class Application implements ContainerInterface, InteropContainerInterface @@ -24,7 +23,7 @@ class Application implements ContainerInterface, InteropContainerInterface public function __construct($basePath = false) { - $this->container = ContainerBuilder::buildDevContainer(); + $this->container = new Container(); $this->bind(Application::class, $this); @@ -232,7 +231,7 @@ public function bootstrapWith(array $bootstrappers) * * @return boolean */ - public function hasRequestBeenHandled() : bool + public function hasRequestBeenHandled(): bool { return $this->requestHandled; } @@ -263,10 +262,10 @@ public function detectWhenRequestHasNotBeenHandled() if ($this->has('__wp-controller-miss-template') && $this->has('__wp-controller-miss-controller')) { wp_die( 'Loaded template ' . - $this->get('__wp-controller-miss-template') . - ' but couldn\'t find class ' . - $this->get('__wp-controller-miss-controller') . - '' + $this->get('__wp-controller-miss-template') . + ' but couldn\'t find class ' . + $this->get('__wp-controller-miss-controller') . + '' ); } } @@ -288,7 +287,7 @@ public function shutdown(?ResponseInterface $response = null) die(); } - protected function removeSentHeadersAndMoveIntoResponse(ResponseInterface $response) : ResponseInterface + protected function removeSentHeadersAndMoveIntoResponse(ResponseInterface $response): ResponseInterface { // 1. Format the previously sent headers into an array of [key, value] // 2. Remove all headers from the output that we find From 338629f918054a52c66ae6efa453ab16cbe8e6fe Mon Sep 17 00:00:00 2001 From: Tom Mitchelmore Date: Mon, 8 Sep 2025 09:41:41 +0100 Subject: [PATCH 03/19] Upgrade container interface methods --- src/Application.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Application.php b/src/Application.php index 81fa4a4..fe368b4 100644 --- a/src/Application.php +++ b/src/Application.php @@ -5,12 +5,11 @@ use Closure; use DI\Container; use Illuminate\Support\Collection; -use Interop\Container\ContainerInterface as InteropContainerInterface; use Psr\Container\ContainerInterface; use Psr\Http\Message\ResponseInterface; use function Http\Response\send; -class Application implements ContainerInterface, InteropContainerInterface +class Application implements ContainerInterface { private $container; private $loadedProviders = []; @@ -151,7 +150,7 @@ private function isSingletonClassBind($id) * * @return bool */ - public function has($id) + public function has(string $id): bool { return $this->container->has($id); } From 55e922c4b37621a67ea8092d96e2975954bde483 Mon Sep 17 00:00:00 2001 From: Tom Mitchelmore Date: Mon, 8 Sep 2025 09:43:47 +0100 Subject: [PATCH 04/19] Replace `\Zend\Diactoros` imports with `\Laminas\Diactoros` --- .../RegisterExceptionHandler.php | 2 +- src/Exceptions/Handler.php | 4 +-- src/Http/Responses/RedirectResponse.php | 2 +- src/Http/Responses/TimberResponse.php | 4 +-- src/Http/ServerRequest.php | 6 ++-- src/Providers/RouterServiceProvider.php | 2 +- .../WordPressControllersServiceProvider.php | 2 +- .../RegisterExceptionHandlerTest.php | 6 ++-- tests/Unit/Exceptions/HandlerTest.php | 8 ++---- tests/Unit/Http/ServerRequestTest.php | 2 +- .../Providers/RouterServiceProviderTest.php | 15 ++++------ ...ordPressControllersServiceProviderTest.php | 28 ++++++------------- 12 files changed, 32 insertions(+), 49 deletions(-) diff --git a/src/Bootstrappers/RegisterExceptionHandler.php b/src/Bootstrappers/RegisterExceptionHandler.php index 14de197..79424c0 100644 --- a/src/Bootstrappers/RegisterExceptionHandler.php +++ b/src/Bootstrappers/RegisterExceptionHandler.php @@ -10,7 +10,7 @@ use Rareloop\Lumberjack\Exceptions\HandlerInterface; use Rareloop\Router\Responsable; use Symfony\Component\Debug\Exception\FatalErrorException; -use Zend\Diactoros\ServerRequestFactory; +use Laminas\Diactoros\ServerRequestFactory; use function Http\Response\send; /** diff --git a/src/Exceptions/Handler.php b/src/Exceptions/Handler.php index 7d59ef8..e6b4067 100644 --- a/src/Exceptions/Handler.php +++ b/src/Exceptions/Handler.php @@ -9,7 +9,7 @@ use Rareloop\Lumberjack\Facades\Config; use Symfony\Component\Debug\ExceptionHandler as SymfonyExceptionHandler; use Symfony\Component\Debug\Exception\FlattenException; -use Zend\Diactoros\Response\HtmlResponse; +use Laminas\Diactoros\Response\HtmlResponse; class Handler implements HandlerInterface { @@ -34,7 +34,7 @@ public function report(Exception $e) } } - public function render(ServerRequestInterface $request, Exception $e) : ResponseInterface + public function render(ServerRequestInterface $request, Exception $e): ResponseInterface { $e = FlattenException::create($e); diff --git a/src/Http/Responses/RedirectResponse.php b/src/Http/Responses/RedirectResponse.php index d51db77..a6d992d 100644 --- a/src/Http/Responses/RedirectResponse.php +++ b/src/Http/Responses/RedirectResponse.php @@ -3,7 +3,7 @@ namespace Rareloop\Lumberjack\Http\Responses; use Rareloop\Lumberjack\Helpers; -use Zend\Diactoros\Response\RedirectResponse as DiactorosRedirectResponse; +use Laminas\Diactoros\Response\RedirectResponse as DiactorosRedirectResponse; class RedirectResponse extends DiactorosRedirectResponse { diff --git a/src/Http/Responses/TimberResponse.php b/src/Http/Responses/TimberResponse.php index 06a31cb..8ac161e 100644 --- a/src/Http/Responses/TimberResponse.php +++ b/src/Http/Responses/TimberResponse.php @@ -6,7 +6,7 @@ use Rareloop\Lumberjack\Contracts\Arrayable; use Rareloop\Lumberjack\Exceptions\TwigTemplateNotFoundException; use Timber\Timber; -use Zend\Diactoros\Response\HtmlResponse; +use Laminas\Diactoros\Response\HtmlResponse; class TimberResponse extends HtmlResponse { @@ -21,7 +21,7 @@ public function __construct($twigTemplate, $context, $status = 200, array $heade parent::__construct($template, $status, $headers); } - private function flattenContextToArrays(array $context) : array + private function flattenContextToArrays(array $context): array { // Recursively walk the array, when we find something that implements the Arrayable interface // flatten it to an array. Because we're passing by reference by updating what the value of diff --git a/src/Http/ServerRequest.php b/src/Http/ServerRequest.php index 5135e39..3274e66 100644 --- a/src/Http/ServerRequest.php +++ b/src/Http/ServerRequest.php @@ -5,7 +5,7 @@ use Psr\Http\Message\ServerRequestInterface; use Rareloop\Psr7ServerRequestExtension\InteractsWithInput; use Rareloop\Psr7ServerRequestExtension\InteractsWithUri; -use Zend\Diactoros\ServerRequest as DiactorosServerRequest; +use Laminas\Diactoros\ServerRequest as DiactorosServerRequest; class ServerRequest extends DiactorosServerRequest { @@ -34,7 +34,7 @@ public static function fromRequest(ServerRequestInterface $request) ); } - public function ajax() : bool + public function ajax(): bool { if (!$this->hasHeader('X-Requested-With')) { return false; @@ -43,7 +43,7 @@ public function ajax() : bool return 'XMLHttpRequest' === $this->getHeader('X-Requested-With')[0]; } - public function getMethod() : string + public function getMethod(): string { return strtoupper(parent::getMethod()); } diff --git a/src/Providers/RouterServiceProvider.php b/src/Providers/RouterServiceProvider.php index 5a61ee5..81f82e1 100644 --- a/src/Providers/RouterServiceProvider.php +++ b/src/Providers/RouterServiceProvider.php @@ -9,7 +9,7 @@ use Rareloop\Lumberjack\Http\Router; use Rareloop\Lumberjack\Http\ServerRequest; use Rareloop\Router\MiddlewareResolver as MiddlewareResolverInterface; -use Zend\Diactoros\ServerRequestFactory; +use Laminas\Diactoros\ServerRequestFactory; class RouterServiceProvider extends ServiceProvider { diff --git a/src/Providers/WordPressControllersServiceProvider.php b/src/Providers/WordPressControllersServiceProvider.php index 94a8716..07766b1 100644 --- a/src/Providers/WordPressControllersServiceProvider.php +++ b/src/Providers/WordPressControllersServiceProvider.php @@ -9,7 +9,7 @@ use Rareloop\Router\ResponseFactory; use Psr\Http\Message\RequestInterface; use Rareloop\Lumberjack\Http\Middleware\PasswordProtected; -use Zend\Diactoros\ServerRequestFactory; +use Laminas\Diactoros\ServerRequestFactory; use Rareloop\Router\ProvidesControllerMiddleware; class WordPressControllersServiceProvider extends ServiceProvider diff --git a/tests/Unit/Bootstrappers/RegisterExceptionHandlerTest.php b/tests/Unit/Bootstrappers/RegisterExceptionHandlerTest.php index 403b4ec..873c272 100644 --- a/tests/Unit/Bootstrappers/RegisterExceptionHandlerTest.php +++ b/tests/Unit/Bootstrappers/RegisterExceptionHandlerTest.php @@ -15,9 +15,9 @@ use Rareloop\Lumberjack\Test\Unit\BrainMonkeyPHPUnitIntegration; use Rareloop\Router\Responsable; use Symfony\Component\Debug\Exception\FatalErrorException; -use Zend\Diactoros\Response; -use Zend\Diactoros\Response\TextResponse; -use Zend\Diactoros\ServerRequest; +use Laminas\Diactoros\Response; +use Laminas\Diactoros\Response\TextResponse; +use Laminas\Diactoros\ServerRequest; /** * @runTestsInSeparateProcesses diff --git a/tests/Unit/Exceptions/HandlerTest.php b/tests/Unit/Exceptions/HandlerTest.php index dda8be0..21889d7 100644 --- a/tests/Unit/Exceptions/HandlerTest.php +++ b/tests/Unit/Exceptions/HandlerTest.php @@ -9,8 +9,8 @@ use Rareloop\Lumberjack\Application; use Rareloop\Lumberjack\Config; use Rareloop\Lumberjack\Exceptions\Handler; -use Zend\Diactoros\Response\HtmlResponse; -use Zend\Diactoros\ServerRequest; +use Laminas\Diactoros\Response\HtmlResponse; +use Laminas\Diactoros\ServerRequest; class HandlerTest extends TestCase { @@ -124,6 +124,4 @@ class HandlerWithBlacklist extends Handler ]; } -class BlacklistedException extends \Exception -{ -} +class BlacklistedException extends \Exception {} diff --git a/tests/Unit/Http/ServerRequestTest.php b/tests/Unit/Http/ServerRequestTest.php index 2fe274c..2aa4667 100644 --- a/tests/Unit/Http/ServerRequestTest.php +++ b/tests/Unit/Http/ServerRequestTest.php @@ -8,7 +8,7 @@ use Rareloop\Lumberjack\Http\ServerRequest; use Rareloop\Psr7ServerRequestExtension\InteractsWithInput; use Rareloop\Psr7ServerRequestExtension\InteractsWithUri; -use Zend\Diactoros\ServerRequest as DiactorosServerRequest; +use Laminas\Diactoros\ServerRequest as DiactorosServerRequest; class ServerRequestTest extends TestCase { diff --git a/tests/Unit/Providers/RouterServiceProviderTest.php b/tests/Unit/Providers/RouterServiceProviderTest.php index b8f0ca2..7926a8c 100644 --- a/tests/Unit/Providers/RouterServiceProviderTest.php +++ b/tests/Unit/Providers/RouterServiceProviderTest.php @@ -18,10 +18,10 @@ use Rareloop\Lumberjack\Providers\RouterServiceProvider; use Rareloop\Lumberjack\Test\Unit\BrainMonkeyPHPUnitIntegration; use Rareloop\Router\MiddlewareResolver; -use Zend\Diactoros\Request; -use Zend\Diactoros\Response\HtmlResponse; -use Zend\Diactoros\Response\TextResponse; -use Zend\Diactoros\ServerRequest; +use Laminas\Diactoros\Request; +use Laminas\Diactoros\Response\HtmlResponse; +use Laminas\Diactoros\Response\TextResponse; +use Laminas\Diactoros\ServerRequest; class RouterServiceProviderTest extends TestCase { @@ -79,8 +79,7 @@ public function configured_router_can_resolve_middleware_aliases() $store->set('middleware-key', new RSPAddHeaderMiddleware('X-Key', 'abc')); $request = new ServerRequest([], [], '/test/123', 'GET'); - $router->get('/test/123', function () { - })->middleware('middleware-key'); + $router->get('/test/123', function () {})->middleware('middleware-key'); $response = $router->match($request); $this->assertTrue($response->hasHeader('X-Key')); @@ -285,9 +284,7 @@ private function setSiteUrl($url) class RSPAddHeaderMiddleware implements MiddlewareInterface { - public function __construct(private $key, private $value) - { - } + public function __construct(private $key, private $value) {} public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { diff --git a/tests/Unit/Providers/WordPressControllersServiceProviderTest.php b/tests/Unit/Providers/WordPressControllersServiceProviderTest.php index 90fc6f2..bee3e8b 100644 --- a/tests/Unit/Providers/WordPressControllersServiceProviderTest.php +++ b/tests/Unit/Providers/WordPressControllersServiceProviderTest.php @@ -22,8 +22,8 @@ use Rareloop\Lumberjack\Providers\WordPressControllersServiceProvider; use Rareloop\Lumberjack\Test\Unit\BrainMonkeyPHPUnitIntegration; use Rareloop\Router\Responsable; -use Zend\Diactoros\Response\TextResponse; -use Zend\Diactoros\ServerRequest; +use Laminas\Diactoros\Response\TextResponse; +use Laminas\Diactoros\ServerRequest; use \Mockery; use Rareloop\Lumberjack\Http\Middleware\PasswordProtected; @@ -399,27 +399,19 @@ public function handle_template_include_will_not_call_app_shutdown_when_it_has_n class TestController { - public function handle() - { - } + public function handle() {} } class TestControllerWithConstructorParams { - public function __construct(Application $app) - { - } + public function __construct(Application $app) {} - public function handle() - { - } + public function handle() {} } class TestControllerWithHandleParams { - public function handle(Application $app) - { - } + public function handle(Application $app) {} } class MyResponsable implements Responsable @@ -440,16 +432,12 @@ public function handle() class TestControllerWithMiddleware extends Controller { - public function handle() - { - } + public function handle() {} } class AddHeaderMiddleware implements MiddlewareInterface { - public function __construct(private $key, private $value) - { - } + public function __construct(private $key, private $value) {} public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { From c7790dce4d07b717be96fa5b1a01f1af5ad60685 Mon Sep 17 00:00:00 2001 From: Tom Mitchelmore Date: Mon, 8 Sep 2025 14:12:43 +0100 Subject: [PATCH 05/19] Replace Blast Facades with own implementation --- composer.json | 1 - src/Bootstrappers/RegisterFacades.php | 4 +- src/FacadeManager.php | 25 ++++++++ src/Facades/Config.php | 5 +- src/Facades/Facade.php | 21 +++++++ src/Facades/Log.php | 5 +- src/Facades/MiddlewareAliases.php | 4 +- src/Facades/Router.php | 5 +- src/Facades/Session.php | 3 +- tests/Unit/Facades/FacadeTest.php | 69 +++++++++++++++++++++++ tests/Unit/Facades/Stubs/Foo.php | 11 ++++ tests/Unit/Facades/Stubs/FooFacade.php | 13 +++++ tests/Unit/Facades/Stubs/FooInterface.php | 8 +++ 13 files changed, 154 insertions(+), 20 deletions(-) create mode 100644 src/FacadeManager.php create mode 100644 src/Facades/Facade.php create mode 100644 tests/Unit/Facades/FacadeTest.php create mode 100644 tests/Unit/Facades/Stubs/Foo.php create mode 100644 tests/Unit/Facades/Stubs/FooFacade.php create mode 100644 tests/Unit/Facades/Stubs/FooInterface.php diff --git a/composer.json b/composer.json index 6f118cb..5604969 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,6 @@ "psr/container": "^2", "psr/http-message": "^2", "psr/http-server-middleware": "^1.0.2", - "blast/facades": "^1.0", "timber/timber": "^2.3.0", "monolog/monolog": "^3.9", "symfony/debug": "^4.4.44", diff --git a/src/Bootstrappers/RegisterFacades.php b/src/Bootstrappers/RegisterFacades.php index d5b34a2..11e8b60 100644 --- a/src/Bootstrappers/RegisterFacades.php +++ b/src/Bootstrappers/RegisterFacades.php @@ -2,13 +2,13 @@ namespace Rareloop\Lumberjack\Bootstrappers; -use Blast\Facades\FacadeFactory; use Rareloop\Lumberjack\Application; +use Rareloop\Lumberjack\FacadeManager; class RegisterFacades { public function bootstrap(Application $app) { - FacadeFactory::setContainer($app); + FacadeManager::setContainer($app); } } diff --git a/src/FacadeManager.php b/src/FacadeManager.php new file mode 100644 index 0000000..97730a0 --- /dev/null +++ b/src/FacadeManager.php @@ -0,0 +1,25 @@ +get($accessor), $name], $arguments); + } +} diff --git a/src/Facades/Config.php b/src/Facades/Config.php index 41b7be7..9c4f604 100644 --- a/src/Facades/Config.php +++ b/src/Facades/Config.php @@ -2,11 +2,8 @@ namespace Rareloop\Lumberjack\Facades; -use Blast\Facades\AbstractFacade; - -class Config extends AbstractFacade +class Config extends Facade { - #[\Override] protected static function accessor() { return 'config'; diff --git a/src/Facades/Facade.php b/src/Facades/Facade.php new file mode 100644 index 0000000..c585d93 --- /dev/null +++ b/src/Facades/Facade.php @@ -0,0 +1,21 @@ +get(static::accessor()); + } + + abstract public static function accessor(): string; +} diff --git a/src/Facades/Log.php b/src/Facades/Log.php index fe0a8c3..164227c 100644 --- a/src/Facades/Log.php +++ b/src/Facades/Log.php @@ -2,11 +2,8 @@ namespace Rareloop\Lumberjack\Facades; -use Blast\Facades\AbstractFacade; - -class Log extends AbstractFacade +class Log extends Facade { - #[\Override] protected static function accessor() { return 'logger'; diff --git a/src/Facades/MiddlewareAliases.php b/src/Facades/MiddlewareAliases.php index 340128b..3b4f703 100644 --- a/src/Facades/MiddlewareAliases.php +++ b/src/Facades/MiddlewareAliases.php @@ -2,11 +2,9 @@ namespace Rareloop\Lumberjack\Facades; -use Blast\Facades\AbstractFacade; -class MiddlewareAliases extends AbstractFacade +class MiddlewareAliases extends Facade { - #[\Override] protected static function accessor() { return 'middleware-alias-store'; diff --git a/src/Facades/Router.php b/src/Facades/Router.php index 5db20d4..0b9e12c 100644 --- a/src/Facades/Router.php +++ b/src/Facades/Router.php @@ -2,11 +2,8 @@ namespace Rareloop\Lumberjack\Facades; -use Blast\Facades\AbstractFacade; - -class Router extends AbstractFacade +class Router extends Facade { - #[\Override] protected static function accessor() { return 'router'; diff --git a/src/Facades/Session.php b/src/Facades/Session.php index 036aad0..b4b0526 100644 --- a/src/Facades/Session.php +++ b/src/Facades/Session.php @@ -4,9 +4,8 @@ use Blast\Facades\AbstractFacade; -class Session extends AbstractFacade +class Session extends Facade { - #[\Override] protected static function accessor() { return 'session'; diff --git a/tests/Unit/Facades/FacadeTest.php b/tests/Unit/Facades/FacadeTest.php new file mode 100644 index 0000000..3c3075c --- /dev/null +++ b/tests/Unit/Facades/FacadeTest.php @@ -0,0 +1,69 @@ +container = new Container(); + $this->container->set(FooFacade::accessor(), new Foo()); + } + + /** @test */ + public function can_initiate_facades() + { + FacadeManager::setContainer($this->container); + $this->assertInstanceOf(ContainerInterface::class, FacadeManager::getContainer()); + } + + /** @test */ + public function can_get_facade_instance() + { + FacadeManager::setContainer($this->container); + + $instance = FooFacade::__instance(); + + $this->assertInstanceOf(FooInterface::class, $instance); + $this->assertInstanceOf(Foo::class, $instance); + } + + /** @test */ + public function can_swap_instances() + { + FacadeManager::setContainer($this->container); + + $instance = FooFacade::__instance(); + + $this->assertInstanceOf(FooInterface::class, $instance); + $this->assertInstanceOf(Foo::class, $instance); + + $this->container->set(FooFacade::accessor(), 'bar'); + + $instance = FooFacade::__instance(); + + $this->assertEquals('bar', $instance); + } + + public function can_call_functions() + { + FacadeManager::setContainer($this->container); + + $this->assertEquals('bar', forward_static_call([FooFacade::class, 'foo'])); + $this->assertEquals('bar', call_user_func('FooFacade::class::foo')); + $this->assertEquals('bar', FooFacade::foo()); + } +} diff --git a/tests/Unit/Facades/Stubs/Foo.php b/tests/Unit/Facades/Stubs/Foo.php new file mode 100644 index 0000000..d5ba726 --- /dev/null +++ b/tests/Unit/Facades/Stubs/Foo.php @@ -0,0 +1,11 @@ + Date: Mon, 8 Sep 2025 14:21:30 +0100 Subject: [PATCH 06/19] Fix facade tests --- src/FacadeManager.php | 2 +- src/Facades/Facade.php | 2 +- src/Facades/Session.php | 2 - .../Bootstrappers/RegisterFacadesTest.php | 5 +-- tests/Unit/Exceptions/HandlerTest.php | 10 ++--- tests/Unit/Facades/ConfigTest.php | 4 +- tests/Unit/Facades/LogTest.php | 4 +- tests/Unit/Facades/MiddlewareAliasesTest.php | 4 +- tests/Unit/Facades/RouterTest.php | 4 +- tests/Unit/Facades/SessionTest.php | 4 +- tests/Unit/HelpersTest.php | 42 +++++++++---------- 11 files changed, 38 insertions(+), 45 deletions(-) diff --git a/src/FacadeManager.php b/src/FacadeManager.php index 97730a0..5892e7c 100644 --- a/src/FacadeManager.php +++ b/src/FacadeManager.php @@ -20,6 +20,6 @@ public static function setContainer(ContainerInterface $container) public static function create(string $accessor, $name, array $arguments = []) { - return call_user_func([static::$container->get($accessor), $name], $arguments); + return call_user_func([static::$container->get($accessor), $name], ...$arguments); } } diff --git a/src/Facades/Facade.php b/src/Facades/Facade.php index c585d93..913d8f6 100644 --- a/src/Facades/Facade.php +++ b/src/Facades/Facade.php @@ -17,5 +17,5 @@ public static function __instance() return FacadeManager::getContainer()->get(static::accessor()); } - abstract public static function accessor(): string; + abstract protected static function accessor(); } diff --git a/src/Facades/Session.php b/src/Facades/Session.php index b4b0526..4dfbfc1 100644 --- a/src/Facades/Session.php +++ b/src/Facades/Session.php @@ -2,8 +2,6 @@ namespace Rareloop\Lumberjack\Facades; -use Blast\Facades\AbstractFacade; - class Session extends Facade { protected static function accessor() diff --git a/tests/Unit/Bootstrappers/RegisterFacadesTest.php b/tests/Unit/Bootstrappers/RegisterFacadesTest.php index 71653c9..871442f 100644 --- a/tests/Unit/Bootstrappers/RegisterFacadesTest.php +++ b/tests/Unit/Bootstrappers/RegisterFacadesTest.php @@ -2,11 +2,10 @@ namespace Rareloop\Lumberjack\Test\Bootstrappers; -use Blast\Facades\FacadeFactory; -use Mockery; use PHPUnit\Framework\TestCase; use Rareloop\Lumberjack\Application; use Rareloop\Lumberjack\Bootstrappers\RegisterFacades; +use Rareloop\Lumberjack\FacadeManager; class RegisterFacadesTest extends TestCase { @@ -18,6 +17,6 @@ public function boots_all_registered_providers() $registerFacadesBootstrapper = new RegisterFacades; $registerFacadesBootstrapper->bootstrap($app); - $this->assertSame($app, FacadeFactory::getContainer()); + $this->assertSame($app, FacadeManager::getContainer()); } } diff --git a/tests/Unit/Exceptions/HandlerTest.php b/tests/Unit/Exceptions/HandlerTest.php index 21889d7..113f5e0 100644 --- a/tests/Unit/Exceptions/HandlerTest.php +++ b/tests/Unit/Exceptions/HandlerTest.php @@ -2,7 +2,6 @@ namespace Rareloop\Lumberjack\Test\Exceptions; -use Blast\Facades\FacadeFactory; use Mockery; use Monolog\Logger; use PHPUnit\Framework\TestCase; @@ -11,6 +10,7 @@ use Rareloop\Lumberjack\Exceptions\Handler; use Laminas\Diactoros\Response\HtmlResponse; use Laminas\Diactoros\ServerRequest; +use Rareloop\Lumberjack\FacadeManager; class HandlerTest extends TestCase { @@ -52,7 +52,7 @@ public function blacklisted_exception_types_will_not_be_logged() public function render_should_return_an_html_response_when_debug_is_enabled() { $app = new Application; - FacadeFactory::setContainer($app); + FacadeManager::setContainer($app); $config = new Config; $config->set('app.debug', true); $app->bind('config', $config); @@ -69,7 +69,7 @@ public function render_should_return_an_html_response_when_debug_is_enabled() public function render_should_return_an_html_response_when_debug_is_disabled() { $app = new Application; - FacadeFactory::setContainer($app); + FacadeManager::setContainer($app); $config = new Config; $config->set('app.debug', false); $app->bind('config', $config); @@ -86,7 +86,7 @@ public function render_should_return_an_html_response_when_debug_is_disabled() public function render_should_include_stack_trace_when_debug_is_enabled() { $app = new Application; - FacadeFactory::setContainer($app); + FacadeManager::setContainer($app); $config = new Config; $config->set('app.debug', true); $app->bind('config', $config); @@ -103,7 +103,7 @@ public function render_should_include_stack_trace_when_debug_is_enabled() public function render_should_not_include_stack_trace_when_debug_is_disabled() { $app = new Application; - FacadeFactory::setContainer($app); + FacadeManager::setContainer($app); $config = new Config; $config->set('app.debug', false); $app->bind('config', $config); diff --git a/tests/Unit/Facades/ConfigTest.php b/tests/Unit/Facades/ConfigTest.php index fef46bd..bbcab55 100644 --- a/tests/Unit/Facades/ConfigTest.php +++ b/tests/Unit/Facades/ConfigTest.php @@ -2,10 +2,10 @@ namespace Rareloop\Lumberjack\Test\Facades; -use Blast\Facades\FacadeFactory; use PHPUnit\Framework\TestCase; use Rareloop\Lumberjack\Application; use Rareloop\Lumberjack\Config; +use Rareloop\Lumberjack\FacadeManager; use Rareloop\Lumberjack\Facades\Config as ConfigFacade; class ConfigTest extends TestCase @@ -14,7 +14,7 @@ class ConfigTest extends TestCase public function test_facade() { $app = new Application(); - FacadeFactory::setContainer($app); + FacadeManager::setContainer($app); $config = new Config(); $config->set('app.environment', 'production'); diff --git a/tests/Unit/Facades/LogTest.php b/tests/Unit/Facades/LogTest.php index 4ae6019..4c42400 100644 --- a/tests/Unit/Facades/LogTest.php +++ b/tests/Unit/Facades/LogTest.php @@ -2,10 +2,10 @@ namespace Rareloop\Lumberjack\Test\Facades; -use Blast\Facades\FacadeFactory; use Monolog\Logger; use PHPUnit\Framework\TestCase; use Rareloop\Lumberjack\Application; +use Rareloop\Lumberjack\FacadeManager; use Rareloop\Lumberjack\Facades\Log as LogFacade; class LogTest extends TestCase @@ -14,7 +14,7 @@ class LogTest extends TestCase public function test_facade() { $app = new Application(); - FacadeFactory::setContainer($app); + FacadeManager::setContainer($app); $logger = new Logger('app'); $app->bind('logger', $logger); diff --git a/tests/Unit/Facades/MiddlewareAliasesTest.php b/tests/Unit/Facades/MiddlewareAliasesTest.php index 5cf4da6..04fdf64 100644 --- a/tests/Unit/Facades/MiddlewareAliasesTest.php +++ b/tests/Unit/Facades/MiddlewareAliasesTest.php @@ -2,9 +2,9 @@ namespace Rareloop\Lumberjack\Test\Facades; -use Blast\Facades\FacadeFactory; use PHPUnit\Framework\TestCase; use Rareloop\Lumberjack\Application; +use Rareloop\Lumberjack\FacadeManager; use Rareloop\Lumberjack\Facades\MiddlewareAliases; use Rareloop\Lumberjack\Http\MiddlewareAliasStore; @@ -14,7 +14,7 @@ class MiddlewareAliasesTest extends TestCase public function test_facade() { $app = new Application(); - FacadeFactory::setContainer($app); + FacadeManager::setContainer($app); $store = new MiddlewareAliasStore(); $app->bind('middleware-alias-store', $store); diff --git a/tests/Unit/Facades/RouterTest.php b/tests/Unit/Facades/RouterTest.php index 71ee82a..ec92e5c 100644 --- a/tests/Unit/Facades/RouterTest.php +++ b/tests/Unit/Facades/RouterTest.php @@ -2,9 +2,9 @@ namespace Rareloop\Lumberjack\Test\Facades; -use Blast\Facades\FacadeFactory; use PHPUnit\Framework\TestCase; use Rareloop\Lumberjack\Application; +use Rareloop\Lumberjack\FacadeManager; use Rareloop\Lumberjack\Facades\Router as RouterFacade; use Rareloop\Lumberjack\Http\Router; @@ -14,7 +14,7 @@ class RouterTest extends TestCase public function test_facade() { $app = new Application(); - FacadeFactory::setContainer($app); + FacadeManager::setContainer($app); $router = new Router(); $app->bind('router', $router); diff --git a/tests/Unit/Facades/SessionTest.php b/tests/Unit/Facades/SessionTest.php index af7103e..1b59eb1 100644 --- a/tests/Unit/Facades/SessionTest.php +++ b/tests/Unit/Facades/SessionTest.php @@ -2,9 +2,9 @@ namespace Rareloop\Lumberjack\Test\Facades; -use Blast\Facades\FacadeFactory; use PHPUnit\Framework\TestCase; use Rareloop\Lumberjack\Application; +use Rareloop\Lumberjack\FacadeManager; use Rareloop\Lumberjack\Facades\Session; use Rareloop\Lumberjack\Session\SessionManager; use Rareloop\Lumberjack\Test\Unit\Session\NullSessionHandler; @@ -15,7 +15,7 @@ class SessionTest extends TestCase public function test_facade() { $app = new Application(); - FacadeFactory::setContainer($app); + FacadeManager::setContainer($app); $store = new SessionManager($app); $app->bind('session', $store); diff --git a/tests/Unit/HelpersTest.php b/tests/Unit/HelpersTest.php index a4d1c7c..129c43d 100644 --- a/tests/Unit/HelpersTest.php +++ b/tests/Unit/HelpersTest.php @@ -6,7 +6,6 @@ use Rareloop\Router\Router; use PHPUnit\Framework\TestCase; use Rareloop\Lumberjack\Config; -use Blast\Facades\FacadeFactory; use Rareloop\Lumberjack\Helpers; use Rareloop\Lumberjack\Application; use Rareloop\Lumberjack\Facades\Session; @@ -18,6 +17,7 @@ use Rareloop\Lumberjack\Http\Responses\TimberResponse; use Rareloop\Lumberjack\Http\Responses\RedirectResponse; use Monolog\Logger; +use Rareloop\Lumberjack\FacadeManager; /** * @runTestsInSeparateProcesses @@ -48,7 +48,7 @@ public function can_resolve_something_from_the_container() public function can_retrieve_a_config_value() { $app = new Application; - FacadeFactory::setContainer($app); + FacadeManager::setContainer($app); $config = new Config(); $config->set('app.environment', 'production'); @@ -61,7 +61,7 @@ public function can_retrieve_a_config_value() public function can_retrieve_a_default_when_no_config_value_is_set() { $app = new Application; - FacadeFactory::setContainer($app); + FacadeManager::setContainer($app); $config = new Config(); $app->bind('config', $config); @@ -73,7 +73,7 @@ public function can_retrieve_a_default_when_no_config_value_is_set() public function can_set_a_config_value_when_array_passed_to_config_helper() { $app = new Application; - FacadeFactory::setContainer($app); + FacadeManager::setContainer($app); $config = new Config(); $app->bind('config', $config); @@ -139,10 +139,9 @@ public function can_get_a_timber_response_with_specific_headers() public function can_get_a_url_for_a_named_route() { $app = new Application; - FacadeFactory::setContainer($app); + FacadeManager::setContainer($app); $router = new Router; - $router->get('test/route', function () { - })->name('test.route'); + $router->get('test/route', function () {})->name('test.route'); $app->bind('router', $router); $url = Helpers::route('test.route'); @@ -154,10 +153,9 @@ public function can_get_a_url_for_a_named_route() public function can_get_a_url_for_a_named_route_with_params() { $app = new Application; - FacadeFactory::setContainer($app); + FacadeManager::setContainer($app); $router = new Router; - $router->get('test/{name}', function ($name) { - })->name('test.route'); + $router->get('test/{name}', function ($name) {})->name('test.route'); $app->bind('router', $router); $url = Helpers::route('test.route', [ @@ -216,7 +214,7 @@ public function can_report_an_exception() public function can_access_an_item_in_the_session_by_key() { $app = new Application; - FacadeFactory::setContainer($app); + FacadeManager::setContainer($app); $store = new SessionManager($app); $app->bind('session', $store); @@ -230,7 +228,7 @@ public function can_access_an_item_in_the_session_by_key() public function can_access_an_item_in_the_session_by_key_with_default() { $app = new Application; - FacadeFactory::setContainer($app); + FacadeManager::setContainer($app); $store = new SessionManager($app); $app->bind('session', $store); @@ -242,7 +240,7 @@ public function can_access_an_item_in_the_session_by_key_with_default() public function can_add_an_item_in_the_session() { $app = new Application; - FacadeFactory::setContainer($app); + FacadeManager::setContainer($app); $store = new SessionManager($app); $app->bind('session', $store); @@ -256,7 +254,7 @@ public function can_add_an_item_in_the_session() public function can_add_multiple_items_to_the_session() { $app = new Application; - FacadeFactory::setContainer($app); + FacadeManager::setContainer($app); $store = new SessionManager($app); $app->bind('session', $store); @@ -271,7 +269,7 @@ public function can_add_multiple_items_to_the_session() public function can_resolve_the_session_manager() { $app = new Application; - FacadeFactory::setContainer($app); + FacadeManager::setContainer($app); $store = new SessionManager($app); $app->bind('session', $store); @@ -283,7 +281,7 @@ public function can_resolve_the_session_manager() public function can_redirect_back() { $app = new Application; - FacadeFactory::setContainer($app); + FacadeManager::setContainer($app); $store = new SessionManager($app); $app->bind('session', $store); $store->setPreviousUrl('http://domain.com/previous/url'); @@ -298,7 +296,7 @@ public function can_redirect_back() public function can_get_server_request() { $app = new Application; - FacadeFactory::setContainer($app); + FacadeManager::setContainer($app); $request = new ServerRequest([], [], '/test/123', 'GET'); $app->bind('request', $request); @@ -310,7 +308,7 @@ public function can_get_server_request() public function can_get_logger() { $app = new Application; - FacadeFactory::setContainer($app); + FacadeManager::setContainer($app); $logger = new Logger('app'); $app->bind('logger', $logger); @@ -325,7 +323,7 @@ public function can_get_logger() public function can_write_debug_log() { $app = new Application; - FacadeFactory::setContainer($app); + FacadeManager::setContainer($app); $logger = \Mockery::mock(Logger::class)->makePartial(); $logger->shouldReceive('debug')->with('Example message', [])->once(); @@ -339,7 +337,7 @@ public function can_write_debug_log() public function can_write_debug_log_with_context() { $app = new Application; - FacadeFactory::setContainer($app); + FacadeManager::setContainer($app); $logger = \Mockery::mock(Logger::class)->makePartial(); $logger->shouldReceive('debug')->with('Example message', [ @@ -373,7 +371,5 @@ class TestExceptionHandler extends Handler class RequiresConstructorParams { - public function __construct(public $param1, public $param2) - { - } + public function __construct(public $param1, public $param2) {} } From 98b9d289d7fab5037fe665830e25a89f503044a7 Mon Sep 17 00:00:00 2001 From: Tom Mitchelmore Date: Wed, 1 Oct 2025 14:19:43 +0100 Subject: [PATCH 07/19] Replace `Logger::[level]` calls with `Level::[level]` --- src/Providers/LogServiceProvider.php | 5 +++-- tests/Unit/Providers/LogServiceProviderTest.php | 17 +++++++++-------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/Providers/LogServiceProvider.php b/src/Providers/LogServiceProvider.php index b04a0b3..a6cf812 100644 --- a/src/Providers/LogServiceProvider.php +++ b/src/Providers/LogServiceProvider.php @@ -7,6 +7,7 @@ use Monolog\Handler\StreamHandler; use Monolog\Formatter\LineFormatter; use Monolog\Handler\ErrorLogHandler; +use Monolog\Level; class LogServiceProvider extends ServiceProvider { @@ -44,9 +45,9 @@ private function shouldUseErrorLogHandler() return $config && $config->get('app.logs.path') === false && $config->get('app.logs.enabled') === true; } - private function getLogLevel() + private function getLogLevel(): Level { - $logLevel = Logger::DEBUG; + $logLevel = Level::Debug; if ($this->app->has('config')) { $logLevel = $this->app->get('config')->get('app.logs.level', $logLevel); diff --git a/tests/Unit/Providers/LogServiceProviderTest.php b/tests/Unit/Providers/LogServiceProviderTest.php index 1b16036..27b60f2 100644 --- a/tests/Unit/Providers/LogServiceProviderTest.php +++ b/tests/Unit/Providers/LogServiceProviderTest.php @@ -4,6 +4,7 @@ use Brain\Monkey\Functions; use Monolog\Handler\ErrorLogHandler; +use Monolog\Level; use Monolog\Logger; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; @@ -22,7 +23,7 @@ public function log_object_is_always_registered() { Functions\expect('is_admin')->once()->andReturn(false); - $app = new Application(__DIR__.'/../'); + $app = new Application(__DIR__ . '/../'); $lumberjack = new Lumberjack($app); $lumberjack->bootstrap(); @@ -37,7 +38,7 @@ public function log_object_is_always_registered() * @codingStandardsIgnoreLine */ function default_handler_is_in_memory_stream() { - $app = new Application(__DIR__.'/../'); + $app = new Application(__DIR__ . '/../'); $config = new Config; $app->bind('config', $config); @@ -52,7 +53,7 @@ function default_handler_is_in_memory_stream() /** @test */ public function default_log_warning_level_is_debug() { - $app = new Application(__DIR__.'/../'); + $app = new Application(__DIR__ . '/../'); $config = new Config; $app->bind('config', $config); @@ -61,13 +62,13 @@ public function default_log_warning_level_is_debug() RegisterProviders::class, ]); - $this->assertSame(Logger::DEBUG, $app->get('logger')->getHandlers()[0]->getLevel()); + $this->assertSame(Level::Debug, $app->get('logger')->getHandlers()[0]->getLevel()); } /** @test */ public function stream_is_used_when_path_is_set_but_logging_is_disabled() { - $app = new Application(__DIR__.'/../'); + $app = new Application(__DIR__ . '/../'); $config = new Config; $config->set('app.logs.enabled', false); @@ -84,17 +85,17 @@ public function stream_is_used_when_path_is_set_but_logging_is_disabled() /** @test */ public function log_warning_level_can_be_set_in_config() { - $app = new Application(__DIR__.'/../'); + $app = new Application(__DIR__ . '/../'); $config = new Config; - $config->set('app.logs.level', Logger::ERROR); + $config->set('app.logs.level', Level::Error); $app->bind('config', $config); $app->bootstrapWith([ RegisterProviders::class, ]); - $this->assertSame(Logger::ERROR, $app->get('logger')->getHandlers()[0]->getLevel()); + $this->assertSame(Level::Error, $app->get('logger')->getHandlers()[0]->getLevel()); } /** @test */ From 4d43027a6594e156363ebbb3a271df0938f834fb Mon Sep 17 00:00:00 2001 From: Tom Mitchelmore Date: Wed, 1 Oct 2025 14:22:50 +0100 Subject: [PATCH 08/19] Update mindplay/middleman ->dispatch to ->handle --- src/Providers/WordPressControllersServiceProvider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Providers/WordPressControllersServiceProvider.php b/src/Providers/WordPressControllersServiceProvider.php index 07766b1..3b3dd2e 100644 --- a/src/Providers/WordPressControllersServiceProvider.php +++ b/src/Providers/WordPressControllersServiceProvider.php @@ -90,7 +90,7 @@ function ($request) use ($controller, $methodName) { ]; $dispatcher = $this->createDispatcher($middlewares); - return $dispatcher->dispatch($request); + return $dispatcher->handle($request); } private function createDispatcher(array $middlewares): Dispatcher From 106232fd95e545cf8e3db954bcf9a6390288c5d3 Mon Sep 17 00:00:00 2001 From: Tom Mitchelmore Date: Wed, 1 Oct 2025 14:25:28 +0100 Subject: [PATCH 09/19] Remove support for callable route destinations (removed in Rareloop router upgrade) --- tests/Unit/Http/RouterTest.php | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/tests/Unit/Http/RouterTest.php b/tests/Unit/Http/RouterTest.php index 1422145..dd00b06 100644 --- a/tests/Unit/Http/RouterTest.php +++ b/tests/Unit/Http/RouterTest.php @@ -36,17 +36,6 @@ public function controller_does_not_have_namespace_added_when_it_already_exists( $this->assertSame(RouterTestController::class . '@test', $route->getActionName()); } - /** @test */ - public function controller_does_not_have_namespace_added_when_it_is_callable() - { - $router = new Router; - $controller = new RouterTestController; - - $route = $router->get('/test/123', $controller->test(...)); - - $this->assertSame(RouterTestController::class . '@test', $route->getActionName()); - } - /** @test */ public function controller_does_not_have_namespace_added_when_it_is_closure() { From 37224e14303dafcc3d75916c33fdc3641bbdf950 Mon Sep 17 00:00:00 2001 From: Tom Mitchelmore Date: Wed, 1 Oct 2025 14:34:31 +0100 Subject: [PATCH 10/19] Resolve `trigger_error` deprecations --- src/Post.php | 3 ++- src/ScopedQueryBuilder.php | 6 ++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Post.php b/src/Post.php index 62fc2d3..2dada06 100644 --- a/src/Post.php +++ b/src/Post.php @@ -2,6 +2,7 @@ namespace Rareloop\Lumberjack; +use Error; use Rareloop\Lumberjack\Exceptions\PostTypeRegistrationException; use Rareloop\Lumberjack\ScopedQueryBuilder; use Spatie\Macroable\Macroable; @@ -47,7 +48,7 @@ public static function __callStatic($name, $arguments) return call_user_func_array([$builder, $name], $arguments); } - trigger_error('Call to undefined method ' . self::class . '::' . $name . '()', E_USER_ERROR); + throw new Error('Call to undefined method ' . self::class . '::' . $name . '()'); } /** diff --git a/src/ScopedQueryBuilder.php b/src/ScopedQueryBuilder.php index 70ba909..b28a777 100644 --- a/src/ScopedQueryBuilder.php +++ b/src/ScopedQueryBuilder.php @@ -2,6 +2,7 @@ namespace Rareloop\Lumberjack; +use Error; use Rareloop\Lumberjack\Contracts\QueryBuilder as QueryBuilderContract; use Rareloop\Lumberjack\Exceptions\CannotRedeclarePostClassOnQueryException; use Rareloop\Lumberjack\Exceptions\CannotRedeclarePostTypeOnQueryException; @@ -40,10 +41,7 @@ public function __call($name, $arguments) $publicMethods = collect($reflection->getMethods(ReflectionMethod::IS_PUBLIC))->map(fn($method) => $method->getName())->toArray(); if (!in_array($scopeFunctionName, $publicMethods)) { - trigger_error( - 'Call to undefined method ' . $this->postClass . '::' . $scopeFunctionName . '()', - E_USER_ERROR - ); + throw new Error('Call to undefined method ' . $this->postClass . '::' . $scopeFunctionName . '()'); } array_unshift($arguments, $this); From dbc3874f657eef8afbd0d7f6b3b08656b01f1e19 Mon Sep 17 00:00:00 2001 From: Tom Mitchelmore Date: Wed, 1 Oct 2025 14:38:43 +0100 Subject: [PATCH 11/19] Bump mmeyer2k/dcrypt --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 5604969..f8a4429 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ "statamic/stringy": "^3.1.3", "laminas/laminas-diactoros": "^3.6.0", "rareloop/psr7-server-request-extension": "dev-master as 3.0", - "mmeyer2k/dcrypt": "^8.3.1", + "mmeyer2k/dcrypt": "^9", "spatie/macroable": "^1.0.1", "mindplay/middleman": "^4.0.4", "psr/log": "^2.0.0", From cc2aa78062d2d85ea554168a1136428ac9629d0c Mon Sep 17 00:00:00 2001 From: Tom Mitchelmore Date: Wed, 1 Oct 2025 14:56:06 +0100 Subject: [PATCH 12/19] Bump bugfix release of mikey179/vfsstream - fixes test failure --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index f8a4429..c2ec483 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,7 @@ "brain/monkey": "^2.6.1", "squizlabs/php_codesniffer": "^3.7.2", "php-mock/php-mock": "^2.6.2", - "mikey179/vfsstream": "1.6.11", + "mikey179/vfsstream": "^1.6.12", "dms/phpunit-arraysubset-asserts": "^0.3.1", "rector/rector": "^2.1" }, From 5f0c4c6d6b6f389f162c810dea36d8c8fd39760b Mon Sep 17 00:00:00 2001 From: Tom Mitchelmore Date: Wed, 1 Oct 2025 16:56:26 +0100 Subject: [PATCH 13/19] Rework encryption --- composer.json | 4 +- src/Contracts/Encrypter.php | 10 --- src/Encrypter.php | 23 ------ src/Providers/EncryptionServiceProvider.php | 7 +- src/Session/EncryptedStore.php | 2 +- src/Session/SessionManager.php | 4 +- src/Session/Store.php | 4 +- tests/Unit/EncrypterTest.php | 81 ------------------- .../EncryptionServiceProviderTest.php | 6 +- tests/Unit/Session/EncryptedStoreTest.php | 18 ++--- tests/Unit/Session/SessionManagerTest.php | 14 ++-- tests/Unit/Session/StoreTest.php | 6 +- 12 files changed, 28 insertions(+), 151 deletions(-) delete mode 100644 src/Contracts/Encrypter.php delete mode 100644 src/Encrypter.php delete mode 100644 tests/Unit/EncrypterTest.php diff --git a/composer.json b/composer.json index c2ec483..8a2f668 100644 --- a/composer.json +++ b/composer.json @@ -16,11 +16,11 @@ "statamic/stringy": "^3.1.3", "laminas/laminas-diactoros": "^3.6.0", "rareloop/psr7-server-request-extension": "dev-master as 3.0", - "mmeyer2k/dcrypt": "^9", "spatie/macroable": "^1.0.1", "mindplay/middleman": "^4.0.4", "psr/log": "^2.0.0", - "symfony/var-dumper": "^5.0||^6.3.6" + "symfony/var-dumper": "^5.0||^6.3.6", + "illuminate/encryption": "^12.32" }, "require-dev": { "phpunit/phpunit": "^9.6.13", diff --git a/src/Contracts/Encrypter.php b/src/Contracts/Encrypter.php deleted file mode 100644 index b6a00c1..0000000 --- a/src/Contracts/Encrypter.php +++ /dev/null @@ -1,10 +0,0 @@ -key); - } - - public function decrypt($data) - { - return @unserialize(AesCbc::decrypt($data, $this->key)); - } -} diff --git a/src/Providers/EncryptionServiceProvider.php b/src/Providers/EncryptionServiceProvider.php index ec762cc..1f462e1 100644 --- a/src/Providers/EncryptionServiceProvider.php +++ b/src/Providers/EncryptionServiceProvider.php @@ -2,11 +2,8 @@ namespace Rareloop\Lumberjack\Providers; -use Rareloop\Lumberjack\Application; -use Rareloop\Lumberjack\Contracts\Encrypter as EncrypterContract; -use Rareloop\Lumberjack\Encrypter; -use Rareloop\Lumberjack\Facades\Config; -use Rareloop\Lumberjack\Session\SessionManager; +use Illuminate\Contracts\Encryption\Encrypter as EncrypterContract; +use Illuminate\Encryption\Encrypter; class EncryptionServiceProvider extends ServiceProvider { diff --git a/src/Session/EncryptedStore.php b/src/Session/EncryptedStore.php index 3992cf4..6fccda0 100644 --- a/src/Session/EncryptedStore.php +++ b/src/Session/EncryptedStore.php @@ -3,8 +3,8 @@ namespace Rareloop\Lumberjack\Session; use Exception; +use Illuminate\Contracts\Encryption\Encrypter; use SessionHandlerInterface; -use Rareloop\Lumberjack\Encrypter; use Rareloop\Lumberjack\Exceptions\HandlerInterface; class EncryptedStore extends Store diff --git a/src/Session/SessionManager.php b/src/Session/SessionManager.php index 0926a03..31bad1a 100644 --- a/src/Session/SessionManager.php +++ b/src/Session/SessionManager.php @@ -2,9 +2,9 @@ namespace Rareloop\Lumberjack\Session; +use Illuminate\Contracts\Encryption\Encrypter; use Rareloop\Lumberjack\Application; use Rareloop\Lumberjack\Config; -use Rareloop\Lumberjack\Contracts\Encrypter as EncrypterContract; use Rareloop\Lumberjack\Manager; class SessionManager extends Manager @@ -53,7 +53,7 @@ protected function buildSession($handler) $sessionId = ($_COOKIE[$this->name] ?? null); if ($this->config->get('session.encrypt')) { - $encrypter = $this->app->get(EncrypterContract::class); + $encrypter = $this->app->get(Encrypter::class); return new EncryptedStore($this->name, $handler, $encrypter, $sessionId); } diff --git a/src/Session/Store.php b/src/Session/Store.php index 62cbbbc..9e73bf9 100644 --- a/src/Session/Store.php +++ b/src/Session/Store.php @@ -36,7 +36,7 @@ protected function loadSession() protected function readFromHandler() { $data = $this->handler->read($this->id); - $data = @unserialize($this->prepareForUnserialize($data)); + $data = $this->prepareForUnserialize($data); if ($data !== false && !is_null($data) && is_array($data)) { return $data; @@ -49,7 +49,7 @@ public function save() { $this->ageFlashData(); - $this->handler->write($this->id, $this->prepareForStorage(@serialize($this->attributes))); + $this->handler->write($this->id, $this->prepareForStorage($this->attributes)); return $this; } diff --git a/tests/Unit/EncrypterTest.php b/tests/Unit/EncrypterTest.php deleted file mode 100644 index df52253..0000000 --- a/tests/Unit/EncrypterTest.php +++ /dev/null @@ -1,81 +0,0 @@ -shouldReceive('encrypt')->withArgs(function ($data, $key) { - if ($key !== 'secret-key') { - return false; - } - - if ($data !== @serialize('test-string')) { - return false; - } - - return true; - })->once(); - - $encrypter = new Encrypter($key); - $encrypter->encrypt('test-string'); - } - - /** @test */ - public function can_decrypt_data() - { - $key = 'secret-key'; - $dcrypt = Mockery::mock('alias:' . AesCbc::class); - $dcrypt->shouldReceive('decrypt')->with('test-string', $key)->once(); - - $encrypter = new Encrypter($key); - $encrypter->decrypt('test-string'); - } - - /** @test */ - public function can_process_strings() - { - $payload = 'test-string'; - $encrypter = new Encrypter('secret-key'); - - $this->assertSame($payload, $encrypter->decrypt($encrypter->encrypt($payload))); - } - - /** @test */ - public function can_process_arrays() - { - $payload = ['foo' => 'bar']; - $encrypter = new Encrypter('secret-key'); - - $this->assertSame($payload, $encrypter->decrypt($encrypter->encrypt($payload))); - } - - /** @test */ - public function can_process_objects() - { - $payload = new \stdClass; - $payload->foo = 'bar'; - $encrypter = new Encrypter('secret-key'); - - $output = $encrypter->decrypt($encrypter->encrypt($payload)); - - $this->assertInstanceOf(\stdClass::class, $output); - $this->assertSame('bar', $output->foo); - } -} diff --git a/tests/Unit/Providers/EncryptionServiceProviderTest.php b/tests/Unit/Providers/EncryptionServiceProviderTest.php index 89ccfdb..001b072 100644 --- a/tests/Unit/Providers/EncryptionServiceProviderTest.php +++ b/tests/Unit/Providers/EncryptionServiceProviderTest.php @@ -2,11 +2,11 @@ namespace Rareloop\Lumberjack\Test\Providers; +use Illuminate\Contracts\Encryption\Encrypter as EncrypterContract; +use Illuminate\Encryption\Encrypter; use PHPUnit\Framework\TestCase; use Rareloop\Lumberjack\Application; use Rareloop\Lumberjack\Config; -use Rareloop\Lumberjack\Contracts\Encrypter as EncrypterContract; -use Rareloop\Lumberjack\Encrypter; use Rareloop\Lumberjack\Providers\EncryptionServiceProvider; use Rareloop\Lumberjack\Test\Unit\BrainMonkeyPHPUnitIntegration; @@ -18,7 +18,7 @@ class EncryptionServiceProviderTest extends TestCase public function encryptor_is_registered_in_container_when_a_config_key_is_present() { $config = new Config; - $config->set('app.key', 'encryption-key'); + $config->set('app.key', Encrypter::generateKey('aes-128-cbc')); $app = new Application(); $app->bind('config', $config); diff --git a/tests/Unit/Session/EncryptedStoreTest.php b/tests/Unit/Session/EncryptedStoreTest.php index 8cd64c4..d9ccb65 100644 --- a/tests/Unit/Session/EncryptedStoreTest.php +++ b/tests/Unit/Session/EncryptedStoreTest.php @@ -3,12 +3,11 @@ namespace Rareloop\Lumberjack\Test; use Dcrypt\AesCbc; +use Illuminate\Encryption\Encrypter; use Mockery; use PHPUnit\Framework\TestCase; -use Rareloop\Lumberjack\Encrypter; use Rareloop\Lumberjack\Exceptions\HandlerInterface; use Rareloop\Lumberjack\Session\EncryptedStore; -use Rareloop\Lumberjack\Session\Store; use Rareloop\Lumberjack\Test\Unit\Session\NullSessionHandler; class EncryptedStoreTest extends TestCase @@ -19,10 +18,8 @@ class EncryptedStoreTest extends TestCase public function data_is_encrypted_before_it_is_saved() { $serializedString = @serialize(['foo' => 'bar']); - $encrypter = Mockery::mock(Encrypter::class . '[encrypt]', ['encryption-key']); - $encrypter->shouldReceive('encrypt')->withArgs(function ($string) { - $array = @unserialize($string); - + $encrypter = Mockery::mock(Encrypter::class); + $encrypter->shouldReceive('encrypt')->withArgs(function ($array) { return $array['foo'] === 'bar'; })->once(); @@ -36,17 +33,16 @@ public function data_is_encrypted_before_it_is_saved() /** @test */ public function data_is_decrypted_before_it_is_loaded() { - $encryptionKey = 'encryption-key'; - + $encrypter = new Encrypter(Encrypter::generateKey('aes-128-cbc')); // Create the string that would have been stored by an encrypted store // Serialize once for the Encrypter and once for the Encrypted store - $encryptedString = AesCbc::encrypt(@serialize(@serialize(['foo' => 'bar'])), $encryptionKey); + $encryptedString = $encrypter->encrypt(['foo' => 'bar']); // Use a mock handler to fake a previously stored state $handler = Mockery::mock(NullSessionHandler::class . '[read]'); $handler->shouldReceive('read')->andReturn($encryptedString); - $store = new EncryptedStore('session-name', $handler, new Encrypter($encryptionKey), 'session-id'); + $store = new EncryptedStore('session-name', $handler, $encrypter, 'session-id'); $store->start(); $this->assertSame('bar', $store->get('foo')); @@ -58,7 +54,7 @@ public function data_is_decrypted_before_it_is_loaded() */ public function unexpected_session_data_is_handled_gracefully($previousSessionValue) { - $encryptionKey = 'encryption-key'; + $encryptionKey = Encrypter::generateKey('aes-128-cbc'); // Use a mock handler to fake a previously stored state $handler = Mockery::mock(NullSessionHandler::class . '[read]'); diff --git a/tests/Unit/Session/SessionManagerTest.php b/tests/Unit/Session/SessionManagerTest.php index f11a012..c5ba3e0 100644 --- a/tests/Unit/Session/SessionManagerTest.php +++ b/tests/Unit/Session/SessionManagerTest.php @@ -3,17 +3,17 @@ namespace Rareloop\Lumberjack\Test; use Mockery; +use org\bovigo\vfs\vfsStream; use PHPUnit\Framework\TestCase; -use Rareloop\Lumberjack\Application; use Rareloop\Lumberjack\Config; -use Rareloop\Lumberjack\Contracts\Encrypter as EncrypterContract; -use Rareloop\Lumberjack\Encrypter; +use Illuminate\Encryption\Encrypter; +use Rareloop\Lumberjack\Application; +use Rareloop\Lumberjack\Session\Store; use Rareloop\Lumberjack\Session\EncryptedStore; -use Rareloop\Lumberjack\Session\FileSessionHandler; use Rareloop\Lumberjack\Session\SessionManager; -use Rareloop\Lumberjack\Session\Store; +use Rareloop\Lumberjack\Session\FileSessionHandler; use Rareloop\Lumberjack\Test\Unit\Session\NullSessionHandler; -use org\bovigo\vfs\vfsStream; +use Illuminate\Contracts\Encryption\Encrypter as EncrypterContract; class SessionManagerTest extends TestCase { @@ -92,7 +92,7 @@ public function can_create_an_unencrypted_store() public function can_create_an_encrypted_store() { $app = $app = $this->appWithSessionDriverConfig('file', 'lumberjack', $encrypted = true); - $app->bind(EncrypterContract::class, new Encrypter('encryption-key')); + $app->bind(EncrypterContract::class, new Encrypter(Encrypter::generateKey('aes-128-cbc'))); $manager = new SessionManager($app); diff --git a/tests/Unit/Session/StoreTest.php b/tests/Unit/Session/StoreTest.php index b167f8a..e399091 100644 --- a/tests/Unit/Session/StoreTest.php +++ b/tests/Unit/Session/StoreTest.php @@ -205,7 +205,7 @@ public function can_flush_all_values() public function starting_a_session_loads_data_from_handler() { $handler = Mockery::mock(NullSessionHandler::class . '[read]'); - $handler->shouldReceive('read')->once()->with('session-id')->andReturn(serialize(['foo' => 'bar'])); + $handler->shouldReceive('read')->once()->with('session-id')->andReturn(['foo' => 'bar']); $store = new Store('session-name', $handler, 'session-id'); @@ -219,9 +219,7 @@ public function saving_a_session_writes_data_to_handler() { $handler = Mockery::mock(NullSessionHandler::class . '[write]'); $handler->shouldReceive('write')->once()->with('session-id', Mockery::on(function ($argument) { - $array = @unserialize($argument); - - return isset($array['foo']) && $array['foo'] === 'bar'; + return isset($argument['foo']) && $argument['foo'] === 'bar'; })); $store = new Store('session-name', $handler, 'session-id'); From 9f304688749ed59c95cf1f513646734603597cf0 Mon Sep 17 00:00:00 2001 From: Tom Mitchelmore Date: Mon, 6 Oct 2025 14:30:47 +0100 Subject: [PATCH 14/19] Re-support php >= 8.1 --- .github/workflows/ci.yml | 2 +- composer.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2dd86fc..b4598b5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php_version: [8.4] + php_version: [8.1, 8.2, 8.3, 8.4] composer_flags: ["", "--prefer-lowest"] steps: diff --git a/composer.json b/composer.json index 8a2f668..80ec94b 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,7 @@ "description": "A powerful MVC framework for the modern WordPress developer. Write better, more expressive and easier to maintain code", "license": "MIT", "require": { - "php": ">=8.4", + "php": ">=8.1", "php-di/php-di": "^7", "rareloop/router": "dev-feature/upgrade-dependencies as 6.0.2", "psr/container": "^2", From 300e934dd5625925952ab8a455c96d4bac95befd Mon Sep 17 00:00:00 2001 From: Tom Mitchelmore Date: Mon, 6 Oct 2025 14:35:48 +0100 Subject: [PATCH 15/19] Refactor Facade -> AbstractFacade --- src/Facades/{Facade.php => AbstractFacade.php} | 3 +-- src/Facades/Config.php | 2 +- src/Facades/Log.php | 2 +- src/Facades/MiddlewareAliases.php | 2 +- src/Facades/Router.php | 2 +- src/Facades/Session.php | 2 +- tests/Unit/Facades/Stubs/FooFacade.php | 4 ++-- 7 files changed, 8 insertions(+), 9 deletions(-) rename src/Facades/{Facade.php => AbstractFacade.php} (92%) diff --git a/src/Facades/Facade.php b/src/Facades/AbstractFacade.php similarity index 92% rename from src/Facades/Facade.php rename to src/Facades/AbstractFacade.php index 913d8f6..22697fa 100644 --- a/src/Facades/Facade.php +++ b/src/Facades/AbstractFacade.php @@ -2,10 +2,9 @@ namespace Rareloop\Lumberjack\Facades; -use Mockery; use Rareloop\Lumberjack\FacadeManager; -abstract class Facade +abstract class AbstractFacade { public static function __callStatic($name, array $arguments = []) { diff --git a/src/Facades/Config.php b/src/Facades/Config.php index 9c4f604..bfd4a26 100644 --- a/src/Facades/Config.php +++ b/src/Facades/Config.php @@ -2,7 +2,7 @@ namespace Rareloop\Lumberjack\Facades; -class Config extends Facade +class Config extends AbstractFacade { protected static function accessor() { diff --git a/src/Facades/Log.php b/src/Facades/Log.php index 164227c..d7bbf8b 100644 --- a/src/Facades/Log.php +++ b/src/Facades/Log.php @@ -2,7 +2,7 @@ namespace Rareloop\Lumberjack\Facades; -class Log extends Facade +class Log extends AbstractFacade { protected static function accessor() { diff --git a/src/Facades/MiddlewareAliases.php b/src/Facades/MiddlewareAliases.php index 3b4f703..dece0e4 100644 --- a/src/Facades/MiddlewareAliases.php +++ b/src/Facades/MiddlewareAliases.php @@ -3,7 +3,7 @@ namespace Rareloop\Lumberjack\Facades; -class MiddlewareAliases extends Facade +class MiddlewareAliases extends AbstractFacade { protected static function accessor() { diff --git a/src/Facades/Router.php b/src/Facades/Router.php index 0b9e12c..85fa666 100644 --- a/src/Facades/Router.php +++ b/src/Facades/Router.php @@ -2,7 +2,7 @@ namespace Rareloop\Lumberjack\Facades; -class Router extends Facade +class Router extends AbstractFacade { protected static function accessor() { diff --git a/src/Facades/Session.php b/src/Facades/Session.php index 4dfbfc1..2b28d9f 100644 --- a/src/Facades/Session.php +++ b/src/Facades/Session.php @@ -2,7 +2,7 @@ namespace Rareloop\Lumberjack\Facades; -class Session extends Facade +class Session extends AbstractFacade { protected static function accessor() { diff --git a/tests/Unit/Facades/Stubs/FooFacade.php b/tests/Unit/Facades/Stubs/FooFacade.php index c9081ec..6f460c4 100644 --- a/tests/Unit/Facades/Stubs/FooFacade.php +++ b/tests/Unit/Facades/Stubs/FooFacade.php @@ -2,9 +2,9 @@ namespace Rareloop\Lumberjack\Test\Unit\Facades\Stubs; -use Rareloop\Lumberjack\Facades\Facade; +use Rareloop\Lumberjack\Facades\AbstractFacade; -class FooFacade extends Facade +class FooFacade extends AbstractFacade { public static function accessor(): string { From ea7735023aaee38c4c1f11e5205bc83bf0844dde Mon Sep 17 00:00:00 2001 From: Tom Mitchelmore Date: Mon, 6 Oct 2025 15:12:59 +0100 Subject: [PATCH 16/19] Switch to Spatie/ignition --- .gitignore | 1 + composer.json | 4 ++-- src/Exceptions/Handler.php | 22 +++++++++++++------ .../RegisterExceptionHandlerTest.php | 1 - tests/Unit/PostQueryBuilderTest.php | 11 ++-------- tests/Unit/ScopedQueryBuilderTest.php | 13 +++-------- 6 files changed, 23 insertions(+), 29 deletions(-) diff --git a/.gitignore b/.gitignore index 188e4c4..3882089 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ vendor composer.lock /tests/Unit/logs +.phpunit.result.cache diff --git a/composer.json b/composer.json index 80ec94b..b690964 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,6 @@ "psr/http-server-middleware": "^1.0.2", "timber/timber": "^2.3.0", "monolog/monolog": "^3.9", - "symfony/debug": "^4.4.44", "illuminate/collections": "^12", "statamic/stringy": "^3.1.3", "laminas/laminas-diactoros": "^3.6.0", @@ -20,7 +19,8 @@ "mindplay/middleman": "^4.0.4", "psr/log": "^2.0.0", "symfony/var-dumper": "^5.0||^6.3.6", - "illuminate/encryption": "^12.32" + "illuminate/encryption": "^12.32", + "spatie/ignition": "^1.15" }, "require-dev": { "phpunit/phpunit": "^9.6.13", diff --git a/src/Exceptions/Handler.php b/src/Exceptions/Handler.php index e6b4067..99c794e 100644 --- a/src/Exceptions/Handler.php +++ b/src/Exceptions/Handler.php @@ -3,13 +3,12 @@ namespace Rareloop\Lumberjack\Exceptions; use Exception; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ServerRequestInterface; +use Spatie\Ignition\Ignition; use Rareloop\Lumberjack\Application; +use Psr\Http\Message\ResponseInterface; use Rareloop\Lumberjack\Facades\Config; -use Symfony\Component\Debug\ExceptionHandler as SymfonyExceptionHandler; -use Symfony\Component\Debug\Exception\FlattenException; use Laminas\Diactoros\Response\HtmlResponse; +use Psr\Http\Message\ServerRequestInterface; class Handler implements HandlerInterface { @@ -36,11 +35,20 @@ public function report(Exception $e) public function render(ServerRequestInterface $request, Exception $e): ResponseInterface { - $e = FlattenException::create($e); + $isDebug = Config::get('app.debug', false) === true; + + $ignition = Ignition::make() + ->shouldDisplayException($isDebug) + ->runningInProductionEnvironment(!$isDebug) + ->register(); + + ob_start(); + + $ignition->handleException($e); - $handler = new SymfonyExceptionHandler(Config::get('app.debug', false)); + $html = ob_get_clean(); - return new HtmlResponse($handler->getHtml($e), $e->getStatusCode(), $e->getHeaders()); + return new HtmlResponse($html); } protected function shouldNotReport(Exception $e) diff --git a/tests/Unit/Bootstrappers/RegisterExceptionHandlerTest.php b/tests/Unit/Bootstrappers/RegisterExceptionHandlerTest.php index 873c272..cf1c230 100644 --- a/tests/Unit/Bootstrappers/RegisterExceptionHandlerTest.php +++ b/tests/Unit/Bootstrappers/RegisterExceptionHandlerTest.php @@ -14,7 +14,6 @@ use Rareloop\Lumberjack\Exceptions\HandlerInterface; use Rareloop\Lumberjack\Test\Unit\BrainMonkeyPHPUnitIntegration; use Rareloop\Router\Responsable; -use Symfony\Component\Debug\Exception\FatalErrorException; use Laminas\Diactoros\Response; use Laminas\Diactoros\Response\TextResponse; use Laminas\Diactoros\ServerRequest; diff --git a/tests/Unit/PostQueryBuilderTest.php b/tests/Unit/PostQueryBuilderTest.php index 0ad0fea..a8af46b 100644 --- a/tests/Unit/PostQueryBuilderTest.php +++ b/tests/Unit/PostQueryBuilderTest.php @@ -47,19 +47,12 @@ public function can_create_a_builder_from_static_functions() /** * @test - * @runInSeparateProcess */ public function throw_error_on_missing_static_function() { - $errorThrown = false; + $this->expectException(Throwable::class); - try { - Post::missingStaticFunction(); - } catch (Throwable) { - $errorThrown = true; - } - - $this->assertTrue($errorThrown); + Post::missingStaticFunction(); } private function assertQueryBuilder($function, $params, $postType) diff --git a/tests/Unit/ScopedQueryBuilderTest.php b/tests/Unit/ScopedQueryBuilderTest.php index 9f3ae13..30afa52 100644 --- a/tests/Unit/ScopedQueryBuilderTest.php +++ b/tests/Unit/ScopedQueryBuilderTest.php @@ -105,20 +105,13 @@ public function can_pass_params_into_a_query_scope_on_post_object() /** * @test - * @runInSeparateProcess */ public function missing_query_scope_throws_an_error() { - $errorThrown = false; - - try { - $builder = new ScopedQueryBuilder(PostWithQueryScope::class); - $builder->nonExistentScope(); - } catch (Throwable) { - $errorThrown = true; - } + $this->expectException(Throwable::class); - $this->assertTrue($errorThrown); + $builder = new ScopedQueryBuilder(PostWithQueryScope::class); + $builder->nonExistentScope(); } /** @test */ From 9cf7e13283ff6bd13421fbd9682558eb6a4b4ca7 Mon Sep 17 00:00:00 2001 From: Tom Mitchelmore Date: Mon, 6 Oct 2025 15:14:01 +0100 Subject: [PATCH 17/19] Upgrade phpunit config --- phpunit.xml | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/phpunit.xml b/phpunit.xml index 62992c9..7157380 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,22 +1,13 @@ - - - - tests - - - - - src/ - - + + + + src/ + + + + + tests + + From 7bbeb1b66010adfa0d37413064e3904b7137e512 Mon Sep 17 00:00:00 2001 From: Tom Mitchelmore Date: Tue, 7 Oct 2025 10:25:41 +0100 Subject: [PATCH 18/19] Remove php84 syntax from Application --- src/Application.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Application.php b/src/Application.php index fe368b4..19ed156 100644 --- a/src/Application.php +++ b/src/Application.php @@ -182,7 +182,7 @@ public function getProvider($provider) { $providerClass = is_string($provider) ? $provider : $provider::class; - return new Collection($this->loadedProviders)->first(fn($provider) => $provider::class === $providerClass); + return (new Collection($this->loadedProviders))->first(fn($provider) => $provider::class === $providerClass); } public function getLoadedProviders() From 27a4e6d03498decf317547387cad9dd2f59e4b5e Mon Sep 17 00:00:00 2001 From: Tom Mitchelmore Date: Tue, 7 Oct 2025 10:37:52 +0100 Subject: [PATCH 19/19] Implement SAPIEmitter and resolve old symfony error usage --- composer.json | 4 +++- src/Application.php | 3 ++- .../RegisterExceptionHandler.php | 22 +++++++++---------- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/composer.json b/composer.json index b690964..c5efefc 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,9 @@ "psr/log": "^2.0.0", "symfony/var-dumper": "^5.0||^6.3.6", "illuminate/encryption": "^12.32", - "spatie/ignition": "^1.15" + "spatie/ignition": "^1.15", + "laminas/laminas-httphandlerrunner": "^2.12", + "symfony/error-handler": "^7.3" }, "require-dev": { "phpunit/phpunit": "^9.6.13", diff --git a/src/Application.php b/src/Application.php index 19ed156..37a1b40 100644 --- a/src/Application.php +++ b/src/Application.php @@ -5,6 +5,7 @@ use Closure; use DI\Container; use Illuminate\Support\Collection; +use Laminas\HttpHandlerRunner\Emitter\SapiEmitter; use Psr\Container\ContainerInterface; use Psr\Http\Message\ResponseInterface; use function Http\Response\send; @@ -280,7 +281,7 @@ public function shutdown(?ResponseInterface $response = null) // If we're handling a WordPressController response at this point then WordPress will already have // sent headers as it happens earlier in the lifecycle. For this scenario we need to do a bit more // work to make sure that duplicate headers are not sent back. - send($this->removeSentHeadersAndMoveIntoResponse($response)); + (new SapiEmitter())->emit($this->removeSentHeadersAndMoveIntoResponse($response)); } die(); diff --git a/src/Bootstrappers/RegisterExceptionHandler.php b/src/Bootstrappers/RegisterExceptionHandler.php index 79424c0..5ca7ba3 100644 --- a/src/Bootstrappers/RegisterExceptionHandler.php +++ b/src/Bootstrappers/RegisterExceptionHandler.php @@ -2,16 +2,18 @@ namespace Rareloop\Lumberjack\Bootstrappers; -use DI\NotFoundException; use Error; use ErrorException; -use Psr\Http\Message\ResponseInterface; +use DI\NotFoundException; +use function Http\Response\send; +use Rareloop\Router\Responsable; use Rareloop\Lumberjack\Application; +use Psr\Http\Message\ResponseInterface; +use Laminas\Diactoros\ServerRequestFactory; +use Laminas\HttpHandlerRunner\Emitter\SapiEmitter; use Rareloop\Lumberjack\Exceptions\HandlerInterface; -use Rareloop\Router\Responsable; use Symfony\Component\Debug\Exception\FatalErrorException; -use Laminas\Diactoros\ServerRequestFactory; -use function Http\Response\send; +use Symfony\Component\ErrorHandler\Error\FatalError; /** * Determine whether or not we should be in debug mode or not @@ -70,7 +72,7 @@ public function handleException($e) public function send(ResponseInterface $response) { - @send($response); + @(new SapiEmitter())->emit($response); } protected function getExceptionHandler(): HandlerInterface @@ -122,16 +124,14 @@ public function handleShutdown() * * @param array $error * @param int|null $traceOffset - * @return \Symfony\Component\Debug\Exception\FatalErrorException + * @return \Symfony\Component\ErrorHandler\Error\FatalError */ protected function fatalExceptionFromError(array $error, $traceOffset = null) { - return new FatalErrorException( + return new FatalError( $error['message'], - $error['type'], 0, - $error['file'], - $error['line'], + $error, $traceOffset ); }