Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@
"phpstan/phpdoc-parser": "^1.30"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8.2",
"bamarni/composer-bin-plugin": "^1.8.3",
"phpstan/extension-installer": "^1.4.3",
"phpstan/phpstan": "^2.1.31",
"phpstan/phpstan": "^2.1.33",
"phpstan/phpstan-deprecation-rules": "^2.0.3",
"phpstan/phpstan-strict-rules": "^2.0.7",
"roave/security-advisories": "dev-latest",
"rector/rector": "^2.2.3",
"rector/rector": "^2.3.0",
"valantic/php-cs-fixer-config": "^2.2.1"
},
"scripts": {
Expand Down
5 changes: 4 additions & 1 deletion src/Contract/Service/ControllerMethodParserInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,8 @@

interface ControllerMethodParserInterface
{
public function parseMethod(\ReflectionMethod $method): MethodDoc;
/**
* @return MethodDoc[]
*/
public function parseMethod(\ReflectionMethod $method): array;
}
120 changes: 67 additions & 53 deletions src/Service/ControllerMethodParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,90 +48,104 @@
) {
}

public function parseMethod(\ReflectionMethod $method): MethodDoc
/**
* @return MethodDoc[]
*/
public function parseMethod(\ReflectionMethod $method): array
{
$routeDoc = $this->parseRoute($method);
$routeDocs = $this->parseRoute($method);
$requestDoc = $this->parseRequest($method);
$responseDoc = $this->parseResponses($method);

$methodDoc = new MethodDoc();
$methodDoc
->setName($method->getName())
->setResponsesDoc($responseDoc)
->setRouteDoc($routeDoc)
;
$methodDocs = [];

foreach ($routeDocs as $idx => $routeDoc) {
$methodDoc = new MethodDoc();
$methodDoc
->setName($method->getName() . '-' . $idx)
->setResponsesDoc($responseDoc)
->setRouteDoc($routeDoc)
;

if ($requestDoc instanceof RequestDoc) {
$methodDoc->setRequestDoc($requestDoc);
}

if ($requestDoc instanceof RequestDoc) {
$methodDoc->setRequestDoc($requestDoc);
$methodDocs[] = $methodDoc;
}

return $methodDoc;
return $methodDocs;
}

private function parseRoute(\ReflectionMethod $method): RouteDoc
/**
* @return RouteDoc[]
*/
private function parseRoute(\ReflectionMethod $method): array
{
$routeDocs = [];

$attributes = $method->getAttributes();

foreach ($attributes as $attribute) {
if ($attribute->getName() === RouteAnnotation::class || $attribute->getName() === RouteAttribute::class) {

Check failure on line 90 in src/Service/ControllerMethodParser.php

View workflow job for this annotation

GitHub Actions / phpstan

Access to constant on deprecated class Symfony\Component\Routing\Annotation\Route: since Symfony 7.4, use {@see \Symfony\Component\Routing\Attribute\Route} instead
$routeAttributeArguments = $attribute->getArguments();

break;
}
}
if (!isset($routeAttributeArguments['path'], $routeAttributeArguments['methods'])) {
throw new IncompleteRouteException(sprintf('Route in %s::%s not defined or missing attributes "path" and/or "methods".', $method->getDeclaringClass()->getName(), $method->getName()));
}

if (!isset($routeAttributeArguments['path'], $routeAttributeArguments['methods'])) {
throw new IncompleteRouteException(sprintf('Route in %s::%s not defined or missing attributes "path" and/or "methods".', $method->getDeclaringClass()->getName(), $method->getName()));
}
if (!isset($routeAttributeArguments['name'])) {
throw new IncompleteRouteException(sprintf('Route in %s::%s does not have a "name" property.', $method->getDeclaringClass()->getName(), $method->getName()));
}

if (!isset($routeAttributeArguments['name'])) {
throw new IncompleteRouteException(sprintf('Route in %s::%s does not have a "name" property.', $method->getDeclaringClass()->getName(), $method->getName()));
}
$route = $this->router->getRouteCollection()->get($routeAttributeArguments['name']);

$route = $this->router->getRouteCollection()->get($routeAttributeArguments['name']);
if (!$route instanceof \Symfony\Component\Routing\Route) {
throw new IncompleteRouteException(sprintf('Route %s not found.', $routeAttributeArguments['name']));
}

if (!$route instanceof \Symfony\Component\Routing\Route) {
throw new IncompleteRouteException(sprintf('Route %s not found.', $routeAttributeArguments['name']));
}
$path = $route->getPath();
preg_match_all('/{([^}]+)}/', $path, $routeParameters);

$path = $route->getPath();
preg_match_all('/{([^}]+)}/', $path, $routeParameters);
$parsedParameters = [];

$parsedParameters = [];
foreach ($routeParameters[1] as $routeParameter) {
$parameterDoc = new ParameterDoc();

$parameterDoc
->setName($routeParameter)
->setIn(ParameterDoc::IN_PATH)
->setRequired(true)
->setSchema([
'type' => 'string',
])
;

foreach ($routeParameters[1] as $routeParameter) {
$parameterDoc = new ParameterDoc();
$parsedParameters[] = $parameterDoc;
}

$parameterDoc
->setName($routeParameter)
->setIn(ParameterDoc::IN_PATH)
->setRequired(true)
->setSchema([
'type' => 'string',
])
;
$routeDoc = new RouteDoc();

$parsedParameters[] = $parameterDoc;
}
$methods = $routeAttributeArguments['methods'];

$routeDoc = new RouteDoc();
if (is_array($methods)) {
if (count($methods) > 1) {
throw new UnsupportedRouteException(sprintf('Route %s has multiple methods. This is not yet supported.', $routeAttributeArguments['name']));
}
$methods = $methods[0];
}

$methods = $routeAttributeArguments['methods'];
$routeDoc
->setPath($path)
->setMethod(strtolower((string) $methods))
->setParameters($parsedParameters)
;

if (is_array($methods)) {
if (count($methods) > 1) {
throw new UnsupportedRouteException(sprintf('Route %s has multiple methods. This is not yet supported.', $routeAttributeArguments['name']));
$routeDocs[] = $routeDoc;
}
$methods = $methods[0];
}

$routeDoc
->setPath($path)
->setMethod(strtolower((string) $methods))
->setParameters($parsedParameters)
;

return $routeDoc;
return $routeDocs;
}

private function parseRequest(\ReflectionMethod $method): ?RequestDoc
Expand Down
7 changes: 5 additions & 2 deletions src/Service/DocsGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
* @param array<class-string> $controllers
*/
public function __construct(
#[TaggedIterator(ValanticPimcoreApiDocumentationExtension::TAG_CONTROLLERS)]

Check failure on line 25 in src/Service/DocsGenerator.php

View workflow job for this annotation

GitHub Actions / phpstan

Attribute class Symfony\Component\DependencyInjection\Attribute\TaggedIterator is deprecated: since Symfony 7.1, use {@see AutowireIterator} instead.
private iterable $controllers,
private ControllerMethodParserInterface $controllerMethodParser,
#[Autowire(param: 'valantic.pimcore_api_doc.base_docs_path')]
Expand Down Expand Up @@ -76,8 +76,11 @@
$controllerDoc = new ControllerDoc();

foreach ($methods as $method) {
$methodDoc = $this->controllerMethodParser->parseMethod($method);
$controllerDoc->addMethodDoc($methodDoc);
$methodDocs = $this->controllerMethodParser->parseMethod($method);

foreach ($methodDocs as $methodDoc) {
$controllerDoc->addMethodDoc($methodDoc);
}
}

return $controllerDoc;
Expand All @@ -103,7 +106,7 @@
&& $method->isPublic()
&& array_reduce(
$method->getAttributes(),
fn (bool $carry, \ReflectionAttribute $attribute): bool => $carry || $attribute->getName() === RouteAnnotation::class || $attribute->getName() === RouteAttribute::class,

Check failure on line 109 in src/Service/DocsGenerator.php

View workflow job for this annotation

GitHub Actions / phpstan

Access to constant on deprecated class Symfony\Component\Routing\Annotation\Route: since Symfony 7.4, use {@see \Symfony\Component\Routing\Attribute\Route} instead
false,
);
});
Expand Down
2 changes: 1 addition & 1 deletion vendor-bin/phpcs/composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.88.2"
"friendsofphp/php-cs-fixer": "^3.92.5"
},
"type": "project"
}
Loading
Loading