annotate vendor/symfony/routing/Loader/AnnotationFileLoader.php @ 0:4c8ae668cc8c

Initial import (non-working)
author Chris Cannam
date Wed, 29 Nov 2017 16:09:58 +0000
parents
children 7a779792577d
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 /*
Chris@0 4 * This file is part of the Symfony package.
Chris@0 5 *
Chris@0 6 * (c) Fabien Potencier <fabien@symfony.com>
Chris@0 7 *
Chris@0 8 * For the full copyright and license information, please view the LICENSE
Chris@0 9 * file that was distributed with this source code.
Chris@0 10 */
Chris@0 11
Chris@0 12 namespace Symfony\Component\Routing\Loader;
Chris@0 13
Chris@0 14 use Symfony\Component\Routing\RouteCollection;
Chris@0 15 use Symfony\Component\Config\Resource\FileResource;
Chris@0 16 use Symfony\Component\Config\Loader\FileLoader;
Chris@0 17 use Symfony\Component\Config\FileLocatorInterface;
Chris@0 18
Chris@0 19 /**
Chris@0 20 * AnnotationFileLoader loads routing information from annotations set
Chris@0 21 * on a PHP class and its methods.
Chris@0 22 *
Chris@0 23 * @author Fabien Potencier <fabien@symfony.com>
Chris@0 24 */
Chris@0 25 class AnnotationFileLoader extends FileLoader
Chris@0 26 {
Chris@0 27 protected $loader;
Chris@0 28
Chris@0 29 /**
Chris@0 30 * Constructor.
Chris@0 31 *
Chris@0 32 * @param FileLocatorInterface $locator A FileLocator instance
Chris@0 33 * @param AnnotationClassLoader $loader An AnnotationClassLoader instance
Chris@0 34 *
Chris@0 35 * @throws \RuntimeException
Chris@0 36 */
Chris@0 37 public function __construct(FileLocatorInterface $locator, AnnotationClassLoader $loader)
Chris@0 38 {
Chris@0 39 if (!function_exists('token_get_all')) {
Chris@0 40 throw new \RuntimeException('The Tokenizer extension is required for the routing annotation loaders.');
Chris@0 41 }
Chris@0 42
Chris@0 43 parent::__construct($locator);
Chris@0 44
Chris@0 45 $this->loader = $loader;
Chris@0 46 }
Chris@0 47
Chris@0 48 /**
Chris@0 49 * Loads from annotations from a file.
Chris@0 50 *
Chris@0 51 * @param string $file A PHP file path
Chris@0 52 * @param string|null $type The resource type
Chris@0 53 *
Chris@0 54 * @return RouteCollection A RouteCollection instance
Chris@0 55 *
Chris@0 56 * @throws \InvalidArgumentException When the file does not exist or its routes cannot be parsed
Chris@0 57 */
Chris@0 58 public function load($file, $type = null)
Chris@0 59 {
Chris@0 60 $path = $this->locator->locate($file);
Chris@0 61
Chris@0 62 $collection = new RouteCollection();
Chris@0 63 if ($class = $this->findClass($path)) {
Chris@0 64 $collection->addResource(new FileResource($path));
Chris@0 65 $collection->addCollection($this->loader->load($class, $type));
Chris@0 66 }
Chris@0 67 if (PHP_VERSION_ID >= 70000) {
Chris@0 68 // PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098
Chris@0 69 gc_mem_caches();
Chris@0 70 }
Chris@0 71
Chris@0 72 return $collection;
Chris@0 73 }
Chris@0 74
Chris@0 75 /**
Chris@0 76 * {@inheritdoc}
Chris@0 77 */
Chris@0 78 public function supports($resource, $type = null)
Chris@0 79 {
Chris@0 80 return is_string($resource) && 'php' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'annotation' === $type);
Chris@0 81 }
Chris@0 82
Chris@0 83 /**
Chris@0 84 * Returns the full class name for the first class in the file.
Chris@0 85 *
Chris@0 86 * @param string $file A PHP file path
Chris@0 87 *
Chris@0 88 * @return string|false Full class name if found, false otherwise
Chris@0 89 */
Chris@0 90 protected function findClass($file)
Chris@0 91 {
Chris@0 92 $class = false;
Chris@0 93 $namespace = false;
Chris@0 94 $tokens = token_get_all(file_get_contents($file));
Chris@0 95
Chris@0 96 if (1 === count($tokens) && T_INLINE_HTML === $tokens[0][0]) {
Chris@0 97 throw new \InvalidArgumentException(sprintf('The file "%s" does not contain PHP code. Did you forgot to add the "<?php" start tag at the beginning of the file?', $file));
Chris@0 98 }
Chris@0 99
Chris@0 100 for ($i = 0; isset($tokens[$i]); ++$i) {
Chris@0 101 $token = $tokens[$i];
Chris@0 102
Chris@0 103 if (!isset($token[1])) {
Chris@0 104 continue;
Chris@0 105 }
Chris@0 106
Chris@0 107 if (true === $class && T_STRING === $token[0]) {
Chris@0 108 return $namespace.'\\'.$token[1];
Chris@0 109 }
Chris@0 110
Chris@0 111 if (true === $namespace && T_STRING === $token[0]) {
Chris@0 112 $namespace = $token[1];
Chris@0 113 while (isset($tokens[++$i][1]) && in_array($tokens[$i][0], array(T_NS_SEPARATOR, T_STRING))) {
Chris@0 114 $namespace .= $tokens[$i][1];
Chris@0 115 }
Chris@0 116 $token = $tokens[$i];
Chris@0 117 }
Chris@0 118
Chris@0 119 if (T_CLASS === $token[0]) {
Chris@0 120 // Skip usage of ::class constant
Chris@0 121 $isClassConstant = false;
Chris@0 122 for ($j = $i - 1; $j > 0; --$j) {
Chris@0 123 if (!isset($tokens[$j][1])) {
Chris@0 124 break;
Chris@0 125 }
Chris@0 126
Chris@0 127 if (T_DOUBLE_COLON === $tokens[$j][0]) {
Chris@0 128 $isClassConstant = true;
Chris@0 129 break;
Chris@0 130 } elseif (!in_array($tokens[$j][0], array(T_WHITESPACE, T_DOC_COMMENT, T_COMMENT))) {
Chris@0 131 break;
Chris@0 132 }
Chris@0 133 }
Chris@0 134
Chris@0 135 if (!$isClassConstant) {
Chris@0 136 $class = true;
Chris@0 137 }
Chris@0 138 }
Chris@0 139
Chris@0 140 if (T_NAMESPACE === $token[0]) {
Chris@0 141 $namespace = true;
Chris@0 142 }
Chris@0 143 }
Chris@0 144
Chris@0 145 return false;
Chris@0 146 }
Chris@0 147 }