Add ApiPlatform support

This commit is contained in:
Ener-Getick 2016-07-29 10:22:40 +02:00
parent abe82b19a9
commit 170249b369
No known key found for this signature in database
GPG Key ID: 9E5D2DB67BF054DD
14 changed files with 203 additions and 38 deletions

View File

@ -21,7 +21,7 @@ HeaderCommentFixer::setHeader($header);
return Config::create() return Config::create()
->level(FixerInterface::SYMFONY_LEVEL) ->level(FixerInterface::SYMFONY_LEVEL)
->fixers(array('align_double_arrow', 'header_comment')) ->fixers(array('header_comment'))
->finder($finder) ->finder($finder)
->setUsingCache(true) ->setUsingCache(true)
; ;

View File

@ -23,6 +23,6 @@ class AddRouteDescribersPass implements CompilerPassInterface
{ {
$routeDescribers = $this->findAndSortTaggedServices('exsyst_api_doc.route_describer', $container); $routeDescribers = $this->findAndSortTaggedServices('exsyst_api_doc.route_describer', $container);
$container->getDefinition('exsyst_api_doc.describers.route')->replaceArgument(2, $routeDescribers); $container->getDefinition('exsyst_api_doc.describers.route')->replaceArgument(3, $routeDescribers);
} }
} }

View File

@ -49,5 +49,11 @@ class EXSystApiDocExtension extends Extension
if (!class_exists(Swagger::class)) { if (!class_exists(Swagger::class)) {
$container->removeDefinition('exsyst_api_doc.describers.swagger_php'); $container->removeDefinition('exsyst_api_doc.describers.swagger_php');
} }
$bundles = $container->getParameter('kernel.bundles');
// ApiPlatform support
if (isset($bundles['ApiPlatformBundle']) && class_exists('ApiPlatform\Core\Documentation\Documentation')) {
$loader->load('api_platform.xml');
}
} }
} }

View File

@ -0,0 +1,28 @@
<?php
/*
* This file is part of the ApiDocBundle package.
*
* (c) EXSyst
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace EXSyst\Bundle\ApiDocBundle\Describer;
use ApiPlatform\Core\Documentation\Documentation;
use ApiPlatform\Core\Swagger\DocumentationNormalizer;
class ApiPlatformDescriber extends ExternalDocDescriber
{
/**
* @param string $projectPath
*/
public function __construct(Documentation $documentation, DocumentationNormalizer $normalizer, bool $overwrite = false)
{
parent::__construct(function () use ($documentation, $normalizer) {
return $normalizer->normalize($documentation);
}, $overwrite);
}
}

View File

@ -11,35 +11,30 @@
namespace EXSyst\Bundle\ApiDocBundle\Describer; namespace EXSyst\Bundle\ApiDocBundle\Describer;
use Doctrine\Common\Util\ClassUtils;
use EXSyst\Bundle\ApiDocBundle\RouteDescriber\RouteDescriberInterface;
use gossi\swagger\Swagger; use gossi\swagger\Swagger;
use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouterInterface;
class ExternalDocDescriber implements DescriberInterface class ExternalDocDescriber implements DescriberInterface
{ {
private $externalDoc; private $externalDoc;
private $stategy; private $overwrite;
/** /**
* @param array|callable $externalDoc * @param array|callable $externalDoc
* @param int $strategy * @param int $strategy
*/ */
public function __construct($externalDoc, $strategy = Swagger::PREFER_ORIGINAL) public function __construct($externalDoc, bool $overwrite = false)
{ {
$this->externalDoc = $externalDoc; $this->externalDoc = $externalDoc;
$this->strategy = $strategy; $this->overwrite = $overwrite;
} }
public function describe(Swagger $api) public function describe(Swagger $api)
{ {
$externalDoc = $this->getExternalDoc(); $externalDoc = $this->getExternalDoc();
$api->merge($externalDoc, $this->strategy); $api->merge($externalDoc, $this->overwrite);
} }
private function getExternalDoc(): array private function getExternalDoc()
{ {
if (is_callable($this->externalDoc)) { if (is_callable($this->externalDoc)) {
return call_user_func($this->externalDoc); return call_user_func($this->externalDoc);

View File

@ -15,20 +15,26 @@ use Doctrine\Common\Util\ClassUtils;
use EXSyst\Bundle\ApiDocBundle\RouteDescriber\RouteDescriberInterface; use EXSyst\Bundle\ApiDocBundle\RouteDescriber\RouteDescriberInterface;
use gossi\swagger\Swagger; use gossi\swagger\Swagger;
use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser; use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Routing\Route; use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouterInterface; use Symfony\Component\Routing\RouterInterface;
class RouteDescriber implements DescriberInterface class RouteDescriber implements DescriberInterface
{ {
private $container;
private $router;
private $controllerNameParser;
private $routeDescribers; private $routeDescribers;
/** /**
* @param ContainerInterface $container
* @param RouterInterface $router * @param RouterInterface $router
* @param ControllerNameParser $controllerNameParser * @param ControllerNameParser $controllerNameParser
* @param RouteDescriberInterface[] $routeDescribers * @param RouteDescriberInterface[] $routeDescribers
*/ */
public function __construct(RouterInterface $router, ControllerNameParser $controllerNameParser, array $routeDescribers) public function __construct(ContainerInterface $container, RouterInterface $router, ControllerNameParser $controllerNameParser, array $routeDescribers)
{ {
$this->container = $container;
$this->router = $router; $this->router = $router;
$this->controllerNameParser = $controllerNameParser; $this->controllerNameParser = $controllerNameParser;
$this->routeDescribers = $routeDescribers; $this->routeDescribers = $routeDescribers;

View File

@ -11,31 +11,17 @@
namespace EXSyst\Bundle\ApiDocBundle\Describer; namespace EXSyst\Bundle\ApiDocBundle\Describer;
use gossi\swagger\Swagger; class SwaggerPhpDescriber extends ExternalDocDescriber
class SwaggerPhpDescriber implements DescriberInterface
{ {
private $projectPath;
private $overwrite;
/** /**
* @param string $projectPath * @param string $projectPath
*/ */
public function __construct(string $projectPath, bool $overwrite = false) public function __construct(string $projectPath, bool $overwrite = false)
{ {
$this->projectPath = $projectPath; parent::__construct(function () use ($projectPath) {
$this->overwrite = $overwrite; $annotation = \Swagger\scan($projectPath);
}
public function describe(Swagger $api) return json_decode(json_encode($annotation));
{ }, $overwrite);
$annotation = \Swagger\scan($this->projectPath);
$api->merge($this->normalize($annotation), $this->overwrite);
}
private function normalize($annotation)
{
return json_decode(json_encode($annotation));
} }
} }

26
Model/ModelDescriber.php Normal file
View File

@ -0,0 +1,26 @@
<?php
namespace EXSyst\Bundle\ApiDocBundle\Model;
use gossi\swagger\Schema;
class ModelDescriber
{
private $namingStrategy;
private $models = [];
public function __construct(callable $namingStrategy = null)
{
if (null === namingStrategy) {
$namingStrategy = function ($class) {
return str_replace('\\', '_', $class);
}
}
$this->namingStrategy = $namingStrategy;
}
public function describe(string $class, array $options = []): Schema
{
}
}

View File

@ -0,0 +1,19 @@
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="exsyst_api_doc.describers.api_platform" class="EXSyst\Bundle\ApiDocBundle\Describer\ApiPlatformDescriber" public="false">
<argument type="service" id="exsyst_api_doc.describers.api_platform.documentation" />
<argument type="service" id="api_platform.swagger.normalizer.documentation" />
<tag name="exsyst_api_doc.describer" priority="-150" />
</service>
<service id="exsyst_api_doc.describers.api_platform.documentation" class="ApiPlatform\Core\Documentation\Documentation" public="false">
<factory service="api_platform.action.documentation" method="__invoke" />
</service>
</services>
</container>

View File

@ -16,6 +16,7 @@
</service> </service>
<service id="exsyst_api_doc.describers.route" class="EXSyst\Bundle\ApiDocBundle\Describer\RouteDescriber" public="false"> <service id="exsyst_api_doc.describers.route" class="EXSyst\Bundle\ApiDocBundle\Describer\RouteDescriber" public="false">
<argument type="service" id="service_container" />
<argument type="service" id="router" /> <argument type="service" id="router" />
<argument type="service" id="controller_name_converter" /> <argument type="service" id="controller_name_converter" />
<argument type="collection" /> <argument type="collection" />

View File

@ -0,0 +1,68 @@
<?php
/*
* This file is part of the ApiDocBundle package.
*
* (c) EXSyst
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace EXSyst\Bundle\ApiDocBundle\Tests\Functional\Entity;
use ApiPlatform\Core\Annotation\ApiProperty;
use ApiPlatform\Core\Annotation\ApiResource;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @author Guilhem N. <egetick@gmail.com>
*
* @ApiResource(
* collectionOperations={"get"={"method"="GET"}},
* itemOperations={"get"={"method"="GET"}})
* )
*/
class Dummy
{
/**
* @var int
*/
private $id;
/**
* @var string
*
* @Assert\NotBlank
* @ApiProperty(iri="http://schema.org/name")
*/
private $name;
/**
* @var array
*/
private $foo;
public function getId(): int
{
return $this->id;
}
public function setName(string $name)
{
$this->name = $name;
}
public function getName(): string
{
return $this->name;
}
public function hasRole(string $role)
{
}
public function setFoo(array $foo = null)
{
}
}

View File

@ -0,0 +1,18 @@
<?php
/*
* This file is part of the ApiDocBundle package.
*
* (c) EXSyst
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace EXSyst\Bundle\ApiDocBundle\Tests\Functional;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class TestBundle extends Bundle
{
}

View File

@ -9,7 +9,9 @@
* file that was distributed with this source code. * file that was distributed with this source code.
*/ */
use ApiPlatform\Core\Bridge\Symfony\Bundle\ApiPlatformBundle;
use EXSyst\Bundle\ApiDocBundle\EXSystApiDocBundle; use EXSyst\Bundle\ApiDocBundle\EXSystApiDocBundle;
use EXSyst\Bundle\ApiDocBundle\Tests\Functional\TestBundle;
use Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle; use Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle;
use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
@ -30,7 +32,9 @@ class TestKernel extends Kernel
return [ return [
new FrameworkBundle(), new FrameworkBundle(),
new SensioFrameworkExtraBundle(), new SensioFrameworkExtraBundle(),
new ApiPlatformBundle(),
new EXSystApiDocBundle(), new EXSystApiDocBundle(),
new TestBundle(),
]; ];
} }
@ -40,6 +44,7 @@ class TestKernel extends Kernel
protected function configureRoutes(RouteCollectionBuilder $routes) protected function configureRoutes(RouteCollectionBuilder $routes)
{ {
$routes->import(__DIR__.'/Controller/', '/', 'annotation'); $routes->import(__DIR__.'/Controller/', '/', 'annotation');
$routes->import('', '/api', 'api_platform');
} }
/** /**
@ -49,7 +54,8 @@ class TestKernel extends Kernel
{ {
$c->loadFromExtension('framework', [ $c->loadFromExtension('framework', [
'secret' => 'MySecretKey', 'secret' => 'MySecretKey',
'test' => null, 'test' => null,
'validation' => null,
]); ]);
} }
} }

View File

@ -10,21 +10,27 @@
], ],
"require": { "require": {
"php": "^7.0", "php": "^7.0",
"symfony/framework-bundle": "^3.2@dev", "symfony/framework-bundle": "^3.2",
"exsyst/swagger": "dev-master" "exsyst/swagger": "dev-master"
}, },
"require-dev": { "require-dev": {
"symfony/browser-kit": "^2.8|^3.0", "symfony/validator": "^3.2",
"symfony/phpunit-bridge": "^3.2@dev", "symfony/property-access": "^3.2",
"symfony/browser-kit": "^3.2",
"symfony/cache": "^3.2",
"symfony/phpunit-bridge": "^3.2",
"sensio/framework-extra-bundle": "^3.0", "sensio/framework-extra-bundle": "^3.0",
"nelmio/api-doc-bundle": "^2.0", "nelmio/api-doc-bundle": "^2.0",
"phpdocumentor/reflection-docblock": "^3.1", "phpdocumentor/reflection-docblock": "^3.1",
"phpunit/phpunit": "^5.4", "phpunit/phpunit": "^5.4",
"zircote/swagger-php": "^2.0" "zircote/swagger-php": "^2.0",
"api-platform/core": "^2.0"
}, },
"suggest": { "suggest": {
"nelmio/api-doc-bundle": "For using the ApiDoc annotation.", "nelmio/api-doc-bundle": "For using the ApiDoc annotation.",
"phpdocumentor/reflection-docblock": "For parsing php docs." "phpdocumentor/reflection-docblock": "For parsing php docs.",
"zircote/swagger-php": "For using swagger annotations.",
"api-platform/core": "For using an API oriented framework."
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {