diff --git a/.github/workflows/bc.yml b/.github/workflows/bc.yml index f8cc564..00041a9 100644 --- a/.github/workflows/bc.yml +++ b/.github/workflows/bc.yml @@ -30,4 +30,4 @@ jobs: os: >- ['ubuntu-latest'] php: >- - ['8.0'] + ['8.1'] diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e96052e..05e7b40 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -31,4 +31,4 @@ jobs: os: >- ['ubuntu-latest', 'windows-latest'] php: >- - ['8.0', '8.1', '8.2', '8.3'] + ['8.1', '8.2', '8.3'] diff --git a/.github/workflows/composer-require-checker.yml b/.github/workflows/composer-require-checker.yml index 5473ec9..a857bce 100644 --- a/.github/workflows/composer-require-checker.yml +++ b/.github/workflows/composer-require-checker.yml @@ -31,4 +31,4 @@ jobs: os: >- ['ubuntu-latest'] php: >- - ['8.0', '8.1', '8.2', '8.3'] + ['8.1', '8.2', '8.3'] diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml index e34190e..e33eca8 100644 --- a/.github/workflows/static.yml +++ b/.github/workflows/static.yml @@ -30,11 +30,3 @@ jobs: ['ubuntu-latest'] php: >- ['8.1', '8.2', '8.3'] - psalm80: - uses: yiisoft/actions/.github/workflows/psalm.yml@master - with: - psalm-config: psalm80.xml - os: >- - ['ubuntu-latest'] - php: >- - ['8.0'] diff --git a/.gitignore b/.gitignore index 29c7af1..efcb7f6 100644 --- a/.gitignore +++ b/.gitignore @@ -16,9 +16,7 @@ Thumbs.db composer.phar composer.lock -# phpunit itself is not needed -phpunit.phar -# local phpunit config +# PHPUnit +/phpunit.phar /phpunit.xml -# phpunit cache -.phpunit.result.cache +/.phpunit.cache diff --git a/CHANGELOG.md b/CHANGELOG.md index 856607b..d294eec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ class (@olegbaturin) - Chg #137: Add separate parameters for each of `HtmlRenderer` settings in constructor. Mark `$settings` parameter as deprecated (@vjik) +- Enh #138: Raise the minimum PHP version to 8.1 and minor refactoring (@vjik) ## 3.3.0 July 11, 2024 diff --git a/README.md b/README.md index 36fa6f3..f985492 100644 --- a/README.md +++ b/README.md @@ -29,9 +29,8 @@ The package provides advanced error handling. The features are: ## Requirements -- PHP 8.0 or higher. +- PHP 8.1 or higher. - `DOM` PHP extension. -- `JSON` PHP extension. - `mbstring` PHP extension. ## Installation diff --git a/composer.json b/composer.json index a7ab3f8..02d53c4 100644 --- a/composer.json +++ b/composer.json @@ -31,9 +31,8 @@ } ], "require": { - "php": "^8.0", + "php": "^8.1", "ext-dom": "*", - "ext-json": "*", "ext-mbstring": "*", "alexkart/curl-builder": "^1.0", "cebe/markdown": "^1.2", @@ -48,16 +47,16 @@ "yiisoft/injector": "^1.0" }, "require-dev": { - "httpsoft/http-message": "^1.0.9", - "maglnet/composer-require-checker": "^4.4", - "phpunit/phpunit": "^9.5", + "httpsoft/http-message": "^1.1.6", + "maglnet/composer-require-checker": "^4.7.1", + "phpunit/phpunit": "^10.5.44", "psr/event-dispatcher": "^1.0", - "rector/rector": "^2.0", - "roave/infection-static-analysis-plugin": "^1.16", - "spatie/phpunit-watcher": "^1.23", - "vimeo/psalm": "^4.30|^5.25", - "yiisoft/di": "^1.1", - "yiisoft/test-support": "^3.0" + "rector/rector": "^2.0.7", + "roave/infection-static-analysis-plugin": "^1.35", + "spatie/phpunit-watcher": "^1.24", + "vimeo/psalm": "^5.26.1|^6", + "yiisoft/di": "^1.3", + "yiisoft/test-support": "^3.0.1" }, "autoload": { "psr-4": { @@ -79,6 +78,7 @@ }, "config": { "sort-packages": true, + "bump-after-update": "dev", "allow-plugins": { "infection/extension-installer": true, "composer/package-versions-deprecated": true diff --git a/phpunit.xml.dist b/phpunit.xml.dist index ba44d31..ea84752 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,19 +1,20 @@ - - - + @@ -22,9 +23,9 @@ - + - ./src + ./src - + diff --git a/psalm80.xml b/psalm80.xml deleted file mode 100644 index d091d59..0000000 --- a/psalm80.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - diff --git a/rector.php b/rector.php index 8dbe349..75ff290 100644 --- a/rector.php +++ b/rector.php @@ -6,24 +6,19 @@ use Rector\Config\RectorConfig; use Rector\Php71\Rector\FuncCall\RemoveExtraParametersRector; use Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector; -use Rector\Set\ValueObject\LevelSetList; +use Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector; -return static function (RectorConfig $rectorConfig): void { - $rectorConfig->paths([ +return RectorConfig::configure() + ->withPaths([ __DIR__ . '/src', __DIR__ . '/tests', - ]); - - // register a single rule - $rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class); - - // define sets of rules - $rectorConfig->sets([ - LevelSetList::UP_TO_PHP_80, - ]); - - $rectorConfig->skip([ + ]) + ->withPhpSets(php81: true) + ->withRules([ + InlineConstructorDefaultToPropertyRector::class, + ]) + ->withSkip([ ClosureToArrowFunctionRector::class, + NullToStrictStringFuncCallArgRector::class, RemoveExtraParametersRector::class, ]); -}; diff --git a/src/CompositeException.php b/src/CompositeException.php index 75cb211..36862ef 100644 --- a/src/CompositeException.php +++ b/src/CompositeException.php @@ -15,10 +15,10 @@ final class CompositeException extends Exception /** * @var Throwable[] */ - private array $rest; + private readonly array $rest; public function __construct( - private Throwable $first, + private readonly Throwable $first, Throwable ...$rest, ) { $this->rest = $rest; diff --git a/src/ErrorData.php b/src/ErrorData.php index 7a5f686..e446a57 100644 --- a/src/ErrorData.php +++ b/src/ErrorData.php @@ -17,8 +17,8 @@ final class ErrorData implements Stringable * @param array $headers The headers to add to the response. */ public function __construct( - private string $content, - private array $headers = [], + private readonly string $content, + private readonly array $headers = [], ) { } diff --git a/src/ErrorHandler.php b/src/ErrorHandler.php index fbf159d..b3d9ae0 100644 --- a/src/ErrorHandler.php +++ b/src/ErrorHandler.php @@ -47,10 +47,10 @@ final class ErrorHandler * @param int $exitShutdownHandlerDepth Depth of the exit() shutdown handler to ensure it's executed last. */ public function __construct( - private LoggerInterface $logger, - private ThrowableRendererInterface $defaultRenderer, - private ?EventDispatcherInterface $eventDispatcher = null, - private int $exitShutdownHandlerDepth = 2 + private readonly LoggerInterface $logger, + private readonly ThrowableRendererInterface $defaultRenderer, + private readonly ?EventDispatcherInterface $eventDispatcher = null, + private readonly int $exitShutdownHandlerDepth = 2 ) { } diff --git a/src/Event/ApplicationError.php b/src/Event/ApplicationError.php index 75791b5..0a5fb66 100644 --- a/src/Event/ApplicationError.php +++ b/src/Event/ApplicationError.php @@ -11,8 +11,9 @@ */ final class ApplicationError { - public function __construct(private Throwable $throwable) - { + public function __construct( + private readonly Throwable $throwable, + ) { } public function getThrowable(): Throwable diff --git a/src/Exception/ErrorException.php b/src/Exception/ErrorException.php index 2c27edf..d2b98f1 100644 --- a/src/Exception/ErrorException.php +++ b/src/Exception/ErrorException.php @@ -40,7 +40,7 @@ class ErrorException extends \ErrorException implements FriendlyExceptionInterfa ]; /** @psalm-param DebugBacktraceType $backtrace */ - public function __construct(string $message = '', int $code = 0, int $severity = 1, string $filename = __FILE__, int $line = __LINE__, Exception $previous = null, private array $backtrace = []) + public function __construct(string $message = '', int $code = 0, int $severity = 1, string $filename = __FILE__, int $line = __LINE__, Exception $previous = null, private readonly array $backtrace = []) { parent::__construct($message, $code, $severity, $filename, $line, $previous); $this->addXDebugTraceToFatalIfAvailable(); diff --git a/src/Middleware/ErrorCatcher.php b/src/Middleware/ErrorCatcher.php index 73ec0a6..097e3da 100644 --- a/src/Middleware/ErrorCatcher.php +++ b/src/Middleware/ErrorCatcher.php @@ -21,8 +21,8 @@ final class ErrorCatcher implements MiddlewareInterface { public function __construct( - private ThrowableResponseFactoryInterface $throwableResponseFactory, - private ?EventDispatcherInterface $eventDispatcher = null, + private readonly ThrowableResponseFactoryInterface $throwableResponseFactory, + private readonly ?EventDispatcherInterface $eventDispatcher = null, ) { } diff --git a/src/Middleware/ExceptionResponder.php b/src/Middleware/ExceptionResponder.php index 21334ab..b912c44 100644 --- a/src/Middleware/ExceptionResponder.php +++ b/src/Middleware/ExceptionResponder.php @@ -55,10 +55,10 @@ final class ExceptionResponder implements MiddlewareInterface * catching exceptions that can be thrown in the process of body generation. */ public function __construct( - private array $exceptionMap, - private ResponseFactoryInterface $responseFactory, - private Injector $injector, - private bool $checkResponseBody = false, + private readonly array $exceptionMap, + private readonly ResponseFactoryInterface $responseFactory, + private readonly Injector $injector, + private readonly bool $checkResponseBody = false, ) { } diff --git a/src/Renderer/HtmlRenderer.php b/src/Renderer/HtmlRenderer.php index 86ba30e..9449187 100644 --- a/src/Renderer/HtmlRenderer.php +++ b/src/Renderer/HtmlRenderer.php @@ -51,36 +51,36 @@ */ final class HtmlRenderer implements ThrowableRendererInterface { - private GithubMarkdown $markdownParser; + private readonly GithubMarkdown $markdownParser; /** * @var string The full path to the default template directory. */ - private string $defaultTemplatePath; + private readonly string $defaultTemplatePath; /** * @var string The full path of the template file for rendering exceptions without call stack information. * * This template should be used in production. */ - private string $template; + private readonly string $template; /** * @var string The full path of the template file for rendering exceptions with call stack information. * * This template should be used in development. */ - private string $verboseTemplate; + private readonly string $verboseTemplate; /** * @var int The maximum number of source code lines to be displayed. Defaults to 19. */ - private int $maxSourceLines; + private readonly int $maxSourceLines; /** * @var int The maximum number of trace source code lines to be displayed. Defaults to 13. */ - private int $maxTraceLines; + private readonly int $maxTraceLines; /** * @var string|null The trace header line with placeholders to be be substituted. Defaults to null. @@ -94,7 +94,7 @@ final class HtmlRenderer implements ThrowableRendererInterface * {icon} * ``` */ - private ?string $traceHeaderLine; + private readonly ?string $traceHeaderLine; /** * @var string[]|null The list of vendor paths is determined automatically. diff --git a/tests/ErrorHandlerTest.php b/tests/ErrorHandlerTest.php index 518a352..a315bb5 100644 --- a/tests/ErrorHandlerTest.php +++ b/tests/ErrorHandlerTest.php @@ -4,6 +4,7 @@ namespace Yiisoft\ErrorHandler\Tests; +use PHPUnit\Framework\Attributes\WithoutErrorHandler; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; use RuntimeException; @@ -85,6 +86,7 @@ public function testHandleThrowableWithoutExposedDetailsCallsRender(): void $this->errorHandler->handle($throwable); } + #[WithoutErrorHandler] public function testHandleError(): void { $array = []; @@ -94,6 +96,7 @@ public function testHandleError(): void $this->errorHandler->unregister(); } + #[WithoutErrorHandler] public function testHandleErrorWithCatching(): void { $this->errorHandler->register(); diff --git a/tests/Renderer/HtmlRendererTest.php b/tests/Renderer/HtmlRendererTest.php index 610653c..aa8026b 100644 --- a/tests/Renderer/HtmlRendererTest.php +++ b/tests/Renderer/HtmlRendererTest.php @@ -6,6 +6,7 @@ use Exception; use HttpSoft\Message\Uri; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ServerRequestInterface; use ReflectionClass; @@ -171,7 +172,7 @@ public function testGetThrowableName(): void $this->assertSame('Error (' . ErrorException::class . ')', $name); } - public function createServerInformationLinkDataProvider(): array + public static function createServerInformationLinkDataProvider(): array { return [ 'not-exist' => [null, ''], @@ -185,9 +186,7 @@ public function createServerInformationLinkDataProvider(): array ]; } - /** - * @dataProvider createServerInformationLinkDataProvider - */ + #[DataProvider('createServerInformationLinkDataProvider')] public function testCreateServerInformationLink(?string $serverSoftware, string $expected): void { $renderer = new HtmlRenderer(); @@ -199,7 +198,7 @@ public function testCreateServerInformationLink(?string $serverSoftware, string $this->assertStringContainsString($expected, $renderer->createServerInformationLink($serverRequestMock)); } - public function argumentsToStringValueDataProvider(): array + public static function argumentsToStringValueDataProvider(): array { return [ 'int' => [[1], '1'], @@ -222,11 +221,7 @@ public function argumentsToStringValueDataProvider(): array ]; } - /** - * @dataProvider argumentsToStringValueDataProvider - * - * @param mixed $args - */ + #[DataProvider('argumentsToStringValueDataProvider')] public function testArgumentsToString(array $args, string $expected): void { $renderer = new HtmlRenderer(); @@ -270,7 +265,7 @@ public function testGroupVendorCallStackItems(): void ])); } - public function isVendorFileReturnFalseDataProvider(): array + public static function isVendorFileReturnFalseDataProvider(): array { return [ 'null' => [null], @@ -279,9 +274,7 @@ public function isVendorFileReturnFalseDataProvider(): array ]; } - /** - * @dataProvider isVendorFileReturnFalseDataProvider - */ + #[DataProvider('isVendorFileReturnFalseDataProvider')] public function testIsVendorFileReturnFalse(?string $file): void { $this->assertFalse($this->invokeMethod(new HtmlRenderer(), 'isVendorFile', ['file' => $file]));