diff --git a/.php_cs.dist b/.php_cs.dist index 88ba9fc..ebd0219 100644 --- a/.php_cs.dist +++ b/.php_cs.dist @@ -12,9 +12,9 @@ return PhpCsFixer\Config::create() 'phpdoc_order' => true, 'header_comment' => [ 'header' => <<resource = !empty($data['resource']) ? $data['resource'] : false; + + if (isset($data['description'])) { + $this->description = $data['description']; + } + + if (isset($data['input'])) { + $this->input = $data['input']; + } + + if (isset($data['filters'])) { + foreach ($data['filters'] as $filter) { + if (!isset($filter['name'])) { + throw new \InvalidArgumentException('A "filter" element has to contain a "name" attribute'); + } + + $name = $filter['name']; + unset($filter['name']); + + $this->addFilter($name, $filter); + } + } + + if (isset($data['requirements'])) { + foreach ($data['requirements'] as $requirement) { + if (!isset($requirement['name'])) { + throw new \InvalidArgumentException('A "requirement" element has to contain a "name" attribute'); + } + + $name = $requirement['name']; + unset($requirement['name']); + + $this->addRequirement($name, $requirement); + } + } + + if (isset($data['views'])) { + if (!is_array($data['views'])) { + $data['views'] = array($data['views']); + } + + foreach ($data['views'] as $view) { + $this->addView($view); + } + } + + if (isset($data['parameters'])) { + foreach ($data['parameters'] as $parameter) { + if (!isset($parameter['name'])) { + throw new \InvalidArgumentException('A "parameter" element has to contain a "name" attribute'); + } + + if (!isset($parameter['dataType'])) { + throw new \InvalidArgumentException(sprintf( + '"%s" parameter element has to contain a "dataType" attribute', + $parameter['name'] + )); + } + + $name = $parameter['name']; + unset($parameter['name']); + + $this->addParameter($name, $parameter); + } + } + + if (isset($data['headers'])) { + foreach ($data['headers'] as $header) { + if (!isset($header['name'])) { + throw new \InvalidArgumentException('A "header" element has to contain a "name" attribute'); + } + + $name = $header['name']; + unset($header['name']); + + $this->addHeader($name, $header); + } + } + + if (isset($data['output'])) { + $this->output = $data['output']; + } + + if (isset($data['statusCodes'])) { + foreach ($data['statusCodes'] as $statusCode => $description) { + $this->addStatusCode($statusCode, $description); + } + } + + if (isset($data['authentication'])) { + $this->setAuthentication((bool) $data['authentication']); + } + + if (isset($data['authenticationRoles'])) { + foreach ($data['authenticationRoles'] as $key => $role) { + $this->authenticationRoles[] = $role; + } + } + + if (isset($data['cache'])) { + $this->setCache($data['cache']); + } + + if (isset($data['section'])) { + $this->section = $data['section']; + } + + 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)) { + $this->addTag($colorCode); + } else { + $this->addTag($tag, $colorCode); + } + } + } else { + $this->tags[] = $data['tags']; + } + } + + if (isset($data['https'])) { + $this->https = $data['https']; + } + + if (isset($data['resourceDescription'])) { + $this->resourceDescription = $data['resourceDescription']; + } + + if (isset($data['responseMap'])) { + $this->responseMap = $data['responseMap']; + if (isset($this->responseMap[200])) { + $this->output = $this->responseMap[200]; + } + } + } + + /** + * @param string $name + * @param array $filter + */ + public function addFilter($name, array $filter) + { + $this->filters[$name] = $filter; + } + + /** + * @param string $statusCode + * @param mixed $description + */ + public function addStatusCode($statusCode, $description) + { + $this->statusCodes[$statusCode] = !is_array($description) ? array($description) : $description; + } + + /** + * @param string $tag + * @param string $colorCode + */ + public function addTag($tag, $colorCode = '#d9534f') + { + $this->tags[$tag] = $colorCode; + } + + /** + * @param string $name + * @param array $requirement + */ + public function addRequirement($name, array $requirement) + { + $this->requirements[$name] = $requirement; + } + + /** + * @param array $requirements + */ + public function setRequirements(array $requirements) + { + $this->requirements = array_merge($this->requirements, $requirements); + } + + /** + * @return string|null + */ + public function getInput() + { + return $this->input; + } + + /** + * @return string|null + */ + public function getOutput() + { + return $this->output; + } + + /** + * @return string + */ + public function getDescription() + { + return $this->description; + } + + /** + * @param string $description + */ + public function setDescription($description) + { + $this->description = $description; + } + + /** + * @param string $link + */ + public function setLink($link) + { + $this->link = $link; + } + + /** + * @param string $section + */ + public function setSection($section) + { + $this->section = $section; + } + + /** + * @return string + */ + public function getSection() + { + return $this->section; + } + + /** + * @return array + */ + public function addView($view) + { + $this->views[] = $view; + } + + /** + * @return array + */ + public function getViews() + { + return $this->views; + } + + /** + * @param string $documentation + */ + public function setDocumentation($documentation) + { + $this->documentation = $documentation; + } + + /** + * @return string + */ + public function getDocumentation() + { + return $this->documentation; + } + + /** + * @return bool + */ + public function isResource() + { + return (bool) $this->resource; + } + + /** + * @return mixed + */ + public function getResource() + { + return $this->resource && is_string($this->resource) ? $this->resource : false; + } + + /** + * @param string $name + * @param array $parameter + */ + public function addParameter($name, array $parameter) + { + $this->parameters[$name] = $parameter; + } + + /** + * @param array $parameters + */ + public function setParameters(array $parameters) + { + $this->parameters = $parameters; + } + + /** + * @param $name + * @param array $header + */ + public function addHeader($name, array $header) + { + $this->headers[$name] = $header; + } + + /** + * Sets the response data as processed by the parsers - same format as parameters. + * + * @param array $response + */ + public function setResponse(array $response) + { + $this->response = $response; + } + + /** + * @param Route $route + */ + public function setRoute(Route $route) + { + $this->route = $route; + + if (method_exists($route, 'getHost')) { + $this->host = $route->getHost() ?: null; + + //replace route placeholders + foreach ($route->getDefaults() as $key => $value) { + if (is_string($value)) { + $this->host = str_replace('{'.$key.'}', $value, $this->host); + } + } + } else { + $this->host = null; + } + + $this->uri = $route->getPath(); + $this->method = $route->getMethods() ? implode('|', $route->getMethods()) : 'ANY'; + } + + /** + * @return Route + */ + public function getRoute() + { + return $this->route; + } + + /** + * @return string + */ + public function getHost() + { + return $this->host; + } + + /** + * @param string $host + */ + public function setHost($host) + { + $this->host = $host; + } + + /** + * @return bool + */ + public function getHttps() + { + return $this->https; + } + + /** + * @param bool $https + */ + public function setHttps($https) + { + $this->https = $https; + } + + /** + * @return bool + */ + public function getAuthentication() + { + return $this->authentication; + } + + /** + * @param bool $authentication + */ + public function setAuthentication($authentication) + { + $this->authentication = $authentication; + } + + /** + * @return array + */ + public function getAuthenticationRoles() + { + return $this->authenticationRoles; + } + + /** + * @param array $authenticationRoles + */ + public function setAuthenticationRoles($authenticationRoles) + { + $this->authenticationRoles = $authenticationRoles; + } + + /** + * @return int + */ + public function getCache() + { + return $this->cache; + } + + /** + * @param int $cache + */ + public function setCache($cache) + { + $this->cache = (int) $cache; + } + + /** + * @return bool + */ + public function getDeprecated() + { + return $this->deprecated; + } + + /** + * @return array + */ + public function getFilters() + { + return $this->filters; + } + + /** + * @return array + */ + public function getRequirements() + { + return $this->requirements; + } + + /** + * @return array + */ + public function getParameters() + { + return $this->parameters; + } + + /** + * @return array + */ + public function getHeaders() + { + return $this->headers; + } + + /** + * @param bool $deprecated + * + * @return $this + */ + public function setDeprecated($deprecated) + { + $this->deprecated = (bool) $deprecated; + + return $this; + } + + /** + * @return string + */ + public function getMethod() + { + return $this->method; + } + + /** + * @return array + */ + public function toArray() + { + $data = array( + 'method' => $this->method, + 'uri' => $this->uri, + ); + + if ($host = $this->host) { + $data['host'] = $host; + } + + if ($description = $this->description) { + $data['description'] = $description; + } + + if ($link = $this->link) { + $data['link'] = $link; + } + + if ($documentation = $this->documentation) { + $data['documentation'] = $documentation; + } + + if ($filters = $this->filters) { + $data['filters'] = $filters; + } + + if ($parameters = $this->parameters) { + $data['parameters'] = $parameters; + } + + if ($headers = $this->headers) { + $data['headers'] = $headers; + } + + if ($requirements = $this->requirements) { + $data['requirements'] = $requirements; + } + + if ($views = $this->views) { + $data['views'] = $views; + } + + if ($response = $this->response) { + $data['response'] = $response; + } + + if ($parsedResponseMap = $this->parsedResponseMap) { + $data['parsedResponseMap'] = $parsedResponseMap; + } + + if ($statusCodes = $this->statusCodes) { + $data['statusCodes'] = $statusCodes; + } + + if ($section = $this->section) { + $data['section'] = $section; + } + + if ($cache = $this->cache) { + $data['cache'] = $cache; + } + + if ($tags = $this->tags) { + $data['tags'] = $tags; + } + + if ($resourceDescription = $this->resourceDescription) { + $data['resourceDescription'] = $resourceDescription; + } + + $data['https'] = $this->https; + $data['authentication'] = $this->authentication; + $data['authenticationRoles'] = $this->authenticationRoles; + $data['deprecated'] = $this->deprecated; + + return $data; + } + + /** + * @return null|string + */ + public function getResourceDescription() + { + return $this->resourceDescription; + } + + /** + * @return array + */ + public function getResponseMap() + { + if (!isset($this->responseMap[200]) && null !== $this->output) { + $this->responseMap[200] = $this->output; + } + + return $this->responseMap; + } + + /** + * @return array + */ + public function getParsedResponseMap() + { + return $this->parsedResponseMap; + } + + /** + * @param $model + * @param $type + * @param int $statusCode + */ + public function setResponseForStatusCode($model, $type, $statusCode = 200) + { + $this->parsedResponseMap[$statusCode] = array('type' => $type, 'model' => $model); + if ($statusCode == 200 && $this->response !== $model) { + $this->response = $model; + } + } +} diff --git a/ApiDocGenerator.php b/ApiDocGenerator.php index a631155..a0f7585 100644 --- a/ApiDocGenerator.php +++ b/ApiDocGenerator.php @@ -1,18 +1,18 @@ findAndSortTaggedServices('exsyst_api_doc.describer', $container); + $describers = $this->findAndSortTaggedServices('nelmio_api_doc.describer', $container); - $container->getDefinition('exsyst_api_doc.generator')->replaceArgument(0, $describers); + $container->getDefinition('nelmio_api_doc.generator')->replaceArgument(0, $describers); } } diff --git a/DependencyInjection/Compiler/AddRouteDescribersPass.php b/DependencyInjection/Compiler/AddRouteDescribersPass.php index c2d2b8a..d1b3e23 100644 --- a/DependencyInjection/Compiler/AddRouteDescribersPass.php +++ b/DependencyInjection/Compiler/AddRouteDescribersPass.php @@ -1,15 +1,15 @@ findAndSortTaggedServices('exsyst_api_doc.route_describer', $container); + $routeDescribers = $this->findAndSortTaggedServices('nelmio_api_doc.route_describer', $container); - $container->getDefinition('exsyst_api_doc.describers.route')->replaceArgument(3, $routeDescribers); + $container->getDefinition('nelmio_api_doc.describers.route')->replaceArgument(3, $routeDescribers); } } diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index d53ace7..5356c53 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -1,15 +1,15 @@ root('exsyst_api_doc') + ->root('nelmio_api_doc') ->children() ->arrayNode('routes') ->info('Filter the routes that are documented') diff --git a/DependencyInjection/EXSystApiDocExtension.php b/DependencyInjection/NelmioApiDocExtension.php similarity index 74% rename from DependencyInjection/EXSystApiDocExtension.php rename to DependencyInjection/NelmioApiDocExtension.php index 843d6be..7178e0b 100644 --- a/DependencyInjection/EXSystApiDocExtension.php +++ b/DependencyInjection/NelmioApiDocExtension.php @@ -1,18 +1,17 @@ load('services.xml'); // Filter routes - $routeCollectionBuilder = $container->getDefinition('exsyst_api_doc.describers.route.filtered_route_collection_builder'); + $routeCollectionBuilder = $container->getDefinition('nelmio_api_doc.describers.route.filtered_route_collection_builder'); $routeCollectionBuilder->replaceArgument(0, $config['routes']['path_patterns']); // Import services needed for each library - if (class_exists(ApiDoc::class)) { - $loader->load('nelmio_apidoc.xml'); - } + $loader->load('nelmio_apidoc.xml'); if (class_exists(DocBlockFactory::class)) { $loader->load('php_doc.xml'); } diff --git a/Describer/ApiPlatformDescriber.php b/Describer/ApiPlatformDescriber.php index ef8aed2..abd5e69 100644 --- a/Describer/ApiPlatformDescriber.php +++ b/Describer/ApiPlatformDescriber.php @@ -1,15 +1,15 @@ addCompilerPass(new AddDescribersPass()); - $container->addCompilerPass(new AddRouteDescribersPass()); - } - - /** - * {@inheritdoc} - */ - public function getContainerExtension() - { - if (null === $this->extension) { - $this->extension = new EXSystApiDocExtension(); - } - if ($this->extension) { - return $this->extension; - } - } -} diff --git a/LICENSE b/LICENSE index 1494f3d..87b56f7 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2016 EXSyst +Copyright (c) 2016 Nelmio Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/NelmioApiDocBundle.php b/NelmioApiDocBundle.php new file mode 100644 index 0000000..7834209 --- /dev/null +++ b/NelmioApiDocBundle.php @@ -0,0 +1,29 @@ +addCompilerPass(new AddDescribersPass()); + $container->addCompilerPass(new AddRouteDescribersPass()); + } +} diff --git a/README.md b/README.md index 70dcf4f..ef7a772 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Just like any bundle, you have to download it using composer: ``` -composer require exsyst/api-doc-bundle dev-master +composer require nelmio/api-doc-bundle dev-master ``` And then add it to your kernel: @@ -18,7 +18,7 @@ class AppKernel extends Kernel $bundles = [ // ... - new EXSyst\Bundle\ApiDocBundle\ApiDocBundle(), + new Nelmio\ApiDocBundle\NelmioApiDocBundle(), ]; // ... @@ -37,7 +37,7 @@ documentation. You can fetch your swagger documentation in your app: ```php -$generator = $container->get('exsyst_api_doc.generator'); +$generator = $container->get('nelmio_api_doc.generator'); $swagger = $generator->generate()->toArray(); ``` diff --git a/Resources/config/api_platform.xml b/Resources/config/api_platform.xml index 1d94baa..51a15c1 100644 --- a/Resources/config/api_platform.xml +++ b/Resources/config/api_platform.xml @@ -4,14 +4,14 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - - + + - + - + diff --git a/Resources/config/fos_rest.xml b/Resources/config/fos_rest.xml index b206fd1..ede8766 100644 --- a/Resources/config/fos_rest.xml +++ b/Resources/config/fos_rest.xml @@ -4,10 +4,10 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - + - + diff --git a/Resources/config/nelmio_apidoc.xml b/Resources/config/nelmio_apidoc.xml index ba5f58e..493eef7 100644 --- a/Resources/config/nelmio_apidoc.xml +++ b/Resources/config/nelmio_apidoc.xml @@ -4,10 +4,10 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - + - + diff --git a/Resources/config/php_doc.xml b/Resources/config/php_doc.xml index d203ce5..47b2624 100644 --- a/Resources/config/php_doc.xml +++ b/Resources/config/php_doc.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - - + + diff --git a/Resources/config/services.xml b/Resources/config/services.xml index 378ff9f..70ee49b 100644 --- a/Resources/config/services.xml +++ b/Resources/config/services.xml @@ -4,21 +4,21 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - + - + - + - + @@ -29,16 +29,16 @@ - + - - + + - - + + diff --git a/Resources/config/swagger_php.xml b/Resources/config/swagger_php.xml index 86859d2..1faa1d1 100644 --- a/Resources/config/swagger_php.xml +++ b/Resources/config/swagger_php.xml @@ -4,10 +4,10 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - + %kernel.root_dir% - + diff --git a/RouteDescriber/FosRestDescriber.php b/RouteDescriber/FosRestDescriber.php index d05bafc..7f69c96 100644 --- a/RouteDescriber/FosRestDescriber.php +++ b/RouteDescriber/FosRestDescriber.php @@ -1,15 +1,15 @@ getContainer()->get('exsyst_api_doc.generator')->generate(); + return static::$kernel->getContainer()->get('nelmio_api_doc.generator')->generate(); } private function getOperation($path, $method) diff --git a/Tests/Functional/TestBundle.php b/Tests/Functional/TestBundle.php index 345fbf1..90d48a9 100644 --- a/Tests/Functional/TestBundle.php +++ b/Tests/Functional/TestBundle.php @@ -1,15 +1,15 @@ loadFromExtension('exsyst_api_doc', [ + $c->loadFromExtension('nelmio_api_doc', [ 'routes' => [ 'path_patterns' => ['^/api(?!/admin)'], ], diff --git a/composer.json b/composer.json index cc1e2b0..a97db83 100644 --- a/composer.json +++ b/composer.json @@ -1,20 +1,27 @@ { - "name": "exsyst/api-doc-bundle", + "name": "nelmio/api-doc-bundle", + "description": "Generates documentation for your REST API from annotations", + "keywords": ["api", "documentation", "doc", "rest"], "type": "symfony-bundle", - "description": "[WIP] Generates Swagger docs from several sources", "license": "MIT", "authors": [ { - "name": "EXSyst" + "name": "Nelmio", + "homepage": "http://nelm.io" + }, + { + "name": "Symfony Community", + "homepage": "https://github.com/nelmio/NelmioApiDocBundle/contributors" } ], "require": { - "php": "^7.0", + "php": "~7.0|~7.1", "symfony/framework-bundle": "^3.2", "exsyst/swagger": "~0.2.2" }, "require-dev": { "symfony/twig-bundle": "^3.2", + "symfony/console": "^3.2", "symfony/config": "^3.2", "symfony/validator": "^3.2", "symfony/property-access": "^3.2", @@ -25,14 +32,12 @@ "phpunit/phpunit": "^5.4", "doctrine/annotations": "^1.2", - "nelmio/api-doc-bundle": "^2.0", "phpdocumentor/reflection-docblock": "^3.1", "zircote/swagger-php": "^2.0", - "api-platform/core": "dev-master", + "api-platform/core": "^2.0", "friendsofsymfony/rest-bundle": "^2.0" }, "suggest": { - "nelmio/api-doc-bundle": "For using the ApiDoc annotation.", "phpdocumentor/reflection-docblock": "For parsing php docs.", "zircote/swagger-php": "For using swagger annotations.", "api-platform/core": "For using an API oriented framework.", @@ -40,14 +45,12 @@ }, "autoload": { "psr-4": { - "EXSyst\\Bundle\\ApiDocBundle\\": "" + "Nelmio\\ApiDocBundle\\": "" } }, "extra": { "branch-alias": { - "dev-master": "0.1.x-dev" + "dev-master": "3.0.x-dev" } - }, - "prefer-stable": true, - "minimum-stability": "dev" + } }