diff --git a/Controller/ApiDocController.php b/Controller/ApiDocController.php index 1d033b3..7972914 100644 --- a/Controller/ApiDocController.php +++ b/Controller/ApiDocController.php @@ -29,8 +29,13 @@ class ApiDocController extends Controller public function swaggerAction(Request $request, $resource = null) { $docs = $this->get('nelmio_api_doc.extractor.api_doc_extractor')->all(); - $formatter = $this->get('nelmio_api_doc.formatter.swagger_formatter'); + $formatter = $this->get('nelmio_api_doc.formatter.request_aware_swagger_formatter'); $spec = $formatter->format($docs, $resource ? '/' . $resource : null); + + if (count($spec['apis']) === 0) { + throw $this->createNotFoundException(sprintf('Cannot find resource "%s"', $resource)); + } + return new JsonResponse($spec); } } diff --git a/DependencyInjection/SwaggerConfigCompilerPass.php b/DependencyInjection/SwaggerConfigCompilerPass.php index e79e6bf..16d81a2 100644 --- a/DependencyInjection/SwaggerConfigCompilerPass.php +++ b/DependencyInjection/SwaggerConfigCompilerPass.php @@ -39,5 +39,12 @@ class SwaggerConfigCompilerPass implements CompilerPassInterface $formatter->addMethodCall('setSwaggerVersion', array($container->getParameter('nelmio_api_doc.swagger.swagger_version'))); $formatter->addMethodCall('setInfo', array($container->getParameter('nelmio_api_doc.swagger.info'))); + $formatter = $container->getDefinition('nelmio_api_doc.formatter.request_aware_swagger_formatter'); + + $formatter->addMethodCall('setBasePath', array($container->getParameter('nelmio_api_doc.swagger.base_path'))); + $formatter->addMethodCall('setApiVersion', array($container->getParameter('nelmio_api_doc.swagger.api_version'))); + $formatter->addMethodCall('setSwaggerVersion', array($container->getParameter('nelmio_api_doc.swagger.swagger_version'))); + $formatter->addMethodCall('setInfo', array($container->getParameter('nelmio_api_doc.swagger.info'))); + } } \ No newline at end of file diff --git a/Extractor/ApiDocExtractor.php b/Extractor/ApiDocExtractor.php index 8249ab0..239167b 100644 --- a/Extractor/ApiDocExtractor.php +++ b/Extractor/ApiDocExtractor.php @@ -485,8 +485,8 @@ class ApiDocExtractor /** * Creates a human-readable version of the `actualType`. `subType` is taken into account. * - * @param string $actualType - * @param string $subType + * @param string $actualType + * @param string $subType * @return string */ protected function generateHumanReadableType($actualType, $subType) @@ -509,6 +509,7 @@ class ApiDocExtractor if (class_exists($subType)) { $parts = explode('\\', $subType); + return sprintf('array of objects (%s)', end($parts)); } diff --git a/Formatter/RequestAwareSwaggerFormatter.php b/Formatter/RequestAwareSwaggerFormatter.php new file mode 100644 index 0000000..0454699 --- /dev/null +++ b/Formatter/RequestAwareSwaggerFormatter.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Nelmio\ApiDocBundle\Formatter; + + +use Symfony\Component\HttpFoundation\Request; + +/** + * Extends SwaggerFormatter which takes into account the request's base URL when generating the documents for direct swagger-ui consumption. + * + * @author Bezalel Hermoso + */ +class RequestAwareSwaggerFormatter extends SwaggerFormatter +{ + /** + * @var \Symfony\Component\HttpFoundation\Request + */ + protected $request; + + + /** + * @param Request $request + */ + public function __construct(Request $request) + { + $this->request = $request; + } + + /** + * @param array $collection + * @param string $resource + * @return array + */ + protected function produceApiDeclaration(array $collection, $resource) + { + $data = parent::produceApiDeclaration($collection, $resource); + $data['basePath'] = $this->request->getBaseUrl() . $data['basePath']; + return $data; + } +} \ No newline at end of file diff --git a/Formatter/SwaggerFormatter.php b/Formatter/SwaggerFormatter.php index 532249a..9610141 100644 --- a/Formatter/SwaggerFormatter.php +++ b/Formatter/SwaggerFormatter.php @@ -14,6 +14,9 @@ namespace Nelmio\ApiDocBundle\Formatter; use Nelmio\ApiDocBundle\Annotation\ApiDoc; use Nelmio\ApiDocBundle\DataTypes; +use Symfony\Component\DependencyInjection\ContainerAwareInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Router; use Symfony\Component\Routing\RouterInterface; @@ -54,6 +57,11 @@ class SwaggerFormatter implements FormatterInterface DataTypes::DATETIME => 'date-time', ); + /** + * @var Request + */ + protected $request; + /** * Format a collection of documentation data. * @@ -144,7 +152,7 @@ class SwaggerFormatter implements FormatterInterface * @param string $resource * @return array */ - private function produceApiDeclaration(array $collection, $resource) + protected function produceApiDeclaration(array $collection, $resource) { $apiDeclaration = array( diff --git a/Resources/config/formatters.xml b/Resources/config/formatters.xml index ed5ddb7..607be2f 100644 --- a/Resources/config/formatters.xml +++ b/Resources/config/formatters.xml @@ -9,6 +9,7 @@ Nelmio\ApiDocBundle\Formatter\SimpleFormatter Nelmio\ApiDocBundle\Formatter\HtmlFormatter Nelmio\ApiDocBundle\Formatter\SwaggerFormatter + Nelmio\ApiDocBundle\Formatter\RequestAwareSwaggerFormatter null @@ -58,6 +59,9 @@ + + + diff --git a/Tests/Controller/ApiDocControllerTest.php b/Tests/Controller/ApiDocControllerTest.php new file mode 100644 index 0000000..e3c955f --- /dev/null +++ b/Tests/Controller/ApiDocControllerTest.php @@ -0,0 +1,66 @@ + + */ +class ApiDocControllerTest extends WebTestCase +{ + public function testSwaggerDocResourceListRoute() + { + $client = static::createClient(); + $client->request('GET', '/api-docs/'); + + $response = $client->getResponse(); + + $this->assertEquals(200, $response->getStatusCode()); + $this->assertEquals('application/json', $response->headers->get('Content-type')); + + } + + public function dataTestApiDeclarations() + { + return array( + array('resources'), + array('tests'), + array('tests2'), + array('TestResource'), + ); + } + + /** + * @dataProvider dataTestApiDeclarations + */ + public function testApiDeclarationRoutes($resource) + { + $client = static::createClient(); + $client->request('GET', '/api-docs/' . $resource); + + $response = $client->getResponse(); + + $this->assertEquals(200, $response->getStatusCode()); + $this->assertEquals('application/json', $response->headers->get('Content-type')); + } + + public function testNonExistingApiDeclaration() + { + $client = static::createClient(); + $client->request('GET', '/api-docs/santa'); + + $response = $client->getResponse(); + $this->assertEquals(404, $response->getStatusCode()); + + } +} diff --git a/Tests/Fixtures/Controller/ResourceController.php b/Tests/Fixtures/Controller/ResourceController.php index e5d77a4..502f9c2 100644 --- a/Tests/Fixtures/Controller/ResourceController.php +++ b/Tests/Fixtures/Controller/ResourceController.php @@ -1,21 +1,17 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. */ namespace Nelmio\ApiDocBundle\Tests\Fixtures\Controller; use Nelmio\ApiDocBundle\Annotation\ApiDoc; - -/** - * Class ResourceController - * - * @package Nelmio\ApiDocBundle\Tests\Fixtures\Controller - * @author Bez Hermoso - */ class ResourceController { /** diff --git a/Tests/Fixtures/app/config/routing.yml b/Tests/Fixtures/app/config/routing.yml index 45b90b6..0ac72be 100644 --- a/Tests/Fixtures/app/config/routing.yml +++ b/Tests/Fixtures/app/config/routing.yml @@ -203,3 +203,7 @@ test_route_update_another_resource: requirements: _method: PUT|PATCH _format: json|xml|html + +swagger_doc: + resource: @NelmioApiDocBundle/Resources/config/swagger_routing.yml + prefix: /api-docs \ No newline at end of file