class AttributeFileLoader
AttributeFileLoader loads routing information from attributes set on a PHP class and its methods.
@author Fabien Potencier <fabien@symfony.com> @author Alexandre Daubois <alex.daubois@gmail.com>
Hierarchy
- class \Symfony\Component\Routing\Loader\AttributeFileLoader extends \Symfony\Component\Config\Loader\FileLoader
Expanded class hierarchy of AttributeFileLoader
File
-
vendor/
symfony/ routing/ Loader/ AttributeFileLoader.php, line 26
Namespace
Symfony\Component\Routing\LoaderView source
class AttributeFileLoader extends FileLoader {
public function __construct(FileLocatorInterface $locator, AttributeClassLoader $loader) {
if (!\function_exists('token_get_all')) {
throw new \LogicException('The Tokenizer extension is required for the routing attribute loader.');
}
parent::__construct($locator);
}
/**
* Loads from attributes from a file.
*
* @throws \InvalidArgumentException When the file does not exist or its routes cannot be parsed
*/
public function load(mixed $file, ?string $type = null) : ?RouteCollection {
$path = $this->locator
->locate($file);
$collection = new RouteCollection();
if ($class = $this->findClass($path)) {
$refl = new \ReflectionClass($class);
if ($refl->isAbstract()) {
return null;
}
$collection->addResource(new FileResource($path));
$collection->addCollection($this->loader
->load($class, $type));
}
gc_mem_caches();
return $collection;
}
public function supports(mixed $resource, ?string $type = null) : bool {
return \is_string($resource) && 'php' === pathinfo($resource, \PATHINFO_EXTENSION) && (!$type || 'attribute' === $type);
}
/**
* Returns the full class name for the first class in the file.
*/
protected function findClass(string $file) : string|false {
$class = false;
$namespace = false;
$tokens = token_get_all(file_get_contents($file));
if (1 === \count($tokens) && \T_INLINE_HTML === $tokens[0][0]) {
throw new \InvalidArgumentException(\sprintf('The file "%s" does not contain PHP code. Did you forget to add the "<?php" start tag at the beginning of the file?', $file));
}
$nsTokens = [
\T_NS_SEPARATOR => true,
\T_STRING => true,
];
if (\defined('T_NAME_QUALIFIED')) {
$nsTokens[\T_NAME_QUALIFIED] = true;
}
for ($i = 0; isset($tokens[$i]); ++$i) {
$token = $tokens[$i];
if (!isset($token[1])) {
continue;
}
if (true === $class && \T_STRING === $token[0]) {
return $namespace . '\\' . $token[1];
}
if (true === $namespace && isset($nsTokens[$token[0]])) {
$namespace = $token[1];
while (isset($tokens[++$i][1], $nsTokens[$tokens[$i][0]])) {
$namespace .= $tokens[$i][1];
}
$token = $tokens[$i];
}
if (\T_CLASS === $token[0]) {
// Skip usage of ::class constant and anonymous classes
$skipClassToken = false;
for ($j = $i - 1; $j > 0; --$j) {
if (!isset($tokens[$j][1])) {
if ('(' === $tokens[$j] || ',' === $tokens[$j]) {
$skipClassToken = true;
}
break;
}
if (\T_DOUBLE_COLON === $tokens[$j][0] || \T_NEW === $tokens[$j][0]) {
$skipClassToken = true;
break;
}
elseif (!\in_array($tokens[$j][0], [
\T_WHITESPACE,
\T_DOC_COMMENT,
\T_COMMENT,
])) {
break;
}
}
if (!$skipClassToken) {
$class = true;
}
}
if (\T_NAMESPACE === $token[0]) {
$namespace = true;
}
}
return false;
}
}
Members
Title Sort descending | Modifiers | Object type | Summary | Overrides |
---|---|---|---|---|
AttributeFileLoader::findClass | protected | function | Returns the full class name for the first class in the file. | |
AttributeFileLoader::load | public | function | Loads from attributes from a file. | 1 |
AttributeFileLoader::supports | public | function | 1 | |
AttributeFileLoader::__construct | public | function |