From 9a7c9066b1d1c248e8ff24da97eea26ebfdb829b Mon Sep 17 00:00:00 2001 From: Christian Kolb Date: Mon, 18 Nov 2024 07:28:21 +0100 Subject: [PATCH] Extend and streamline parameters --- src/Command/CommandHandlerInterface.php | 4 +- src/Controller/CommandController.php | 41 ++++-- src/Controller/QueryController.php | 41 ++++-- .../SerializerDTOConstructor.php | 8 +- src/DTOValidator/DTOValidatorInterface.php | 11 +- .../CQSRoutingExtension.php | 20 +-- src/HandlerWrapper/DTO/HandlerWrapperStep.php | 23 ++- .../HandlerWrapperInterface.php | 13 +- src/HandlerWrapper/SilentExceptionWrapper.php | 12 +- src/Query/QueryHandlerInterface.php | 4 +- .../RequestDataTransformerInterface.php | 11 +- src/RequestDecoder/JsonRequestDecoder.php | 4 +- .../RequestValidatorInterface.php | 11 +- .../ResponseConstructorInterface.php | 4 +- .../SerializerJsonResponseConstructor.php | 4 +- .../StreamedResponseConstructor.php | 4 +- src/Routing/RouteBuilder.php | 71 +++++----- src/Routing/RoutePayload.php | 134 +++++++++--------- src/ServiceMap/ServiceMap.php | 32 +++-- 19 files changed, 282 insertions(+), 170 deletions(-) diff --git a/src/Command/CommandHandlerInterface.php b/src/Command/CommandHandlerInterface.php index 45eeb9d..6396a04 100644 --- a/src/Command/CommandHandlerInterface.php +++ b/src/Command/CommandHandlerInterface.php @@ -4,7 +4,9 @@ namespace DigitalCraftsman\CQSRouting\Command; -/** @method void __invoke(Command $command) */ +/** + * @method void __invoke(Command $command) + */ interface CommandHandlerInterface { } diff --git a/src/Controller/CommandController.php b/src/Controller/CommandController.php index 2c7edac..8dc6da1 100644 --- a/src/Controller/CommandController.php +++ b/src/Controller/CommandController.php @@ -19,16 +19,19 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +/** + * @psalm-import-type NormalizedConfigurationParameters from RoutePayload + */ final class CommandController extends AbstractController { /** - * @param array, scalar|array|null>|null $defaultRequestValidatorClasses - * @param class-string|null $defaultRequestDecoderClass - * @param array, scalar|array|null>|null $defaultRequestDataTransformerClasses - * @param class-string|null $defaultDTOConstructorClass - * @param array, scalar|array|null>|null $defaultDTOValidatorClasses - * @param array, scalar|array|null>|null $defaultHandlerWrapperClasses - * @param class-string|null $defaultResponseConstructorClass + * @param array, NormalizedConfigurationParameters>|null $defaultRequestValidatorClasses + * @param class-string|null $defaultRequestDecoderClass + * @param array, NormalizedConfigurationParameters>|null $defaultRequestDataTransformerClasses + * @param class-string|null $defaultDTOConstructorClass + * @param array, NormalizedConfigurationParameters>|null $defaultDTOValidatorClasses + * @param array, NormalizedConfigurationParameters>|null $defaultHandlerWrapperClasses + * @param class-string|null $defaultResponseConstructorClass * * @codeCoverageIgnore */ @@ -44,12 +47,16 @@ public function __construct( ) { } - /** We don't type the $routePayload because we never trigger it manually, it's only supplied through Symfony. */ + /** + * We don't type the $routePayload because we never trigger it manually, it's only supplied through Symfony. + */ public function handle( Request $request, array $routePayload, ): Response { - /** @psalm-suppress MixedArgumentTypeCoercion */ + /** + * @psalm-suppress MixedArgumentTypeCoercion + */ $configuration = RoutePayload::fromPayload($routePayload); // -- Validate request @@ -87,7 +94,9 @@ public function handle( $this->defaultDTOConstructorClass, ); - /** @var Command $command */ + /** + * @var Command $command + */ $command = $dtoConstructor->constructDTO($requestData, $configuration->dtoClass); // -- Validate command @@ -102,7 +111,9 @@ public function handle( } // -- Wrap handlers - /** The wrapper handlers are quite complex, so additional explanation can be found in @HandlerWrapperStep */ + /** + * The wrapper handlers are quite complex, so additional explanation can be found in @HandlerWrapperStep. + */ $handlerWrapperClasses = RoutePayload::mergeHandlerWrapperClassesFromRouteWithDefaults( $configuration->handlerWrapperClasses, $configuration->handlerWrapperClassesToMergeWithDefault, @@ -121,9 +132,13 @@ public function handle( try { // -- Trigger command through command handler - /** @psalm-suppress PossiblyInvalidArgument */ + /** + * @psalm-suppress PossiblyInvalidArgument + */ $commandHandler = $this->serviceMap->getCommandHandler($configuration->handlerClass); - /** @psalm-suppress InvalidFunctionCall */ + /** + * @psalm-suppress InvalidFunctionCall + */ $commandHandler($command); $handlerWrapperClassesForThenStep = HandlerWrapperStep::then($handlerWrapperClasses); diff --git a/src/Controller/QueryController.php b/src/Controller/QueryController.php index ab9dd57..60709bc 100644 --- a/src/Controller/QueryController.php +++ b/src/Controller/QueryController.php @@ -19,16 +19,19 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +/** + * @psalm-import-type NormalizedConfigurationParameters from RoutePayload + */ final class QueryController extends AbstractController { /** - * @param array, scalar|array|null>|null $defaultRequestValidatorClasses - * @param class-string|null $defaultRequestDecoderClass - * @param array, scalar|array|null>|null $defaultRequestDataTransformerClasses - * @param class-string|null $defaultDTOConstructorClass - * @param array, scalar|array|null>|null $defaultDTOValidatorClasses - * @param array, scalar|array|null>|null $defaultHandlerWrapperClasses - * @param class-string|null $defaultResponseConstructorClass + * @param array, NormalizedConfigurationParameters>|null $defaultRequestValidatorClasses + * @param class-string|null $defaultRequestDecoderClass + * @param array, NormalizedConfigurationParameters>|null $defaultRequestDataTransformerClasses + * @param class-string|null $defaultDTOConstructorClass + * @param array, NormalizedConfigurationParameters>|null $defaultDTOValidatorClasses + * @param array, NormalizedConfigurationParameters>|null $defaultHandlerWrapperClasses + * @param class-string|null $defaultResponseConstructorClass * * @codeCoverageIgnore */ @@ -44,12 +47,16 @@ public function __construct( ) { } - /** We don't type the $routePayload because we never trigger it manually, it's only supplied through Symfony. */ + /** + * We don't type the $routePayload because we never trigger it manually, it's only supplied through Symfony. + */ public function handle( Request $request, array $routePayload, ): Response { - /** @psalm-suppress MixedArgumentTypeCoercion */ + /** + * @psalm-suppress MixedArgumentTypeCoercion + */ $configuration = RoutePayload::fromPayload($routePayload); // -- Validate request @@ -87,7 +94,9 @@ public function handle( $this->defaultDTOConstructorClass, ); - /** @var Query $query */ + /** + * @var Query $query + */ $query = $dtoConstructor->constructDTO($requestData, $configuration->dtoClass); // -- Validate query @@ -102,7 +111,9 @@ public function handle( } // -- Wrap handlers - /** The wrapper handlers are quite complex, so additional explanation can be found in @HandlerWrapperStep */ + /** + * The wrapper handlers are quite complex, so additional explanation can be found in @HandlerWrapperStep. + */ $handlerWrapperClasses = RoutePayload::mergeHandlerWrapperClassesFromRouteWithDefaults( $configuration->handlerWrapperClasses, $configuration->handlerWrapperClassesToMergeWithDefault, @@ -120,13 +131,17 @@ public function handle( } // -- Trigger query through query handler - /** @psalm-suppress PossiblyInvalidArgument */ + /** + * @psalm-suppress PossiblyInvalidArgument + */ $queryHandler = $this->serviceMap->getQueryHandler($configuration->handlerClass); $result = null; try { - /** @psalm-suppress InvalidFunctionCall */ + /** + * @psalm-suppress InvalidFunctionCall + */ $result = $queryHandler($query); $handlerWrapperClassesForThenStep = HandlerWrapperStep::then($handlerWrapperClasses); diff --git a/src/DTOConstructor/SerializerDTOConstructor.php b/src/DTOConstructor/SerializerDTOConstructor.php index aa47a93..3fc3423 100644 --- a/src/DTOConstructor/SerializerDTOConstructor.php +++ b/src/DTOConstructor/SerializerDTOConstructor.php @@ -10,7 +10,9 @@ final readonly class SerializerDTOConstructor implements DTOConstructorInterface { - /** @codeCoverageIgnore */ + /** + * @codeCoverageIgnore + */ public function __construct( private DenormalizerInterface $serializer, ) { @@ -25,7 +27,9 @@ public function __construct( */ public function constructDTO(array $requestData, string $dtoClass): Command | Query { - /** @psalm-var T */ + /** + * @psalm-var T + */ return $this->serializer->denormalize($requestData, $dtoClass); } } diff --git a/src/DTOValidator/DTOValidatorInterface.php b/src/DTOValidator/DTOValidatorInterface.php index ce29c30..c960f8d 100644 --- a/src/DTOValidator/DTOValidatorInterface.php +++ b/src/DTOValidator/DTOValidatorInterface.php @@ -6,6 +6,7 @@ use DigitalCraftsman\CQSRouting\Command\Command; use DigitalCraftsman\CQSRouting\Query\Query; +use DigitalCraftsman\CQSRouting\Routing\RoutePayload; use Symfony\Component\HttpFoundation\Request; /** @@ -20,16 +21,22 @@ * * @see https://github.com/digital-craftsman-de/cqs-routing/blob/main/docs/process.md * @see https://github.com/digital-craftsman-de/cqs-routing/blob/main/docs/examples/dto-validator.md + * + * @psalm-import-type NormalizedConfigurationParameters from RoutePayload */ interface DTOValidatorInterface { - /** @param scalar|array|null $parameters */ + /** + * @param NormalizedConfigurationParameters $parameters + */ public function validateDTO( Request $request, Command | Query $dto, mixed $parameters, ): void; - /** @param scalar|array|null $parameters */ + /** + * @param NormalizedConfigurationParameters $parameters + */ public static function areParametersValid(mixed $parameters): bool; } diff --git a/src/DependencyInjection/CQSRoutingExtension.php b/src/DependencyInjection/CQSRoutingExtension.php index c901eb3..87cf797 100644 --- a/src/DependencyInjection/CQSRoutingExtension.php +++ b/src/DependencyInjection/CQSRoutingExtension.php @@ -14,11 +14,15 @@ use DigitalCraftsman\CQSRouting\RequestValidator\RequestValidatorInterface; use DigitalCraftsman\CQSRouting\ResponseConstructor\ResponseConstructorInterface; use DigitalCraftsman\CQSRouting\Routing\RouteBuilder; +use DigitalCraftsman\CQSRouting\Routing\RoutePayload; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Extension\Extension; use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; +/** + * @psalm-import-type NormalizedConfigurationParameters from RoutePayload + */ final class CQSRoutingExtension extends Extension { public function load(array $configs, ContainerBuilder $container): void @@ -67,21 +71,21 @@ public function load(array $configs, ContainerBuilder $container): void /** * @var array{ * query_controller: array{ - * default_request_validator_classes: array, scalar|array|null>|null, + * default_request_validator_classes: array, NormalizedConfigurationParameters>|null, * default_request_decoder_class: class-string|null, - * default_request_data_transformer_classes: array, scalar|array|null>|null, + * default_request_data_transformer_classes: array, NormalizedConfigurationParameters>|null, * default_dto_constructor_class: class-string|null, - * default_dto_validator_classes: array, scalar|array|null>|null, - * default_handler_wrapper_classes: array, scalar|array|null>|null, + * default_dto_validator_classes: array, NormalizedConfigurationParameters>|null, + * default_handler_wrapper_classes: array, NormalizedConfigurationParameters>|null, * default_response_constructor_class: class-string|null, * }, * command_controller: array{ - * default_request_validator_classes: array, scalar|array|null>|null, + * default_request_validator_classes: array, NormalizedConfigurationParameters>|null, * default_request_decoder_class: class-string|null, - * default_request_data_transformer_classes: array, scalar|array|null>|null, + * default_request_data_transformer_classes: array, NormalizedConfigurationParameters>|null, * default_dto_constructor_class: class-string|null, - * default_dto_validator_classes: array, scalar|array|null>|null, - * default_handler_wrapper_classes: array, scalar|array|null>|null, + * default_dto_validator_classes: array, NormalizedConfigurationParameters>|null, + * default_handler_wrapper_classes: array, NormalizedConfigurationParameters>|null, * default_response_constructor_class: class-string|null, * }, * } $config diff --git a/src/HandlerWrapper/DTO/HandlerWrapperStep.php b/src/HandlerWrapper/DTO/HandlerWrapperStep.php index 4e01973..c2cfcd8 100644 --- a/src/HandlerWrapper/DTO/HandlerWrapperStep.php +++ b/src/HandlerWrapper/DTO/HandlerWrapperStep.php @@ -5,6 +5,7 @@ namespace DigitalCraftsman\CQSRouting\HandlerWrapper\DTO; use DigitalCraftsman\CQSRouting\HandlerWrapper\HandlerWrapperInterface; +use DigitalCraftsman\CQSRouting\Routing\RoutePayload; /** * Handler wrappers are used to wrap command handlers and query handlers. With them, it's possible to for example start a doctrine @@ -14,6 +15,8 @@ * To wrap this logic we first combine the wrappers with the parameters and then sort them by the priority of the handlers for the separate * steps. After this the controller is able to simply select a step and get all relevant wrappers in the correct order. * + * @psalm-import-type NormalizedConfigurationParameters from RoutePayload + * * @codeCoverageIgnore * * @internal @@ -24,12 +27,14 @@ public const STEP_THEN = 'THEN'; public const STEP_CATCH = 'CATCH'; - /** @var array, scalar|array|null> */ + /** + * @var array, NormalizedConfigurationParameters> + */ public array $orderedHandlerWrapperClasses; /** - * @param array, scalar|array|null> $handlerWrapperClasses - * @param self::STEP_* $step + * @param array, NormalizedConfigurationParameters> $handlerWrapperClasses + * @param self::STEP_* $step */ private function __construct( array $handlerWrapperClasses, @@ -51,7 +56,9 @@ private function __construct( $this->orderedHandlerWrapperClasses = $handlerWrapperClasses; } - /** @param array, scalar|array|null> $handlerWrapperClasses */ + /** + * @param array, NormalizedConfigurationParameters> $handlerWrapperClasses + */ public static function prepare(array $handlerWrapperClasses): self { return new self( @@ -60,7 +67,9 @@ public static function prepare(array $handlerWrapperClasses): self ); } - /** @param array, scalar|array|null> $handlerWrapperClasses */ + /** + * @param array, NormalizedConfigurationParameters> $handlerWrapperClasses + */ public static function then(array $handlerWrapperClasses): self { return new self( @@ -69,7 +78,9 @@ public static function then(array $handlerWrapperClasses): self ); } - /** @param array, scalar|array|null> $handlerWrapperClasses */ + /** + * @param array, NormalizedConfigurationParameters> $handlerWrapperClasses + */ public static function catch(array $handlerWrapperClasses): self { return new self( diff --git a/src/HandlerWrapper/HandlerWrapperInterface.php b/src/HandlerWrapper/HandlerWrapperInterface.php index 51bd0fd..f8dd7de 100644 --- a/src/HandlerWrapper/HandlerWrapperInterface.php +++ b/src/HandlerWrapper/HandlerWrapperInterface.php @@ -6,6 +6,7 @@ use DigitalCraftsman\CQSRouting\Command\Command; use DigitalCraftsman\CQSRouting\Query\Query; +use DigitalCraftsman\CQSRouting\Routing\RoutePayload; use Symfony\Component\HttpFoundation\Request; /** @@ -27,13 +28,15 @@ * * @see https://github.com/digital-craftsman-de/cqs-routing/blob/main/docs/process.md * @see https://github.com/digital-craftsman-de/cqs-routing/blob/main/docs/examples/handler-wrapper.md + * + * @psalm-import-type NormalizedConfigurationParameters from RoutePayload */ interface HandlerWrapperInterface { /** * Triggered right before the handler is triggered. * - * @param scalar|array|null $parameters + * @param NormalizedConfigurationParameters $parameters */ public function prepare( Command | Query $dto, @@ -44,7 +47,7 @@ public function prepare( /** * Triggered only if the handler was run without exception. * - * @param scalar|array|null $parameters + * @param NormalizedConfigurationParameters $parameters */ public function then( Command | Query $dto, @@ -56,7 +59,7 @@ public function then( * Triggered only when an exception occurred while executing the handler. * The exception must be returned if it's not explicitly the last exception that should be handled. * - * @param scalar|array|null $parameters + * @param NormalizedConfigurationParameters $parameters */ public function catch( Command | Query $dto, @@ -71,6 +74,8 @@ public static function thenPriority(): int; public static function catchPriority(): int; - /** @param scalar|array|null $parameters */ + /** + * @param NormalizedConfigurationParameters $parameters + */ public static function areParametersValid(mixed $parameters): bool; } diff --git a/src/HandlerWrapper/SilentExceptionWrapper.php b/src/HandlerWrapper/SilentExceptionWrapper.php index 0450d2f..6c2c825 100644 --- a/src/HandlerWrapper/SilentExceptionWrapper.php +++ b/src/HandlerWrapper/SilentExceptionWrapper.php @@ -31,7 +31,9 @@ public function prepare( // Nothing to do } - /** @param array $parameters Exception class strings to be swallowed */ + /** + * @param array $parameters Exception class strings to be swallowed + */ #[\Override] public function catch( Command | Query $dto, @@ -90,7 +92,9 @@ public static function thenPriority(): int return 0; } - /** @param array> $parameters Needs to be at least one exception class */ + /** + * @param array> $parameters Needs to be at least one exception class + */ #[\Override] public static function areParametersValid(mixed $parameters): bool { @@ -108,7 +112,9 @@ public static function areParametersValid(mixed $parameters): bool } $reflectionClass = new \ReflectionClass($exceptionClass); - /** @psalm-suppress TypeDoesNotContainType It's possible that someone puts in something other than an exception. */ + /** + * @psalm-suppress TypeDoesNotContainType It's possible that someone puts in something other than an exception. + */ if (!$reflectionClass->implementsInterface(\Throwable::class)) { return false; } diff --git a/src/Query/QueryHandlerInterface.php b/src/Query/QueryHandlerInterface.php index 06d02f6..94082c3 100644 --- a/src/Query/QueryHandlerInterface.php +++ b/src/Query/QueryHandlerInterface.php @@ -4,7 +4,9 @@ namespace DigitalCraftsman\CQSRouting\Query; -/** @method mixed __invoke(Query $query) */ +/** + * @method mixed __invoke(Query $query) + */ interface QueryHandlerInterface { } diff --git a/src/RequestDataTransformer/RequestDataTransformerInterface.php b/src/RequestDataTransformer/RequestDataTransformerInterface.php index ae1ebde..a4cb038 100644 --- a/src/RequestDataTransformer/RequestDataTransformerInterface.php +++ b/src/RequestDataTransformer/RequestDataTransformerInterface.php @@ -6,6 +6,7 @@ use DigitalCraftsman\CQSRouting\Command\Command; use DigitalCraftsman\CQSRouting\Query\Query; +use DigitalCraftsman\CQSRouting\Routing\RoutePayload; /** * The data transformer can have three kinds of tasks and multiple data transformers can be used with one request. @@ -17,12 +18,14 @@ * * @see https://github.com/digital-craftsman-de/cqs-routing/blob/main/docs/process.md * @see https://github.com/digital-craftsman-de/cqs-routing/blob/main/docs/examples/request-data-transformer.md + * + * @psalm-import-type NormalizedConfigurationParameters from RoutePayload */ interface RequestDataTransformerInterface { /** - * @param class-string $dtoClass - * @param scalar|array|null $parameters + * @param class-string $dtoClass + * @param NormalizedConfigurationParameters $parameters */ public function transformRequestData( string $dtoClass, @@ -30,6 +33,8 @@ public function transformRequestData( mixed $parameters, ): array; - /** @param scalar|array|null $parameters */ + /** + * @param NormalizedConfigurationParameters $parameters + */ public static function areParametersValid(mixed $parameters): bool; } diff --git a/src/RequestDecoder/JsonRequestDecoder.php b/src/RequestDecoder/JsonRequestDecoder.php index 83fbadf..9eaee0e 100644 --- a/src/RequestDecoder/JsonRequestDecoder.php +++ b/src/RequestDecoder/JsonRequestDecoder.php @@ -10,7 +10,9 @@ { public function decodeRequest(Request $request): array { - /** @var string $content */ + /** + * @var string $content + */ $content = $request->getContent(); return (array) json_decode($content, true, 512, JSON_THROW_ON_ERROR); diff --git a/src/RequestValidator/RequestValidatorInterface.php b/src/RequestValidator/RequestValidatorInterface.php index 76fc988..fb552cb 100644 --- a/src/RequestValidator/RequestValidatorInterface.php +++ b/src/RequestValidator/RequestValidatorInterface.php @@ -4,6 +4,7 @@ namespace DigitalCraftsman\CQSRouting\RequestValidator; +use DigitalCraftsman\CQSRouting\Routing\RoutePayload; use Symfony\Component\HttpFoundation\Request; /** @@ -19,15 +20,21 @@ * * @see https://github.com/digital-craftsman-de/cqs-routing/blob/main/docs/process.md * @see https://github.com/digital-craftsman-de/cqs-routing/blob/main/docs/examples/request-validator.md + * + * @psalm-import-type NormalizedConfigurationParameters from RoutePayload */ interface RequestValidatorInterface { - /** @param scalar|array|null $parameters */ + /** + * @param NormalizedConfigurationParameters $parameters + */ public function validateRequest( Request $request, mixed $parameters, ): void; - /** @param scalar|array|null $parameters */ + /** + * @param NormalizedConfigurationParameters $parameters + */ public static function areParametersValid(mixed $parameters): bool; } diff --git a/src/ResponseConstructor/ResponseConstructorInterface.php b/src/ResponseConstructor/ResponseConstructorInterface.php index c1dac55..31f6731 100644 --- a/src/ResponseConstructor/ResponseConstructorInterface.php +++ b/src/ResponseConstructor/ResponseConstructorInterface.php @@ -19,6 +19,8 @@ */ interface ResponseConstructorInterface { - /** @param ?mixed $data */ + /** + * @param ?mixed $data + */ public function constructResponse($data, Request $request): Response; } diff --git a/src/ResponseConstructor/SerializerJsonResponseConstructor.php b/src/ResponseConstructor/SerializerJsonResponseConstructor.php index 1f2068a..ac69888 100644 --- a/src/ResponseConstructor/SerializerJsonResponseConstructor.php +++ b/src/ResponseConstructor/SerializerJsonResponseConstructor.php @@ -12,7 +12,9 @@ final readonly class SerializerJsonResponseConstructor implements ResponseConstructorInterface { - /** @codeCoverageIgnore */ + /** + * @codeCoverageIgnore + */ public function __construct( private SerializerInterface $serializer, ) { diff --git a/src/ResponseConstructor/StreamedResponseConstructor.php b/src/ResponseConstructor/StreamedResponseConstructor.php index 5217789..3d12357 100644 --- a/src/ResponseConstructor/StreamedResponseConstructor.php +++ b/src/ResponseConstructor/StreamedResponseConstructor.php @@ -10,7 +10,9 @@ final readonly class StreamedResponseConstructor implements ResponseConstructorInterface { - /** @param callable $data */ + /** + * @param callable $data + */ public function constructResponse($data, Request $request): Response { return new StreamedResponse($data); diff --git a/src/Routing/RouteBuilder.php b/src/Routing/RouteBuilder.php index 9126ccf..ff99dec 100644 --- a/src/Routing/RouteBuilder.php +++ b/src/Routing/RouteBuilder.php @@ -32,6 +32,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; +/** + * @psalm-import-type NormalizedConfigurationParameters from RoutePayload + */ final readonly class RouteBuilder { private const DEFAULT_METHOD = Request::METHOD_POST; @@ -41,19 +44,19 @@ * Default name is generated from path. Set it specifically when you're using the name as a reference somewhere. * Default method is POST. * - * @param class-string|class-string $dtoClass - * @param class-string|class-string $handlerClass - * @param array, scalar|array|null>|null $requestValidatorClasses - * @param array, scalar|array|null>|null $requestValidatorClassesToMergeWithDefault - * @param class-string|null $requestDecoderClass - * @param array, scalar|array|null>|null $requestDataTransformerClasses - * @param array, scalar|array|null>|null $requestDataTransformerClassesToMergeWithDefault - * @param class-string|null $dtoConstructorClass - * @param array, scalar|array|null>|null $dtoValidatorClasses - * @param array, scalar|array|null>|null $dtoValidatorClassesToMergeWithDefault - * @param array, scalar|array|null>|null $handlerWrapperClasses - * @param array, scalar|array|null>|null $handlerWrapperClassesToMergeWithDefault - * @param class-string|null $responseConstructorClass + * @param class-string|class-string $dtoClass + * @param class-string|class-string $handlerClass + * @param array, NormalizedConfigurationParameters>|null $requestValidatorClasses + * @param array, NormalizedConfigurationParameters>|null $requestValidatorClassesToMergeWithDefault + * @param class-string|null $requestDecoderClass + * @param array, NormalizedConfigurationParameters>|null $requestDataTransformerClasses + * @param array, NormalizedConfigurationParameters>|null $requestDataTransformerClassesToMergeWithDefault + * @param class-string|null $dtoConstructorClass + * @param array, NormalizedConfigurationParameters>|null $dtoValidatorClasses + * @param array, NormalizedConfigurationParameters>|null $dtoValidatorClassesToMergeWithDefault + * @param array, NormalizedConfigurationParameters>|null $handlerWrapperClasses + * @param array, NormalizedConfigurationParameters>|null $handlerWrapperClassesToMergeWithDefault + * @param class-string|null $responseConstructorClass * * @codeCoverageIgnore * There seems to be no way to get a RoutingConfigurator instance. Therefore, it's not really possible to test this builder. @@ -137,19 +140,19 @@ public static function addQueryRoute( * Default name is generated from path. Set it specifically when you're using the name as a reference somewhere. * Default method is POST. * - * @param class-string|class-string $dtoClass - * @param class-string|class-string $handlerClass - * @param array, scalar|array|null>|null $requestValidatorClasses - * @param array, scalar|array|null>|null $requestValidatorClassesToMergeWithDefault - * @param class-string|null $requestDecoderClass - * @param array, scalar|array|null>|null $requestDataTransformerClasses - * @param array, scalar|array|null>|null $requestDataTransformerClassesToMergeWithDefault - * @param class-string|null $dtoConstructorClass - * @param array, scalar|array|null>|null $dtoValidatorClasses - * @param array, scalar|array|null>|null $dtoValidatorClassesToMergeWithDefault - * @param array, scalar|array|null>|null $handlerWrapperClasses - * @param array, scalar|array|null>|null $handlerWrapperClassesToMergeWithDefault - * @param class-string|null $responseConstructorClass + * @param class-string|class-string $dtoClass + * @param class-string|class-string $handlerClass + * @param array, NormalizedConfigurationParameters>|null $requestValidatorClasses + * @param array, NormalizedConfigurationParameters>|null $requestValidatorClassesToMergeWithDefault + * @param class-string|null $requestDecoderClass + * @param array, NormalizedConfigurationParameters>|null $requestDataTransformerClasses + * @param array, NormalizedConfigurationParameters>|null $requestDataTransformerClassesToMergeWithDefault + * @param class-string|null $dtoConstructorClass + * @param array, NormalizedConfigurationParameters>|null $dtoValidatorClasses + * @param array, NormalizedConfigurationParameters>|null $dtoValidatorClassesToMergeWithDefault + * @param array, NormalizedConfigurationParameters>|null $handlerWrapperClasses + * @param array, NormalizedConfigurationParameters>|null $handlerWrapperClassesToMergeWithDefault + * @param class-string|null $responseConstructorClass * * @codeCoverageIgnore * There seems to be no way to get a RoutingConfigurator instance. Therefore, it's not really possible to test this builder. @@ -284,8 +287,8 @@ public static function validateHandlerClass(string $handlerClass): void } /** - * @param array, scalar|array|null>|null $requestValidatorClasses - * @param array, scalar|array|null>|null $requestValidatorClassesToMergeWithDefault + * @param array, NormalizedConfigurationParameters>|null $requestValidatorClasses + * @param array, NormalizedConfigurationParameters>|null $requestValidatorClassesToMergeWithDefault * * @internal */ @@ -351,8 +354,8 @@ public static function validateRequestDecoderClass(?string $requestDecoderClass) } /** - * @param array, scalar|array|null>|null $requestDataTransformerClasses - * @param array, scalar|array|null>|null $requestDataTransformerClassesToMergeWithDefault + * @param array, NormalizedConfigurationParameters>|null $requestDataTransformerClasses + * @param array, NormalizedConfigurationParameters>|null $requestDataTransformerClassesToMergeWithDefault * * @internal */ @@ -418,8 +421,8 @@ public static function validateDTOConstructorClass(?string $dtoConstructorClass) } /** - * @param array, scalar|array|null>|null $dtoValidatorClasses - * @param array, scalar|array|null>|null $dtoValidatorClassesToMergeWithDefault + * @param array, NormalizedConfigurationParameters>|null $dtoValidatorClasses + * @param array, NormalizedConfigurationParameters>|null $dtoValidatorClassesToMergeWithDefault * * @internal */ @@ -465,8 +468,8 @@ public static function validateDTOValidatorClasses( } /** - * @param array, scalar|array|null>|null $handlerWrapperClasses - * @param array, scalar|array|null>|null $handlerWrapperClassesToMergeWithDefault + * @param array, NormalizedConfigurationParameters>|null $handlerWrapperClasses + * @param array, NormalizedConfigurationParameters>|null $handlerWrapperClassesToMergeWithDefault * * @internal */ diff --git a/src/Routing/RoutePayload.php b/src/Routing/RoutePayload.php index 7d05b61..046194e 100644 --- a/src/Routing/RoutePayload.php +++ b/src/Routing/RoutePayload.php @@ -19,23 +19,25 @@ /** * The symfony routing does not support the usage of objects as it has to dump them into a php file for caching. Therefore, we create an * object and convert into and from an array. The validation is done through the RouteBuilder at build time (cache warmup). + * + * @psalm-type NormalizedConfigurationParameters = scalar|array|null>|null */ final readonly class RoutePayload { /** - * @param class-string|class-string $dtoClass - * @param class-string|class-string $handlerClass - * @param array, scalar|array|null>|null $requestValidatorClasses - * @param array, scalar|array|null>|null $requestValidatorClassesToMergeWithDefault - * @param class-string|null $requestDecoderClass - * @param array, scalar|array|null>|null $requestDataTransformerClasses - * @param array, scalar|array|null>|null $requestDataTransformerClassesToMergeWithDefault - * @param class-string|null $dtoConstructorClass - * @param array, scalar|array|null>|null $dtoValidatorClasses - * @param array, scalar|array|null>|null $dtoValidatorClassesToMergeWithDefault - * @param array, scalar|array|null>|null $handlerWrapperClasses - * @param array, scalar|array|null>|null $handlerWrapperClassesToMergeWithDefault - * @param class-string|null $responseConstructorClass + * @param class-string|class-string $dtoClass + * @param class-string|class-string $handlerClass + * @param array, NormalizedConfigurationParameters>|null $requestValidatorClasses + * @param array, NormalizedConfigurationParameters>|null $requestValidatorClassesToMergeWithDefault + * @param class-string|null $requestDecoderClass + * @param array, NormalizedConfigurationParameters>|null $requestDataTransformerClasses + * @param array, NormalizedConfigurationParameters>|null $requestDataTransformerClassesToMergeWithDefault + * @param class-string|null $dtoConstructorClass + * @param array, NormalizedConfigurationParameters>|null $dtoValidatorClasses + * @param array, NormalizedConfigurationParameters>|null $dtoValidatorClassesToMergeWithDefault + * @param array, NormalizedConfigurationParameters>|null $handlerWrapperClasses + * @param array, NormalizedConfigurationParameters>|null $handlerWrapperClassesToMergeWithDefault + * @param class-string|null $responseConstructorClass */ private function __construct( public string $dtoClass, @@ -55,35 +57,35 @@ private function __construct( } /** - * @param class-string|class-string $dtoClass - * @param class-string|class-string $handlerClass - * @param array, scalar|array|null>|null $requestValidatorClasses - * @param array, scalar|array|null>|null $requestValidatorClassesToMergeWithDefault - * @param class-string|null $requestDecoderClass - * @param array, scalar|array|null>|null $requestDataTransformerClasses - * @param array, scalar|array|null>|null $requestDataTransformerClassesToMergeWithDefault - * @param class-string|null $dtoConstructorClass - * @param array, scalar|array|null>|null $dtoValidatorClasses - * @param array, scalar|array|null>|null $dtoValidatorClassesToMergeWithDefault - * @param array, scalar|array|null>|null $handlerWrapperClasses - * @param array, scalar|array|null>|null $handlerWrapperClassesToMergeWithDefault - * @param class-string|null $responseConstructorClass + * @param class-string|class-string $dtoClass + * @param class-string|class-string $handlerClass + * @param array, NormalizedConfigurationParameters>|null $requestValidatorClasses + * @param array, NormalizedConfigurationParameters>|null $requestValidatorClassesToMergeWithDefault + * @param class-string|null $requestDecoderClass + * @param array, NormalizedConfigurationParameters>|null $requestDataTransformerClasses + * @param array, NormalizedConfigurationParameters>|null $requestDataTransformerClassesToMergeWithDefault + * @param class-string|null $dtoConstructorClass + * @param array, NormalizedConfigurationParameters>|null $dtoValidatorClasses + * @param array, NormalizedConfigurationParameters>|null $dtoValidatorClassesToMergeWithDefault + * @param array, NormalizedConfigurationParameters>|null $handlerWrapperClasses + * @param array, NormalizedConfigurationParameters>|null $handlerWrapperClassesToMergeWithDefault + * @param class-string|null $responseConstructorClass * * @internal * * @return array{ * dtoClass: class-string|class-string, * handlerClass: class-string|class-string, - * requestValidatorClasses: array, scalar|array|null>, - * requestValidatorClassesToMergeWithDefault: array, scalar|array|null>, + * requestValidatorClasses: array, NormalizedConfigurationParameters>, + * requestValidatorClassesToMergeWithDefault: array, NormalizedConfigurationParameters>, * requestDecoderClass: class-string|null, - * requestDataTransformerClasses: array, scalar|array|null>, - * requestDataTransformerClassesToMergeWithDefault: array, scalar|array|null>, + * requestDataTransformerClasses: array, NormalizedConfigurationParameters>, + * requestDataTransformerClassesToMergeWithDefault: array, NormalizedConfigurationParameters>, * dtoConstructorClass: class-string|null, - * dtoValidatorClasses: array, scalar|array|null>, - * dtoValidatorClassesToMergeWithDefault: array, scalar|array|null>, - * handlerWrapperClasses: array, scalar|array|null>, - * handlerWrapperClassesToMergeWithDefault: array, scalar|array|null>, + * dtoValidatorClasses: array, NormalizedConfigurationParameters>, + * dtoValidatorClassesToMergeWithDefault: array, NormalizedConfigurationParameters>, + * handlerWrapperClasses: array, NormalizedConfigurationParameters>, + * handlerWrapperClassesToMergeWithDefault: array, NormalizedConfigurationParameters>, * responseConstructorClass: class-string|null, * } */ @@ -125,16 +127,16 @@ public static function generatePayload( * @param array{ * dtoClass: class-string|class-string, * handlerClass: class-string|class-string, - * requestValidatorClasses: array, scalar|array|null>|null, - * requestValidatorClassesToMergeWithDefault: array, scalar|array|null>|null, + * requestValidatorClasses: array, NormalizedConfigurationParameters>|null, + * requestValidatorClassesToMergeWithDefault: array, NormalizedConfigurationParameters>|null, * requestDecoderClass: class-string|null, - * requestDataTransformerClasses: array, scalar|array|null>|null, - * requestDataTransformerClassesToMergeWithDefault: array, scalar|array|null>|null, + * requestDataTransformerClasses: array, NormalizedConfigurationParameters>|null, + * requestDataTransformerClassesToMergeWithDefault: array, NormalizedConfigurationParameters>|null, * dtoConstructorClass: class-string|null, - * dtoValidatorClasses: array, scalar|array|null>|null, - * dtoValidatorClassesToMergeWithDefault: array, scalar|array|null>|null, - * handlerWrapperClasses: array, scalar|array|null>|null, - * handlerWrapperClassesToMergeWithDefault: array, scalar|array|null>|null, + * dtoValidatorClasses: array, NormalizedConfigurationParameters>|null, + * dtoValidatorClassesToMergeWithDefault: array, NormalizedConfigurationParameters>|null, + * handlerWrapperClasses: array, NormalizedConfigurationParameters>|null, + * handlerWrapperClassesToMergeWithDefault: array, NormalizedConfigurationParameters>|null, * responseConstructorClass: class-string|null, * } $payload * @@ -163,16 +165,16 @@ public static function fromPayload(array $payload): self * @return array{ * dtoClass: class-string|class-string, * handlerClass: class-string|class-string, - * requestValidatorClasses: array, scalar|array|null>, - * requestValidatorClassesToMergeWithDefault: array, scalar|array|null>, + * requestValidatorClasses: array, NormalizedConfigurationParameters>, + * requestValidatorClassesToMergeWithDefault: array, NormalizedConfigurationParameters>, * requestDecoderClass: class-string|null, - * requestDataTransformerClasses: array, scalar|array|null>, - * requestDataTransformerClassesToMergeWithDefault: array, scalar|array|null>, + * requestDataTransformerClasses: array, NormalizedConfigurationParameters>, + * requestDataTransformerClassesToMergeWithDefault: array, NormalizedConfigurationParameters>, * dtoConstructorClass: class-string|null, - * dtoValidatorClasses: array, scalar|array|null>, - * dtoValidatorClassesToMergeWithDefault: array, scalar|array|null>, - * handlerWrapperClasses: array, scalar|array|null>, - * handlerWrapperClassesToMergeWithDefault: array, scalar|array|null>, + * dtoValidatorClasses: array, NormalizedConfigurationParameters>, + * dtoValidatorClassesToMergeWithDefault: array, NormalizedConfigurationParameters>, + * handlerWrapperClasses: array, NormalizedConfigurationParameters>, + * handlerWrapperClassesToMergeWithDefault: array, NormalizedConfigurationParameters>, * responseConstructorClass: class-string|null, * } * @@ -202,11 +204,11 @@ private function toPayload(): array * Otherwise, the ones from the route that should be merged with default are merged with the default. The parameters of the list to * merge with default are used when the same class is used in the default and the ones to merge. * - * @param array, scalar|array|null>|null $classesFromRoute - * @param array, scalar|array|null>|null $classesFromRouteToMergeWithDefault - * @param array, scalar|array|null>|null $classesFromDefault + * @param array, NormalizedConfigurationParameters>|null $classesFromRoute + * @param array, NormalizedConfigurationParameters>|null $classesFromRouteToMergeWithDefault + * @param array, NormalizedConfigurationParameters>|null $classesFromDefault * - * @return array, scalar|array|null> + * @return array, NormalizedConfigurationParameters> * * @internal * @@ -228,11 +230,11 @@ public static function mergeRequestValidatorClassesFromRouteWithDefaults( * Otherwise, the ones from the route that should be merged with default are merged with the default. The parameters of the list to * merge with default are used when the same class is used in the default and the ones to merge. * - * @param array, scalar|array|null>|null $classesFromRoute - * @param array, scalar|array|null>|null $classesFromRouteToMergeWithDefault - * @param array, scalar|array|null>|null $classesFromDefault + * @param array, NormalizedConfigurationParameters>|null $classesFromRoute + * @param array, NormalizedConfigurationParameters>|null $classesFromRouteToMergeWithDefault + * @param array, NormalizedConfigurationParameters>|null $classesFromDefault * - * @return array, scalar|array|null> + * @return array, NormalizedConfigurationParameters> * * @internal * @@ -254,11 +256,11 @@ public static function mergeRequestDataTransformerClassesFromRouteWithDefaults( * Otherwise, the ones from the route that should be merged with default are merged with the default. The parameters of the list to * merge with default are used when the same class is used in the default and the ones to merge. * - * @param array, scalar|array|null>|null $classesFromRoute - * @param array, scalar|array|null>|null $classesFromRouteToMergeWithDefault - * @param array, scalar|array|null>|null $classesFromDefault + * @param array, NormalizedConfigurationParameters>|null $classesFromRoute + * @param array, NormalizedConfigurationParameters>|null $classesFromRouteToMergeWithDefault + * @param array, NormalizedConfigurationParameters>|null $classesFromDefault * - * @return array, scalar|array|null> + * @return array, NormalizedConfigurationParameters> * * @internal * @@ -280,11 +282,11 @@ public static function mergeDTOValidatorClassesFromRouteWithDefaults( * Otherwise, the ones from the route that should be merged with default are merged with the default. The parameters of the list to * merge with default are used when the same class is used in the default and the ones to merge. * - * @param array, scalar|array|null>|null $classesFromRoute - * @param array, scalar|array|null>|null $classesFromRouteToMergeWithDefault - * @param array, scalar|array|null>|null $classesFromDefault + * @param array, NormalizedConfigurationParameters>|null $classesFromRoute + * @param array, NormalizedConfigurationParameters>|null $classesFromRouteToMergeWithDefault + * @param array, NormalizedConfigurationParameters>|null $classesFromDefault * - * @return array, scalar|array|null> + * @return array, NormalizedConfigurationParameters> * * @internal */ diff --git a/src/ServiceMap/ServiceMap.php b/src/ServiceMap/ServiceMap.php index 052f782..a0281f8 100644 --- a/src/ServiceMap/ServiceMap.php +++ b/src/ServiceMap/ServiceMap.php @@ -29,7 +29,9 @@ use Psr\Container\NotFoundExceptionInterface; use Symfony\Contracts\Service\ServiceProviderInterface; -/** @internal */ +/** + * @internal + */ final readonly class ServiceMap { public function __construct( @@ -45,7 +47,9 @@ public function __construct( ) { } - /** @param class-string $requestValidatorClass */ + /** + * @param class-string $requestValidatorClass + */ public function getRequestValidator(string $requestValidatorClass): RequestValidatorInterface { try { @@ -73,7 +77,9 @@ public function getRequestDecoder(?string $requestDecoderClass, ?string $default } } - /** @param class-string $requestDataTransformerClass */ + /** + * @param class-string $requestDataTransformerClass + */ public function getRequestDataTransformer(string $requestDataTransformerClass): RequestDataTransformerInterface { try { @@ -101,7 +107,9 @@ public function getDTOConstructor(?string $dtoConstructorClass, ?string $default } } - /** @param class-string $dtoValidatorClass */ + /** + * @param class-string $dtoValidatorClass + */ public function getDTOValidator(string $dtoValidatorClass): DTOValidatorInterface { try { @@ -111,7 +119,9 @@ public function getDTOValidator(string $dtoValidatorClass): DTOValidatorInterfac } } - /** @param class-string $handlerWrapperClass */ + /** + * @param class-string $handlerWrapperClass + */ public function getHandlerWrapper(string $handlerWrapperClass): HandlerWrapperInterface { try { @@ -121,7 +131,9 @@ public function getHandlerWrapper(string $handlerWrapperClass): HandlerWrapperIn } } - /** @param class-string $handlerClass */ + /** + * @param class-string $handlerClass + */ public function getCommandHandler(string $handlerClass): CommandHandlerInterface { try { @@ -131,7 +143,9 @@ public function getCommandHandler(string $handlerClass): CommandHandlerInterface } } - /** @param class-string $handlerClass */ + /** + * @param class-string $handlerClass + */ public function getQueryHandler(string $handlerClass): QueryHandlerInterface { try { @@ -141,7 +155,9 @@ public function getQueryHandler(string $handlerClass): QueryHandlerInterface } } - /** @param class-string $responseConstructorClass */ + /** + * @param class-string $responseConstructorClass + */ public function getResponseConstructor( ?string $responseConstructorClass, ?string $defaultResponseConstructorClass,