NelmioApiDocBundle/Extractor/ApiDocExtractor.php

158 lines
4.8 KiB
PHP
Raw Normal View History

<?php
2012-04-13 11:03:05 +02:00
/*
* This file is part of the NelmioApiDocBundle.
*
* (c) Nelmio <hello@nelm.io>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
2012-04-12 18:37:42 +02:00
namespace Nelmio\ApiDocBundle\Extractor;
use Doctrine\Common\Annotations\Reader;
use Symfony\Component\Routing\RouterInterface;
2012-04-13 16:33:24 +02:00
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
class ApiDocExtractor
{
2012-04-12 18:37:42 +02:00
const ANNOTATION_CLASS = 'Nelmio\\ApiDocBundle\\Annotation\\ApiDoc';
2012-04-13 16:33:24 +02:00
/**
* @var \Symfony\Component\DependencyInjection\ContainerInterface
*/
private $container;
/**
2012-04-12 17:48:21 +02:00
* @var \ymfony\Component\Routing\RouterInterface
*/
private $router;
/**
* @var \Doctrine\Common\Annotations\Reader
*/
private $reader;
2012-04-13 16:33:24 +02:00
public function __construct(ContainerInterface $container, RouterInterface $router, Reader $reader)
{
2012-04-13 16:33:24 +02:00
$this->container = $container;
$this->router = $router;
$this->reader = $reader;
}
2012-04-12 17:48:21 +02:00
/**
* Returns an array of data where each data is an array with the following keys:
* - annotation
* - route
* - resource
*
* @return array
*/
public function all()
{
$array = array();
$resources = array();
2012-04-13 16:33:24 +02:00
foreach ($this->router->getRouteCollection()->all() as $route) {
$method = false;
if (preg_match('#(.+)::([\w]+)#', $route->getDefault('_controller'), $matches)) {
$method = new \ReflectionMethod($matches[1], $matches[2]);
} elseif (preg_match('#(.+):([\w]+)#', $route->getDefault('_controller'), $matches)) {
$controller = $matches[1];
if ($this->container->has($controller)) {
$this->container->enterScope('request');
$this->container->set('request', new Request);
$class = get_class($this->container->get($controller));
$this->container->leaveScope('request');
$method = new \ReflectionMethod($class, $matches[2]);
}
2012-04-13 16:33:24 +02:00
}
2012-04-13 16:33:24 +02:00
if ($method) {
$annot = $this->reader->getMethodAnnotation($method, self::ANNOTATION_CLASS);
if ($annot) {
if ($annot->isResource()) {
$resources[] = $route->getPattern();
}
$array[] = array('annotation' => $annot, 'route' => $route);
}
}
}
rsort($resources);
foreach ($array as $index => $element) {
$hasResource = false;
$pattern = $element['route']->getPattern();
foreach ($resources as $resource) {
if (0 === strpos($pattern, $resource)) {
$array[$index]['resource'] = $resource;
$hasResource = true;
break;
}
}
if (false === $hasResource) {
$array[$index]['resource'] = 'others';
}
}
2012-04-13 10:48:25 +02:00
$methodOrder = array('GET', 'POST', 'PUT', 'DELETE');
usort($array, function($a, $b) use ($methodOrder) {
if ($a['resource'] === $b['resource']) {
if ($a['route']->getPattern() === $b['route']->getPattern()) {
2012-04-13 10:48:25 +02:00
$methodA = array_search($a['route']->getRequirement('_method'), $methodOrder);
$methodB = array_search($b['route']->getRequirement('_method'), $methodOrder);
if ($methodA === $methodB) {
return strcmp($a['route']->getRequirement('_method'), $b['route']->getRequirement('_method'));
}
return $methodA > $methodB ? 1 : -1;
}
return strcmp($a['route']->getPattern(), $b['route']->getPattern());
}
return strcmp($a['resource'], $b['resource']);
});
return $array;
}
2012-04-12 17:48:21 +02:00
/**
* Returns an array containing two values with the following keys:
* - annotation
* - route
*
* @param string $controller
* @param Route $route
* @return array|null
*/
public function get($controller, $route)
{
if (!preg_match('#(.+)::([\w]+)#', $controller, $matches)) {
2012-04-13 14:42:28 +02:00
return null;
}
2012-04-13 14:42:28 +02:00
try {
$method = new \ReflectionMethod($matches[1], $matches[2]);
} catch (\ReflectionException $e) {
return null;
}
if ($annot = $this->reader->getMethodAnnotation($method, self::ANNOTATION_CLASS)) {
if ($route = $this->router->getRouteCollection()->get($route)) {
return array('annotation' => $annot, 'route' => $route);
}
}
2012-04-13 14:42:28 +02:00
return null;
}
}