AnnotationClassLoader.php 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. <?php
  2. namespace Symfony\Component\Routing\Loader;
  3. use Symfony\Component\Routing\RouteCollection;
  4. use Symfony\Component\Routing\Route;
  5. use Doctrine\Common\Annotations\AnnotationReader;
  6. use Symfony\Component\Routing\Annotation\Route as RouteAnnotation;
  7. use Symfony\Component\Routing\Loader\LoaderResolver;
  8. /*
  9. * This file is part of the Symfony framework.
  10. *
  11. * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
  12. *
  13. * This source file is subject to the MIT license that is bundled
  14. * with this source code in the file LICENSE.
  15. */
  16. /**
  17. * AnnotationClassLoader loads routing information from a PHP class and its methods.
  18. *
  19. * You need to define an implementation for the getRouteDefaults() method. Most of the
  20. * time, this method should define some PHP callable to be called for the route
  21. * (a controller in MVC speak).
  22. *
  23. * The @Route annotation can be set on the class (for global parameters),
  24. * and on each method.
  25. *
  26. * The @Route annotation main value is the route pattern. The annotation also
  27. * recognizes three parameters: requirements, options, and name. The name parameter
  28. * is mandatory. Here is an example of how you should be able to use it:
  29. *
  30. * /**
  31. * * @Route("/Blog")
  32. * * /
  33. * class Blog
  34. * {
  35. * /**
  36. * * @Route("/", name="blog_index")
  37. * * /
  38. * public function index()
  39. * {
  40. * }
  41. *
  42. * /**
  43. * * @Route("/:id", name="blog_post", requirements = {"id" = "\d+"})
  44. * * /
  45. * public function show()
  46. * {
  47. * }
  48. * }
  49. *
  50. * @author Fabien Potencier <fabien.potencier@symfony-project.com>
  51. */
  52. abstract class AnnotationClassLoader implements LoaderInterface
  53. {
  54. protected $reader;
  55. /**
  56. * Constructor.
  57. */
  58. public function __construct(AnnotationReader $reader)
  59. {
  60. $this->reader = $reader;
  61. }
  62. /**
  63. * Loads from annotations from a class.
  64. *
  65. * @param string $class A class name
  66. *
  67. * @return RouteCollection A RouteCollection instance
  68. *
  69. * @throws \InvalidArgumentException When route can't be parsed
  70. */
  71. public function load($class)
  72. {
  73. if (!class_exists($class)) {
  74. throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class));
  75. }
  76. $class = new \ReflectionClass($class);
  77. $annotClass = 'Symfony\\Component\\Routing\\Annotation\\Route';
  78. $globals = array(
  79. 'pattern' => '',
  80. 'requirements' => array(),
  81. 'options' => array(),
  82. 'defaults' => array(),
  83. );
  84. if ($annot = $this->reader->getClassAnnotation($class, $annotClass)) {
  85. if (null !== $annot->getPattern()) {
  86. $globals['pattern'] = $annot->getPattern();
  87. }
  88. if (null !== $annot->getRequirements()) {
  89. $globals['requirements'] = $annot->getRequirements();
  90. }
  91. if (null !== $annot->getOptions()) {
  92. $globals['options'] = $annot->getOptions();
  93. }
  94. if (null !== $annot->getDefaults()) {
  95. $globals['defaults'] = $annot->getDefaults();
  96. }
  97. }
  98. $this->reader->setDefaultAnnotationNamespace('Symfony\\Component\\Routing\\Annotation\\');
  99. $collection = new RouteCollection();
  100. foreach ($class->getMethods() as $method) {
  101. if ($annot = $this->reader->getMethodAnnotation($method, $annotClass)) {
  102. if (null === $annot->getName()) {
  103. $annot->setName($this->getDefaultRouteName($class, $method));
  104. }
  105. $defaults = array_merge($globals['defaults'], $annot->getDefaults());
  106. $requirements = array_merge($globals['requirements'], $annot->getRequirements());
  107. $options = array_merge($globals['options'], $annot->getOptions());
  108. $route = new Route($globals['pattern'].$annot->getPattern(), $defaults, $requirements, $options);
  109. $this->configureRoute($route, $class, $method);
  110. $collection->add($annot->getName(), $route);
  111. }
  112. }
  113. return $collection;
  114. }
  115. protected function getDefaultRouteName(\ReflectionClass $class, \ReflectionMethod $method)
  116. {
  117. return strtolower(str_replace('\\', '_', $class->getName()).'_'.$method->getName());
  118. }
  119. /**
  120. * Returns true if this class supports the given resource.
  121. *
  122. * @param mixed $resource A resource
  123. *
  124. * @return Boolean true if this class supports the given resource, false otherwise
  125. */
  126. public function supports($resource)
  127. {
  128. return is_string($resource) && class_exists($resource);
  129. }
  130. /**
  131. * Sets the loader resolver.
  132. *
  133. * @param LoaderResolver $resolver A LoaderResolver instance
  134. */
  135. public function setResolver(LoaderResolver $resolver)
  136. {
  137. }
  138. /**
  139. * Gets the loader resolver.
  140. *
  141. * @return LoaderResolver A LoaderResolver instance
  142. */
  143. public function getResolver()
  144. {
  145. }
  146. abstract protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method);
  147. }