mirror of
https://github.com/retailcrm/NelmioApiDocBundle.git
synced 2025-02-02 15:51:48 +03:00
Introduced ApiBundle
This commit is contained in:
commit
0dc8883e09
61
Annotation/ApiDoc.php
Normal file
61
Annotation/ApiDoc.php
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Nelmio\ApiBundle\Annotation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Annotation
|
||||||
|
*/
|
||||||
|
class ApiDoc
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $filters = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $formType = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $comment = null;
|
||||||
|
|
||||||
|
public function __construct(array $data)
|
||||||
|
{
|
||||||
|
if (isset($data['formType'])) {
|
||||||
|
$this->formType = $data['formType'];
|
||||||
|
} else 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->filters[$name] = $filter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($data['comment'])) {
|
||||||
|
$this->comment = $data['comment'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFilters()
|
||||||
|
{
|
||||||
|
return $this->filters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFormType()
|
||||||
|
{
|
||||||
|
return $this->formType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getComment()
|
||||||
|
{
|
||||||
|
return $this->comment;
|
||||||
|
}
|
||||||
|
}
|
21
DependencyInjection/NelmioApiExtension.php
Normal file
21
DependencyInjection/NelmioApiExtension.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Nelmio\ApiBundle\DependencyInjection;
|
||||||
|
|
||||||
|
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
||||||
|
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
|
||||||
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
|
use Symfony\Component\Config\FileLocator;
|
||||||
|
|
||||||
|
class NelmioApiExtension extends Extension
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function load(array $configs, ContainerBuilder $container)
|
||||||
|
{
|
||||||
|
$loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
|
||||||
|
$loader->load('request_listener.xml');
|
||||||
|
$loader->load('services.xml');
|
||||||
|
}
|
||||||
|
}
|
57
EventListener/RequestListener.php
Normal file
57
EventListener/RequestListener.php
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Nelmio\ApiBundle\EventListener;
|
||||||
|
|
||||||
|
use Doctrine\Common\Annotations\Reader;
|
||||||
|
use Nelmio\ApiBundle\Formatter\ApiDocFormatter;
|
||||||
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||||
|
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||||
|
use Symfony\Component\Routing\RouterInterface;
|
||||||
|
|
||||||
|
class RequestListener
|
||||||
|
{
|
||||||
|
protected $annotationClass = 'Nelmio\\ApiBundle\\Annotation\\ApiDoc';
|
||||||
|
|
||||||
|
protected $reader;
|
||||||
|
|
||||||
|
protected $router;
|
||||||
|
|
||||||
|
protected $formatter;
|
||||||
|
|
||||||
|
public function __construct(Reader $reader, RouterInterface $router, ApiDocFormatter $formatter)
|
||||||
|
{
|
||||||
|
$this->reader = $reader;
|
||||||
|
$this->router = $router;
|
||||||
|
$this->formatter = $formatter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function onKernelRequest(GetResponseEvent $event)
|
||||||
|
{
|
||||||
|
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$request = $event->getRequest();
|
||||||
|
|
||||||
|
if (!$request->get('_doc')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
preg_match('#(.+)::([\w]+)#', $request->get('_controller'), $matches);
|
||||||
|
$method = new \ReflectionMethod($matches[1], $matches[2]);
|
||||||
|
$route = $request->get('_route');
|
||||||
|
|
||||||
|
if ($annot = $this->reader->getMethodAnnotation($method, $this->annotationClass)) {
|
||||||
|
if ($route = $this->router->getRouteCollection()->get($route)) {
|
||||||
|
$result = $this->formatter->format($annot, $route);
|
||||||
|
|
||||||
|
$event->setResponse(new JsonResponse($result));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
53
Formatter/ApiDocFormatter.php
Normal file
53
Formatter/ApiDocFormatter.php
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Nelmio\ApiBundle\Formatter;
|
||||||
|
|
||||||
|
use Nelmio\ApiBundle\Annotation\ApiDoc;
|
||||||
|
use Nelmio\ApiBundle\Parser\FormTypeParser;
|
||||||
|
use Symfony\Component\Routing\Route;
|
||||||
|
|
||||||
|
class ApiDocFormatter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var \Nelmio\ApiBundle\Parser\FormTypeParser
|
||||||
|
*/
|
||||||
|
protected $parser;
|
||||||
|
|
||||||
|
public function __construct(FormTypeParser $parser)
|
||||||
|
{
|
||||||
|
$this->parser = $parser;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function format(ApiDoc $apiDoc, Route $route)
|
||||||
|
{
|
||||||
|
$method = $route->getRequirement('_method');
|
||||||
|
$data = array(
|
||||||
|
'method' => $method,
|
||||||
|
'uri' => $route->compile()->getPattern(),
|
||||||
|
'requirements' => $route->compile()->getRequirements(),
|
||||||
|
);
|
||||||
|
|
||||||
|
unset($data['requirements']['_method']);
|
||||||
|
|
||||||
|
if (null !== $formType = $apiDoc->getFormType()) {
|
||||||
|
$data['parameters'] = $this->parser->parse(new $formType());
|
||||||
|
|
||||||
|
if ('PUT' === $method) {
|
||||||
|
// All parameters are optional with PUT (update)
|
||||||
|
array_walk($data['parameters'], function($val, $key) use (&$data) {
|
||||||
|
$data['parameters'][$key]['is_required'] = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($filters = $apiDoc->getFilters()) {
|
||||||
|
$data['filters'] = $filters;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($comment = $apiDoc->getComment()) {
|
||||||
|
$data['comment'] = $comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
}
|
9
NelmioApiBundle.php
Normal file
9
NelmioApiBundle.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Nelmio\ApiBundle;
|
||||||
|
|
||||||
|
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||||
|
|
||||||
|
class NelmioApiBundle extends Bundle
|
||||||
|
{
|
||||||
|
}
|
53
Parser/FormTypeParser.php
Normal file
53
Parser/FormTypeParser.php
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Nelmio\ApiBundle\Parser;
|
||||||
|
|
||||||
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
use Symfony\Component\Form\FormBuilder;
|
||||||
|
use Symfony\Component\Form\FormFactoryInterface;
|
||||||
|
|
||||||
|
class FormTypeParser
|
||||||
|
{
|
||||||
|
protected $formFactory;
|
||||||
|
|
||||||
|
protected $mapTypes = array(
|
||||||
|
'text' => 'string',
|
||||||
|
'date' => 'date',
|
||||||
|
'datetime' => 'datetime',
|
||||||
|
'checkbox' => 'boolean',
|
||||||
|
'time' => 'time',
|
||||||
|
'number' => 'float',
|
||||||
|
'integer' => 'int',
|
||||||
|
'textarea' => 'string',
|
||||||
|
);
|
||||||
|
|
||||||
|
public function __construct(FormFactoryInterface $formFactory)
|
||||||
|
{
|
||||||
|
$this->formFactory = $formFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parse(AbstractType $type)
|
||||||
|
{
|
||||||
|
$builder = $this->formFactory->createBuilder($type);
|
||||||
|
|
||||||
|
$parameters = array();
|
||||||
|
foreach ($builder->all() as $name => $child) {
|
||||||
|
$b = $builder->create($name, $child['type'], $child['options']);
|
||||||
|
|
||||||
|
$bestType = '';
|
||||||
|
foreach ($b->getTypes() as $type) {
|
||||||
|
if (isset($this->mapTypes[$type->getName()])) {
|
||||||
|
$bestType = $this->mapTypes[$type->getName()];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$parameters[] = array(
|
||||||
|
'name' => $name,
|
||||||
|
'type' => $bestType,
|
||||||
|
'is_required' => $b->getRequired()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $parameters;
|
||||||
|
}
|
||||||
|
}
|
19
Resources/config/request_listener.xml
Normal file
19
Resources/config/request_listener.xml
Normal 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">
|
||||||
|
|
||||||
|
<parameters>
|
||||||
|
<parameter key="nelmio.api.event_listener.request.class">Nelmio\ApiBundle\EventListener\RequestListener</parameter>
|
||||||
|
</parameters>
|
||||||
|
|
||||||
|
<services>
|
||||||
|
<service id="nelmio.api.event_listener.request" class="%nelmio.api.event_listener.request.class%">
|
||||||
|
<argument type="service" id="annotation_reader" />
|
||||||
|
<argument type="service" id="router" />
|
||||||
|
<argument type="service" id="nelmio.api.formatter.api_doc_formatter" />
|
||||||
|
<tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" />
|
||||||
|
</service>
|
||||||
|
</services>
|
||||||
|
|
||||||
|
</container>
|
20
Resources/config/services.xml
Normal file
20
Resources/config/services.xml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?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">
|
||||||
|
|
||||||
|
<parameters>
|
||||||
|
<parameter key="nelmio.api.parser.form_type_parser.class">Nelmio\ApiBundle\Parser\FormTypeParser</parameter>
|
||||||
|
<parameter key="nelmio.api.formatter.api_doc_formatter.class">Nelmio\ApiBundle\Formatter\ApiDocFormatter</parameter>
|
||||||
|
</parameters>
|
||||||
|
|
||||||
|
<services>
|
||||||
|
<service id="nelmio.api.parser.form_type_parser" class="%nelmio.api.parser.form_type_parser.class%">
|
||||||
|
<argument type="service" id="form.factory" />
|
||||||
|
</service>
|
||||||
|
<service id="nelmio.api.formatter.api_doc_formatter" class="%nelmio.api.formatter.api_doc_formatter.class%">
|
||||||
|
<argument type="service" id="nelmio.api.parser.form_type_parser" />
|
||||||
|
</service>
|
||||||
|
</services>
|
||||||
|
|
||||||
|
</container>
|
Loading…
x
Reference in New Issue
Block a user