From 144770aa59f6ddfae5b555943e8bbbe0a03ddb9c Mon Sep 17 00:00:00 2001 From: Daniel Burger <48986191+danielburger1337@users.noreply.github.com> Date: Sun, 2 Nov 2025 19:42:59 +0100 Subject: [PATCH 01/15] Drop phpstan/phpstan-symfony as dependency --- composer.json | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/composer.json b/composer.json index 890e459..6433932 100644 --- a/composer.json +++ b/composer.json @@ -23,9 +23,7 @@ }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.89", - "phpstan/extension-installer": "^1.1", "phpstan/phpstan": "^1.4", - "phpstan/phpstan-symfony": "^1.1", "sbsedv/form-bundle": "^1.7", "symfony/validator": "^7.0" }, @@ -35,9 +33,6 @@ } }, "config": { - "sort-packages": true, - "allow-plugins": { - "phpstan/extension-installer": true - } + "sort-packages": true } } From 9bb478f46b646019052f7c09fcb59e7cd72c5406 Mon Sep 17 00:00:00 2001 From: Daniel Burger <48986191+danielburger1337@users.noreply.github.com> Date: Sun, 2 Nov 2025 19:43:17 +0100 Subject: [PATCH 02/15] Rename PHPStan config to phpstan.dist.neon --- phpstan.neon => phpstan.dist.neon | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename phpstan.neon => phpstan.dist.neon (100%) diff --git a/phpstan.neon b/phpstan.dist.neon similarity index 100% rename from phpstan.neon rename to phpstan.dist.neon From d02f6c7f0ee0e3d7b90785dc4ea118f55952d783 Mon Sep 17 00:00:00 2001 From: Daniel Burger <48986191+danielburger1337@users.noreply.github.com> Date: Sun, 2 Nov 2025 19:43:46 +0100 Subject: [PATCH 03/15] Add config directory to phpstan --- phpstan.dist.neon | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/phpstan.dist.neon b/phpstan.dist.neon index 0eeffd0..e74dcf3 100644 --- a/phpstan.dist.neon +++ b/phpstan.dist.neon @@ -1,10 +1,11 @@ parameters: level: 9 + paths: + - src/ + - config/ + reportUnmatchedIgnoredErrors: false ignoreErrors: - identifier: missingType.iterableValue - - paths: - - src From c1bf5a92dd0cad45477a22699dc7aaab29fa5d0c Mon Sep 17 00:00:00 2001 From: Daniel Burger <48986191+danielburger1337@users.noreply.github.com> Date: Sun, 2 Nov 2025 19:44:01 +0100 Subject: [PATCH 04/15] Remove "reportUnmatchedIgnoredErrors" from phpstan config --- phpstan.dist.neon | 2 -- 1 file changed, 2 deletions(-) diff --git a/phpstan.dist.neon b/phpstan.dist.neon index e74dcf3..9d59566 100644 --- a/phpstan.dist.neon +++ b/phpstan.dist.neon @@ -5,7 +5,5 @@ parameters: - src/ - config/ - reportUnmatchedIgnoredErrors: false - ignoreErrors: - identifier: missingType.iterableValue From 05c7955abb124db4df7de65337edd7ba5d747ae3 Mon Sep 17 00:00:00 2001 From: Daniel Burger <48986191+danielburger1337@users.noreply.github.com> Date: Sun, 2 Nov 2025 19:44:47 +0100 Subject: [PATCH 05/15] Bump PHPStan to v2.1 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 6433932..7a0be98 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,7 @@ }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.89", - "phpstan/phpstan": "^1.4", + "phpstan/phpstan": "^2.1", "sbsedv/form-bundle": "^1.7", "symfony/validator": "^7.0" }, From 2ea4eedd16b5a3977733c222d65a196f3f91d82d Mon Sep 17 00:00:00 2001 From: Daniel Burger <48986191+danielburger1337@users.noreply.github.com> Date: Sun, 2 Nov 2025 19:46:16 +0100 Subject: [PATCH 06/15] Ignore "method.notFound" phpstan error in config definitions --- config/definitions/event_listener.php | 2 +- config/definitions/other.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/definitions/event_listener.php b/config/definitions/event_listener.php index 7e4db5a..6e3b423 100644 --- a/config/definitions/event_listener.php +++ b/config/definitions/event_listener.php @@ -3,7 +3,7 @@ namespace Symfony\Component\Config\Definition\Configurator; return function (DefinitionConfigurator $definition): void { - $definition + $definition // @phpstan-ignore method.notFound ->rootNode() ->children() ->arrayNode('event_listeners') diff --git a/config/definitions/other.php b/config/definitions/other.php index 9546e48..4de380b 100644 --- a/config/definitions/other.php +++ b/config/definitions/other.php @@ -3,7 +3,7 @@ namespace Symfony\Component\Config\Definition\Configurator; return function (DefinitionConfigurator $definition): void { - $definition + $definition // @phpstan-ignore method.notFound ->rootNode() ->children() ->booleanNode('exception_normalizer')->defaultTrue()->end() From 4d429074beabdd5f9812bfa96f5f8f06b05830e9 Mon Sep 17 00:00:00 2001 From: Daniel Burger <48986191+danielburger1337@users.noreply.github.com> Date: Sun, 2 Nov 2025 19:59:12 +0100 Subject: [PATCH 07/15] Add missing array shape to AccessDeniedException --- src/Exception/AccessDeniedException.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Exception/AccessDeniedException.php b/src/Exception/AccessDeniedException.php index ad34767..766ef3c 100644 --- a/src/Exception/AccessDeniedException.php +++ b/src/Exception/AccessDeniedException.php @@ -7,6 +7,10 @@ class AccessDeniedException extends HttpException { + /** + * @param array $headers + * @param array $other + */ public function __construct( TranslatableInterface|string $message = 'Access denied.', ?\Throwable $previous = null, From 0657fff1338f3eb14e3d81a7169536dce591cd41 Mon Sep 17 00:00:00 2001 From: Daniel Burger <48986191+danielburger1337@users.noreply.github.com> Date: Sun, 2 Nov 2025 19:59:29 +0100 Subject: [PATCH 08/15] Add array shape phpdoc in InvalidFormExceptionEventListener --- src/EventListener/InvalidFormExceptionEventListener.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/EventListener/InvalidFormExceptionEventListener.php b/src/EventListener/InvalidFormExceptionEventListener.php index 518b025..311a971 100644 --- a/src/EventListener/InvalidFormExceptionEventListener.php +++ b/src/EventListener/InvalidFormExceptionEventListener.php @@ -11,6 +11,7 @@ use Symfony\Component\HttpKernel\Event\ExceptionEvent; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; use Symfony\Component\Translation\TranslatableMessage; +use Symfony\Contracts\Translation\TranslatableInterface; class InvalidFormExceptionEventListener implements EventSubscriberInterface { @@ -43,7 +44,7 @@ public function __invoke(ExceptionEvent $event): void $errors = []; - /** @var array $formError */ + /** @var array{'message': string|TranslatableInterface, 'cause'?: string, 'type'?: string, 'cause'?: string} $formError */ foreach ($formErrors as $formError) { $dto = new ApiResponseErrorDto($formError['message'], 'invalid_request_error', $formError['cause'] ?? null); From 1f4a18db82abe1e135a8d4fc1361d53a9cc70cc0 Mon Sep 17 00:00:00 2001 From: Daniel Burger <48986191+danielburger1337@users.noreply.github.com> Date: Sun, 2 Nov 2025 20:02:14 +0100 Subject: [PATCH 09/15] Add missing array shape to BundledHttpException --- src/Exception/BundledHttpException.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Exception/BundledHttpException.php b/src/Exception/BundledHttpException.php index fa0ccff..735e82e 100644 --- a/src/Exception/BundledHttpException.php +++ b/src/Exception/BundledHttpException.php @@ -7,7 +7,9 @@ class BundledHttpException extends HttpException { /** - * @param HttpException[] $exceptions The exceptions to bundle. + * @param HttpException[] $exceptions The exceptions to bundle. + * @param array $headers + * @param array $other */ public function __construct( private array $exceptions, From cb4e18bf2a4fdc45cb340cb88ab88bb2003fa76a Mon Sep 17 00:00:00 2001 From: Daniel Burger <48986191+danielburger1337@users.noreply.github.com> Date: Sun, 2 Nov 2025 20:02:30 +0100 Subject: [PATCH 10/15] Add missing array shape to DuplicateResourceException --- src/Exception/DuplicateResourceException.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Exception/DuplicateResourceException.php b/src/Exception/DuplicateResourceException.php index 31b6da6..3bf93a0 100644 --- a/src/Exception/DuplicateResourceException.php +++ b/src/Exception/DuplicateResourceException.php @@ -8,7 +8,9 @@ class DuplicateResourceException extends HttpException { /** - * @param mixed $resourceIdentifier The duplicate resource identifier. + * @param scalar|\Stringable|null $resourceIdentifier The duplicate resource identifier. + * @param array $headers + * @param array $other */ public function __construct( TranslatableInterface|string $message, @@ -24,6 +26,7 @@ public function __construct( $resourceIdentifier = (string) $resourceIdentifier; } + // @phpstan-ignore-next-line function.alreadyNarrowedType if (null !== $resourceIdentifier && !\is_scalar($resourceIdentifier)) { throw new \InvalidArgumentException('The $resourceIdentifier must have a scalar value.'); } From 4f52e5ca6c3630862cb3eaf70021436c0f9b91a6 Mon Sep 17 00:00:00 2001 From: Daniel Burger <48986191+danielburger1337@users.noreply.github.com> Date: Sun, 2 Nov 2025 20:10:08 +0100 Subject: [PATCH 11/15] Ignore untyped config array in SBSEDVResponseBundle --- src/SBSEDVResponseBundle.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/SBSEDVResponseBundle.php b/src/SBSEDVResponseBundle.php index c728dcd..e55e140 100644 --- a/src/SBSEDVResponseBundle.php +++ b/src/SBSEDVResponseBundle.php @@ -17,6 +17,7 @@ public function configure(DefinitionConfigurator $definition): void $definition->import('../config/definitions/*.php'); } + // @phpstan-ignore-next-line missingType.iterableValue public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): void { if ($config['exception_normalizer'] === true) { From 3093a5e4e425c711940c731277a913871ab8bdb3 Mon Sep 17 00:00:00 2001 From: Daniel Burger <48986191+danielburger1337@users.noreply.github.com> Date: Sun, 2 Nov 2025 20:10:29 +0100 Subject: [PATCH 12/15] Add missing array shape to HttpException --- src/Exception/HttpException.php | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/Exception/HttpException.php b/src/Exception/HttpException.php index 1586cdb..34fba7e 100644 --- a/src/Exception/HttpException.php +++ b/src/Exception/HttpException.php @@ -14,14 +14,14 @@ class HttpException extends \Exception implements HttpExceptionInterface protected ?TranslatableInterface $translatable = null; /** - * @param TranslatableInterface|string $message The Exception message to throw. - * @param int $code [optional] The Exception code. - * @param \Throwable|null $previous [optional] The previous throwable used for the exception chaining. - * @param string|null $cause [optional] The error cause. - * @param array $headers [optional] Additional http response headers. - * @param array $other [optional] Additional error parameters. - * @param bool $isLoggable [optional] Whether the exception should be logged. - * @param string $logLevel [optional] The desired log level. + * @param TranslatableInterface|string $message The Exception message to throw. + * @param int $code [optional] The Exception code. + * @param \Throwable|null $previous [optional] The previous throwable used for the exception chaining. + * @param string|null $cause [optional] The error cause. + * @param array $headers [optional] Additional http response headers. + * @param array $other [optional] Additional error parameters. + * @param bool $isLoggable [optional] Whether the exception should be logged. + * @param string $logLevel [optional] The desired log level. */ public function __construct( TranslatableInterface|string $message, @@ -80,7 +80,9 @@ public function getType(): string } /** - * Get the extra data. + * The extra data. + * + * @return array */ public function getOther(): array { @@ -92,6 +94,9 @@ public function getStatusCode(): int return $this->code; } + /** + * @return array + */ public function getHeaders(): array { return $this->headers; From 9852acf2ea4e6af4be8410c428affab416064b90 Mon Sep 17 00:00:00 2001 From: Daniel Burger <48986191+danielburger1337@users.noreply.github.com> Date: Sun, 2 Nov 2025 20:10:45 +0100 Subject: [PATCH 13/15] Add missing array shapes to normalizers --- .../Normalizer/ApiResponseErrorNormalizer.php | 8 +++++++- src/Serializer/Normalizer/ApiResponseNormalizer.php | 8 +++++++- src/Serializer/Normalizer/HttpExceptionNormalizer.php | 10 ++++++++-- src/Serializer/Normalizer/LinkCollectionNormalizer.php | 8 +++++++- src/Serializer/Normalizer/LinkNormalizer.php | 8 +++++++- src/Serializer/Normalizer/ProblemNormalizer.php | 10 ++++++++-- 6 files changed, 44 insertions(+), 8 deletions(-) diff --git a/src/Serializer/Normalizer/ApiResponseErrorNormalizer.php b/src/Serializer/Normalizer/ApiResponseErrorNormalizer.php index e265542..a23936a 100644 --- a/src/Serializer/Normalizer/ApiResponseErrorNormalizer.php +++ b/src/Serializer/Normalizer/ApiResponseErrorNormalizer.php @@ -17,7 +17,10 @@ public function __construct( } /** - * @param ApiResponseErrorDto $object + * @param ApiResponseErrorDto $object + * @param array $context + * + * @return array */ public function normalize(mixed $object, ?string $format = null, array $context = []): array { @@ -43,6 +46,9 @@ public function normalize(mixed $object, ?string $format = null, array $context return $error; } + /** + * @param array $context + */ public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool { return $data instanceof ApiResponseErrorDto; diff --git a/src/Serializer/Normalizer/ApiResponseNormalizer.php b/src/Serializer/Normalizer/ApiResponseNormalizer.php index fc6086e..11aeae5 100644 --- a/src/Serializer/Normalizer/ApiResponseNormalizer.php +++ b/src/Serializer/Normalizer/ApiResponseNormalizer.php @@ -20,7 +20,10 @@ public function __construct( } /** - * @param ApiResponseDto $object + * @param ApiResponseDto $object + * @param array $context + * + * @return array */ public function normalize(mixed $object, ?string $format = null, array $context = []): array { @@ -38,6 +41,9 @@ public function normalize(mixed $object, ?string $format = null, array $context ]; } + /** + * @param array $context + */ public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool { return $data instanceof ApiResponseDto; diff --git a/src/Serializer/Normalizer/HttpExceptionNormalizer.php b/src/Serializer/Normalizer/HttpExceptionNormalizer.php index 611422f..6d44488 100644 --- a/src/Serializer/Normalizer/HttpExceptionNormalizer.php +++ b/src/Serializer/Normalizer/HttpExceptionNormalizer.php @@ -17,7 +17,10 @@ class HttpExceptionNormalizer implements NormalizerInterface, NormalizerAwareInt use NormalizerAwareTrait; /** - * @param FlattenException $object + * @param FlattenException $object + * @param array $context + * + * @return array */ public function normalize(mixed $object, ?string $format = null, array $context = []): array { @@ -44,10 +47,13 @@ public function normalize(mixed $object, ?string $format = null, array $context $response = new ApiResponseDto($message, null, $errors, $object->getStatusCode()); - // @phpstan-ignore-next-line + // @phpstan-ignore-next-line return.type return $this->normalizer->normalize($response, $format, $context); } + /** + * @param array $context + */ public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool { return $data instanceof FlattenException && isset($context['exception']) && $context['exception'] instanceof HttpException; diff --git a/src/Serializer/Normalizer/LinkCollectionNormalizer.php b/src/Serializer/Normalizer/LinkCollectionNormalizer.php index 5e04e8f..def2359 100644 --- a/src/Serializer/Normalizer/LinkCollectionNormalizer.php +++ b/src/Serializer/Normalizer/LinkCollectionNormalizer.php @@ -12,7 +12,10 @@ class LinkCollectionNormalizer implements NormalizerInterface, NormalizerAwareIn use NormalizerAwareTrait; /** - * @param LinkCollection $object + * @param LinkCollection $object + * @param array $context + * + * @return array */ public function normalize(mixed $object, ?string $format = null, array $context = []): array { @@ -25,6 +28,9 @@ public function normalize(mixed $object, ?string $format = null, array $context return $data; } + /** + * @param array $context + */ public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool { return $data instanceof LinkCollection; diff --git a/src/Serializer/Normalizer/LinkNormalizer.php b/src/Serializer/Normalizer/LinkNormalizer.php index 00505ab..1d22359 100644 --- a/src/Serializer/Normalizer/LinkNormalizer.php +++ b/src/Serializer/Normalizer/LinkNormalizer.php @@ -14,7 +14,10 @@ public function __construct( } /** - * @param Link $object + * @param Link $object + * @param array $context + * + * @return array */ public function normalize(mixed $object, ?string $format = null, array $context = []): array { @@ -27,6 +30,9 @@ public function normalize(mixed $object, ?string $format = null, array $context return [...$object->other, 'href' => $href]; } + /** + * @param array $context + */ public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool { return $data instanceof Link; diff --git a/src/Serializer/Normalizer/ProblemNormalizer.php b/src/Serializer/Normalizer/ProblemNormalizer.php index e07a015..2eb8e5a 100644 --- a/src/Serializer/Normalizer/ProblemNormalizer.php +++ b/src/Serializer/Normalizer/ProblemNormalizer.php @@ -24,7 +24,10 @@ public function __construct( } /** - * @param FlattenException $object + * @param FlattenException $object + * @param array $context + * + * @return array */ public function normalize(mixed $object, ?string $format = null, array $context = []): array { @@ -61,10 +64,13 @@ public function normalize(mixed $object, ?string $format = null, array $context $response = new ApiResponseDto($msg, null, [$error], $object->getStatusCode()); - // @phpstan-ignore-next-line + // @phpstan-ignore-next-line return.type return $this->normalizer->normalize($response, $format, $context); } + /** + * @param array $context + */ public function supportsNormalization(mixed $data, ?string $format = null, array $context = []): bool { return $data instanceof FlattenException && (!($context['exception'] ?? null) instanceof HttpException); From a6e0f8e537194480abf132a4cd8886f976969d4b Mon Sep 17 00:00:00 2001 From: Daniel Burger <48986191+danielburger1337@users.noreply.github.com> Date: Sun, 2 Nov 2025 20:11:09 +0100 Subject: [PATCH 14/15] Remove global ignore of "missingType.iterableValue" phpstan error --- phpstan.dist.neon | 3 --- 1 file changed, 3 deletions(-) diff --git a/phpstan.dist.neon b/phpstan.dist.neon index 9d59566..dbb01d3 100644 --- a/phpstan.dist.neon +++ b/phpstan.dist.neon @@ -4,6 +4,3 @@ parameters: paths: - src/ - config/ - - ignoreErrors: - - identifier: missingType.iterableValue From 0b35ec8c62c27b733ae1030093ab9527b9d82936 Mon Sep 17 00:00:00 2001 From: Daniel Burger <48986191+danielburger1337@users.noreply.github.com> Date: Sun, 2 Nov 2025 20:11:17 +0100 Subject: [PATCH 15/15] Add missing array shapes to ApiResponseFactory --- src/Response/ApiResponseFactory.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Response/ApiResponseFactory.php b/src/Response/ApiResponseFactory.php index 8bd688a..b193d3a 100644 --- a/src/Response/ApiResponseFactory.php +++ b/src/Response/ApiResponseFactory.php @@ -21,9 +21,9 @@ public function __construct( /** * Create an API response. * - * @param ApiResponseDto $apiResponseDto The ApiResponse DTO object. - * @param array $headers [optional] An array of headers that will be added to the response. - * @param array $context [optional] The serialization context. + * @param ApiResponseDto $apiResponseDto The ApiResponse DTO object. + * @param array $headers [optional] An array of headers that will be added to the response. + * @param array $context [optional] The serialization context. */ public function createApiResponse(ApiResponseDto $apiResponseDto, array $headers = [], array $context = []): Response {