diff --git a/Classes/Application/ParameterFactory.php b/Classes/Application/ParameterFactory.php index 5b0f7f1..7bda268 100644 --- a/Classes/Application/ParameterFactory.php +++ b/Classes/Application/ParameterFactory.php @@ -8,6 +8,7 @@ use Neos\Flow\ObjectManagement\Proxy\ProxyInterface; use Sitegeist\SchemeOnYou\Domain\Metadata\Parameter as ParameterAttribute; use Sitegeist\SchemeOnYou\Domain\Metadata\RequestBody; +use Sitegeist\SchemeOnYou\Domain\Path\NoSuchParameter; use Sitegeist\SchemeOnYou\Domain\Schema\SchemaDenormalizer; class ParameterFactory @@ -37,18 +38,20 @@ public static function resolveParameters(string $className, string $methodName, $requestBodyAttribute = RequestBody::tryFromReflectionParameter($parameter); if ($requestBodyAttribute) { $parameterValueFromRequest = $requestBodyAttribute->contentType->resolveParameterFromRequest($request, $parameter->name); - $parameterValueFromRequest = $requestBodyAttribute->contentType->decodeParameterValue($parameterValueFromRequest); + if (!$parameterValueFromRequest instanceof NoSuchParameter) { + $parameterValueFromRequest = $requestBodyAttribute->contentType->decodeParameterValue($parameterValueFromRequest); + } } else { $parameterAttribute = ParameterAttribute::fromReflectionParameter($parameter); $parameterValueFromRequest = $parameterAttribute->in->resolveParameterFromRequest($request, $parameter->name); - $parameterValueFromRequest = $parameterAttribute->style->decodeParameterValue($parameterValueFromRequest); + if (!$parameterValueFromRequest instanceof NoSuchParameter) { + $parameterValueFromRequest = $parameterAttribute->style->decodeParameterValue($parameterValueFromRequest); + } } - - if ($parameterValueFromRequest !== null || $parameter->isDefaultValueAvailable() === false) { + if (!$parameterValueFromRequest instanceof NoSuchParameter) { $parameters[$parameter->name] = SchemaDenormalizer::denormalizeValue($parameterValueFromRequest, $type->getName(), $parameter); } } - return $parameters; } } diff --git a/Classes/Domain/Path/NoSuchParameter.php b/Classes/Domain/Path/NoSuchParameter.php new file mode 100644 index 0000000..9c5ae76 --- /dev/null +++ b/Classes/Domain/Path/NoSuchParameter.php @@ -0,0 +1,9 @@ +|int|bool|string|float|null + * @return NoSuchParameter|array|int|bool|string|float|null */ - public function resolveParameterFromRequest(ActionRequest $request, string $parameterName): array|int|bool|string|float|null + public function resolveParameterFromRequest(ActionRequest $request, string $parameterName): NoSuchParameter|array|int|bool|string|float|null { return match ($this) { - ParameterLocation::LOCATION_PATH => $request->hasArgument($parameterName) ? $request->getArgument($parameterName) : null, - ParameterLocation::LOCATION_QUERY => $request->getHttpRequest()->getQueryParams()[$parameterName] ?? null, - ParameterLocation::LOCATION_HEADER => $request->getHttpRequest()->hasHeader($parameterName) ? $request->getHttpRequest()->getHeader($parameterName) : null, - ParameterLocation::LOCATION_COOKIE => $request->getHttpRequest()->getCookieParams()[$parameterName] ?? null, + ParameterLocation::LOCATION_PATH => $request->hasArgument($parameterName) ? $request->getArgument($parameterName) : new NoSuchParameter(), + ParameterLocation::LOCATION_QUERY => array_key_exists($parameterName, $request->getHttpRequest()->getQueryParams()) ? $request->getHttpRequest()->getQueryParams()[$parameterName] : new NoSuchParameter(), + ParameterLocation::LOCATION_HEADER => $request->getHttpRequest()->hasHeader($parameterName) ? $request->getHttpRequest()->getHeader($parameterName) : new NoSuchParameter(), + ParameterLocation::LOCATION_COOKIE => $request->getHttpRequest()->getCookieParams()[$parameterName] ?? new NoSuchParameter(), }; } diff --git a/Classes/Domain/Path/RequestBodyContentType.php b/Classes/Domain/Path/RequestBodyContentType.php index 5a72edf..1b3b3bc 100644 --- a/Classes/Domain/Path/RequestBodyContentType.php +++ b/Classes/Domain/Path/RequestBodyContentType.php @@ -13,13 +13,13 @@ enum RequestBodyContentType: string implements \JsonSerializable /** * @todo really? - * @return array|int|bool|string|float|null + * @return NoSuchParameter|array|int|bool|string|float|null */ - public function resolveParameterFromRequest(ActionRequest $request, string $parameterName): array|int|bool|string|float|null + public function resolveParameterFromRequest(ActionRequest $request, string $parameterName): NoSuchParameter|array|int|bool|string|float|null { return match ($this) { RequestBodyContentType::CONTENT_TYPE_JSON => (string)$request->getHttpRequest()->getBody(), - RequestBodyContentType::CONTENT_TYPE_FORM => $request->getArgument($parameterName) + RequestBodyContentType::CONTENT_TYPE_FORM => $request->hasArgument($parameterName) ? $request->getArgument($parameterName) : new NoSuchParameter() }; } diff --git a/Tests/Fixtures/Controller/PathController.php b/Tests/Fixtures/Controller/PathController.php index 84e2a6f..a07bc7f 100644 --- a/Tests/Fixtures/Controller/PathController.php +++ b/Tests/Fixtures/Controller/PathController.php @@ -81,38 +81,6 @@ public function scalarNullableParameterEndpointAction( return new EndpointResponse('acknowledged'); } - public function scalarNullableParameterWithoutDefaultEndpointAction( - #[OpenApi\Parameter(ParameterLocation::LOCATION_QUERY)] - ?string $message, - #[OpenApi\Parameter(ParameterLocation::LOCATION_QUERY)] - ?int $number, - #[OpenApi\Parameter(ParameterLocation::LOCATION_QUERY)] - ?float $weight, - #[OpenApi\Parameter(ParameterLocation::LOCATION_QUERY)] - ?bool $switch, - #[OpenApi\Parameter(ParameterLocation::LOCATION_QUERY)] - ?\DateTime $dateTime, - #[OpenApi\Parameter(ParameterLocation::LOCATION_QUERY)] - ?\DateTime $dateTimeImmutable, - #[OpenApi\Parameter(ParameterLocation::LOCATION_QUERY)] - ?\DateInterval $dateInterval, - ): EndpointResponse { - return new EndpointResponse('acknowledged'); - } - - public function scalarParameterWithDefaultValuesAction( - #[OpenApi\Parameter(ParameterLocation::LOCATION_QUERY)] - string $message = "suppe", - #[OpenApi\Parameter(ParameterLocation::LOCATION_QUERY)] - int $number = 42, - #[OpenApi\Parameter(ParameterLocation::LOCATION_QUERY)] - float $weight = 666, - #[OpenApi\Parameter(ParameterLocation::LOCATION_QUERY)] - bool $switch = false, - ): EndpointResponse { - return new EndpointResponse('acknowledged'); - } - public function requestBodyAndSingleResponseEndpointAction( #[OpenApi\RequestBody(RequestBodyContentType::CONTENT_TYPE_JSON)] EndpointQuery $endpointQuery diff --git a/Tests/Unit/Application/ParameterFactoryTest.php b/Tests/Unit/Application/ParameterFactoryTest.php index 10ef2a0..72ba2f1 100644 --- a/Tests/Unit/Application/ParameterFactoryTest.php +++ b/Tests/Unit/Application/ParameterFactoryTest.php @@ -94,7 +94,7 @@ public static function parameterProvider(): iterable ] ]; - yield 'withScalarNullableParameters' => [ + yield 'withScalarNullableParametersNoQueryArguments' => [ 'request' => ActionRequest::fromHttpRequest( (new ServerRequest( HttpMethod::METHOD_GET->value, @@ -107,15 +107,23 @@ public static function parameterProvider(): iterable ] ]; - yield 'withScalarNullableNoDefaultParameters' => [ + yield 'withScalarNullableParametersNullPassed' => [ 'request' => ActionRequest::fromHttpRequest( (new ServerRequest( HttpMethod::METHOD_GET->value, new Uri('https://acme.site/') - ))->withQueryParams([]) + ))->withQueryParams([ + 'message' => null, + 'number' => null, + 'weight' => null, + 'switch' => null, + 'dateTime' => null, + 'dateTimeImmutable' => null, + 'dateInterval' => null + ]) ), 'className' => PathController::class, - 'methodName' => 'scalarNullableParameterWithoutDefaultEndpointAction', + 'methodName' => 'scalarNullableParameterEndpointAction', 'expectedParameters' => [ 'message' => null, 'number' => null, @@ -127,16 +135,32 @@ public static function parameterProvider(): iterable ] ]; - yield 'withScalarParametersAndDefaultValues' => [ + yield 'withScalarNullableParametersValuePassed' => [ 'request' => ActionRequest::fromHttpRequest( (new ServerRequest( HttpMethod::METHOD_GET->value, new Uri('https://acme.site/') - ))->withQueryParams([]) + ))->withQueryParams([ + 'message' => 'aaa', + 'number' => 123, + 'weight' => 456.0, + 'switch' => 1, + 'dateTime' => '2005-08-15T15:52:01+00:00', + 'dateTimeImmutable' => '2005-08-15T15:52:01+00:00', + 'dateInterval' => 'P7D' + ]) ), 'className' => PathController::class, - 'methodName' => 'scalarParameterWithDefaultValuesAction', - 'expectedParameters' => [] + 'methodName' => 'scalarNullableParameterEndpointAction', + 'expectedParameters' => [ + 'message' => 'aaa', + 'number' => 123, + 'weight' => 456.0, + 'switch' => true, + 'dateTime' => \DateTime::createFromFormat(\DateTime::ATOM, '2005-08-15T15:52:01+00:00'), + 'dateTimeImmutable' => \DateTimeImmutable::createFromFormat(\DateTime::ATOM, '2005-08-15T15:52:01+00:00'), + 'dateInterval' => new \DateInterval("P7D") + ] ]; $multipleParametersRequest = ActionRequest::fromHttpRequest(