1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10:
11:
12: namespace Symfony\Component\Routing\Loader;
13:
14: use Doctrine\Common\Annotations\Reader;
15: use Symfony\Component\Config\Resource\FileResource;
16: use Symfony\Component\Routing\Route;
17: use Symfony\Component\Routing\RouteCollection;
18: use Symfony\Component\Config\Loader\LoaderInterface;
19: use Symfony\Component\Config\Loader\LoaderResolverInterface;
20:
21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57:
58: abstract class AnnotationClassLoader implements LoaderInterface
59: {
60: 61: 62:
63: protected $reader;
64:
65: 66: 67:
68: protected $routeAnnotationClass = 'Symfony\\Component\\Routing\\Annotation\\Route';
69:
70: 71: 72:
73: protected $defaultRouteIndex = 0;
74:
75: 76: 77: 78: 79:
80: public function __construct(Reader $reader)
81: {
82: $this->reader = $reader;
83: }
84:
85: 86: 87: 88: 89:
90: public function setRouteAnnotationClass($class)
91: {
92: $this->routeAnnotationClass = $class;
93: }
94:
95: 96: 97: 98: 99: 100: 101: 102: 103: 104:
105: public function load($class, $type = null)
106: {
107: if (!class_exists($class)) {
108: throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class));
109: }
110:
111: $class = new \ReflectionClass($class);
112: if ($class->isAbstract()) {
113: throw new \InvalidArgumentException(sprintf('Annotations from class "%s" cannot be read as it is abstract.', $class->getName()));
114: }
115:
116: $globals = $this->getGlobals($class);
117:
118: $collection = new RouteCollection();
119: $collection->addResource(new FileResource($class->getFileName()));
120:
121: foreach ($class->getMethods() as $method) {
122: $this->defaultRouteIndex = 0;
123: foreach ($this->reader->getMethodAnnotations($method) as $annot) {
124: if ($annot instanceof $this->routeAnnotationClass) {
125: $this->addRoute($collection, $annot, $globals, $class, $method);
126: }
127: }
128: }
129:
130: return $collection;
131: }
132:
133: protected function addRoute(RouteCollection $collection, $annot, $globals, \ReflectionClass $class, \ReflectionMethod $method)
134: {
135: $name = $annot->getName();
136: if (null === $name) {
137: $name = $this->getDefaultRouteName($class, $method);
138: }
139:
140: $defaults = array_replace($globals['defaults'], $annot->getDefaults());
141: foreach ($method->getParameters() as $param) {
142: if (false !== strpos($globals['path'].$annot->getPath(), sprintf('{%s}', $param->getName())) && !isset($defaults[$param->getName()]) && $param->isDefaultValueAvailable()) {
143: $defaults[$param->getName()] = $param->getDefaultValue();
144: }
145: }
146: $requirements = array_replace($globals['requirements'], $annot->getRequirements());
147: $options = array_replace($globals['options'], $annot->getOptions());
148: $schemes = array_merge($globals['schemes'], $annot->getSchemes());
149: $methods = array_merge($globals['methods'], $annot->getMethods());
150:
151: $host = $annot->getHost();
152: if (null === $host) {
153: $host = $globals['host'];
154: }
155:
156: $condition = $annot->getCondition();
157: if (null === $condition) {
158: $condition = $globals['condition'];
159: }
160:
161: $route = $this->createRoute($globals['path'].$annot->getPath(), $defaults, $requirements, $options, $host, $schemes, $methods, $condition);
162:
163: $this->configureRoute($route, $class, $method, $annot);
164:
165: $collection->add($name, $route);
166: }
167:
168: 169: 170:
171: public function supports($resource, $type = null)
172: {
173: return is_string($resource) && preg_match('/^(?:\\\\?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)+$/', $resource) && (!$type || 'annotation' === $type);
174: }
175:
176: 177: 178:
179: public function setResolver(LoaderResolverInterface $resolver)
180: {
181: }
182:
183: 184: 185:
186: public function getResolver()
187: {
188: }
189:
190: 191: 192: 193: 194: 195: 196: 197:
198: protected function getDefaultRouteName(\ReflectionClass $class, \ReflectionMethod $method)
199: {
200: $name = strtolower(str_replace('\\', '_', $class->name).'_'.$method->name);
201: if ($this->defaultRouteIndex > 0) {
202: $name .= '_'.$this->defaultRouteIndex;
203: }
204: ++$this->defaultRouteIndex;
205:
206: return $name;
207: }
208:
209: protected function getGlobals(\ReflectionClass $class)
210: {
211: $globals = array(
212: 'path' => '',
213: 'requirements' => array(),
214: 'options' => array(),
215: 'defaults' => array(),
216: 'schemes' => array(),
217: 'methods' => array(),
218: 'host' => '',
219: 'condition' => '',
220: );
221:
222: if ($annot = $this->reader->getClassAnnotation($class, $this->routeAnnotationClass)) {
223:
224: if (null !== $annot->getPath()) {
225: $globals['path'] = $annot->getPath();
226: } elseif (null !== $annot->getPattern()) {
227: $globals['path'] = $annot->getPattern();
228: }
229:
230: if (null !== $annot->getRequirements()) {
231: $globals['requirements'] = $annot->getRequirements();
232: }
233:
234: if (null !== $annot->getOptions()) {
235: $globals['options'] = $annot->getOptions();
236: }
237:
238: if (null !== $annot->getDefaults()) {
239: $globals['defaults'] = $annot->getDefaults();
240: }
241:
242: if (null !== $annot->getSchemes()) {
243: $globals['schemes'] = $annot->getSchemes();
244: }
245:
246: if (null !== $annot->getMethods()) {
247: $globals['methods'] = $annot->getMethods();
248: }
249:
250: if (null !== $annot->getHost()) {
251: $globals['host'] = $annot->getHost();
252: }
253:
254: if (null !== $annot->getCondition()) {
255: $globals['condition'] = $annot->getCondition();
256: }
257: }
258:
259: return $globals;
260: }
261:
262: protected function createRoute($path, $defaults, $requirements, $options, $host, $schemes, $methods, $condition)
263: {
264: return new Route($path, $defaults, $requirements, $options, $host, $schemes, $methods, $condition);
265: }
266:
267: abstract protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, $annot);
268: }
269: