annotate vendor/symfony/routing/Loader/AnnotationFileLoader.php @ 14:1fec387a4317

Update Drupal core to 8.5.2 via Composer
author Chris Cannam
date Mon, 23 Apr 2018 09:46:53 +0100
parents 7a779792577d
children 129ea1e6d783
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 * @throws \RuntimeException
Chris@0 31 */
Chris@0 32 public function __construct(FileLocatorInterface $locator, AnnotationClassLoader $loader)
Chris@0 33 {
Chris@0 34 if (!function_exists('token_get_all')) {
Chris@0 35 throw new \RuntimeException('The Tokenizer extension is required for the routing annotation loaders.');
Chris@0 36 }
Chris@0 37
Chris@0 38 parent::__construct($locator);
Chris@0 39
Chris@0 40 $this->loader = $loader;
Chris@0 41 }
Chris@0 42
Chris@0 43 /**
Chris@0 44 * Loads from annotations from a file.
Chris@0 45 *
Chris@0 46 * @param string $file A PHP file path
Chris@0 47 * @param string|null $type The resource type
Chris@0 48 *
Chris@0 49 * @return RouteCollection A RouteCollection instance
Chris@0 50 *
Chris@0 51 * @throws \InvalidArgumentException When the file does not exist or its routes cannot be parsed
Chris@0 52 */
Chris@0 53 public function load($file, $type = null)
Chris@0 54 {
Chris@0 55 $path = $this->locator->locate($file);
Chris@0 56
Chris@0 57 $collection = new RouteCollection();
Chris@0 58 if ($class = $this->findClass($path)) {
Chris@0 59 $collection->addResource(new FileResource($path));
Chris@0 60 $collection->addCollection($this->loader->load($class, $type));
Chris@0 61 }
Chris@12 62 if (\PHP_VERSION_ID >= 70000) {
Chris@0 63 // PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098
Chris@0 64 gc_mem_caches();
Chris@0 65 }
Chris@0 66
Chris@0 67 return $collection;
Chris@0 68 }
Chris@0 69
Chris@0 70 /**
Chris@0 71 * {@inheritdoc}
Chris@0 72 */
Chris@0 73 public function supports($resource, $type = null)
Chris@0 74 {
Chris@0 75 return is_string($resource) && 'php' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'annotation' === $type);
Chris@0 76 }
Chris@0 77
Chris@0 78 /**
Chris@0 79 * Returns the full class name for the first class in the file.
Chris@0 80 *
Chris@0 81 * @param string $file A PHP file path
Chris@0 82 *
Chris@0 83 * @return string|false Full class name if found, false otherwise
Chris@0 84 */
Chris@0 85 protected function findClass($file)
Chris@0 86 {
Chris@0 87 $class = false;
Chris@0 88 $namespace = false;
Chris@0 89 $tokens = token_get_all(file_get_contents($file));
Chris@0 90
Chris@0 91 if (1 === count($tokens) && T_INLINE_HTML === $tokens[0][0]) {
Chris@0 92 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 93 }
Chris@0 94
Chris@0 95 for ($i = 0; isset($tokens[$i]); ++$i) {
Chris@0 96 $token = $tokens[$i];
Chris@0 97
Chris@0 98 if (!isset($token[1])) {
Chris@0 99 continue;
Chris@0 100 }
Chris@0 101
Chris@0 102 if (true === $class && T_STRING === $token[0]) {
Chris@0 103 return $namespace.'\\'.$token[1];
Chris@0 104 }
Chris@0 105
Chris@0 106 if (true === $namespace && T_STRING === $token[0]) {
Chris@0 107 $namespace = $token[1];
Chris@0 108 while (isset($tokens[++$i][1]) && in_array($tokens[$i][0], array(T_NS_SEPARATOR, T_STRING))) {
Chris@0 109 $namespace .= $tokens[$i][1];
Chris@0 110 }
Chris@0 111 $token = $tokens[$i];
Chris@0 112 }
Chris@0 113
Chris@0 114 if (T_CLASS === $token[0]) {
Chris@14 115 // Skip usage of ::class constant and anonymous classes
Chris@14 116 $skipClassToken = false;
Chris@0 117 for ($j = $i - 1; $j > 0; --$j) {
Chris@0 118 if (!isset($tokens[$j][1])) {
Chris@0 119 break;
Chris@0 120 }
Chris@0 121
Chris@14 122 if (T_DOUBLE_COLON === $tokens[$j][0] || T_NEW === $tokens[$j][0]) {
Chris@14 123 $skipClassToken = true;
Chris@0 124 break;
Chris@0 125 } elseif (!in_array($tokens[$j][0], array(T_WHITESPACE, T_DOC_COMMENT, T_COMMENT))) {
Chris@0 126 break;
Chris@0 127 }
Chris@0 128 }
Chris@0 129
Chris@14 130 if (!$skipClassToken) {
Chris@0 131 $class = true;
Chris@0 132 }
Chris@0 133 }
Chris@0 134
Chris@0 135 if (T_NAMESPACE === $token[0]) {
Chris@0 136 $namespace = true;
Chris@0 137 }
Chris@0 138 }
Chris@0 139
Chris@0 140 return false;
Chris@0 141 }
Chris@0 142 }