Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 0dc8883
Showing
8 changed files
with
293 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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)); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<?php | ||
|
||
namespace Nelmio\ApiBundle; | ||
|
||
use Symfony\Component\HttpKernel\Bundle\Bundle; | ||
|
||
class NelmioApiBundle extends Bundle | ||
{ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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> |