From 8f4676855bf63dedf113b52bcd709ca84c0b5b11 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 29 Dec 2024 12:48:27 +0700 Subject: [PATCH 01/16] Bump to PHP 8.2 and PHP 8.4 support --- .github/workflows/ci_build.yml | 3 +- composer.json | 18 +++--- rector.php | 37 +++-------- spec/Listener/ForceHttpsSpec.php | 1 - spec/Middleware/ForceHttpsSpec.php | 100 +++++++++++++++++------------ src/HttpsTrait.php | 18 ++---- src/Middleware/ForceHttps.php | 5 +- 7 files changed, 88 insertions(+), 94 deletions(-) diff --git a/.github/workflows/ci_build.yml b/.github/workflows/ci_build.yml index a67c08b..6547b02 100644 --- a/.github/workflows/ci_build.yml +++ b/.github/workflows/ci_build.yml @@ -13,7 +13,7 @@ jobs: strategy: fail-fast: false matrix: - php-versions: ['7.4', '8.0', '8.1'] + php-versions: ['8.2', '8.3', '8.4'] steps: - name: Setup PHP Action uses: shivammathur/setup-php@v2 @@ -35,6 +35,7 @@ jobs: - name: "Run test suite" run: "mkdir -p build/logs && bin/kahlan --coverage=4 --reporter=verbose --clover=build/logs/clover.xml" - name: Upload coverage to Codecov + if: github.event.pull_request.head.repo.full_name == 'samsonasik/ForceHttpsModule' uses: codecov/codecov-action@v1 with: token: ${{ secrets.CODECOV_TOKEN }} diff --git a/composer.json b/composer.json index f152210..2d2dd59 100644 --- a/composer.json +++ b/composer.json @@ -24,21 +24,21 @@ } ], "require": { - "php": "^7.4|^8.0", - "webmozart/assert": "^1.9" + "php": "^8.2", + "webmozart/assert": "^1.11" }, "conflict": { "mezzio/mezzio": "<3.0", "laminas/laminas-mvc": "<3.0" }, "require-dev": { - "kahlan/kahlan": "^5.2", - "laminas/laminas-coding-standard": "^2.0", - "laminas/laminas-mvc": "^3.0", - "mezzio/mezzio": "^3.0", - "php-coveralls/php-coveralls": "^2.1", - "phpstan/phpstan": "^1.1", - "phpstan/phpstan-webmozart-assert": "^1.0", + "kahlan/kahlan": "^6.0", + "laminas/laminas-coding-standard": "^2.5", + "laminas/laminas-mvc": "^3.8", + "mezzio/mezzio": "^3.20.1", + "php-coveralls/php-coveralls": "^2.7", + "phpstan/phpstan": "^2.0.4", + "phpstan/phpstan-webmozart-assert": "^2.0", "rector/rector": "dev-main" }, "config": { diff --git a/rector.php b/rector.php index 6fe2fbe..a020c9b 100644 --- a/rector.php +++ b/rector.php @@ -2,37 +2,20 @@ declare(strict_types=1); -use Rector\CodeQuality\Rector\Array_\CallableThisArrayToAnonymousFunctionRector; -use Rector\CodingStyle\Rector\ArrowFunction\StaticArrowFunctionRector; -use Rector\CodingStyle\Rector\Closure\StaticClosureRector; use Rector\Config\RectorConfig; -use Rector\Set\ValueObject\LevelSetList; -use Rector\Set\ValueObject\SetList; +use Rector\Php81\Rector\Array_\FirstClassCallableRector; -return static function (RectorConfig $rectorConfig): void { - $rectorConfig->sets([ - SetList::DEAD_CODE, - LevelSetList::UP_TO_PHP_74, - SetList::CODE_QUALITY, - SetList::NAMING, - SetList::TYPE_DECLARATION, - SetList::CODING_STYLE, - ]); - - $rectorConfig->paths([ +return RectorConfig::configure() + ->withPhpSets(php82: true) + ->withPreparedSets(deadCode: true, codeQuality: true, naming: true, typeDeclarations: true, codingStyle: true) + ->withImportNames(removeUnusedImports: true) + ->withPaths([ __DIR__ . '/config', __DIR__ . '/src', __DIR__ . '/spec', __DIR__ . '/rector.php' + ]) + ->withRootFiles() + ->withSkip([ + FirstClassCallableRector::class, ]); - $rectorConfig->importNames(); - $rectorConfig->skip([ - CallableThisArrayToAnonymousFunctionRector::class, - StaticArrowFunctionRector::class => [ - __DIR__ . '/spec', - ], - StaticClosureRector::class => [ - __DIR__ . '/spec', - ], - ]); -}; diff --git a/spec/Listener/ForceHttpsSpec.php b/spec/Listener/ForceHttpsSpec.php index 079bba2..05b9fbb 100644 --- a/spec/Listener/ForceHttpsSpec.php +++ b/spec/Listener/ForceHttpsSpec.php @@ -6,7 +6,6 @@ use Kahlan\Plugin\Double; use Kahlan\Plugin\Quit; use Kahlan\QuitException; -use Laminas\Console\Console; use Laminas\EventManager\EventManagerInterface; use Laminas\Http\PhpEnvironment\Request; use Laminas\Http\PhpEnvironment\Response; diff --git a/spec/Middleware/ForceHttpsSpec.php b/spec/Middleware/ForceHttpsSpec.php index e8a5cbc..eccca45 100644 --- a/spec/Middleware/ForceHttpsSpec.php +++ b/spec/Middleware/ForceHttpsSpec.php @@ -39,9 +39,12 @@ it('not redirect on router not match', function (): void { - $match = RouteResult::fromRouteFailure(null); - allow($this->router)->toReceive('match')->andReturn($match); - allow($this->request)->toReceive('getUri', 'getScheme')->andReturn('http'); + $routeResult = RouteResult::fromRouteFailure(null); + + allow($this->router)->toReceive('match')->andReturn($routeResult); + + allow($this->request)->toReceive('getUri')->andReturn($this->uri); + allow($this->uri)->toReceive('getScheme')->andReturn('http'); $listener = new ForceHttps(['enable' => true], $this->router); @@ -56,9 +59,13 @@ it('not redirect on router not match and config allow_404 is false', function (): void { - $match = RouteResult::fromRouteFailure(null); - allow($this->router)->toReceive('match')->andReturn($match); - allow($this->request)->toReceive('getUri', 'getScheme')->andReturn('http'); + $routeResult = RouteResult::fromRouteFailure(null); + + allow($this->router)->toReceive('match')->andReturn($routeResult); + + allow($this->request)->toReceive('getUri')->andReturn($this->uri); + allow($this->uri)->toReceive('__toString')->andReturn('http://example.com/404'); + allow($this->uri)->toReceive('getScheme')->andReturn('http'); $listener = new ForceHttps( [ @@ -79,11 +86,13 @@ it('not redirect on https and match but no strict_transport_security config', function (): void { - $match = RouteResult::fromRoute(new Route('/about', Double::instance(['implements' => MiddlewareInterface::class]))); + $routeResult = RouteResult::fromRoute(new Route('/about', Double::instance(['implements' => MiddlewareInterface::class]))); - allow($this->router)->toReceive('match')->andReturn($match); + allow($this->router)->toReceive('match')->andReturn($routeResult); - allow($this->request)->toReceive('getUri', 'getScheme')->andReturn('https'); + allow($this->request)->toReceive('getUri')->andReturn($this->uri); + allow($this->uri)->toReceive('__toString')->andReturn('https://example.com/about'); + allow($this->uri)->toReceive('getScheme')->andReturn('https'); $listener = new ForceHttps(['enable' => true, 'force_all_routes' => true], $this->router); @@ -98,10 +107,12 @@ it('not redirect on http and match, with force_all_routes is false and matched route name not in force_specific_routes config', function (): void { - $match = RouteResult::fromRoute(new Route('/about', Double::instance(['implements' => MiddlewareInterface::class]))); - allow($this->router)->toReceive('match')->andReturn($match); + $routeResult = RouteResult::fromRoute(new Route('/about', Double::instance(['implements' => MiddlewareInterface::class]))); + allow($this->router)->toReceive('match')->andReturn($routeResult); - allow($this->request)->toReceive('getUri', 'getScheme')->andReturn('http'); + allow($this->request)->toReceive('getUri')->andReturn($this->uri); + allow($this->uri)->toReceive('__toString')->andReturn('http://example.com/about'); + allow($this->uri)->toReceive('getScheme')->andReturn('http'); $listener = new ForceHttps( [ @@ -127,11 +138,13 @@ it('not redirect on https and match, with strict_transport_security config, but disabled', function (): void { - $match = RouteResult::fromRoute(new Route('/about', Double::instance(['implements' => MiddlewareInterface::class]))); + $routeResult = RouteResult::fromRoute(new Route('/about', Double::instance(['implements' => MiddlewareInterface::class]))); - allow($this->router)->toReceive('match')->andReturn($match); + allow($this->router)->toReceive('match')->andReturn($routeResult); - allow($this->request)->toReceive('getUri', 'getScheme')->andReturn('https'); + allow($this->request)->toReceive('getUri')->andReturn($this->uri); + allow($this->uri)->toReceive('__toString')->andReturn('https://example.com/about'); + allow($this->uri)->toReceive('getScheme')->andReturn('https'); $listener = new ForceHttps( [ @@ -157,10 +170,12 @@ it('not redirect on https and match, with strict_transport_security config, and enabled', function (): void { - $match = RouteResult::fromRoute(new Route('/about', Double::instance(['implements' => MiddlewareInterface::class]))); + $routeResult = RouteResult::fromRoute(new Route('/about', Double::instance(['implements' => MiddlewareInterface::class]))); - allow($this->router)->toReceive('match')->andReturn($match); - allow($this->request)->toReceive('getUri', 'getScheme')->andReturn('https'); + allow($this->router)->toReceive('match')->andReturn($routeResult); + allow($this->request)->toReceive('getUri')->andReturn($this->uri); + allow($this->uri)->toReceive('__toString')->andReturn('https://example.com/about'); + allow($this->uri)->toReceive('getScheme')->andReturn('https'); $listener = new ForceHttps( [ @@ -186,11 +201,14 @@ it('return Response with 308 status on http and match', function (): void { - $match = RouteResult::fromRoute(new Route('/about', Double::instance(['implements' => MiddlewareInterface::class]))); + $routeResult = RouteResult::fromRoute(new Route('/about', Double::instance(['implements' => MiddlewareInterface::class]))); + + allow($this->router)->toReceive('match')->andReturn($routeResult); - allow($this->router)->toReceive('match')->andReturn($match); - allow($this->request)->toReceive('getUri', 'getScheme')->andReturn('http'); - allow($this->request)->toReceive('getUri', 'withScheme', '__toString')->andReturn('https://example.com/about'); + allow($this->request)->toReceive('getUri')->andReturn($this->uri); + allow($this->uri)->toReceive('getScheme')->andReturn('http'); + allow($this->uri)->toReceive('withScheme')->andReturn($this->uri); + allow($this->uri)->toReceive('__toString')->andReturn('https://example.com/about'); $handler = Double::instance(['implements' => RequestHandlerInterface::class]); allow($handler)->toReceive('handle')->with($this->request)->andReturn($this->response); @@ -217,11 +235,14 @@ it('return Response with 308 status on http and not match, but allow_404 is true', function (): void { - $match = RouteResult::fromRouteFailure(null); + $routeResult = RouteResult::fromRouteFailure(null); - allow($this->router)->toReceive('match')->andReturn($match); - allow($this->request)->toReceive('getUri', 'getScheme')->andReturn('http'); - allow($this->request)->toReceive('getUri', 'withScheme', '__toString')->andReturn('https://example.com/404'); + allow($this->router)->toReceive('match')->andReturn($routeResult); + + allow($this->request)->toReceive('getUri')->andReturn($this->uri); + allow($this->uri)->toReceive('getScheme')->andReturn('http'); + allow($this->uri)->toReceive('withScheme')->andReturn($this->uri); + allow($this->uri)->toReceive('__toString')->andReturn('https://example.com/404'); $handler = Double::instance(['implements' => RequestHandlerInterface::class]); allow($handler)->toReceive('handle')->with($this->request)->andReturn($this->response); @@ -244,11 +265,13 @@ it('return Response with 308 status with include www prefix on http and match with configurable "add_www_prefix"', function (): void { - $match = RouteResult::fromRoute(new Route('/about', Double::instance(['implements' => MiddlewareInterface::class]))); + $routeResult = RouteResult::fromRoute(new Route('/about', Double::instance(['implements' => MiddlewareInterface::class]))); - allow($this->router)->toReceive('match')->andReturn($match); - allow($this->request)->toReceive('getUri', 'getScheme')->andReturn('http'); - allow($this->request)->toReceive('getUri', 'withScheme', '__toString')->andReturn('https://example.com/about'); + allow($this->router)->toReceive('match')->andReturn($routeResult); + allow($this->request)->toReceive('getUri')->andReturn($this->uri); + allow($this->uri)->toReceive('getScheme')->andReturn('http'); + allow($this->uri)->toReceive('withScheme')->andReturn($this->uri); + allow($this->uri)->toReceive('__toString')->andReturn('https://example.com/about'); $handler = Double::instance(['implements' => RequestHandlerInterface::class]); allow($handler)->toReceive('handle')->with($this->request)->andReturn($this->response); @@ -276,16 +299,13 @@ it('return Response with 308 status with remove www prefix on http and match with configurable "remove_www_prefix"', function (): void { - $match = RouteResult::fromRoute(new Route('/about', Double::instance(['implements' => MiddlewareInterface::class]))); + $routeResult = RouteResult::fromRoute(new Route('/about', Double::instance(['implements' => MiddlewareInterface::class]))); - allow($this->request)->toReceive('getUri', '__toString')->andReturn('http://www.example.com/about'); - allow($this->router)->toReceive('match')->andReturn($match); - allow($this->request)->toReceive('getUri', 'getScheme')->andReturn('http'); - allow($this->request)->toReceive('getUri', 'withScheme', '__toString')->andReturn('https://www.example.com/about'); - - allow($this->response)->toReceive('withStatus')->andReturn($this->response); - $handler = Double::instance(['implements' => RequestHandlerInterface::class]); - allow($handler)->toReceive('handle')->with($this->request)->andReturn($this->response); + allow($this->router)->toReceive('match')->andReturn($routeResult); + allow($this->request)->toReceive('getUri')->andReturn($this->uri); + allow($this->uri)->toReceive('getScheme')->andReturn('http'); + allow($this->uri)->toReceive('withScheme')->andReturn($this->uri); + allow($this->uri)->toReceive('__toString')->andReturn('https://www.example.com/about'); $handler = Double::instance(['implements' => RequestHandlerInterface::class]); allow($handler)->toReceive('handle')->with($this->request)->andReturn($this->response); @@ -300,12 +320,10 @@ 'enable' => true, 'value' => 'max-age=31536000', ], - 'add_www_prefix' => false, 'remove_www_prefix' => true, ], $this->router ); - $listener->process($this->request, $handler); expect($this->response)->toReceive('withStatus')->with(308); diff --git a/src/HttpsTrait.php b/src/HttpsTrait.php index dcc9c84..a1b95d8 100644 --- a/src/HttpsTrait.php +++ b/src/HttpsTrait.php @@ -14,11 +14,9 @@ trait HttpsTrait { - /** @var bool */ - private $needsWwwPrefix = false; + private bool $needsWwwPrefix = false; - /** @var bool */ - private $alreadyHasWwwPrefix = false; + private bool $alreadyHasWwwPrefix = false; private function isSchemeHttps(string $uriScheme): bool { @@ -27,10 +25,8 @@ private function isSchemeHttps(string $uriScheme): bool /** * Check Config if is going to be forced to https. - * - * @param RouteMatch|RouteResult|null $match */ - private function isGoingToBeForcedToHttps($match = null): bool + private function isGoingToBeForcedToHttps(RouteMatch|RouteResult|null $match = null): bool { if ($match === null || ($match instanceof RouteResult && $match->isFailure())) { return $this->config['allow_404'] ?? false; @@ -49,11 +45,11 @@ private function isGoingToBeForcedToHttps($match = null): bool /** * Check if Setup Strict-Transport-Security need to be skipped. - * - * @param RouteMatch|RouteResult|null $match */ - private function isSkippedHttpStrictTransportSecurity(string $uriScheme, $match = null): bool - { + private function isSkippedHttpStrictTransportSecurity( + string $uriScheme, + RouteMatch|RouteResult|null $match = null + ): bool { return ! $this->isSchemeHttps($uriScheme) || ! $this->isGoingToBeForcedToHttps($match) || ! isset( diff --git a/src/Middleware/ForceHttps.php b/src/Middleware/ForceHttps.php index 23cffe2..11885ae 100644 --- a/src/Middleware/ForceHttps.php +++ b/src/Middleware/ForceHttps.php @@ -18,15 +18,12 @@ class ForceHttps implements MiddlewareInterface private array $config; - private RouterInterface $router; - /** * @param mixed[] $config */ - public function __construct(array $config, RouterInterface $router) + public function __construct(array $config, private RouterInterface $router) { $this->config = $config; - $this->router = $router; } private function setHttpStrictTransportSecurity( From 3f2c75517751878203b943000006ff6da839b310 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 29 Dec 2024 12:49:56 +0700 Subject: [PATCH 02/16] test fix --- spec/Middleware/ForceHttpsSpec.php | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/Middleware/ForceHttpsSpec.php b/spec/Middleware/ForceHttpsSpec.php index eccca45..697027f 100644 --- a/spec/Middleware/ForceHttpsSpec.php +++ b/spec/Middleware/ForceHttpsSpec.php @@ -320,6 +320,7 @@ 'enable' => true, 'value' => 'max-age=31536000', ], + 'add_www_prefix' => false, 'remove_www_prefix' => true, ], $this->router From 065741b0df2e98f4f8d617e54a4d889108396e30 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 29 Dec 2024 12:51:58 +0700 Subject: [PATCH 03/16] fix test --- spec/Middleware/ForceHttpsSpec.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/Middleware/ForceHttpsSpec.php b/spec/Middleware/ForceHttpsSpec.php index 697027f..f3bf9a7 100644 --- a/spec/Middleware/ForceHttpsSpec.php +++ b/spec/Middleware/ForceHttpsSpec.php @@ -302,10 +302,11 @@ $routeResult = RouteResult::fromRoute(new Route('/about', Double::instance(['implements' => MiddlewareInterface::class]))); allow($this->router)->toReceive('match')->andReturn($routeResult); + allow($this->uri)->toReceive('__toString')->andReturn('https://www.example.com/about'); allow($this->request)->toReceive('getUri')->andReturn($this->uri); allow($this->uri)->toReceive('getScheme')->andReturn('http'); allow($this->uri)->toReceive('withScheme')->andReturn($this->uri); - allow($this->uri)->toReceive('__toString')->andReturn('https://www.example.com/about'); + allow($this->uri)->toReceive('__toString')->andReturn('https://example.com/about'); $handler = Double::instance(['implements' => RequestHandlerInterface::class]); allow($handler)->toReceive('handle')->with($this->request)->andReturn($this->response); From bde52dcb564077e0ee31a03daed2d98175caff36 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 29 Dec 2024 12:54:13 +0700 Subject: [PATCH 04/16] fix test --- spec/Middleware/ForceHttpsSpec.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/Middleware/ForceHttpsSpec.php b/spec/Middleware/ForceHttpsSpec.php index f3bf9a7..750e5a3 100644 --- a/spec/Middleware/ForceHttpsSpec.php +++ b/spec/Middleware/ForceHttpsSpec.php @@ -269,9 +269,10 @@ allow($this->router)->toReceive('match')->andReturn($routeResult); allow($this->request)->toReceive('getUri')->andReturn($this->uri); + allow($this->uri)->toReceive('__toString')->andReturn('https://example.com/about'); allow($this->uri)->toReceive('getScheme')->andReturn('http'); allow($this->uri)->toReceive('withScheme')->andReturn($this->uri); - allow($this->uri)->toReceive('__toString')->andReturn('https://example.com/about'); + allow($this->uri)->toReceive('__toString')->andReturn('https://www.example.com/about'); $handler = Double::instance(['implements' => RequestHandlerInterface::class]); allow($handler)->toReceive('handle')->with($this->request)->andReturn($this->response); From 40900310b563e5ffe896edc3d0e5c32c3e31c7ae Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 29 Dec 2024 12:56:26 +0700 Subject: [PATCH 05/16] fix phpstan --- phpstan.neon | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/phpstan.neon b/phpstan.neon index 8f6ad3d..5a23f3d 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,6 +1,3 @@ includes: - vendor/phpstan/phpstan-webmozart-assert/extension.neon - -parameters: - checkMissingIterableValueType: false - + - phpstan-baseline.neon From f5eac5fb9e71dfd7d2fa581ad10cfa3302b270f6 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 29 Dec 2024 12:56:30 +0700 Subject: [PATCH 06/16] fix phpstan --- phpstan-baseline.neon | 133 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 phpstan-baseline.neon diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon new file mode 100644 index 0000000..79be4c4 --- /dev/null +++ b/phpstan-baseline.neon @@ -0,0 +1,133 @@ +parameters: + ignoreErrors: + - + message: '#^Call to static method Webmozart\\Assert\\Assert\:\:notNull\(\) with Laminas\\Router\\RouteMatch\|Mezzio\\Router\\RouteResult will always evaluate to true\.$#' + identifier: staticMethod.alreadyNarrowedType + count: 1 + path: src/Listener/ForceHttps.php + + - + message: '#^Cannot access offset ''enable'' on mixed\.$#' + identifier: offsetAccess.nonOffsetAccessible + count: 2 + path: src/Listener/ForceHttps.php + + - + message: '#^Cannot access offset ''value'' on mixed\.$#' + identifier: offsetAccess.nonOffsetAccessible + count: 2 + path: src/Listener/ForceHttps.php + + - + message: '#^Method ForceHttpsModule\\Listener\\ForceHttps\:\:isGoingToBeForcedToHttps\(\) should return bool but returns mixed\.$#' + identifier: return.type + count: 1 + path: src/Listener/ForceHttps.php + + - + message: '#^Parameter \#2 \$haystack of function in_array expects array, mixed given\.$#' + identifier: argument.type + count: 2 + path: src/Listener/ForceHttps.php + + - + message: '#^Parameter \#2 \.\.\.\$values of function sprintf expects bool\|float\|int\|string\|null, mixed given\.$#' + identifier: argument.type + count: 1 + path: src/Listener/ForceHttps.php + + - + message: '#^Property ForceHttpsModule\\Listener\\ForceHttps\:\:\$config type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue + count: 1 + path: src/Listener/ForceHttps.php + + - + message: '#^Property ForceHttpsModule\\Listener\\ForceHttps\:\:\$needsWwwPrefix \(bool\) does not accept mixed\.$#' + identifier: assign.propertyType + count: 1 + path: src/Listener/ForceHttps.php + + - + message: '#^Cannot access offset ''force\-https\-module'' on mixed\.$#' + identifier: offsetAccess.nonOffsetAccessible + count: 1 + path: src/Listener/ForceHttpsFactory.php + + - + message: '#^Parameter \#1 \$config of class ForceHttpsModule\\Listener\\ForceHttps constructor expects array\, mixed given\.$#' + identifier: argument.type + count: 1 + path: src/Listener/ForceHttpsFactory.php + + - + message: '#^Call to static method Webmozart\\Assert\\Assert\:\:notNull\(\) with Laminas\\Router\\RouteMatch\|Mezzio\\Router\\RouteResult will always evaluate to true\.$#' + identifier: staticMethod.alreadyNarrowedType + count: 1 + path: src/Middleware/ForceHttps.php + + - + message: '#^Cannot access offset ''enable'' on mixed\.$#' + identifier: offsetAccess.nonOffsetAccessible + count: 2 + path: src/Middleware/ForceHttps.php + + - + message: '#^Cannot access offset ''value'' on mixed\.$#' + identifier: offsetAccess.nonOffsetAccessible + count: 2 + path: src/Middleware/ForceHttps.php + + - + message: '#^Method ForceHttpsModule\\Middleware\\ForceHttps\:\:isGoingToBeForcedToHttps\(\) should return bool but returns mixed\.$#' + identifier: return.type + count: 1 + path: src/Middleware/ForceHttps.php + + - + message: '#^Parameter \#2 \$haystack of function in_array expects array, mixed given\.$#' + identifier: argument.type + count: 2 + path: src/Middleware/ForceHttps.php + + - + message: '#^Parameter \#2 \$value of method Psr\\Http\\Message\\MessageInterface\:\:withHeader\(\) expects array\\|string, mixed given\.$#' + identifier: argument.type + count: 1 + path: src/Middleware/ForceHttps.php + + - + message: '#^Property ForceHttpsModule\\Middleware\\ForceHttps\:\:\$config type has no value type specified in iterable type array\.$#' + identifier: missingType.iterableValue + count: 1 + path: src/Middleware/ForceHttps.php + + - + message: '#^Property ForceHttpsModule\\Middleware\\ForceHttps\:\:\$needsWwwPrefix \(bool\) does not accept mixed\.$#' + identifier: assign.propertyType + count: 1 + path: src/Middleware/ForceHttps.php + + - + message: '#^Cannot access offset ''force\-https\-module'' on mixed\.$#' + identifier: offsetAccess.nonOffsetAccessible + count: 1 + path: src/Middleware/ForceHttpsFactory.php + + - + message: '#^Parameter \#1 \$config of class ForceHttpsModule\\Middleware\\ForceHttps constructor expects array\, mixed given\.$#' + identifier: argument.type + count: 1 + path: src/Middleware/ForceHttpsFactory.php + + - + message: '#^Parameter \#2 \$router of class ForceHttpsModule\\Middleware\\ForceHttps constructor expects Mezzio\\Router\\RouterInterface, mixed given\.$#' + identifier: argument.type + count: 1 + path: src/Middleware/ForceHttpsFactory.php + + - + message: '#^Method ForceHttpsModule\\Module\:\:getConfig\(\) should return array\ but returns mixed\.$#' + identifier: return.type + count: 1 + path: src/Module.php From f93f144e387ca2d61fc7aa10dcaa300ea11810d7 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 29 Dec 2024 12:57:21 +0700 Subject: [PATCH 07/16] fix phpstan --- phpstan-baseline.neon | 6 ------ src/Middleware/ForceHttpsFactory.php | 1 + 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 79be4c4..c351413 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -120,12 +120,6 @@ parameters: count: 1 path: src/Middleware/ForceHttpsFactory.php - - - message: '#^Parameter \#2 \$router of class ForceHttpsModule\\Middleware\\ForceHttps constructor expects Mezzio\\Router\\RouterInterface, mixed given\.$#' - identifier: argument.type - count: 1 - path: src/Middleware/ForceHttpsFactory.php - - message: '#^Method ForceHttpsModule\\Module\:\:getConfig\(\) should return array\ but returns mixed\.$#' identifier: return.type diff --git a/src/Middleware/ForceHttpsFactory.php b/src/Middleware/ForceHttpsFactory.php index 1784dad..5bc80a6 100644 --- a/src/Middleware/ForceHttpsFactory.php +++ b/src/Middleware/ForceHttpsFactory.php @@ -12,6 +12,7 @@ class ForceHttpsFactory public function __invoke(ContainerInterface $container): ForceHttps { $config = $container->get('config'); + /** @var RouterInterface $router */ $router = $container->get(RouterInterface::class); $forceHttpsConfig = $config['force-https-module'] ?? ['enable' => false]; From e6ed329aa30f5e90012875d10578e1953ec14ace Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 29 Dec 2024 12:59:18 +0700 Subject: [PATCH 08/16] fix phpstan --- phpstan-baseline.neon | 12 ------------ src/HttpsTrait.php | 2 -- 2 files changed, 14 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index c351413..58748e5 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,11 +1,5 @@ parameters: ignoreErrors: - - - message: '#^Call to static method Webmozart\\Assert\\Assert\:\:notNull\(\) with Laminas\\Router\\RouteMatch\|Mezzio\\Router\\RouteResult will always evaluate to true\.$#' - identifier: staticMethod.alreadyNarrowedType - count: 1 - path: src/Listener/ForceHttps.php - - message: '#^Cannot access offset ''enable'' on mixed\.$#' identifier: offsetAccess.nonOffsetAccessible @@ -60,12 +54,6 @@ parameters: count: 1 path: src/Listener/ForceHttpsFactory.php - - - message: '#^Call to static method Webmozart\\Assert\\Assert\:\:notNull\(\) with Laminas\\Router\\RouteMatch\|Mezzio\\Router\\RouteResult will always evaluate to true\.$#' - identifier: staticMethod.alreadyNarrowedType - count: 1 - path: src/Middleware/ForceHttps.php - - message: '#^Cannot access offset ''enable'' on mixed\.$#' identifier: offsetAccess.nonOffsetAccessible diff --git a/src/HttpsTrait.php b/src/HttpsTrait.php index a1b95d8..c71367a 100644 --- a/src/HttpsTrait.php +++ b/src/HttpsTrait.php @@ -6,7 +6,6 @@ use Laminas\Router\RouteMatch; use Mezzio\Router\RouteResult; -use Webmozart\Assert\Assert; use function in_array; use function strpos; @@ -32,7 +31,6 @@ private function isGoingToBeForcedToHttps(RouteMatch|RouteResult|null $match = n return $this->config['allow_404'] ?? false; } - Assert::notNull($match); $matchedRouteName = $match->getMatchedRouteName(); if ($this->config['force_all_routes']) { From f5438e9d1508b27c987c09370dd10f3f946efd04 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 29 Dec 2024 12:59:59 +0700 Subject: [PATCH 09/16] fix phpstan --- phpstan-baseline.neon | 8 ++++---- src/HttpsTrait.php | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 58748e5..c1bd9e8 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -13,8 +13,8 @@ parameters: path: src/Listener/ForceHttps.php - - message: '#^Method ForceHttpsModule\\Listener\\ForceHttps\:\:isGoingToBeForcedToHttps\(\) should return bool but returns mixed\.$#' - identifier: return.type + message: '#^Expression on left side of \?\? is not nullable\.$#' + identifier: nullCoalesce.expr count: 1 path: src/Listener/ForceHttps.php @@ -67,8 +67,8 @@ parameters: path: src/Middleware/ForceHttps.php - - message: '#^Method ForceHttpsModule\\Middleware\\ForceHttps\:\:isGoingToBeForcedToHttps\(\) should return bool but returns mixed\.$#' - identifier: return.type + message: '#^Expression on left side of \?\? is not nullable\.$#' + identifier: nullCoalesce.expr count: 1 path: src/Middleware/ForceHttps.php diff --git a/src/HttpsTrait.php b/src/HttpsTrait.php index c71367a..f1d9292 100644 --- a/src/HttpsTrait.php +++ b/src/HttpsTrait.php @@ -28,7 +28,7 @@ private function isSchemeHttps(string $uriScheme): bool private function isGoingToBeForcedToHttps(RouteMatch|RouteResult|null $match = null): bool { if ($match === null || ($match instanceof RouteResult && $match->isFailure())) { - return $this->config['allow_404'] ?? false; + return (bool) $this->config['allow_404'] ?? false; } $matchedRouteName = $match->getMatchedRouteName(); From 61a0ecc5e34fbd34a0f6a9fbe6a3b6913db91189 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 29 Dec 2024 13:01:31 +0700 Subject: [PATCH 10/16] cs fix --- src/Middleware/ForceHttpsFactory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Middleware/ForceHttpsFactory.php b/src/Middleware/ForceHttpsFactory.php index 5bc80a6..82cd675 100644 --- a/src/Middleware/ForceHttpsFactory.php +++ b/src/Middleware/ForceHttpsFactory.php @@ -11,7 +11,7 @@ class ForceHttpsFactory { public function __invoke(ContainerInterface $container): ForceHttps { - $config = $container->get('config'); + $config = $container->get('config'); /** @var RouterInterface $router */ $router = $container->get(RouterInterface::class); $forceHttpsConfig = $config['force-https-module'] ?? ['enable' => false]; From 98ac16922bf181f3cbb71b704cf248a358e47612 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 29 Dec 2024 13:02:07 +0700 Subject: [PATCH 11/16] export ignore phsptan-baseline.neon --- .gitattributes | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitattributes b/.gitattributes index fe5c282..f82fa3a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -6,4 +6,5 @@ /CONTRIBUTING.md export-ignore /phpcs.xml export-ignore /kahlan-config.php export-ignore -/rector.php export-ignore \ No newline at end of file +/rector.php export-ignore +/phpstan-baseline.neon export-ignore From 67a3bb7b2955b46c065ad26b4ab01d0460f1adbc Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 29 Dec 2024 13:03:22 +0700 Subject: [PATCH 12/16] phpstan max --- .github/workflows/ci_build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_build.yml b/.github/workflows/ci_build.yml index 6547b02..1c836fc 100644 --- a/.github/workflows/ci_build.yml +++ b/.github/workflows/ci_build.yml @@ -30,7 +30,7 @@ jobs: run: "composer cs-check" - name: "Code analyze" run: | - bin/phpstan analyse src/ --level=8 -c phpstan.neon + bin/phpstan analyse src/ --level=max -c phpstan.neon bin/rector process --dry-run - name: "Run test suite" run: "mkdir -p build/logs && bin/kahlan --coverage=4 --reporter=verbose --clover=build/logs/clover.xml" From bf9661f1cbcf262612207e2b594114ab5c4a04ab Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 29 Dec 2024 13:06:02 +0700 Subject: [PATCH 13/16] fix --- src/HttpsTrait.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/HttpsTrait.php b/src/HttpsTrait.php index f1d9292..0cddffe 100644 --- a/src/HttpsTrait.php +++ b/src/HttpsTrait.php @@ -28,7 +28,7 @@ private function isSchemeHttps(string $uriScheme): bool private function isGoingToBeForcedToHttps(RouteMatch|RouteResult|null $match = null): bool { if ($match === null || ($match instanceof RouteResult && $match->isFailure())) { - return (bool) $this->config['allow_404'] ?? false; + return (bool) ($this->config['allow_404'] ?? false); } $matchedRouteName = $match->getMatchedRouteName(); From a9556fa431b9e4431c5a41b44932e7e2b9127472 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 29 Dec 2024 13:06:07 +0700 Subject: [PATCH 14/16] fix --- phpstan-baseline.neon | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index c1bd9e8..a766667 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -12,12 +12,6 @@ parameters: count: 2 path: src/Listener/ForceHttps.php - - - message: '#^Expression on left side of \?\? is not nullable\.$#' - identifier: nullCoalesce.expr - count: 1 - path: src/Listener/ForceHttps.php - - message: '#^Parameter \#2 \$haystack of function in_array expects array, mixed given\.$#' identifier: argument.type @@ -66,12 +60,6 @@ parameters: count: 2 path: src/Middleware/ForceHttps.php - - - message: '#^Expression on left side of \?\? is not nullable\.$#' - identifier: nullCoalesce.expr - count: 1 - path: src/Middleware/ForceHttps.php - - message: '#^Parameter \#2 \$haystack of function in_array expects array, mixed given\.$#' identifier: argument.type From 9c35dcd7cb492f3231c84281fe082f3fe40de495 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 29 Dec 2024 13:07:06 +0700 Subject: [PATCH 15/16] fix --- phpstan-baseline.neon | 12 ++++++++++++ src/HttpsTrait.php | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index a766667..58748e5 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -12,6 +12,12 @@ parameters: count: 2 path: src/Listener/ForceHttps.php + - + message: '#^Method ForceHttpsModule\\Listener\\ForceHttps\:\:isGoingToBeForcedToHttps\(\) should return bool but returns mixed\.$#' + identifier: return.type + count: 1 + path: src/Listener/ForceHttps.php + - message: '#^Parameter \#2 \$haystack of function in_array expects array, mixed given\.$#' identifier: argument.type @@ -60,6 +66,12 @@ parameters: count: 2 path: src/Middleware/ForceHttps.php + - + message: '#^Method ForceHttpsModule\\Middleware\\ForceHttps\:\:isGoingToBeForcedToHttps\(\) should return bool but returns mixed\.$#' + identifier: return.type + count: 1 + path: src/Middleware/ForceHttps.php + - message: '#^Parameter \#2 \$haystack of function in_array expects array, mixed given\.$#' identifier: argument.type diff --git a/src/HttpsTrait.php b/src/HttpsTrait.php index 0cddffe..c71367a 100644 --- a/src/HttpsTrait.php +++ b/src/HttpsTrait.php @@ -28,7 +28,7 @@ private function isSchemeHttps(string $uriScheme): bool private function isGoingToBeForcedToHttps(RouteMatch|RouteResult|null $match = null): bool { if ($match === null || ($match instanceof RouteResult && $match->isFailure())) { - return (bool) ($this->config['allow_404'] ?? false); + return $this->config['allow_404'] ?? false; } $matchedRouteName = $match->getMatchedRouteName(); From d210ae7c415ed516104a671f2179341dcb2f1a42 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sun, 29 Dec 2024 13:09:08 +0700 Subject: [PATCH 16/16] config is readonly --- phpstan-baseline.neon | 12 ------------ src/Listener/ForceHttps.php | 5 +---- src/Middleware/ForceHttps.php | 4 +--- 3 files changed, 2 insertions(+), 19 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 58748e5..8f1c10b 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -30,12 +30,6 @@ parameters: count: 1 path: src/Listener/ForceHttps.php - - - message: '#^Property ForceHttpsModule\\Listener\\ForceHttps\:\:\$config type has no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: src/Listener/ForceHttps.php - - message: '#^Property ForceHttpsModule\\Listener\\ForceHttps\:\:\$needsWwwPrefix \(bool\) does not accept mixed\.$#' identifier: assign.propertyType @@ -84,12 +78,6 @@ parameters: count: 1 path: src/Middleware/ForceHttps.php - - - message: '#^Property ForceHttpsModule\\Middleware\\ForceHttps\:\:\$config type has no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue - count: 1 - path: src/Middleware/ForceHttps.php - - message: '#^Property ForceHttpsModule\\Middleware\\ForceHttps\:\:\$needsWwwPrefix \(bool\) does not accept mixed\.$#' identifier: assign.propertyType diff --git a/src/Listener/ForceHttps.php b/src/Listener/ForceHttps.php index c1c8bd2..76878a5 100644 --- a/src/Listener/ForceHttps.php +++ b/src/Listener/ForceHttps.php @@ -21,14 +21,11 @@ class ForceHttps extends AbstractListenerAggregate { use HttpsTrait; - private array $config; - /** * @param mixed[] $config */ - public function __construct(array $config) + public function __construct(private readonly array $config) { - $this->config = $config; } /** diff --git a/src/Middleware/ForceHttps.php b/src/Middleware/ForceHttps.php index 11885ae..dc32bb6 100644 --- a/src/Middleware/ForceHttps.php +++ b/src/Middleware/ForceHttps.php @@ -16,12 +16,10 @@ class ForceHttps implements MiddlewareInterface { use HttpsTrait; - private array $config; - /** * @param mixed[] $config */ - public function __construct(array $config, private RouterInterface $router) + public function __construct(private array $config, private RouterInterface $router) { $this->config = $config; }