191 lines
5.6 KiB
PHP
191 lines
5.6 KiB
PHP
<?php
|
|
|
|
namespace Doctrine\Common\Annotations;
|
|
|
|
use function array_key_exists;
|
|
use function array_merge;
|
|
use function class_exists;
|
|
use function in_array;
|
|
use function is_file;
|
|
use function str_replace;
|
|
use function stream_resolve_include_path;
|
|
use function strpos;
|
|
|
|
use const DIRECTORY_SEPARATOR;
|
|
|
|
final class AnnotationRegistry
|
|
{
|
|
/**
|
|
* A map of namespaces to use for autoloading purposes based on a PSR-0 convention.
|
|
*
|
|
* Contains the namespace as key and an array of directories as value. If the value is NULL
|
|
* the include path is used for checking for the corresponding file.
|
|
*
|
|
* This autoloading mechanism does not utilize the PHP autoloading but implements autoloading on its own.
|
|
*
|
|
* @var string[][]|string[]|null[]
|
|
*/
|
|
private static $autoloadNamespaces = [];
|
|
|
|
/**
|
|
* A map of autoloader callables.
|
|
*
|
|
* @var callable[]
|
|
*/
|
|
private static $loaders = [];
|
|
|
|
/**
|
|
* An array of classes which cannot be found
|
|
*
|
|
* @var null[] indexed by class name
|
|
*/
|
|
private static $failedToAutoload = [];
|
|
|
|
/**
|
|
* Whenever registerFile() was used. Disables use of standard autoloader.
|
|
*
|
|
* @var bool
|
|
*/
|
|
private static $registerFileUsed = false;
|
|
|
|
public static function reset(): void
|
|
{
|
|
self::$autoloadNamespaces = [];
|
|
self::$loaders = [];
|
|
self::$failedToAutoload = [];
|
|
self::$registerFileUsed = false;
|
|
}
|
|
|
|
/**
|
|
* Registers file.
|
|
*
|
|
* @deprecated This method is deprecated and will be removed in
|
|
* doctrine/annotations 2.0. Annotations will be autoloaded in 2.0.
|
|
*/
|
|
public static function registerFile(string $file): void
|
|
{
|
|
self::$registerFileUsed = true;
|
|
|
|
require_once $file;
|
|
}
|
|
|
|
/**
|
|
* Adds a namespace with one or many directories to look for files or null for the include path.
|
|
*
|
|
* Loading of this namespaces will be done with a PSR-0 namespace loading algorithm.
|
|
*
|
|
* @deprecated This method is deprecated and will be removed in
|
|
* doctrine/annotations 2.0. Annotations will be autoloaded in 2.0.
|
|
*
|
|
* @phpstan-param string|list<string>|null $dirs
|
|
*/
|
|
public static function registerAutoloadNamespace(string $namespace, $dirs = null): void
|
|
{
|
|
self::$autoloadNamespaces[$namespace] = $dirs;
|
|
}
|
|
|
|
/**
|
|
* Registers multiple namespaces.
|
|
*
|
|
* Loading of this namespaces will be done with a PSR-0 namespace loading algorithm.
|
|
*
|
|
* @deprecated This method is deprecated and will be removed in
|
|
* doctrine/annotations 2.0. Annotations will be autoloaded in 2.0.
|
|
*
|
|
* @param string[][]|string[]|null[] $namespaces indexed by namespace name
|
|
*/
|
|
public static function registerAutoloadNamespaces(array $namespaces): void
|
|
{
|
|
self::$autoloadNamespaces = array_merge(self::$autoloadNamespaces, $namespaces);
|
|
}
|
|
|
|
/**
|
|
* Registers an autoloading callable for annotations, much like spl_autoload_register().
|
|
*
|
|
* NOTE: These class loaders HAVE to be silent when a class was not found!
|
|
* IMPORTANT: Loaders have to return true if they loaded a class that could contain the searched annotation class.
|
|
*
|
|
* @deprecated This method is deprecated and will be removed in
|
|
* doctrine/annotations 2.0. Annotations will be autoloaded in 2.0.
|
|
*/
|
|
public static function registerLoader(callable $callable): void
|
|
{
|
|
// Reset our static cache now that we have a new loader to work with
|
|
self::$failedToAutoload = [];
|
|
self::$loaders[] = $callable;
|
|
}
|
|
|
|
/**
|
|
* Registers an autoloading callable for annotations, if it is not already registered
|
|
*
|
|
* @deprecated This method is deprecated and will be removed in
|
|
* doctrine/annotations 2.0. Annotations will be autoloaded in 2.0.
|
|
*/
|
|
public static function registerUniqueLoader(callable $callable): void
|
|
{
|
|
if (in_array($callable, self::$loaders, true)) {
|
|
return;
|
|
}
|
|
|
|
self::registerLoader($callable);
|
|
}
|
|
|
|
/**
|
|
* Autoloads an annotation class silently.
|
|
*/
|
|
public static function loadAnnotationClass(string $class): bool
|
|
{
|
|
if (class_exists($class, false)) {
|
|
return true;
|
|
}
|
|
|
|
if (array_key_exists($class, self::$failedToAutoload)) {
|
|
return false;
|
|
}
|
|
|
|
foreach (self::$autoloadNamespaces as $namespace => $dirs) {
|
|
if (strpos($class, $namespace) !== 0) {
|
|
continue;
|
|
}
|
|
|
|
$file = str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';
|
|
|
|
if ($dirs === null) {
|
|
$path = stream_resolve_include_path($file);
|
|
if ($path) {
|
|
require $path;
|
|
|
|
return true;
|
|
}
|
|
} else {
|
|
foreach ((array) $dirs as $dir) {
|
|
if (is_file($dir . DIRECTORY_SEPARATOR . $file)) {
|
|
require $dir . DIRECTORY_SEPARATOR . $file;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach (self::$loaders as $loader) {
|
|
if ($loader($class) === true) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if (
|
|
self::$loaders === [] &&
|
|
self::$autoloadNamespaces === [] &&
|
|
self::$registerFileUsed === false &&
|
|
class_exists($class)
|
|
) {
|
|
return true;
|
|
}
|
|
|
|
self::$failedToAutoload[$class] = null;
|
|
|
|
return false;
|
|
}
|
|
}
|