Skip to content

Commit e51d885

Browse files
authored
Merge pull request #30 from sitegeist/feature/supportPathParameters
BUGFIX: Detect routes with LOCATION_PATH parameters
2 parents fd45e4e + 3b3b221 commit e51d885

File tree

2 files changed

+39
-36
lines changed

2 files changed

+39
-36
lines changed

Classes/Domain/OpenApiDocumentFactory.php

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Neos\Flow\ObjectManagement\Proxy\ProxyInterface;
1111
use Neos\Flow\Reflection\ClassReflection;
1212
use Neos\Flow\Reflection\MethodReflection;
13+
use Neos\Flow\Reflection\ParameterReflection;
1314
use Neos\Flow\Reflection\ReflectionService;
1415
use Neos\Utility\Arrays;
1516
use Psr\Http\Message\UriFactoryInterface;
@@ -23,6 +24,7 @@
2324
use Sitegeist\SchemeOnYou\Domain\Path\OpenApiPathItem;
2425
use Sitegeist\SchemeOnYou\Domain\Path\OpenApiRequestBody;
2526
use Sitegeist\SchemeOnYou\Domain\Path\OpenApiResponses;
27+
use Sitegeist\SchemeOnYou\Domain\Path\ParameterLocation;
2628
use Sitegeist\SchemeOnYou\Domain\Path\PathDefinition;
2729
use Sitegeist\SchemeOnYou\Domain\Schema\IsSupportedInSchema;
2830
use Sitegeist\SchemeOnYou\Domain\Schema\OpenApiSchemaCollection;
@@ -99,7 +101,7 @@ public function createOpenApiDocumentFromNameAndClassNamePattern(
99101
}
100102
}
101103
}
102-
$paths = $paths->merge($this->createPathsFromPathAndMethodReflection($classReflection, $methodReflection));
104+
$paths = $paths->merge($this->createPathsFromClassAndMethodReflection($classReflection, $methodReflection));
103105
}
104106

105107
$requiredSchemaClasses = $this->addConstructorArgumentTypesToRequiredSchemaClasses($requiredSchemaClasses);
@@ -121,7 +123,7 @@ public function createOpenApiDocumentFromNameAndClassNamePattern(
121123
);
122124
}
123125

124-
private function createPathsFromPathAndMethodReflection(ClassReflection $classReflection, MethodReflection $methodReflection): OpenApiPathCollection
126+
private function createPathsFromClassAndMethodReflection(ClassReflection $classReflection, MethodReflection $methodReflection): OpenApiPathCollection
125127
{
126128
/**
127129
* @var OpenApiPathItem[] $paths
@@ -159,27 +161,14 @@ private function createPathsFromPathAndMethodReflection(ClassReflection $classRe
159161
$controller = substr($controllerName, 0, -10);
160162
$action = substr($methodName, 0, -6);
161163

162-
$resolveContext = new ResolveContext(
163-
$this->uriFactory->createUri('http://localhost'),
164-
[
165-
'@package' => $controllerPackageKey,
166-
'@subpackage' => $subPackage,
167-
'@controller' => $controller,
168-
'@action' => $action,
169-
],
170-
false,
171-
'',
172-
RouteParameters::createEmpty()->withParameter('requestUriHost', 'localhost')
173-
);
174-
175164
$requestBody = null;
176165
$parameters = [];
177-
foreach ($methodReflection->getParameters() as $reflectionParameter) {
178-
$parameterProcessed = false;
166+
$bodyParameterIsAlreadyProcessed = false;
179167

168+
foreach ($methodReflection->getParameters() as $reflectionParameter) {
180169
if ($bodyAttributes = $reflectionParameter->getAttributes(RequestBody::class)) {
181170
foreach ($bodyAttributes as $attribute) {
182-
if ($parameterProcessed) {
171+
if ($bodyParameterIsAlreadyProcessed) {
183172
throw new \DomainException(
184173
'Method parameter ' . $methodReflection->getDeclaringClass()->name
185174
. '::' . $methodReflection->getName() . '::' . $reflectionParameter->name
@@ -194,26 +183,42 @@ private function createPathsFromPathAndMethodReflection(ClassReflection $classRe
194183
);
195184
}
196185
$requestBody = OpenApiRequestBody::fromReflectionParameter($reflectionParameter);
197-
$parameterProcessed = true;
198-
}
199-
} elseif ($parameterAttributes = $reflectionParameter->getAttributes(Parameter::class)) {
200-
foreach ($parameterAttributes as $attribute) {
201-
if ($parameterProcessed) {
202-
throw new \DomainException(
203-
'Method parameter ' . $methodReflection->getDeclaringClass()->name
204-
. '::' . $methodReflection->getName() . '::' . $reflectionParameter->name
205-
. ' must be attributed as either OpenAPI Parameter or RequestBody'
206-
. ' and was already attributed'
207-
);
208-
}
209-
$parameters[] = OpenApiParameter::fromReflectionParameter($reflectionParameter);
210-
$parameterProcessed = true;
186+
$bodyParameterIsAlreadyProcessed = true;
211187
}
212188
} else {
213189
$parameters[] = OpenApiParameter::fromReflectionParameter($reflectionParameter);
214190
}
215191
}
216192

193+
// add fake string parameters for the LOCATION_PATH parameters
194+
$additionalRouteValues = array_reduce(
195+
$parameters,
196+
function (array $carry, OpenApiParameter $parameter) {
197+
if ($parameter->in === ParameterLocation::LOCATION_PATH) {
198+
$carry[$parameter->name] = "string";
199+
}
200+
return $carry;
201+
},
202+
[]
203+
);
204+
205+
// we try to route the parameter
206+
$resolveContext = new ResolveContext(
207+
$this->uriFactory->createUri('http://localhost'),
208+
array_merge(
209+
[
210+
'@package' => $controllerPackageKey,
211+
'@subpackage' => $subPackage,
212+
'@controller' => $controller,
213+
'@action' => $action,
214+
],
215+
$additionalRouteValues
216+
),
217+
false,
218+
'',
219+
RouteParameters::createEmpty()->withParameter('requestUriHost', 'localhost')
220+
);
221+
217222
foreach ($this->router->getRoutes() as $route) {
218223
if ($route->resolves($resolveContext)) {
219224
$path = str_replace(
@@ -233,8 +238,6 @@ private function createPathsFromPathAndMethodReflection(ClassReflection $classRe
233238
);
234239
}
235240
}
236-
// only the first matching route is needed so we can break the loop here
237-
break;
238241
}
239242
}
240243

Tests/Unit/Domain/OpenApiDocumentFactoryTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ public function setUp(): void
108108
),
109109
$this->createMockRoute(
110110
'multipleParametersAndResponsesEndpoint',
111-
'my-multiple-parameters-and-responses-endpoint'
111+
'my-multiple-parameters-and-responses-endpoint/{endpointQuery}'
112112
),
113113
$this->createMockRoute(
114114
'singleValueObjectsParameterEndpoint',
@@ -420,7 +420,7 @@ public function testFromClassNameCreatesDefinitionsForValidClasses(): void
420420
)
421421
),
422422
new OpenApiPathItem(
423-
new PathDefinition('/my-multiple-parameters-and-responses-endpoint'),
423+
new PathDefinition('/my-multiple-parameters-and-responses-endpoint/{endpointQuery}'),
424424
HttpMethod::METHOD_GET,
425425
new OpenApiParameterCollection(
426426
new OpenApiParameter(

0 commit comments

Comments
 (0)