Migrate annotation ApiDoc to attribute

This commit is contained in:
Ilyas Salikhov 2024-10-01 23:00:23 +03:00
parent 8135dec035
commit a9fceca8df
21 changed files with 375 additions and 602 deletions

View File

@ -1,21 +1,10 @@
<?php <?php
/* namespace Nelmio\ApiDocBundle\Attribute;
* This file is part of the NelmioApiDocBundle.
*
* (c) Nelmio <hello@nelm.io>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Nelmio\ApiDocBundle\Annotation;
use Symfony\Component\Routing\Route; use Symfony\Component\Routing\Route;
/** #[\Attribute(\Attribute::TARGET_METHOD)]
* @Annotation
*/
class ApiDoc class ApiDoc
{ {
public const DEFAULT_VIEW = 'default'; public const DEFAULT_VIEW = 'default';
@ -23,158 +12,93 @@ class ApiDoc
/** /**
* Requirements are mandatory parameters in a route. * Requirements are mandatory parameters in a route.
* *
* @var array * @var array<string, array<string, string>>
*/ */
private $requirements = []; private array $requirements = [];
/** /**
* Which views is this route used. Defaults to "Default" * Which views is this route used. Defaults to "Default"
* *
* @var array * @var string[]
*/ */
private $views = []; private array $views = [];
/** /**
* Filters are optional parameters in the query string. * Filters are optional parameters in the query string.
* *
* @var array * @var array<string, array<string, string>>
*/ */
private $filters = []; private array $filters = [];
/** /**
* Parameters are data a client can send. * Parameters are data a client can send.
* *
* @var array * @var array<string, array<string, mixed>>
*/ */
private $parameters = []; private array $parameters = [];
/** /**
* Headers that client can send. * Headers that client can send.
* *
* @var array * @var array<string, array<string, mixed>>
*/ */
private $headers = []; private array $headers = [];
/** private ?string $link = null;
* @var string
*/
private $input;
/**
* @var string
*/
private $inputs;
/**
* @var string
*/
private $output;
/**
* @var string
*/
private $link;
/**
* Most of the time, a single line of text describing the action.
*
* @var string
*/
private $description;
/**
* Section to group actions together.
*
* @var string
*/
private $section;
/** /**
* Extended documentation. * Extended documentation.
*
* @var string
*/ */
private $documentation; private ?string $documentation = null;
private Route $route;
private ?string $host = null;
private string $method;
private string $uri;
private array $response = [];
/** /**
* @var bool * @var array<int|string, string[]>
*/ */
private $resource = false; private array $statusCodes = [];
/** /**
* @var string * @var array<int, array<mixed>>
*/ */
private $method; private array $responseMap = [];
private array $parsedResponseMap = [];
/** /**
* @var string * @var array<string|int, string>
*/ */
private $host; private array $tags = [];
/**
* @var string
*/
private $uri;
/**
* @var array
*/
private $response = [];
/**
* @var Route
*/
private $route;
/**
* @var bool
*/
private $deprecated = false;
/**
* @var array
*/
private $statusCodes = [];
/**
* @var string|null
*/
private $resourceDescription;
/**
* @var array
*/
private $responseMap = [];
/**
* @var array
*/
private $parsedResponseMap = [];
/**
* @var array
*/
private $tags = [];
private ?string $scope = null; private ?string $scope = null;
public function __construct(array $data) /**
{ * @param string[]|string|null $description
$this->resource = !empty($data['resource']) ? $data['resource'] : false; */
public function __construct(
if (isset($data['description'])) { private string|bool $resource = false,
$this->description = $data['description']; private array|string|null $description = null,
} private string|array|null $input = null,
private ?array $inputs = null,
if (isset($data['input'])) { private string|array|null $output = null,
$this->input = $data['input']; private ?string $section = null,
} private bool $deprecated = false,
private ?string $resourceDescription = null,
if (isset($data['inputs'])) { ?array $filters = null,
$this->inputs = $data['inputs']; ?array $requirements = null,
} array|string|null $views = null,
?array $parameters = null,
if (isset($data['filters'])) { ?array $headers = null,
foreach ($data['filters'] as $filter) { ?array $statusCodes = null,
array|string|int|null $tags = null,
?array $responseMap = null,
) {
if (null !== $filters) {
foreach ($filters as $filter) {
if (!isset($filter['name'])) { if (!isset($filter['name'])) {
throw new \InvalidArgumentException('A "filter" element has to contain a "name" attribute'); throw new \InvalidArgumentException('A "filter" element has to contain a "name" attribute');
} }
@ -186,8 +110,8 @@ class ApiDoc
} }
} }
if (isset($data['requirements'])) { if (null !== $requirements) {
foreach ($data['requirements'] as $requirement) { foreach ($requirements as $requirement) {
if (!isset($requirement['name'])) { if (!isset($requirement['name'])) {
throw new \InvalidArgumentException('A "requirement" element has to contain a "name" attribute'); throw new \InvalidArgumentException('A "requirement" element has to contain a "name" attribute');
} }
@ -199,18 +123,18 @@ class ApiDoc
} }
} }
if (isset($data['views'])) { if (null !== $views) {
if (!is_array($data['views'])) { if (!is_array($views)) {
$data['views'] = [$data['views']]; $views = [$views];
} }
foreach ($data['views'] as $view) { foreach ($views as $view) {
$this->addView($view); $this->addView($view);
} }
} }
if (isset($data['parameters'])) { if (null !== $parameters) {
foreach ($data['parameters'] as $parameter) { foreach ($parameters as $parameter) {
if (!isset($parameter['name'])) { if (!isset($parameter['name'])) {
throw new \InvalidArgumentException('A "parameter" element has to contain a "name" attribute'); throw new \InvalidArgumentException('A "parameter" element has to contain a "name" attribute');
} }
@ -229,8 +153,8 @@ class ApiDoc
} }
} }
if (isset($data['headers'])) { if (null !== $headers) {
foreach ($data['headers'] as $header) { foreach ($headers as $header) {
if (!isset($header['name'])) { if (!isset($header['name'])) {
throw new \InvalidArgumentException('A "header" element has to contain a "name" attribute'); throw new \InvalidArgumentException('A "header" element has to contain a "name" attribute');
} }
@ -242,27 +166,15 @@ class ApiDoc
} }
} }
if (isset($data['output'])) { if (null !== $statusCodes) {
$this->output = $data['output']; foreach ($statusCodes as $statusCode => $statusDescription) {
} $this->addStatusCode($statusCode, $statusDescription);
if (isset($data['statusCodes'])) {
foreach ($data['statusCodes'] as $statusCode => $description) {
$this->addStatusCode($statusCode, $description);
} }
} }
if (isset($data['section'])) { if (null !== $tags) {
$this->section = $data['section']; if (is_array($tags)) {
} foreach ($tags as $tag => $colorCode) {
if (isset($data['deprecated'])) {
$this->deprecated = $data['deprecated'];
}
if (isset($data['tags'])) {
if (is_array($data['tags'])) {
foreach ($data['tags'] as $tag => $colorCode) {
if (is_numeric($tag)) { if (is_numeric($tag)) {
$this->addTag($colorCode); $this->addTag($colorCode);
} else { } else {
@ -270,51 +182,34 @@ class ApiDoc
} }
} }
} else { } else {
$this->tags[] = $data['tags']; $this->tags[] = $tags;
} }
} }
if (isset($data['resourceDescription'])) { if (null !== $responseMap) {
$this->resourceDescription = $data['resourceDescription']; $this->responseMap = $responseMap;
}
if (isset($data['responseMap'])) {
$this->responseMap = $data['responseMap'];
if (isset($this->responseMap[200])) { if (isset($this->responseMap[200])) {
$this->output = $this->responseMap[200]; $this->output = $this->responseMap[200];
} }
} }
} }
/** public function addFilter(string $name, array $filter): void
* @param string $name
*/
public function addFilter($name, array $filter): void
{ {
$this->filters[$name] = $filter; $this->filters[$name] = $filter;
} }
/** public function addStatusCode(int|string $statusCode, string|array $description): void
* @param string $statusCode
*/
public function addStatusCode($statusCode, $description): void
{ {
$this->statusCodes[$statusCode] = !is_array($description) ? [$description] : $description; $this->statusCodes[$statusCode] = !is_array($description) ? [$description] : $description;
} }
/** public function addTag(int|string $tag, string $colorCode = '#d9534f'): void
* @param string $tag
* @param string $colorCode
*/
public function addTag($tag, $colorCode = '#d9534f'): void
{ {
$this->tags[$tag] = $colorCode; $this->tags[$tag] = $colorCode;
} }
/** public function addRequirement(string $name, array $requirement): void
* @param string $name
*/
public function addRequirement($name, array $requirement): void
{ {
$this->requirements[$name] = $requirement; $this->requirements[$name] = $requirement;
} }
@ -324,119 +219,81 @@ class ApiDoc
$this->requirements = array_merge($this->requirements, $requirements); $this->requirements = array_merge($this->requirements, $requirements);
} }
/** public function getInput(): string|array|null
* @return string|null
*/
public function getInput()
{ {
return $this->input; return $this->input;
} }
/** public function getInputs(): ?array
* @return array|null
*/
public function getInputs()
{ {
return $this->inputs; return $this->inputs;
} }
/** public function getOutput(): array|string|null
* @return string|null
*/
public function getOutput()
{ {
return $this->output; return $this->output;
} }
/** /**
* @return string * @return string[]|string|null
*/ */
public function getDescription() public function getDescription(): array|string|null
{ {
return $this->description; return $this->description;
} }
/** /**
* @param string $description * @param string[]|string|null $description
*/ */
public function setDescription($description): void public function setDescription(array|string|null $description): void
{ {
$this->description = $description; $this->description = $description;
} }
/** public function setLink(?string $link): void
* @param string $link
*/
public function setLink($link): void
{ {
$this->link = $link; $this->link = $link;
} }
/** public function getSection(): ?string
* @param string $section
*/
public function setSection($section): void
{
$this->section = $section;
}
/**
* @return string
*/
public function getSection()
{ {
return $this->section; return $this->section;
} }
/** public function addView(string $view): void
* @return array
*/
public function addView($view)
{ {
$this->views[] = $view; $this->views[] = $view;
} }
/** /**
* @return array * @return string[]
*/ */
public function getViews() public function getViews(): array
{ {
return $this->views; return $this->views;
} }
/** public function setDocumentation(?string $documentation): void
* @param string $documentation
*/
public function setDocumentation($documentation): void
{ {
$this->documentation = $documentation; $this->documentation = $documentation;
} }
/** public function getDocumentation(): ?string
* @return string
*/
public function getDocumentation()
{ {
return $this->documentation; return $this->documentation;
} }
/** public function isResource(): bool
* @return bool
*/
public function isResource()
{ {
return (bool) $this->resource; return (bool) $this->resource;
} }
public function getResource() public function getResource(): string|bool
{ {
return $this->resource && is_string($this->resource) ? $this->resource : false; return $this->resource && is_string($this->resource) ? $this->resource : false;
} }
/** public function addParameter(string $name, array $parameter): void
* @param string $name
*/
public function addParameter($name, array $parameter): void
{ {
$this->parameters[$name] = $parameter; $this->parameters[$name] = $parameter;
} }
@ -480,86 +337,50 @@ class ApiDoc
$this->method = $route->getMethods() ? implode('|', $route->getMethods()) : 'ANY'; $this->method = $route->getMethods() ? implode('|', $route->getMethods()) : 'ANY';
} }
/** public function getRoute(): Route
* @return Route
*/
public function getRoute()
{ {
return $this->route; return $this->route;
} }
/** public function getHost(): ?string
* @return string
*/
public function getHost()
{ {
return $this->host; return $this->host;
} }
/** public function getDeprecated(): bool
* @param string $host
*/
public function setHost($host): void
{
$this->host = $host;
}
/**
* @return bool
*/
public function getDeprecated()
{ {
return $this->deprecated; return $this->deprecated;
} }
/** /**
* @return array * @return array<string, array<string, string>>
*/ */
public function getFilters() public function getFilters(): array
{ {
return $this->filters; return $this->filters;
} }
/** public function getRequirements(): array
* @return array
*/
public function getRequirements()
{ {
return $this->requirements; return $this->requirements;
} }
/** public function getParameters(): array
* @return array
*/
public function getParameters()
{ {
return $this->parameters; return $this->parameters;
} }
/** public function getHeaders(): array
* @return array
*/
public function getHeaders()
{ {
return $this->headers; return $this->headers;
} }
/** public function setDeprecated(bool $deprecated): void
* @param bool $deprecated
*
* @return $this
*/
public function setDeprecated($deprecated)
{ {
$this->deprecated = (bool) $deprecated; $this->deprecated = $deprecated;
return $this;
} }
/** public function getMethod(): string
* @return string
*/
public function getMethod()
{ {
return $this->method; return $this->method;
} }
@ -580,8 +401,8 @@ class ApiDoc
public function toArray() public function toArray()
{ {
$data = [ $data = [
'method' => $this->method, 'method' => $this->method ?? null,
'uri' => $this->uri, 'uri' => $this->uri ?? null,
]; ];
if ($host = $this->host) { if ($host = $this->host) {
@ -650,18 +471,12 @@ class ApiDoc
return $data; return $data;
} }
/** public function getResourceDescription(): ?string
* @return string|null
*/
public function getResourceDescription()
{ {
return $this->resourceDescription; return $this->resourceDescription;
} }
/** public function getResponseMap(): array
* @return array
*/
public function getResponseMap()
{ {
if (!isset($this->responseMap[200]) && null !== $this->output) { if (!isset($this->responseMap[200]) && null !== $this->output) {
$this->responseMap[200] = $this->output; $this->responseMap[200] = $this->output;
@ -670,21 +485,15 @@ class ApiDoc
return $this->responseMap; return $this->responseMap;
} }
/** public function getParsedResponseMap(): array
* @return array
*/
public function getParsedResponseMap()
{ {
return $this->parsedResponseMap; return $this->parsedResponseMap;
} }
/** public function setResponseForStatusCode(array $model, array $type, int $statusCode = 200): void
* @param int $statusCode
*/
public function setResponseForStatusCode($model, $type, $statusCode = 200): void
{ {
$this->parsedResponseMap[$statusCode] = ['type' => $type, 'model' => $model]; $this->parsedResponseMap[$statusCode] = ['type' => $type, 'model' => $model];
if (200 == $statusCode && $this->response !== $model) { if (200 === $statusCode && $this->response !== $model) {
$this->response = $model; $this->response = $model;
} }
} }

View File

@ -11,7 +11,7 @@
namespace Nelmio\ApiDocBundle\Command; namespace Nelmio\ApiDocBundle\Command;
use Nelmio\ApiDocBundle\Annotation\ApiDoc; use Nelmio\ApiDocBundle\Attribute\ApiDoc;
use Nelmio\ApiDocBundle\Extractor\ApiDocExtractor; use Nelmio\ApiDocBundle\Extractor\ApiDocExtractor;
use Nelmio\ApiDocBundle\Formatter\HtmlFormatter; use Nelmio\ApiDocBundle\Formatter\HtmlFormatter;
use Nelmio\ApiDocBundle\Formatter\MarkdownFormatter; use Nelmio\ApiDocBundle\Formatter\MarkdownFormatter;

View File

@ -11,7 +11,7 @@
namespace Nelmio\ApiDocBundle\Controller; namespace Nelmio\ApiDocBundle\Controller;
use Nelmio\ApiDocBundle\Annotation\ApiDoc; use Nelmio\ApiDocBundle\Attribute\ApiDoc;
use Nelmio\ApiDocBundle\Extractor\ApiDocExtractor; use Nelmio\ApiDocBundle\Extractor\ApiDocExtractor;
use Nelmio\ApiDocBundle\Formatter\HtmlFormatter; use Nelmio\ApiDocBundle\Formatter\HtmlFormatter;
use Nelmio\ApiDocBundle\Formatter\RequestAwareSwaggerFormatter; use Nelmio\ApiDocBundle\Formatter\RequestAwareSwaggerFormatter;

View File

@ -26,7 +26,7 @@ class ExtractorHandlerCompilerPass implements CompilerPassInterface
$container $container
->getDefinition('nelmio_api_doc.extractor.api_doc_extractor') ->getDefinition('nelmio_api_doc.extractor.api_doc_extractor')
->replaceArgument(3, $handlers) ->replaceArgument(2, $handlers)
; ;
} }
} }

View File

@ -11,8 +11,7 @@
namespace Nelmio\ApiDocBundle\Extractor; namespace Nelmio\ApiDocBundle\Extractor;
use Doctrine\Common\Annotations\Reader; use Nelmio\ApiDocBundle\Attribute\ApiDoc;
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use Nelmio\ApiDocBundle\DataTypes; use Nelmio\ApiDocBundle\DataTypes;
use Nelmio\ApiDocBundle\Parser\ParserInterface; use Nelmio\ApiDocBundle\Parser\ParserInterface;
use Nelmio\ApiDocBundle\Parser\PostParserInterface; use Nelmio\ApiDocBundle\Parser\PostParserInterface;
@ -22,8 +21,6 @@ use Symfony\Component\Routing\RouterInterface;
class ApiDocExtractor class ApiDocExtractor
{ {
public const ANNOTATION_CLASS = ApiDoc::class;
/** /**
* @var ParserInterface[] * @var ParserInterface[]
*/ */
@ -35,7 +32,6 @@ class ApiDocExtractor
*/ */
public function __construct( public function __construct(
protected RouterInterface $router, protected RouterInterface $router,
protected Reader $reader,
protected DocCommentExtractor $commentExtractor, protected DocCommentExtractor $commentExtractor,
protected array $handlers, protected array $handlers,
protected array $excludeSections, protected array $excludeSections,
@ -49,17 +45,15 @@ class ApiDocExtractor
* *
* @return Route[] An array of routes * @return Route[] An array of routes
*/ */
public function getRoutes() public function getRoutes(): array
{ {
return $this->router->getRouteCollection()->all(); return $this->router->getRouteCollection()->all();
} }
/** /*
* Extracts annotations from all known routes * Extracts annotations from all known routes
*
* @return array
*/ */
public function all($view = ApiDoc::DEFAULT_VIEW) public function all($view = ApiDoc::DEFAULT_VIEW): array
{ {
return $this->extractAnnotations($this->getRoutes(), $view); return $this->extractAnnotations($this->getRoutes(), $view);
} }
@ -69,10 +63,8 @@ class ApiDocExtractor
* *
* @param string $apiVersion API version * @param string $apiVersion API version
* @param string $view * @param string $view
*
* @return array
*/ */
public function allForVersion($apiVersion, $view = ApiDoc::DEFAULT_VIEW) public function allForVersion($apiVersion, $view = ApiDoc::DEFAULT_VIEW): array
{ {
$data = $this->all($view); $data = $this->all($view);
foreach ($data as $k => $a) { foreach ($data as $k => $a) {
@ -94,10 +86,8 @@ class ApiDocExtractor
* - resource * - resource
* *
* @param array $routes array of Route-objects for which the annotations should be extracted * @param array $routes array of Route-objects for which the annotations should be extracted
*
* @return array
*/ */
public function extractAnnotations(array $routes, $view = ApiDoc::DEFAULT_VIEW) public function extractAnnotations(array $routes, $view = ApiDoc::DEFAULT_VIEW): array
{ {
$array = []; $array = [];
$resources = []; $resources = [];
@ -108,7 +98,7 @@ class ApiDocExtractor
} }
if ($method = $this->getReflectionMethod($route->getDefault('_controller'))) { if ($method = $this->getReflectionMethod($route->getDefault('_controller'))) {
$annotation = $this->reader->getMethodAnnotation($method, static::ANNOTATION_CLASS); $annotation = $this->getMethodApiDoc($method);
if ( if (
$annotation && !in_array($annotation->getSection(), $this->excludeSections) $annotation && !in_array($annotation->getSection(), $this->excludeSections)
&& (in_array($view, $annotation->getViews()) || (0 === count($annotation->getViews()) && ApiDoc::DEFAULT_VIEW === $view)) && (in_array($view, $annotation->getViews()) || (0 === count($annotation->getViews()) && ApiDoc::DEFAULT_VIEW === $view))
@ -214,7 +204,7 @@ class ApiDocExtractor
public function get($controller, $route) public function get($controller, $route)
{ {
if ($method = $this->getReflectionMethod($controller)) { if ($method = $this->getReflectionMethod($controller)) {
if ($annotation = $this->reader->getMethodAnnotation($method, static::ANNOTATION_CLASS)) { if ($annotation = $this->getMethodApiDoc($method)) {
if ($route = $this->router->getRouteCollection()->get($route)) { if ($route = $this->router->getRouteCollection()->get($route)) {
return $this->extractData($annotation, $route, $method); return $this->extractData($annotation, $route, $method);
} }
@ -224,6 +214,16 @@ class ApiDocExtractor
return null; return null;
} }
protected function getMethodApiDoc(\ReflectionMethod $method): ?ApiDoc
{
$attributes = $method->getAttributes(ApiDoc::class, \ReflectionAttribute::IS_INSTANCEOF);
if (!$attributes) {
return null;
}
return $attributes[0]->newInstance();
}
/** /**
* Registers a class parser to use for parsing input class metadata * Registers a class parser to use for parsing input class metadata
*/ */
@ -444,13 +444,13 @@ class ApiDocExtractor
} elseif (null !== $value) { } elseif (null !== $value) {
if (in_array($name, ['required', 'readonly'])) { if (in_array($name, ['required', 'readonly'])) {
$v1[$name] = $v1[$name] || $value; $v1[$name] = $v1[$name] || $value;
} elseif (in_array($name, ['requirement'])) { } elseif ('requirement' === $name) {
if (isset($v1[$name])) { if (isset($v1[$name])) {
$v1[$name] .= ', ' . $value; $v1[$name] .= ', ' . $value;
} else { } else {
$v1[$name] = $value; $v1[$name] = $value;
} }
} elseif ('default' == $name) { } elseif ('default' === $name) {
if (isset($v1[$name])) { if (isset($v1[$name])) {
$v1[$name] = $value ?? $v1[$name]; $v1[$name] = $value ?? $v1[$name];
} else { } else {
@ -472,8 +472,6 @@ class ApiDocExtractor
/** /**
* Parses annotations for a given method, and adds new information to the given ApiDoc * Parses annotations for a given method, and adds new information to the given ApiDoc
* annotation. Useful to extract information from the FOSRestBundle annotations. * annotation. Useful to extract information from the FOSRestBundle annotations.
*
* @param ReflectionMethod $method
*/ */
protected function parseAnnotations(ApiDoc $annotation, Route $route, \ReflectionMethod $method): void protected function parseAnnotations(ApiDoc $annotation, Route $route, \ReflectionMethod $method): void
{ {

View File

@ -11,8 +11,7 @@
namespace Nelmio\ApiDocBundle\Extractor; namespace Nelmio\ApiDocBundle\Extractor;
use Doctrine\Common\Annotations\Reader; use Nelmio\ApiDocBundle\Attribute\ApiDoc;
use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use Nelmio\ApiDocBundle\Util\DocCommentExtractor; use Nelmio\ApiDocBundle\Util\DocCommentExtractor;
use Symfony\Component\Config\ConfigCache; use Symfony\Component\Config\ConfigCache;
use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Config\Resource\FileResource;
@ -32,14 +31,13 @@ class CachingApiDocExtractor extends ApiDocExtractor
*/ */
public function __construct( public function __construct(
RouterInterface $router, RouterInterface $router,
Reader $reader,
DocCommentExtractor $commentExtractor, DocCommentExtractor $commentExtractor,
array $handlers, array $handlers,
array $excludeSections, array $excludeSections,
private string $cacheFile, private string $cacheFile,
private bool $debug = false, private bool $debug = false,
) { ) {
parent::__construct($router, $reader, $commentExtractor, $handlers, $excludeSections); parent::__construct($router, $commentExtractor, $handlers, $excludeSections);
} }
/** /**
@ -47,15 +45,17 @@ class CachingApiDocExtractor extends ApiDocExtractor
* *
* @return array|mixed * @return array|mixed
*/ */
public function all($view = ApiDoc::DEFAULT_VIEW) public function all($view = ApiDoc::DEFAULT_VIEW): array
{ {
$cache = $this->getViewCache($view); $cache = $this->getViewCache($view);
if (!$cache->isFresh()) { if (!$cache->isFresh()) {
$resources = []; $resources = [];
foreach ($this->getRoutes() as $route) { foreach ($this->getRoutes() as $route) {
if (null !== ($method = $this->getReflectionMethod($route->getDefault('_controller'))) if (
&& null !== ($annotation = $this->reader->getMethodAnnotation($method, self::ANNOTATION_CLASS))) { null !== ($method = $this->getReflectionMethod($route->getDefault('_controller')))
&& null !== $this->getMethodApiDoc($method)
) {
$file = $method->getDeclaringClass()->getFileName(); $file = $method->getDeclaringClass()->getFileName();
$resources[] = new FileResource($file); $resources[] = new FileResource($file);
} }

View File

@ -11,7 +11,7 @@
namespace Nelmio\ApiDocBundle\Extractor\Handler; namespace Nelmio\ApiDocBundle\Extractor\Handler;
use Nelmio\ApiDocBundle\Annotation\ApiDoc; use Nelmio\ApiDocBundle\Attribute\ApiDoc;
use Nelmio\ApiDocBundle\Extractor\HandlerInterface; use Nelmio\ApiDocBundle\Extractor\HandlerInterface;
use Nelmio\ApiDocBundle\Util\DocCommentExtractor; use Nelmio\ApiDocBundle\Util\DocCommentExtractor;
use Symfony\Component\Routing\Route; use Symfony\Component\Routing\Route;
@ -74,7 +74,7 @@ class PhpDocHandler implements HandlerInterface
$found = false; $found = false;
foreach ($paramDocs as $paramDoc) { foreach ($paramDocs as $paramDoc) {
if (preg_match(sprintf($regexp, preg_quote($var)), $paramDoc, $matches)) { if (preg_match(sprintf($regexp, preg_quote($var)), $paramDoc, $matches)) {
$annotationRequirements = $annotation->getrequirements(); $annotationRequirements = $annotation->getRequirements();
if (!isset($annotationRequirements[$var]['dataType'])) { if (!isset($annotationRequirements[$var]['dataType'])) {
$requirements[$var]['dataType'] = $matches[1] ?? ''; $requirements[$var]['dataType'] = $matches[1] ?? '';

View File

@ -11,7 +11,7 @@
namespace Nelmio\ApiDocBundle\Extractor; namespace Nelmio\ApiDocBundle\Extractor;
use Nelmio\ApiDocBundle\Annotation\ApiDoc; use Nelmio\ApiDocBundle\Attribute\ApiDoc;
use Symfony\Component\Routing\Route; use Symfony\Component\Routing\Route;
interface HandlerInterface interface HandlerInterface

View File

@ -11,7 +11,7 @@
namespace Nelmio\ApiDocBundle\Formatter; namespace Nelmio\ApiDocBundle\Formatter;
use Nelmio\ApiDocBundle\Annotation\ApiDoc; use Nelmio\ApiDocBundle\Attribute\ApiDoc;
use Nelmio\ApiDocBundle\DataTypes; use Nelmio\ApiDocBundle\DataTypes;
abstract class AbstractFormatter implements FormatterInterface abstract class AbstractFormatter implements FormatterInterface

View File

@ -11,7 +11,7 @@
namespace Nelmio\ApiDocBundle\Formatter; namespace Nelmio\ApiDocBundle\Formatter;
use Nelmio\ApiDocBundle\Annotation\ApiDoc; use Nelmio\ApiDocBundle\Attribute\ApiDoc;
interface FormatterInterface interface FormatterInterface
{ {

View File

@ -11,7 +11,7 @@
namespace Nelmio\ApiDocBundle\Formatter; namespace Nelmio\ApiDocBundle\Formatter;
use Nelmio\ApiDocBundle\Annotation\ApiDoc; use Nelmio\ApiDocBundle\Attribute\ApiDoc;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
/** /**

View File

@ -11,7 +11,7 @@
namespace Nelmio\ApiDocBundle\Formatter; namespace Nelmio\ApiDocBundle\Formatter;
use Nelmio\ApiDocBundle\Annotation\ApiDoc; use Nelmio\ApiDocBundle\Attribute\ApiDoc;
class SimpleFormatter extends AbstractFormatter class SimpleFormatter extends AbstractFormatter
{ {

View File

@ -11,7 +11,7 @@
namespace Nelmio\ApiDocBundle\Formatter; namespace Nelmio\ApiDocBundle\Formatter;
use Nelmio\ApiDocBundle\Annotation\ApiDoc; use Nelmio\ApiDocBundle\Attribute\ApiDoc;
use Nelmio\ApiDocBundle\DataTypes; use Nelmio\ApiDocBundle\DataTypes;
use Nelmio\ApiDocBundle\Swagger\ModelRegistry; use Nelmio\ApiDocBundle\Swagger\ModelRegistry;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;

View File

@ -25,7 +25,6 @@
<service id="nelmio_api_doc.extractor.api_doc_extractor" class="%nelmio_api_doc.extractor.api_doc_extractor.class%" public="true"> <service id="nelmio_api_doc.extractor.api_doc_extractor" class="%nelmio_api_doc.extractor.api_doc_extractor.class%" public="true">
<argument type="service" id="router" /> <argument type="service" id="router" />
<argument type="service" id="annotation_reader" />
<argument type="service" id="nelmio_api_doc.doc_comment_extractor" /> <argument type="service" id="nelmio_api_doc.doc_comment_extractor" />
<argument type="collection" /> <argument type="collection" />
<argument>%nelmio_api_doc.exclude_sections%</argument> <argument>%nelmio_api_doc.exclude_sections%</argument>

View File

@ -5,7 +5,7 @@ The bundle provides an ``ApiDoc()`` annotation for your controllers::
namespace Your\Namespace; namespace Your\Namespace;
use Nelmio\ApiDocBundle\Annotation\ApiDoc; use Nelmio\ApiDocBundle\Attribute\ApiDoc;
class YourController extends Controller class YourController extends Controller
{ {

View File

@ -11,7 +11,7 @@
namespace Nelmio\ApiDocBundle\Tests\Annotation; namespace Nelmio\ApiDocBundle\Tests\Annotation;
use Nelmio\ApiDocBundle\Annotation\ApiDoc; use Nelmio\ApiDocBundle\Attribute\ApiDoc;
use Nelmio\ApiDocBundle\Tests\TestCase; use Nelmio\ApiDocBundle\Tests\TestCase;
use Symfony\Component\Routing\Route; use Symfony\Component\Routing\Route;
@ -19,9 +19,7 @@ class ApiDocTest extends TestCase
{ {
public function testConstructWithoutData(): void public function testConstructWithoutData(): void
{ {
$data = []; $annot = new ApiDoc();
$annot = new ApiDoc($data);
$array = $annot->toArray(); $array = $annot->toArray();
$this->assertTrue(is_array($array)); $this->assertTrue(is_array($array));
@ -38,12 +36,7 @@ class ApiDocTest extends TestCase
public function testConstructWithInvalidData(): void public function testConstructWithInvalidData(): void
{ {
$data = [ $annot = new ApiDoc();
'unknown' => 'foo',
'array' => ['bar' => 'bar'],
];
$annot = new ApiDoc($data);
$array = $annot->toArray(); $array = $annot->toArray();
$this->assertTrue(is_array($array)); $this->assertTrue(is_array($array));
@ -62,7 +55,7 @@ class ApiDocTest extends TestCase
'description' => 'Heya', 'description' => 'Heya',
]; ];
$annot = new ApiDoc($data); $annot = new ApiDoc(description: $data['description']);
$array = $annot->toArray(); $array = $annot->toArray();
$this->assertTrue(is_array($array)); $this->assertTrue(is_array($array));
@ -82,7 +75,10 @@ class ApiDocTest extends TestCase
'input' => 'My\Form\Type', 'input' => 'My\Form\Type',
]; ];
$annot = new ApiDoc($data); $annot = new ApiDoc(
description: $data['description'],
input: $data['input']
);
$array = $annot->toArray(); $array = $annot->toArray();
$this->assertTrue(is_array($array)); $this->assertTrue(is_array($array));
@ -104,7 +100,12 @@ class ApiDocTest extends TestCase
'input' => 'My\Form\Type', 'input' => 'My\Form\Type',
]; ];
$annot = new ApiDoc($data); $annot = new ApiDoc(
resource: $data['resource'],
description: $data['description'],
deprecated: $data['deprecated'],
input: $data['input']
);
$array = $annot->toArray(); $array = $annot->toArray();
$this->assertTrue(is_array($array)); $this->assertTrue(is_array($array));
@ -126,7 +127,12 @@ class ApiDocTest extends TestCase
'input' => 'My\Form\Type', 'input' => 'My\Form\Type',
]; ];
$annot = new ApiDoc($data); $annot = new ApiDoc(
resource: $data['resource'],
description: $data['description'],
deprecated: $data['deprecated'],
input: $data['input']
);
$array = $annot->toArray(); $array = $annot->toArray();
$this->assertTrue(is_array($array)); $this->assertTrue(is_array($array));
@ -150,7 +156,12 @@ class ApiDocTest extends TestCase
], ],
]; ];
$annot = new ApiDoc($data); $annot = new ApiDoc(
resource: $data['resource'],
description: $data['description'],
deprecated: $data['deprecated'],
filters: $data['filters']
);
$array = $annot->toArray(); $array = $annot->toArray();
$this->assertTrue(is_array($array)); $this->assertTrue(is_array($array));
@ -176,7 +187,10 @@ class ApiDocTest extends TestCase
], ],
]; ];
$annot = new ApiDoc($data); $annot = new ApiDoc(
description: $data['description'],
filters: $data['filters']
);
} }
public function testConstructWithStatusCodes(): void public function testConstructWithStatusCodes(): void
@ -193,7 +207,10 @@ class ApiDocTest extends TestCase
], ],
]; ];
$annot = new ApiDoc($data); $annot = new ApiDoc(
description: $data['description'],
statusCodes: $data['statusCodes']
);
$array = $annot->toArray(); $array = $annot->toArray();
$this->assertTrue(is_array($array)); $this->assertTrue(is_array($array));
@ -216,7 +233,9 @@ class ApiDocTest extends TestCase
], ],
]; ];
$annot = new ApiDoc($data); $annot = new ApiDoc(
requirements: $data['requirements']
);
$array = $annot->toArray(); $array = $annot->toArray();
$this->assertTrue(is_array($array)); $this->assertTrue(is_array($array));
@ -236,7 +255,9 @@ class ApiDocTest extends TestCase
], ],
]; ];
$annot = new ApiDoc($data); $annot = new ApiDoc(
parameters: $data['parameters']
);
$array = $annot->toArray(); $array = $annot->toArray();
$this->assertTrue(is_array($array)); $this->assertTrue(is_array($array));
@ -255,7 +276,9 @@ class ApiDocTest extends TestCase
], ],
]; ];
$annot = new ApiDoc($data); $annot = new ApiDoc(
headers: $data['headers']
);
$array = $annot->toArray(); $array = $annot->toArray();
$this->assertArrayHasKey('headerName', $array['headers']); $this->assertArrayHasKey('headerName', $array['headers']);
@ -272,7 +295,9 @@ class ApiDocTest extends TestCase
'tags' => 'beta', 'tags' => 'beta',
]; ];
$annot = new ApiDoc($data); $annot = new ApiDoc(
tags: $data['tags']
);
$array = $annot->toArray(); $array = $annot->toArray();
$this->assertTrue(is_array($array)); $this->assertTrue(is_array($array));
@ -288,7 +313,9 @@ class ApiDocTest extends TestCase
], ],
]; ];
$annot = new ApiDoc($data); $annot = new ApiDoc(
tags: $data['tags']
);
$array = $annot->toArray(); $array = $annot->toArray();
$this->assertTrue(is_array($array)); $this->assertTrue(is_array($array));
@ -305,7 +332,9 @@ class ApiDocTest extends TestCase
], ],
]; ];
$annot = new ApiDoc($data); $annot = new ApiDoc(
tags: $data['tags']
);
$array = $annot->toArray(); $array = $annot->toArray();
$this->assertTrue(is_array($array)); $this->assertTrue(is_array($array));
@ -322,7 +351,10 @@ class ApiDocTest extends TestCase
], ],
]; ];
$apiDoc = new ApiDoc($data); $apiDoc = new ApiDoc(
output: $data['output'],
responseMap: $data['responseMap']
);
$map = $apiDoc->getResponseMap(); $map = $apiDoc->getResponseMap();
@ -341,7 +373,9 @@ class ApiDocTest extends TestCase
], ],
]; ];
$apiDoc = new ApiDoc($data); $apiDoc = new ApiDoc(
responseMap: $data['responseMap']
);
$map = $apiDoc->getResponseMap(); $map = $apiDoc->getResponseMap();
$this->assertCount(2, $map); $this->assertCount(2, $map);
@ -366,7 +400,7 @@ class ApiDocTest extends TestCase
'{foo}.awesome_host.com' '{foo}.awesome_host.com'
); );
$apiDoc = new ApiDoc([]); $apiDoc = new ApiDoc();
$apiDoc->setRoute($route); $apiDoc->setRoute($route);
$this->assertSame($route, $apiDoc->getRoute()); $this->assertSame($route, $apiDoc->getRoute());

View File

@ -11,7 +11,7 @@
namespace Nelmio\ApiDocBundle\Tests\Extractor; namespace Nelmio\ApiDocBundle\Tests\Extractor;
use Nelmio\ApiDocBundle\Annotation\ApiDoc; use Nelmio\ApiDocBundle\Attribute\ApiDoc;
use Nelmio\ApiDocBundle\Extractor\ApiDocExtractor; use Nelmio\ApiDocBundle\Extractor\ApiDocExtractor;
use Nelmio\ApiDocBundle\Tests\WebTestCase; use Nelmio\ApiDocBundle\Tests\WebTestCase;
@ -41,7 +41,7 @@ class ApiDocExtractorTest extends WebTestCase
$this->assertArrayHasKey('annotation', $d); $this->assertArrayHasKey('annotation', $d);
$this->assertArrayHasKey('resource', $d); $this->assertArrayHasKey('resource', $d);
$this->assertInstanceOf('Nelmio\ApiDocBundle\Annotation\ApiDoc', $d['annotation']); $this->assertInstanceOf('Nelmio\ApiDocBundle\Attribute\ApiDoc', $d['annotation']);
$this->assertInstanceOf('Symfony\Component\Routing\Route', $d['annotation']->getRoute()); $this->assertInstanceOf('Symfony\Component\Routing\Route', $d['annotation']->getRoute());
$this->assertNotNull($d['resource']); $this->assertNotNull($d['resource']);
} }
@ -65,7 +65,7 @@ class ApiDocExtractorTest extends WebTestCase
$extractor = $container->get('nelmio_api_doc.extractor.api_doc_extractor'); $extractor = $container->get('nelmio_api_doc.extractor.api_doc_extractor');
$annotation = $extractor->get('Nelmio\ApiDocBundle\Tests\Fixtures\Controller\TestController::indexAction', 'test_route_1'); $annotation = $extractor->get('Nelmio\ApiDocBundle\Tests\Fixtures\Controller\TestController::indexAction', 'test_route_1');
$this->assertInstanceOf('Nelmio\ApiDocBundle\Annotation\ApiDoc', $annotation); $this->assertInstanceOf('Nelmio\ApiDocBundle\Attribute\ApiDoc', $annotation);
$this->assertTrue($annotation->isResource()); $this->assertTrue($annotation->isResource());
$this->assertEquals('index action', $annotation->getDescription()); $this->assertEquals('index action', $annotation->getDescription());
@ -312,7 +312,7 @@ class ApiDocExtractorTest extends WebTestCase
'test_route_27' 'test_route_27'
); );
$this->assertInstanceOf('Nelmio\ApiDocBundle\Annotation\ApiDoc', $annotation); $this->assertInstanceOf('Nelmio\ApiDocBundle\Attribute\ApiDoc', $annotation);
$array = $annotation->toArray(); $array = $annotation->toArray();
$this->assertTrue(is_array($array['parameters'])); $this->assertTrue(is_array($array['parameters']));
@ -345,7 +345,7 @@ class ApiDocExtractorTest extends WebTestCase
'test_route_27' 'test_route_27'
); );
$this->assertInstanceOf('Nelmio\ApiDocBundle\Annotation\ApiDoc', $annotation); $this->assertInstanceOf('Nelmio\ApiDocBundle\Attribute\ApiDoc', $annotation);
$array = $annotation->toArray(); $array = $annotation->toArray();
$this->assertTrue(is_array($array['parameters'])); $this->assertTrue(is_array($array['parameters']));

View File

@ -11,7 +11,7 @@
namespace Nelmio\ApiDocBundle\Tests\Extractor; namespace Nelmio\ApiDocBundle\Tests\Extractor;
use Nelmio\ApiDocBundle\Annotation\ApiDoc; use Nelmio\ApiDocBundle\Attribute\ApiDoc;
use Nelmio\ApiDocBundle\Extractor\CachingApiDocExtractor; use Nelmio\ApiDocBundle\Extractor\CachingApiDocExtractor;
use Nelmio\ApiDocBundle\Tests\WebTestCase; use Nelmio\ApiDocBundle\Tests\WebTestCase;

View File

@ -11,76 +11,62 @@
namespace Nelmio\ApiDocBundle\Tests\Fixtures\Controller; namespace Nelmio\ApiDocBundle\Tests\Fixtures\Controller;
use Nelmio\ApiDocBundle\Annotation\ApiDoc; use Nelmio\ApiDocBundle\Attribute\ApiDoc;
class ResourceController class ResourceController
{ {
/** #[ApiDoc(
* @ApiDoc( resource: true,
* resource=true, views: ['test', 'premium', 'default'],
* views={ "test", "premium", "default" }, resourceDescription: 'Operations on resource.',
* resourceDescription="Operations on resource.", description: 'List resources.',
* description="List resources.", output: "array<Nelmio\ApiDocBundle\Tests\Fixtures\Model\Test> as tests",
* output="array<Nelmio\ApiDocBundle\Tests\Fixtures\Model\Test> as tests", statusCodes: [200 => 'Returned on success.', 404 => 'Returned if resource cannot be found.']
* statusCodes={200 = "Returned on success.", 404 = "Returned if resource cannot be found."} )]
* )
*/
public function listResourcesAction(): void public function listResourcesAction(): void
{ {
} }
/** #[ApiDoc(description: 'Retrieve a resource by ID.')]
* @ApiDoc(description="Retrieve a resource by ID.")
*/
public function getResourceAction(): void public function getResourceAction(): void
{ {
} }
/** #[ApiDoc(description: 'Delete a resource by ID.')]
* @ApiDoc(description="Delete a resource by ID.")
*/
public function deleteResourceAction(): void public function deleteResourceAction(): void
{ {
} }
/** #[ApiDoc(
* @ApiDoc( description: 'Create a new resource.',
* description="Create a new resource.", views: ['default', 'premium'],
* views={ "default", "premium" }, input: ['class' => "Nelmio\ApiDocBundle\Tests\Fixtures\Form\SimpleType", 'name' => ''],
* input={"class" = "Nelmio\ApiDocBundle\Tests\Fixtures\Form\SimpleType", "name" = ""}, output: "Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsNested",
* output="Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsNested", responseMap: [
* responseMap={ 400 => ['class' => "Nelmio\ApiDocBundle\Tests\Fixtures\Form\SimpleType", 'form_errors' => true],
* 400 = {"class" = "Nelmio\ApiDocBundle\Tests\Fixtures\Form\SimpleType", "form_errors" = true} ]
* } )]
* )
*/
public function createResourceAction(): void public function createResourceAction(): void
{ {
} }
/** #[ApiDoc(
* @ApiDoc( resource: true,
* resource=true, views: ['default', 'premium'],
* views={ "default", "premium" }, description: 'List another resource.',
* description="List another resource.", resourceDescription: 'Operations on another resource.',
* resourceDescription="Operations on another resource.", output: "array<Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsTest>"
* output="array<Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsTest>" )]
* )
*/
public function listAnotherResourcesAction(): void public function listAnotherResourcesAction(): void
{ {
} }
/** #[ApiDoc(description: 'Retrieve another resource by ID.')]
* @ApiDoc(description="Retrieve another resource by ID.")
*/
public function getAnotherResourceAction(): void public function getAnotherResourceAction(): void
{ {
} }
/** #[ApiDoc(description: 'Update a resource bu ID.')]
* @ApiDoc(description="Update a resource bu ID.")
*/
public function updateAnotherResourceAction(): void public function updateAnotherResourceAction(): void
{ {
} }

View File

@ -11,65 +11,57 @@
namespace Nelmio\ApiDocBundle\Tests\Fixtures\Controller; namespace Nelmio\ApiDocBundle\Tests\Fixtures\Controller;
use Nelmio\ApiDocBundle\Annotation\ApiDoc; use Nelmio\ApiDocBundle\Attribute\ApiDoc;
use Nelmio\ApiDocBundle\Tests\Fixtures\DependencyTypePath; use Nelmio\ApiDocBundle\Tests\Fixtures\DependencyTypePath;
use Nelmio\ApiDocBundle\Tests\Fixtures\Form\TestType;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
class TestController class TestController
{ {
/** #[ApiDoc(
* @ApiDoc( resource: 'TestResource',
* resource="TestResource", views: 'default'
* views="default" )]
* )
*/
public function namedResourceAction(): void public function namedResourceAction(): void
{ {
} }
/** #[ApiDoc(
* @ApiDoc( resource: true,
* resource=true, description: 'index action',
* description="index action", filters: [
* filters={ ['name' => 'a', 'dataType' => 'integer'],
* {"name"="a", "dataType"="integer"}, ['name' => 'b', 'dataType' => 'string', 'arbitrary' => ['arg1', 'arg2']],
* {"name"="b", "dataType"="string", "arbitrary"={"arg1", "arg2"}} ],
* } )]
* )
*/
public function indexAction() public function indexAction()
{ {
return new Response('tests'); return new Response('tests');
} }
/** #[ApiDoc(
* @ApiDoc( resource: true,
* resource=true, description: 'create test',
* description="create test", views: ['default', 'premium'],
* views={ "default", "premium" }, input: TestType::class
* input="Nelmio\ApiDocBundle\Tests\Fixtures\Form\TestType" )]
* )
*/
public function postTestAction(): void public function postTestAction(): void
{ {
} }
/** #[ApiDoc(
* @ApiDoc( description: 'post test 2',
* description="post test 2", views: ['default', 'premium'],
* views={ "default", "premium" }, resource: true
* resource=true )]
* )
*/
public function postTest2Action(): void public function postTest2Action(): void
{ {
} }
/** #[ApiDoc(
* @ApiDoc( description: 'Action with required parameters',
* input="Nelmio\ApiDocBundle\Tests\Fixtures\Form\RequiredType" input: "Nelmio\ApiDocBundle\Tests\Fixtures\Form\RequiredType"
* ) )]
*/
public function requiredParametersAction(): void public function requiredParametersAction(): void
{ {
} }
@ -78,16 +70,12 @@ class TestController
{ {
} }
/** #[ApiDoc]
* @ApiDoc()
*/
public function routeVersionAction(): void public function routeVersionAction(): void
{ {
} }
/** #[ApiDoc(description: 'Action without HTTP verb')]
* @ApiDoc(description="Action without HTTP verb")
*/
public function anyAction(): void public function anyAction(): void
{ {
} }
@ -96,233 +84,192 @@ class TestController
* This method is useful to test if the getDocComment works. * This method is useful to test if the getDocComment works.
* And, it supports multilines until the first '@' char. * And, it supports multilines until the first '@' char.
* *
* @ApiDoc()
*
* @param int $id A nice comment * @param int $id A nice comment
* @param int $page * @param int $page
* @param int $paramType The param type * @param int $paramType The param type
* @param int $param The param id * @param int $param The param id
*/ */
#[ApiDoc]
public function myCommentedAction($id, $page, int $paramType, int $param): void public function myCommentedAction($id, $page, int $paramType, int $param): void
{ {
} }
/** #[ApiDoc]
* @ApiDoc()
*/
public function yetAnotherAction(): void public function yetAnotherAction(): void
{ {
} }
/** #[ApiDoc(
* @ApiDoc( views: ['default', 'test'],
* views= { "default", "test" }, description: 'create another test',
* description="create another test", input: DependencyTypePath::TYPE
* input=DependencyTypePath::TYPE )]
* )
*/
public function anotherPostAction(): void public function anotherPostAction(): void
{ {
} }
/** #[ApiDoc(
* @ApiDoc( description: 'Testing JMS',
* description="Testing JMS", input: "Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsTest"
* input="Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsTest" )]
* )
*/
public function jmsInputTestAction(): void public function jmsInputTestAction(): void
{ {
} }
/** #[ApiDoc(
* @ApiDoc( description: 'Testing return',
* description="Testing return", output: DependencyTypePath::TYPE
* output=DependencyTypePath::TYPE )]
* )
*/
public function jmsReturnTestAction(): void public function jmsReturnTestAction(): void
{ {
} }
/** #[ApiDoc]
* @ApiDoc()
*/
public function zCachedAction(): void public function zCachedAction(): void
{ {
} }
/** #[ApiDoc]
* @ApiDoc()
*/
public function zSecuredAction(): void public function zSecuredAction(): void
{ {
} }
/** /**
* @ApiDoc()
*
* @deprecated * @deprecated
*/ */
#[ApiDoc]
public function deprecatedAction(): void public function deprecatedAction(): void
{ {
} }
/** #[ApiDoc(
* @ApiDoc( output: "Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsTest"
* output="Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsTest" )]
* )
*/
public function jmsReturnNestedOutputAction(): void public function jmsReturnNestedOutputAction(): void
{ {
} }
/** #[ApiDoc(
* @ApiDoc( output: "Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsChild"
* output="Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsChild" )]
* )
*/
public function jmsReturnNestedExtendedOutputAction(): void public function jmsReturnNestedExtendedOutputAction(): void
{ {
} }
/** #[ApiDoc(
* @ApiDoc( output: "Nelmio\ApiDocBundle\Tests\Fixtures\Model\MultipleTest"
* output="Nelmio\ApiDocBundle\Tests\Fixtures\Model\MultipleTest" )]
* )
*/
public function zReturnJmsAndValidationOutputAction(): void public function zReturnJmsAndValidationOutputAction(): void
{ {
} }
/** #[ApiDoc(
* @ApiDoc( description: 'Returns a collection of Object',
* description="Returns a collection of Object", requirements: [
* requirements={ ['name' => 'limit', 'dataType' => 'integer', 'requirement' => "\d+", 'description' => 'how many objects to return'],
* {"name"="limit", "dataType"="integer", "requirement"="\d+", "description"="how many objects to return"} ],
* }, parameters: [
* parameters={ ['name' => 'categoryId', 'dataType' => 'integer', 'required' => true, 'description' => 'category id'],
* {"name"="categoryId", "dataType"="integer", "required"=true, "description"="category id"} ]
* } )]
* )
*/
public function cgetAction($id): void public function cgetAction($id): void
{ {
} }
/** #[ApiDoc(
* @ApiDoc( input: [
* input={ 'class' => TestType::class,
* "class"="Nelmio\ApiDocBundle\Tests\Fixtures\Form\TestType", 'parsers' => ["Nelmio\ApiDocBundle\Parser\FormTypeParser"],
* "parsers"={ ]
* "Nelmio\ApiDocBundle\Parser\FormTypeParser", )]
* }
* }
* )
*/
public function zReturnSelectedParsersInputAction(): void public function zReturnSelectedParsersInputAction(): void
{ {
} }
/** #[ApiDoc(
* @ApiDoc( output: [
* output={ 'class' => "Nelmio\ApiDocBundle\Tests\Fixtures\Model\MultipleTest",
* "class"="Nelmio\ApiDocBundle\Tests\Fixtures\Model\MultipleTest", 'parsers' => [
* "parsers"={ "Nelmio\ApiDocBundle\Parser\JmsMetadataParser",
* "Nelmio\ApiDocBundle\Parser\JmsMetadataParser", "Nelmio\ApiDocBundle\Parser\ValidationParser",
* "Nelmio\ApiDocBundle\Parser\ValidationParser" ],
* } ]
* } )]
* )
*/
public function zReturnSelectedParsersOutputAction(): void public function zReturnSelectedParsersOutputAction(): void
{ {
} }
/** #[ApiDoc(
* @ApiDoc( section: 'private'
* section="private" )]
* )
*/
public function privateAction(): void public function privateAction(): void
{ {
} }
/** #[ApiDoc(
* @ApiDoc( section: 'exclusive'
* section="exclusive" )]
* )
*/
public function exclusiveAction(): void public function exclusiveAction(): void
{ {
} }
/** /**
* @ApiDoc()
*
* @see http://symfony.com * @see http://symfony.com
*/ */
#[ApiDoc]
public function withLinkAction(): void public function withLinkAction(): void
{ {
} }
/** #[ApiDoc(
* @ApiDoc( input: ['class' => "Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsTest"],
* output="Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsTest", output: "Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsTest",
* input={ parameters: [
* "class" = "Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsTest" [
* }, 'name' => 'number',
* parameters={ 'dataType' => 'integer',
* { 'actualType' => 'string',
* "name"="number", 'subType' => null,
* "dataType"="integer", 'required' => true,
* "actualType"="string", 'description' => 'This is the new description',
* "subType"=null, 'readonly' => false,
* "required"=true, 'sinceVersion' => 'v3.0',
* "description"="This is the new description", 'untilVersion' => 'v4.0',
* "readonly"=false, ],
* "sinceVersion"="v3.0", [
* "untilVersion"="v4.0" 'name' => 'arr',
* }, 'dataType' => 'object (ArrayCollection)',
* { ],
* "name"="arr", [
* "dataType"="object (ArrayCollection)" 'name' => 'nested',
* }, 'dataType' => 'object (JmsNested)',
* { 'children' => [
* "name"="nested", 'bar' => [
* "dataType"="object (JmsNested)", 'dataType' => 'integer',
* "children": { 'format' => 'd+',
* "bar": { ],
* "dataType"="integer", ],
* "format"="d+" ],
* } ]
* } )]
* }
* }
* )
*/
public function overrideJmsAnnotationWithApiDocParametersAction(): void public function overrideJmsAnnotationWithApiDocParametersAction(): void
{ {
} }
/** #[ApiDoc(
* @ApiDoc( output: "Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsTest",
* output="Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsTest", input: [
* input={ 'class' => "Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsTest",
* "class" = "Nelmio\ApiDocBundle\Tests\Fixtures\Model\JmsTest" ],
* } )]
* )
*/
public function defaultJmsAnnotations(): void public function defaultJmsAnnotations(): void
{ {
} }
/** #[ApiDoc(
* @ApiDoc( description: 'Route with host placeholder',
* description="Route with host placeholder", views: ['default']
* views={ "default" } )]
* )
*/
public function routeWithHostAction(): void public function routeWithHostAction(): void
{ {
} }

View File

@ -14,4 +14,4 @@ if ((!$loader = includeIfExists(__DIR__ . '/../vendor/autoload.php')) && (!$load
} }
// force loading the ApiDoc annotation since the composer target-dir autoloader does not run through $loader::loadClass // force loading the ApiDoc annotation since the composer target-dir autoloader does not run through $loader::loadClass
class_exists('Nelmio\ApiDocBundle\Annotation\ApiDoc'); class_exists('Nelmio\ApiDocBundle\Attribute\ApiDoc');