Download project

This commit is contained in:
Roman Pyrih
2024-11-20 09:09:44 +01:00
parent 547a138d6a
commit 5ff041757f
40737 changed files with 7766183 additions and 0 deletions

View File

@@ -0,0 +1,48 @@
<?php
namespace ps_metrics_module_v4_0_5\Doctrine\Common\Annotations;
use BadMethodCallException;
use function sprintf;
/**
* Annotations class.
*/
class Annotation
{
/**
* Value property. Common among all derived classes.
*
* @var mixed
*/
public $value;
/** @param array<string, mixed> $data Key-value for properties to be defined in this class. */
public final function __construct(array $data)
{
foreach ($data as $key => $value) {
$this->{$key} = $value;
}
}
/**
* Error handler for unknown property accessor in Annotation class.
*
* @param string $name Unknown property name.
*
* @throws BadMethodCallException
*/
public function __get($name)
{
throw new BadMethodCallException(sprintf("Unknown property '%s' on annotation '%s'.", $name, static::class));
}
/**
* Error handler for unknown property mutator in Annotation class.
*
* @param string $name Unknown property name.
* @param mixed $value Property value.
*
* @throws BadMethodCallException
*/
public function __set($name, $value)
{
throw new BadMethodCallException(sprintf("Unknown property '%s' on annotation '%s'.", $name, static::class));
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace ps_metrics_module_v4_0_5\Doctrine\Common\Annotations\Annotation;
/**
* Annotation that can be used to signal to the parser
* to check the attribute type during the parsing process.
*
* @Annotation
*/
final class Attribute
{
/** @var string */
public $name;
/** @var string */
public $type;
/** @var bool */
public $required = \false;
}

View File

@@ -0,0 +1,15 @@
<?php
namespace ps_metrics_module_v4_0_5\Doctrine\Common\Annotations\Annotation;
/**
* Annotation that can be used to signal to the parser
* to check the types of all declared attributes during the parsing process.
*
* @Annotation
*/
final class Attributes
{
/** @var array<Attribute> */
public $value;
}

View File

@@ -0,0 +1,55 @@
<?php
namespace ps_metrics_module_v4_0_5\Doctrine\Common\Annotations\Annotation;
use InvalidArgumentException;
use function get_class;
use function gettype;
use function in_array;
use function is_object;
use function is_scalar;
use function sprintf;
/**
* Annotation that can be used to signal to the parser
* to check the available values during the parsing process.
*
* @Annotation
* @Attributes({
* @Attribute("value", required = true, type = "array"),
* @Attribute("literal", required = false, type = "array")
* })
*/
final class Enum
{
/** @phpstan-var list<scalar> */
public $value;
/**
* Literal target declaration.
*
* @var mixed[]
*/
public $literal;
/**
* @phpstan-param array{literal?: mixed[], value: list<scalar>} $values
*
* @throws InvalidArgumentException
*/
public function __construct(array $values)
{
if (!isset($values['literal'])) {
$values['literal'] = [];
}
foreach ($values['value'] as $var) {
if (!is_scalar($var)) {
throw new InvalidArgumentException(sprintf('@Enum supports only scalar values "%s" given.', is_object($var) ? get_class($var) : gettype($var)));
}
}
foreach ($values['literal'] as $key => $var) {
if (!in_array($key, $values['value'])) {
throw new InvalidArgumentException(sprintf('Undefined enumerator value "%s" for literal "%s".', $key, $var));
}
}
$this->value = $values['value'];
$this->literal = $values['literal'];
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace ps_metrics_module_v4_0_5\Doctrine\Common\Annotations\Annotation;
use RuntimeException;
use function is_array;
use function is_string;
use function json_encode;
use function sprintf;
/**
* Annotation that can be used to signal to the parser to ignore specific
* annotations during the parsing process.
*
* @Annotation
*/
final class IgnoreAnnotation
{
/** @phpstan-var list<string> */
public $names;
/**
* @phpstan-param array{value: string|list<string>} $values
*
* @throws RuntimeException
*/
public function __construct(array $values)
{
if (is_string($values['value'])) {
$values['value'] = [$values['value']];
}
if (!is_array($values['value'])) {
throw new RuntimeException(sprintf('@IgnoreAnnotation expects either a string name, or an array of strings, but got %s.', json_encode($values['value'])));
}
$this->names = $values['value'];
}
}

View File

@@ -0,0 +1,13 @@
<?php
namespace ps_metrics_module_v4_0_5\Doctrine\Common\Annotations\Annotation;
/**
* Annotation that indicates that the annotated class should be constructed with a named argument call.
*
* @Annotation
* @Target("CLASS")
*/
final class NamedArgumentConstructor
{
}

View File

@@ -0,0 +1,13 @@
<?php
namespace ps_metrics_module_v4_0_5\Doctrine\Common\Annotations\Annotation;
/**
* Annotation that can be used to signal to the parser
* to check if that attribute is required during the parsing process.
*
* @Annotation
*/
final class Required
{
}

View File

@@ -0,0 +1,71 @@
<?php
namespace ps_metrics_module_v4_0_5\Doctrine\Common\Annotations\Annotation;
use InvalidArgumentException;
use function array_keys;
use function get_class;
use function gettype;
use function implode;
use function is_array;
use function is_object;
use function is_string;
use function sprintf;
/**
* Annotation that can be used to signal to the parser
* to check the annotation target during the parsing process.
*
* @Annotation
*/
final class Target
{
public const TARGET_CLASS = 1;
public const TARGET_METHOD = 2;
public const TARGET_PROPERTY = 4;
public const TARGET_ANNOTATION = 8;
public const TARGET_FUNCTION = 16;
public const TARGET_ALL = 31;
/** @var array<string, int> */
private static $map = ['ALL' => self::TARGET_ALL, 'CLASS' => self::TARGET_CLASS, 'METHOD' => self::TARGET_METHOD, 'PROPERTY' => self::TARGET_PROPERTY, 'FUNCTION' => self::TARGET_FUNCTION, 'ANNOTATION' => self::TARGET_ANNOTATION];
/** @phpstan-var list<string> */
public $value;
/**
* Targets as bitmask.
*
* @var int
*/
public $targets;
/**
* Literal target declaration.
*
* @var string
*/
public $literal;
/**
* @phpstan-param array{value?: string|list<string>} $values
*
* @throws InvalidArgumentException
*/
public function __construct(array $values)
{
if (!isset($values['value'])) {
$values['value'] = null;
}
if (is_string($values['value'])) {
$values['value'] = [$values['value']];
}
if (!is_array($values['value'])) {
throw new InvalidArgumentException(sprintf('@Target expects either a string value, or an array of strings, "%s" given.', is_object($values['value']) ? get_class($values['value']) : gettype($values['value'])));
}
$bitmask = 0;
foreach ($values['value'] as $literal) {
if (!isset(self::$map[$literal])) {
throw new InvalidArgumentException(sprintf('Invalid Target "%s". Available targets: [%s]', $literal, implode(', ', array_keys(self::$map))));
}
$bitmask |= self::$map[$literal];
}
$this->targets = $bitmask;
$this->value = $values['value'];
$this->literal = implode(', ', $this->value);
}
}

View File

@@ -0,0 +1,11 @@
<?php
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,128 @@
<?php
namespace ps_metrics_module_v4_0_5\Doctrine\Common\Annotations;
use Exception;
use Throwable;
use function get_class;
use function gettype;
use function implode;
use function is_object;
use function sprintf;
/**
* Description of AnnotationException
*/
class AnnotationException extends Exception
{
/**
* Creates a new AnnotationException describing a Syntax error.
*
* @param string $message Exception message
*
* @return AnnotationException
*/
public static function syntaxError($message)
{
return new self('[Syntax Error] ' . $message);
}
/**
* Creates a new AnnotationException describing a Semantical error.
*
* @param string $message Exception message
*
* @return AnnotationException
*/
public static function semanticalError($message)
{
return new self('[Semantical Error] ' . $message);
}
/**
* Creates a new AnnotationException describing an error which occurred during
* the creation of the annotation.
*
* @param string $message
*
* @return AnnotationException
*/
public static function creationError($message, ?Throwable $previous = null)
{
return new self('[Creation Error] ' . $message, 0, $previous);
}
/**
* Creates a new AnnotationException describing a type error.
*
* @param string $message
*
* @return AnnotationException
*/
public static function typeError($message)
{
return new self('[Type Error] ' . $message);
}
/**
* Creates a new AnnotationException describing a constant semantical error.
*
* @param string $identifier
* @param string $context
*
* @return AnnotationException
*/
public static function semanticalErrorConstants($identifier, $context = null)
{
return self::semanticalError(sprintf("Couldn't find constant %s%s.", $identifier, $context ? ', ' . $context : ''));
}
/**
* Creates a new AnnotationException describing an type error of an attribute.
*
* @param string $attributeName
* @param string $annotationName
* @param string $context
* @param string $expected
* @param mixed $actual
*
* @return AnnotationException
*/
public static function attributeTypeError($attributeName, $annotationName, $context, $expected, $actual)
{
return self::typeError(sprintf('Attribute "%s" of @%s declared on %s expects %s, but got %s.', $attributeName, $annotationName, $context, $expected, is_object($actual) ? 'an instance of ' . get_class($actual) : gettype($actual)));
}
/**
* Creates a new AnnotationException describing an required error of an attribute.
*
* @param string $attributeName
* @param string $annotationName
* @param string $context
* @param string $expected
*
* @return AnnotationException
*/
public static function requiredError($attributeName, $annotationName, $context, $expected)
{
return self::typeError(sprintf('Attribute "%s" of @%s declared on %s expects %s. This value should not be null.', $attributeName, $annotationName, $context, $expected));
}
/**
* Creates a new AnnotationException describing a invalid enummerator.
*
* @param string $attributeName
* @param string $annotationName
* @param string $context
* @param mixed $given
* @phpstan-param list<string> $available
*
* @return AnnotationException
*/
public static function enumeratorError($attributeName, $annotationName, $context, $available, $given)
{
return new self(sprintf('[Enum Error] Attribute "%s" of @%s declared on %s accepts only [%s], but got %s.', $attributeName, $annotationName, $context, implode(', ', $available), is_object($given) ? get_class($given) : $given));
}
/** @return AnnotationException */
public static function optimizerPlusSaveComments()
{
return new self('You have to enable opcache.save_comments=1 or zend_optimizerplus.save_comments=1.');
}
/** @return AnnotationException */
public static function optimizerPlusLoadComments()
{
return new self('You have to enable opcache.load_comments=1 or zend_optimizerplus.load_comments=1.');
}
}

View File

@@ -0,0 +1,309 @@
<?php
namespace ps_metrics_module_v4_0_5\Doctrine\Common\Annotations;
use ps_metrics_module_v4_0_5\Doctrine\Common\Annotations\Annotation\IgnoreAnnotation;
use ps_metrics_module_v4_0_5\Doctrine\Common\Annotations\Annotation\Target;
use ReflectionClass;
use ReflectionFunction;
use ReflectionMethod;
use ReflectionProperty;
use function array_merge;
use function class_exists;
use function extension_loaded;
use function ini_get;
/**
* A reader for docblock annotations.
*/
class AnnotationReader implements Reader
{
/**
* Global map for imports.
*
* @var array<string, class-string>
*/
private static $globalImports = ['ignoreannotation' => Annotation\IgnoreAnnotation::class];
/**
* A list with annotations that are not causing exceptions when not resolved to an annotation class.
*
* The names are case sensitive.
*
* @var array<string, true>
*/
private static $globalIgnoredNames = ImplicitlyIgnoredAnnotationNames::LIST;
/**
* A list with annotations that are not causing exceptions when not resolved to an annotation class.
*
* The names are case sensitive.
*
* @var array<string, true>
*/
private static $globalIgnoredNamespaces = [];
/**
* Add a new annotation to the globally ignored annotation names with regard to exception handling.
*
* @param string $name
*/
public static function addGlobalIgnoredName($name)
{
self::$globalIgnoredNames[$name] = \true;
}
/**
* Add a new annotation to the globally ignored annotation namespaces with regard to exception handling.
*
* @param string $namespace
*/
public static function addGlobalIgnoredNamespace($namespace)
{
self::$globalIgnoredNamespaces[$namespace] = \true;
}
/**
* Annotations parser.
*
* @var DocParser
*/
private $parser;
/**
* Annotations parser used to collect parsing metadata.
*
* @var DocParser
*/
private $preParser;
/**
* PHP parser used to collect imports.
*
* @var PhpParser
*/
private $phpParser;
/**
* In-memory cache mechanism to store imported annotations per class.
*
* @psalm-var array<'class'|'function', array<string, array<string, class-string>>>
*/
private $imports = [];
/**
* In-memory cache mechanism to store ignored annotations per class.
*
* @psalm-var array<'class'|'function', array<string, array<string, true>>>
*/
private $ignoredAnnotationNames = [];
/**
* Initializes a new AnnotationReader.
*
* @throws AnnotationException
*/
public function __construct(?DocParser $parser = null)
{
if (extension_loaded('Zend Optimizer+') && (ini_get('zend_optimizerplus.save_comments') === '0' || ini_get('opcache.save_comments') === '0')) {
throw AnnotationException::optimizerPlusSaveComments();
}
if (extension_loaded('Zend OPcache') && ini_get('opcache.save_comments') === 0) {
throw AnnotationException::optimizerPlusSaveComments();
}
// Make sure that the IgnoreAnnotation annotation is loaded
class_exists(IgnoreAnnotation::class);
$this->parser = $parser ?: new DocParser();
$this->preParser = new DocParser();
$this->preParser->setImports(self::$globalImports);
$this->preParser->setIgnoreNotImportedAnnotations(\true);
$this->preParser->setIgnoredAnnotationNames(self::$globalIgnoredNames);
$this->phpParser = new PhpParser();
}
/**
* {@inheritDoc}
*/
public function getClassAnnotations(ReflectionClass $class)
{
$this->parser->setTarget(Target::TARGET_CLASS);
$this->parser->setImports($this->getImports($class));
$this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class));
$this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces);
return $this->parser->parse($class->getDocComment(), 'class ' . $class->getName());
}
/**
* {@inheritDoc}
*/
public function getClassAnnotation(ReflectionClass $class, $annotationName)
{
$annotations = $this->getClassAnnotations($class);
foreach ($annotations as $annotation) {
if ($annotation instanceof $annotationName) {
return $annotation;
}
}
return null;
}
/**
* {@inheritDoc}
*/
public function getPropertyAnnotations(ReflectionProperty $property)
{
$class = $property->getDeclaringClass();
$context = 'property ' . $class->getName() . '::$' . $property->getName();
$this->parser->setTarget(Target::TARGET_PROPERTY);
$this->parser->setImports($this->getPropertyImports($property));
$this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class));
$this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces);
return $this->parser->parse($property->getDocComment(), $context);
}
/**
* {@inheritDoc}
*/
public function getPropertyAnnotation(ReflectionProperty $property, $annotationName)
{
$annotations = $this->getPropertyAnnotations($property);
foreach ($annotations as $annotation) {
if ($annotation instanceof $annotationName) {
return $annotation;
}
}
return null;
}
/**
* {@inheritDoc}
*/
public function getMethodAnnotations(ReflectionMethod $method)
{
$class = $method->getDeclaringClass();
$context = 'method ' . $class->getName() . '::' . $method->getName() . '()';
$this->parser->setTarget(Target::TARGET_METHOD);
$this->parser->setImports($this->getMethodImports($method));
$this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class));
$this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces);
return $this->parser->parse($method->getDocComment(), $context);
}
/**
* {@inheritDoc}
*/
public function getMethodAnnotation(ReflectionMethod $method, $annotationName)
{
$annotations = $this->getMethodAnnotations($method);
foreach ($annotations as $annotation) {
if ($annotation instanceof $annotationName) {
return $annotation;
}
}
return null;
}
/**
* Gets the annotations applied to a function.
*
* @phpstan-return list<object> An array of Annotations.
*/
public function getFunctionAnnotations(ReflectionFunction $function) : array
{
$context = 'function ' . $function->getName();
$this->parser->setTarget(Target::TARGET_FUNCTION);
$this->parser->setImports($this->getImports($function));
$this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($function));
$this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces);
return $this->parser->parse($function->getDocComment(), $context);
}
/**
* Gets a function annotation.
*
* @return object|null The Annotation or NULL, if the requested annotation does not exist.
*/
public function getFunctionAnnotation(ReflectionFunction $function, string $annotationName)
{
$annotations = $this->getFunctionAnnotations($function);
foreach ($annotations as $annotation) {
if ($annotation instanceof $annotationName) {
return $annotation;
}
}
return null;
}
/**
* Returns the ignored annotations for the given class or function.
*
* @param ReflectionClass|ReflectionFunction $reflection
*
* @return array<string, true>
*/
private function getIgnoredAnnotationNames($reflection) : array
{
$type = $reflection instanceof ReflectionClass ? 'class' : 'function';
$name = $reflection->getName();
if (isset($this->ignoredAnnotationNames[$type][$name])) {
return $this->ignoredAnnotationNames[$type][$name];
}
$this->collectParsingMetadata($reflection);
return $this->ignoredAnnotationNames[$type][$name];
}
/**
* Retrieves imports for a class or a function.
*
* @param ReflectionClass|ReflectionFunction $reflection
*
* @return array<string, class-string>
*/
private function getImports($reflection) : array
{
$type = $reflection instanceof ReflectionClass ? 'class' : 'function';
$name = $reflection->getName();
if (isset($this->imports[$type][$name])) {
return $this->imports[$type][$name];
}
$this->collectParsingMetadata($reflection);
return $this->imports[$type][$name];
}
/**
* Retrieves imports for methods.
*
* @return array<string, class-string>
*/
private function getMethodImports(ReflectionMethod $method)
{
$class = $method->getDeclaringClass();
$classImports = $this->getImports($class);
$traitImports = [];
foreach ($class->getTraits() as $trait) {
if (!$trait->hasMethod($method->getName()) || $trait->getFileName() !== $method->getFileName()) {
continue;
}
$traitImports = array_merge($traitImports, $this->phpParser->parseUseStatements($trait));
}
return array_merge($classImports, $traitImports);
}
/**
* Retrieves imports for properties.
*
* @return array<string, class-string>
*/
private function getPropertyImports(ReflectionProperty $property)
{
$class = $property->getDeclaringClass();
$classImports = $this->getImports($class);
$traitImports = [];
foreach ($class->getTraits() as $trait) {
if (!$trait->hasProperty($property->getName())) {
continue;
}
$traitImports = array_merge($traitImports, $this->phpParser->parseUseStatements($trait));
}
return array_merge($classImports, $traitImports);
}
/**
* Collects parsing metadata for a given class or function.
*
* @param ReflectionClass|ReflectionFunction $reflection
*/
private function collectParsingMetadata($reflection) : void
{
$type = $reflection instanceof ReflectionClass ? 'class' : 'function';
$name = $reflection->getName();
$ignoredAnnotationNames = self::$globalIgnoredNames;
$annotations = $this->preParser->parse($reflection->getDocComment(), $type . ' ' . $name);
foreach ($annotations as $annotation) {
if (!$annotation instanceof IgnoreAnnotation) {
continue;
}
foreach ($annotation->names as $annot) {
$ignoredAnnotationNames[$annot] = \true;
}
}
$this->imports[$type][$name] = array_merge(self::$globalImports, $this->phpParser->parseUseStatements($reflection), ['__NAMESPACE__' => $reflection->getNamespaceName(), 'self' => $name]);
$this->ignoredAnnotationNames[$type][$name] = $ignoredAnnotationNames;
}
}

View File

@@ -0,0 +1,161 @@
<?php
namespace ps_metrics_module_v4_0_5\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;
}
}

View File

@@ -0,0 +1,215 @@
<?php
namespace ps_metrics_module_v4_0_5\Doctrine\Common\Annotations;
use ps_metrics_module_v4_0_5\Doctrine\Common\Cache\Cache;
use ReflectionClass;
use ReflectionMethod;
use ReflectionProperty;
use function array_map;
use function array_merge;
use function assert;
use function filemtime;
use function max;
use function time;
/**
* A cache aware annotation reader.
*
* @deprecated the CachedReader is deprecated and will be removed
* in version 2.0.0 of doctrine/annotations. Please use the
* {@see \Doctrine\Common\Annotations\PsrCachedReader} instead.
*/
final class CachedReader implements Reader
{
/** @var Reader */
private $delegate;
/** @var Cache */
private $cache;
/** @var bool */
private $debug;
/** @var array<string, array<object>> */
private $loadedAnnotations = [];
/** @var int[] */
private $loadedFilemtimes = [];
/** @param bool $debug */
public function __construct(Reader $reader, Cache $cache, $debug = \false)
{
$this->delegate = $reader;
$this->cache = $cache;
$this->debug = (bool) $debug;
}
/**
* {@inheritDoc}
*/
public function getClassAnnotations(ReflectionClass $class)
{
$cacheKey = $class->getName();
if (isset($this->loadedAnnotations[$cacheKey])) {
return $this->loadedAnnotations[$cacheKey];
}
$annots = $this->fetchFromCache($cacheKey, $class);
if ($annots === \false) {
$annots = $this->delegate->getClassAnnotations($class);
$this->saveToCache($cacheKey, $annots);
}
return $this->loadedAnnotations[$cacheKey] = $annots;
}
/**
* {@inheritDoc}
*/
public function getClassAnnotation(ReflectionClass $class, $annotationName)
{
foreach ($this->getClassAnnotations($class) as $annot) {
if ($annot instanceof $annotationName) {
return $annot;
}
}
return null;
}
/**
* {@inheritDoc}
*/
public function getPropertyAnnotations(ReflectionProperty $property)
{
$class = $property->getDeclaringClass();
$cacheKey = $class->getName() . '$' . $property->getName();
if (isset($this->loadedAnnotations[$cacheKey])) {
return $this->loadedAnnotations[$cacheKey];
}
$annots = $this->fetchFromCache($cacheKey, $class);
if ($annots === \false) {
$annots = $this->delegate->getPropertyAnnotations($property);
$this->saveToCache($cacheKey, $annots);
}
return $this->loadedAnnotations[$cacheKey] = $annots;
}
/**
* {@inheritDoc}
*/
public function getPropertyAnnotation(ReflectionProperty $property, $annotationName)
{
foreach ($this->getPropertyAnnotations($property) as $annot) {
if ($annot instanceof $annotationName) {
return $annot;
}
}
return null;
}
/**
* {@inheritDoc}
*/
public function getMethodAnnotations(ReflectionMethod $method)
{
$class = $method->getDeclaringClass();
$cacheKey = $class->getName() . '#' . $method->getName();
if (isset($this->loadedAnnotations[$cacheKey])) {
return $this->loadedAnnotations[$cacheKey];
}
$annots = $this->fetchFromCache($cacheKey, $class);
if ($annots === \false) {
$annots = $this->delegate->getMethodAnnotations($method);
$this->saveToCache($cacheKey, $annots);
}
return $this->loadedAnnotations[$cacheKey] = $annots;
}
/**
* {@inheritDoc}
*/
public function getMethodAnnotation(ReflectionMethod $method, $annotationName)
{
foreach ($this->getMethodAnnotations($method) as $annot) {
if ($annot instanceof $annotationName) {
return $annot;
}
}
return null;
}
/**
* Clears loaded annotations.
*
* @return void
*/
public function clearLoadedAnnotations()
{
$this->loadedAnnotations = [];
$this->loadedFilemtimes = [];
}
/**
* Fetches a value from the cache.
*
* @param string $cacheKey The cache key.
*
* @return mixed The cached value or false when the value is not in cache.
*/
private function fetchFromCache($cacheKey, ReflectionClass $class)
{
$data = $this->cache->fetch($cacheKey);
if ($data !== \false) {
if (!$this->debug || $this->isCacheFresh($cacheKey, $class)) {
return $data;
}
}
return \false;
}
/**
* Saves a value to the cache.
*
* @param string $cacheKey The cache key.
* @param mixed $value The value.
*
* @return void
*/
private function saveToCache($cacheKey, $value)
{
$this->cache->save($cacheKey, $value);
if (!$this->debug) {
return;
}
$this->cache->save('[C]' . $cacheKey, time());
}
/**
* Checks if the cache is fresh.
*
* @param string $cacheKey
*
* @return bool
*/
private function isCacheFresh($cacheKey, ReflectionClass $class)
{
$lastModification = $this->getLastModification($class);
if ($lastModification === 0) {
return \true;
}
return $this->cache->fetch('[C]' . $cacheKey) >= $lastModification;
}
/**
* Returns the time the class was last modified, testing traits and parents
*/
private function getLastModification(ReflectionClass $class) : int
{
$filename = $class->getFileName();
if (isset($this->loadedFilemtimes[$filename])) {
return $this->loadedFilemtimes[$filename];
}
$parent = $class->getParentClass();
$lastModification = max(array_merge([$filename ? filemtime($filename) : 0], array_map(function (ReflectionClass $reflectionTrait) : int {
return $this->getTraitLastModificationTime($reflectionTrait);
}, $class->getTraits()), array_map(function (ReflectionClass $class) : int {
return $this->getLastModification($class);
}, $class->getInterfaces()), $parent ? [$this->getLastModification($parent)] : []));
assert($lastModification !== \false);
return $this->loadedFilemtimes[$filename] = $lastModification;
}
private function getTraitLastModificationTime(ReflectionClass $reflectionTrait) : int
{
$fileName = $reflectionTrait->getFileName();
if (isset($this->loadedFilemtimes[$fileName])) {
return $this->loadedFilemtimes[$fileName];
}
$lastModificationTime = max(array_merge([$fileName ? filemtime($fileName) : 0], array_map(function (ReflectionClass $reflectionTrait) : int {
return $this->getTraitLastModificationTime($reflectionTrait);
}, $reflectionTrait->getTraits())));
assert($lastModificationTime !== \false);
return $this->loadedFilemtimes[$fileName] = $lastModificationTime;
}
}

View File

@@ -0,0 +1,101 @@
<?php
namespace ps_metrics_module_v4_0_5\Doctrine\Common\Annotations;
use ps_metrics_module_v4_0_5\Doctrine\Common\Lexer\AbstractLexer;
use function ctype_alpha;
use function is_numeric;
use function str_replace;
use function stripos;
use function strlen;
use function strpos;
use function strtolower;
use function substr;
/**
* Simple lexer for docblock annotations.
*
* @template-extends AbstractLexer<DocLexer::T_*, string>
*/
final class DocLexer extends AbstractLexer
{
public const T_NONE = 1;
public const T_INTEGER = 2;
public const T_STRING = 3;
public const T_FLOAT = 4;
// All tokens that are also identifiers should be >= 100
public const T_IDENTIFIER = 100;
public const T_AT = 101;
public const T_CLOSE_CURLY_BRACES = 102;
public const T_CLOSE_PARENTHESIS = 103;
public const T_COMMA = 104;
public const T_EQUALS = 105;
public const T_FALSE = 106;
public const T_NAMESPACE_SEPARATOR = 107;
public const T_OPEN_CURLY_BRACES = 108;
public const T_OPEN_PARENTHESIS = 109;
public const T_TRUE = 110;
public const T_NULL = 111;
public const T_COLON = 112;
public const T_MINUS = 113;
/** @var array<string, self::T*> */
protected $noCase = ['@' => self::T_AT, ',' => self::T_COMMA, '(' => self::T_OPEN_PARENTHESIS, ')' => self::T_CLOSE_PARENTHESIS, '{' => self::T_OPEN_CURLY_BRACES, '}' => self::T_CLOSE_CURLY_BRACES, '=' => self::T_EQUALS, ':' => self::T_COLON, '-' => self::T_MINUS, '\\' => self::T_NAMESPACE_SEPARATOR];
/** @var array<string, self::T*> */
protected $withCase = ['true' => self::T_TRUE, 'false' => self::T_FALSE, 'null' => self::T_NULL];
/**
* Whether the next token starts immediately, or if there were
* non-captured symbols before that
*/
public function nextTokenIsAdjacent() : bool
{
return $this->token === null || $this->lookahead !== null && $this->lookahead['position'] - $this->token['position'] === strlen($this->token['value']);
}
/**
* {@inheritDoc}
*/
protected function getCatchablePatterns()
{
return ['[a-z_\\\\][a-z0-9_\\:\\\\]*[a-z_][a-z0-9_]*', '(?:[+-]?[0-9]+(?:[\\.][0-9]+)*)(?:[eE][+-]?[0-9]+)?', '"(?:""|[^"])*+"'];
}
/**
* {@inheritDoc}
*/
protected function getNonCatchablePatterns()
{
return ['\\s+', '\\*+', '(.)'];
}
/**
* {@inheritDoc}
*/
protected function getType(&$value)
{
$type = self::T_NONE;
if ($value[0] === '"') {
$value = str_replace('""', '"', substr($value, 1, strlen($value) - 2));
return self::T_STRING;
}
if (isset($this->noCase[$value])) {
return $this->noCase[$value];
}
if ($value[0] === '_' || $value[0] === '\\' || ctype_alpha($value[0])) {
return self::T_IDENTIFIER;
}
$lowerValue = strtolower($value);
if (isset($this->withCase[$lowerValue])) {
return $this->withCase[$lowerValue];
}
// Checking numeric value
if (is_numeric($value)) {
return strpos($value, '.') !== \false || stripos($value, 'e') !== \false ? self::T_FLOAT : self::T_INTEGER;
}
return $type;
}
/** @return array{value: int|string, type:self::T_*|null, position:int} */
public function peek() : ?array
{
$token = parent::peek();
if ($token === null) {
return null;
}
return (array) $token;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,234 @@
<?php
namespace ps_metrics_module_v4_0_5\Doctrine\Common\Annotations;
use InvalidArgumentException;
use ReflectionClass;
use ReflectionMethod;
use ReflectionProperty;
use RuntimeException;
use function chmod;
use function file_put_contents;
use function filemtime;
use function gettype;
use function is_dir;
use function is_file;
use function is_int;
use function is_writable;
use function mkdir;
use function rename;
use function rtrim;
use function serialize;
use function sha1;
use function sprintf;
use function strtr;
use function tempnam;
use function uniqid;
use function unlink;
use function var_export;
/**
* File cache reader for annotations.
*
* @deprecated the FileCacheReader is deprecated and will be removed
* in version 2.0.0 of doctrine/annotations. Please use the
* {@see \Doctrine\Common\Annotations\PsrCachedReader} instead.
*/
class FileCacheReader implements Reader
{
/** @var Reader */
private $reader;
/** @var string */
private $dir;
/** @var bool */
private $debug;
/** @phpstan-var array<string, list<object>> */
private $loadedAnnotations = [];
/** @var array<string, string> */
private $classNameHashes = [];
/** @var int */
private $umask;
/**
* @param string $cacheDir
* @param bool $debug
* @param int $umask
*
* @throws InvalidArgumentException
*/
public function __construct(Reader $reader, $cacheDir, $debug = \false, $umask = 02)
{
if (!is_int($umask)) {
throw new InvalidArgumentException(sprintf('The parameter umask must be an integer, was: %s', gettype($umask)));
}
$this->reader = $reader;
$this->umask = $umask;
if (!is_dir($cacheDir) && !@mkdir($cacheDir, 0777 & ~$this->umask, \true)) {
throw new InvalidArgumentException(sprintf('The directory "%s" does not exist and could not be created.', $cacheDir));
}
$this->dir = rtrim($cacheDir, '\\/');
$this->debug = $debug;
}
/**
* {@inheritDoc}
*/
public function getClassAnnotations(ReflectionClass $class)
{
if (!isset($this->classNameHashes[$class->name])) {
$this->classNameHashes[$class->name] = sha1($class->name);
}
$key = $this->classNameHashes[$class->name];
if (isset($this->loadedAnnotations[$key])) {
return $this->loadedAnnotations[$key];
}
$path = $this->dir . '/' . strtr($key, '\\', '-') . '.cache.php';
if (!is_file($path)) {
$annot = $this->reader->getClassAnnotations($class);
$this->saveCacheFile($path, $annot);
return $this->loadedAnnotations[$key] = $annot;
}
$filename = $class->getFilename();
if ($this->debug && $filename !== \false && filemtime($path) < filemtime($filename)) {
@unlink($path);
$annot = $this->reader->getClassAnnotations($class);
$this->saveCacheFile($path, $annot);
return $this->loadedAnnotations[$key] = $annot;
}
return $this->loadedAnnotations[$key] = (include $path);
}
/**
* {@inheritDoc}
*/
public function getPropertyAnnotations(ReflectionProperty $property)
{
$class = $property->getDeclaringClass();
if (!isset($this->classNameHashes[$class->name])) {
$this->classNameHashes[$class->name] = sha1($class->name);
}
$key = $this->classNameHashes[$class->name] . '$' . $property->getName();
if (isset($this->loadedAnnotations[$key])) {
return $this->loadedAnnotations[$key];
}
$path = $this->dir . '/' . strtr($key, '\\', '-') . '.cache.php';
if (!is_file($path)) {
$annot = $this->reader->getPropertyAnnotations($property);
$this->saveCacheFile($path, $annot);
return $this->loadedAnnotations[$key] = $annot;
}
$filename = $class->getFilename();
if ($this->debug && $filename !== \false && filemtime($path) < filemtime($filename)) {
@unlink($path);
$annot = $this->reader->getPropertyAnnotations($property);
$this->saveCacheFile($path, $annot);
return $this->loadedAnnotations[$key] = $annot;
}
return $this->loadedAnnotations[$key] = (include $path);
}
/**
* {@inheritDoc}
*/
public function getMethodAnnotations(ReflectionMethod $method)
{
$class = $method->getDeclaringClass();
if (!isset($this->classNameHashes[$class->name])) {
$this->classNameHashes[$class->name] = sha1($class->name);
}
$key = $this->classNameHashes[$class->name] . '#' . $method->getName();
if (isset($this->loadedAnnotations[$key])) {
return $this->loadedAnnotations[$key];
}
$path = $this->dir . '/' . strtr($key, '\\', '-') . '.cache.php';
if (!is_file($path)) {
$annot = $this->reader->getMethodAnnotations($method);
$this->saveCacheFile($path, $annot);
return $this->loadedAnnotations[$key] = $annot;
}
$filename = $class->getFilename();
if ($this->debug && $filename !== \false && filemtime($path) < filemtime($filename)) {
@unlink($path);
$annot = $this->reader->getMethodAnnotations($method);
$this->saveCacheFile($path, $annot);
return $this->loadedAnnotations[$key] = $annot;
}
return $this->loadedAnnotations[$key] = (include $path);
}
/**
* Saves the cache file.
*
* @param string $path
* @param mixed $data
*
* @return void
*/
private function saveCacheFile($path, $data)
{
if (!is_writable($this->dir)) {
throw new InvalidArgumentException(sprintf(<<<'EXCEPTION'
The directory "%s" is not writable. Both the webserver and the console user need access.
You can manage access rights for multiple users with "chmod +a".
If your system does not support this, check out the acl package.,
EXCEPTION
, $this->dir));
}
$tempfile = tempnam($this->dir, uniqid('', \true));
if ($tempfile === \false) {
throw new RuntimeException(sprintf('Unable to create tempfile in directory: %s', $this->dir));
}
@chmod($tempfile, 0666 & ~$this->umask);
$written = file_put_contents($tempfile, '<?php return unserialize(' . var_export(serialize($data), \true) . ');');
if ($written === \false) {
throw new RuntimeException(sprintf('Unable to write cached file to: %s', $tempfile));
}
@chmod($tempfile, 0666 & ~$this->umask);
if (rename($tempfile, $path) === \false) {
@unlink($tempfile);
throw new RuntimeException(sprintf('Unable to rename %s to %s', $tempfile, $path));
}
}
/**
* {@inheritDoc}
*/
public function getClassAnnotation(ReflectionClass $class, $annotationName)
{
$annotations = $this->getClassAnnotations($class);
foreach ($annotations as $annotation) {
if ($annotation instanceof $annotationName) {
return $annotation;
}
}
return null;
}
/**
* {@inheritDoc}
*/
public function getMethodAnnotation(ReflectionMethod $method, $annotationName)
{
$annotations = $this->getMethodAnnotations($method);
foreach ($annotations as $annotation) {
if ($annotation instanceof $annotationName) {
return $annotation;
}
}
return null;
}
/**
* {@inheritDoc}
*/
public function getPropertyAnnotation(ReflectionProperty $property, $annotationName)
{
$annotations = $this->getPropertyAnnotations($property);
foreach ($annotations as $annotation) {
if ($annotation instanceof $annotationName) {
return $annotation;
}
}
return null;
}
/**
* Clears loaded annotations.
*
* @return void
*/
public function clearLoadedAnnotations()
{
$this->loadedAnnotations = [];
}
}

View File

@@ -0,0 +1,82 @@
<?php
declare (strict_types=1);
namespace ps_metrics_module_v4_0_5\Doctrine\Common\Annotations;
/**
* A list of annotations that are implicitly ignored during the parsing process.
*
* All names are case sensitive.
*/
final class ImplicitlyIgnoredAnnotationNames
{
private const Reserved = [
'Annotation' => \true,
'Attribute' => \true,
'Attributes' => \true,
/* Can we enable this? 'Enum' => true, */
'Required' => \true,
'Target' => \true,
'NamedArgumentConstructor' => \true,
];
private const WidelyUsedNonStandard = ['fix' => \true, 'fixme' => \true, 'override' => \true];
private const PhpDocumentor1 = ['abstract' => \true, 'access' => \true, 'code' => \true, 'deprec' => \true, 'endcode' => \true, 'exception' => \true, 'final' => \true, 'ingroup' => \true, 'inheritdoc' => \true, 'inheritDoc' => \true, 'magic' => \true, 'name' => \true, 'private' => \true, 'static' => \true, 'staticvar' => \true, 'staticVar' => \true, 'toc' => \true, 'tutorial' => \true, 'throw' => \true];
private const PhpDocumentor2 = [
'api' => \true,
'author' => \true,
'category' => \true,
'copyright' => \true,
'deprecated' => \true,
'example' => \true,
'filesource' => \true,
'global' => \true,
'ignore' => \true,
/* Can we enable this? 'index' => true, */
'internal' => \true,
'license' => \true,
'link' => \true,
'method' => \true,
'package' => \true,
'param' => \true,
'property' => \true,
'property-read' => \true,
'property-write' => \true,
'return' => \true,
'see' => \true,
'since' => \true,
'source' => \true,
'subpackage' => \true,
'throws' => \true,
'todo' => \true,
'TODO' => \true,
'usedby' => \true,
'uses' => \true,
'var' => \true,
'version' => \true,
];
private const PHPUnit = ['author' => \true, 'after' => \true, 'afterClass' => \true, 'backupGlobals' => \true, 'backupStaticAttributes' => \true, 'before' => \true, 'beforeClass' => \true, 'codeCoverageIgnore' => \true, 'codeCoverageIgnoreStart' => \true, 'codeCoverageIgnoreEnd' => \true, 'covers' => \true, 'coversDefaultClass' => \true, 'coversNothing' => \true, 'dataProvider' => \true, 'depends' => \true, 'doesNotPerformAssertions' => \true, 'expectedException' => \true, 'expectedExceptionCode' => \true, 'expectedExceptionMessage' => \true, 'expectedExceptionMessageRegExp' => \true, 'group' => \true, 'large' => \true, 'medium' => \true, 'preserveGlobalState' => \true, 'requires' => \true, 'runTestsInSeparateProcesses' => \true, 'runInSeparateProcess' => \true, 'small' => \true, 'test' => \true, 'testdox' => \true, 'testWith' => \true, 'ticket' => \true, 'uses' => \true];
private const PhpCheckStyle = ['SuppressWarnings' => \true];
private const PhpStorm = ['noinspection' => \true];
private const PEAR = ['package_version' => \true];
private const PlainUML = ['startuml' => \true, 'enduml' => \true];
private const Symfony = ['experimental' => \true];
private const PhpCodeSniffer = ['codingStandardsIgnoreStart' => \true, 'codingStandardsIgnoreEnd' => \true];
private const SlevomatCodingStandard = ['phpcsSuppress' => \true];
private const Phan = ['suppress' => \true];
private const Rector = ['noRector' => \true];
private const StaticAnalysis = [
// PHPStan, Psalm
'extends' => \true,
'implements' => \true,
'readonly' => \true,
'template' => \true,
'use' => \true,
// Psalm
'pure' => \true,
'immutable' => \true,
];
public const LIST = self::Reserved + self::WidelyUsedNonStandard + self::PhpDocumentor1 + self::PhpDocumentor2 + self::PHPUnit + self::PhpCheckStyle + self::PhpStorm + self::PEAR + self::PlainUML + self::Symfony + self::SlevomatCodingStandard + self::PhpCodeSniffer + self::Phan + self::Rector + self::StaticAnalysis;
private function __construct()
{
}
}

View File

@@ -0,0 +1,87 @@
<?php
namespace ps_metrics_module_v4_0_5\Doctrine\Common\Annotations;
use ReflectionClass;
use ReflectionMethod;
use ReflectionProperty;
use function call_user_func_array;
use function get_class;
/**
* Allows the reader to be used in-place of Doctrine's reader.
*/
class IndexedReader implements Reader
{
/** @var Reader */
private $delegate;
public function __construct(Reader $reader)
{
$this->delegate = $reader;
}
/**
* {@inheritDoc}
*/
public function getClassAnnotations(ReflectionClass $class)
{
$annotations = [];
foreach ($this->delegate->getClassAnnotations($class) as $annot) {
$annotations[get_class($annot)] = $annot;
}
return $annotations;
}
/**
* {@inheritDoc}
*/
public function getClassAnnotation(ReflectionClass $class, $annotationName)
{
return $this->delegate->getClassAnnotation($class, $annotationName);
}
/**
* {@inheritDoc}
*/
public function getMethodAnnotations(ReflectionMethod $method)
{
$annotations = [];
foreach ($this->delegate->getMethodAnnotations($method) as $annot) {
$annotations[get_class($annot)] = $annot;
}
return $annotations;
}
/**
* {@inheritDoc}
*/
public function getMethodAnnotation(ReflectionMethod $method, $annotationName)
{
return $this->delegate->getMethodAnnotation($method, $annotationName);
}
/**
* {@inheritDoc}
*/
public function getPropertyAnnotations(ReflectionProperty $property)
{
$annotations = [];
foreach ($this->delegate->getPropertyAnnotations($property) as $annot) {
$annotations[get_class($annot)] = $annot;
}
return $annotations;
}
/**
* {@inheritDoc}
*/
public function getPropertyAnnotation(ReflectionProperty $property, $annotationName)
{
return $this->delegate->getPropertyAnnotation($property, $annotationName);
}
/**
* Proxies all methods to the delegate.
*
* @param string $method
* @param mixed[] $args
*
* @return mixed
*/
public function __call($method, $args)
{
return call_user_func_array([$this->delegate, $method], $args);
}
}

View File

@@ -0,0 +1,14 @@
<?php
namespace ps_metrics_module_v4_0_5\Doctrine\Common\Annotations;
/**
* Marker interface for PHP7/PHP8 compatible support
* for named arguments (and constructor property promotion).
*
* @deprecated Implementing this interface is deprecated
* Use the Annotation @NamedArgumentConstructor instead
*/
interface NamedArgumentConstructorAnnotation
{
}

View File

@@ -0,0 +1,79 @@
<?php
namespace ps_metrics_module_v4_0_5\Doctrine\Common\Annotations;
use ReflectionClass;
use ReflectionFunction;
use SplFileObject;
use function is_file;
use function method_exists;
use function preg_quote;
use function preg_replace;
/**
* Parses a file for namespaces/use/class declarations.
*/
final class PhpParser
{
/**
* Parses a class.
*
* @deprecated use parseUseStatements instead
*
* @param ReflectionClass $class A <code>ReflectionClass</code> object.
*
* @return array<string, class-string> A list with use statements in the form (Alias => FQN).
*/
public function parseClass(ReflectionClass $class)
{
return $this->parseUseStatements($class);
}
/**
* Parse a class or function for use statements.
*
* @param ReflectionClass|ReflectionFunction $reflection
*
* @psalm-return array<string, string> a list with use statements in the form (Alias => FQN).
*/
public function parseUseStatements($reflection) : array
{
if (method_exists($reflection, 'getUseStatements')) {
return $reflection->getUseStatements();
}
$filename = $reflection->getFileName();
if ($filename === \false) {
return [];
}
$content = $this->getFileContent($filename, $reflection->getStartLine());
if ($content === null) {
return [];
}
$namespace = preg_quote($reflection->getNamespaceName());
$content = preg_replace('/^.*?(\\bnamespace\\s+' . $namespace . '\\s*[;{].*)$/s', '\\1', $content);
$tokenizer = new TokenParser('<?php ' . $content);
return $tokenizer->parseUseStatements($reflection->getNamespaceName());
}
/**
* Gets the content of the file right up to the given line number.
*
* @param string $filename The name of the file to load.
* @param int $lineNumber The number of lines to read from file.
*
* @return string|null The content of the file or null if the file does not exist.
*/
private function getFileContent($filename, $lineNumber)
{
if (!is_file($filename)) {
return null;
}
$content = '';
$lineCnt = 0;
$file = new SplFileObject($filename);
while (!$file->eof()) {
if ($lineCnt++ === $lineNumber) {
break;
}
$content .= $file->fgets();
}
return $content;
}
}

View File

@@ -0,0 +1,176 @@
<?php
namespace ps_metrics_module_v4_0_5\Doctrine\Common\Annotations;
use Psr\Cache\CacheItemPoolInterface;
use ReflectionClass;
use ReflectionMethod;
use ReflectionProperty;
use Reflector;
use function array_map;
use function array_merge;
use function assert;
use function filemtime;
use function max;
use function rawurlencode;
use function time;
/**
* A cache aware annotation reader.
*/
final class PsrCachedReader implements Reader
{
/** @var Reader */
private $delegate;
/** @var CacheItemPoolInterface */
private $cache;
/** @var bool */
private $debug;
/** @var array<string, array<object>> */
private $loadedAnnotations = [];
/** @var int[] */
private $loadedFilemtimes = [];
public function __construct(Reader $reader, CacheItemPoolInterface $cache, bool $debug = \false)
{
$this->delegate = $reader;
$this->cache = $cache;
$this->debug = (bool) $debug;
}
/**
* {@inheritDoc}
*/
public function getClassAnnotations(ReflectionClass $class)
{
$cacheKey = $class->getName();
if (isset($this->loadedAnnotations[$cacheKey])) {
return $this->loadedAnnotations[$cacheKey];
}
$annots = $this->fetchFromCache($cacheKey, $class, 'getClassAnnotations', $class);
return $this->loadedAnnotations[$cacheKey] = $annots;
}
/**
* {@inheritDoc}
*/
public function getClassAnnotation(ReflectionClass $class, $annotationName)
{
foreach ($this->getClassAnnotations($class) as $annot) {
if ($annot instanceof $annotationName) {
return $annot;
}
}
return null;
}
/**
* {@inheritDoc}
*/
public function getPropertyAnnotations(ReflectionProperty $property)
{
$class = $property->getDeclaringClass();
$cacheKey = $class->getName() . '$' . $property->getName();
if (isset($this->loadedAnnotations[$cacheKey])) {
return $this->loadedAnnotations[$cacheKey];
}
$annots = $this->fetchFromCache($cacheKey, $class, 'getPropertyAnnotations', $property);
return $this->loadedAnnotations[$cacheKey] = $annots;
}
/**
* {@inheritDoc}
*/
public function getPropertyAnnotation(ReflectionProperty $property, $annotationName)
{
foreach ($this->getPropertyAnnotations($property) as $annot) {
if ($annot instanceof $annotationName) {
return $annot;
}
}
return null;
}
/**
* {@inheritDoc}
*/
public function getMethodAnnotations(ReflectionMethod $method)
{
$class = $method->getDeclaringClass();
$cacheKey = $class->getName() . '#' . $method->getName();
if (isset($this->loadedAnnotations[$cacheKey])) {
return $this->loadedAnnotations[$cacheKey];
}
$annots = $this->fetchFromCache($cacheKey, $class, 'getMethodAnnotations', $method);
return $this->loadedAnnotations[$cacheKey] = $annots;
}
/**
* {@inheritDoc}
*/
public function getMethodAnnotation(ReflectionMethod $method, $annotationName)
{
foreach ($this->getMethodAnnotations($method) as $annot) {
if ($annot instanceof $annotationName) {
return $annot;
}
}
return null;
}
public function clearLoadedAnnotations() : void
{
$this->loadedAnnotations = [];
$this->loadedFilemtimes = [];
}
/** @return mixed[] */
private function fetchFromCache(string $cacheKey, ReflectionClass $class, string $method, Reflector $reflector) : array
{
$cacheKey = rawurlencode($cacheKey);
$item = $this->cache->getItem($cacheKey);
if ($this->debug && !$this->refresh($cacheKey, $class) || !$item->isHit()) {
$this->cache->save($item->set($this->delegate->{$method}($reflector)));
}
return $item->get();
}
/**
* Used in debug mode to check if the cache is fresh.
*
* @return bool Returns true if the cache was fresh, or false if the class
* being read was modified since writing to the cache.
*/
private function refresh(string $cacheKey, ReflectionClass $class) : bool
{
$lastModification = $this->getLastModification($class);
if ($lastModification === 0) {
return \true;
}
$item = $this->cache->getItem('[C]' . $cacheKey);
if ($item->isHit() && $item->get() >= $lastModification) {
return \true;
}
$this->cache->save($item->set(time()));
return \false;
}
/**
* Returns the time the class was last modified, testing traits and parents
*/
private function getLastModification(ReflectionClass $class) : int
{
$filename = $class->getFileName();
if (isset($this->loadedFilemtimes[$filename])) {
return $this->loadedFilemtimes[$filename];
}
$parent = $class->getParentClass();
$lastModification = max(array_merge([$filename ? filemtime($filename) : 0], array_map(function (ReflectionClass $reflectionTrait) : int {
return $this->getTraitLastModificationTime($reflectionTrait);
}, $class->getTraits()), array_map(function (ReflectionClass $class) : int {
return $this->getLastModification($class);
}, $class->getInterfaces()), $parent ? [$this->getLastModification($parent)] : []));
assert($lastModification !== \false);
return $this->loadedFilemtimes[$filename] = $lastModification;
}
private function getTraitLastModificationTime(ReflectionClass $reflectionTrait) : int
{
$fileName = $reflectionTrait->getFileName();
if (isset($this->loadedFilemtimes[$fileName])) {
return $this->loadedFilemtimes[$fileName];
}
$lastModificationTime = max(array_merge([$fileName ? filemtime($fileName) : 0], array_map(function (ReflectionClass $reflectionTrait) : int {
return $this->getTraitLastModificationTime($reflectionTrait);
}, $reflectionTrait->getTraits())));
assert($lastModificationTime !== \false);
return $this->loadedFilemtimes[$fileName] = $lastModificationTime;
}
}

View File

@@ -0,0 +1,74 @@
<?php
namespace ps_metrics_module_v4_0_5\Doctrine\Common\Annotations;
use ReflectionClass;
use ReflectionMethod;
use ReflectionProperty;
/**
* Interface for annotation readers.
*/
interface Reader
{
/**
* Gets the annotations applied to a class.
*
* @param ReflectionClass $class The ReflectionClass of the class from which
* the class annotations should be read.
*
* @return array<object> An array of Annotations.
*/
public function getClassAnnotations(ReflectionClass $class);
/**
* Gets a class annotation.
*
* @param ReflectionClass $class The ReflectionClass of the class from which
* the class annotations should be read.
* @param class-string<T> $annotationName The name of the annotation.
*
* @return T|null The Annotation or NULL, if the requested annotation does not exist.
*
* @template T
*/
public function getClassAnnotation(ReflectionClass $class, $annotationName);
/**
* Gets the annotations applied to a method.
*
* @param ReflectionMethod $method The ReflectionMethod of the method from which
* the annotations should be read.
*
* @return array<object> An array of Annotations.
*/
public function getMethodAnnotations(ReflectionMethod $method);
/**
* Gets a method annotation.
*
* @param ReflectionMethod $method The ReflectionMethod to read the annotations from.
* @param class-string<T> $annotationName The name of the annotation.
*
* @return T|null The Annotation or NULL, if the requested annotation does not exist.
*
* @template T
*/
public function getMethodAnnotation(ReflectionMethod $method, $annotationName);
/**
* Gets the annotations applied to a property.
*
* @param ReflectionProperty $property The ReflectionProperty of the property
* from which the annotations should be read.
*
* @return array<object> An array of Annotations.
*/
public function getPropertyAnnotations(ReflectionProperty $property);
/**
* Gets a property annotation.
*
* @param ReflectionProperty $property The ReflectionProperty to read the annotations from.
* @param class-string<T> $annotationName The name of the annotation.
*
* @return T|null The Annotation or NULL, if the requested annotation does not exist.
*
* @template T
*/
public function getPropertyAnnotation(ReflectionProperty $property, $annotationName);
}

View File

@@ -0,0 +1,96 @@
<?php
namespace ps_metrics_module_v4_0_5\Doctrine\Common\Annotations;
use ReflectionClass;
use ReflectionMethod;
use ReflectionProperty;
/**
* Simple Annotation Reader.
*
* This annotation reader is intended to be used in projects where you have
* full-control over all annotations that are available.
*
* @deprecated Deprecated in favour of using AnnotationReader
*/
class SimpleAnnotationReader implements Reader
{
/** @var DocParser */
private $parser;
/**
* Initializes a new SimpleAnnotationReader.
*/
public function __construct()
{
$this->parser = new DocParser();
$this->parser->setIgnoreNotImportedAnnotations(\true);
}
/**
* Adds a namespace in which we will look for annotations.
*
* @param string $namespace
*
* @return void
*/
public function addNamespace($namespace)
{
$this->parser->addNamespace($namespace);
}
/**
* {@inheritDoc}
*/
public function getClassAnnotations(ReflectionClass $class)
{
return $this->parser->parse($class->getDocComment(), 'class ' . $class->getName());
}
/**
* {@inheritDoc}
*/
public function getMethodAnnotations(ReflectionMethod $method)
{
return $this->parser->parse($method->getDocComment(), 'method ' . $method->getDeclaringClass()->name . '::' . $method->getName() . '()');
}
/**
* {@inheritDoc}
*/
public function getPropertyAnnotations(ReflectionProperty $property)
{
return $this->parser->parse($property->getDocComment(), 'property ' . $property->getDeclaringClass()->name . '::$' . $property->getName());
}
/**
* {@inheritDoc}
*/
public function getClassAnnotation(ReflectionClass $class, $annotationName)
{
foreach ($this->getClassAnnotations($class) as $annot) {
if ($annot instanceof $annotationName) {
return $annot;
}
}
return null;
}
/**
* {@inheritDoc}
*/
public function getMethodAnnotation(ReflectionMethod $method, $annotationName)
{
foreach ($this->getMethodAnnotations($method) as $annot) {
if ($annot instanceof $annotationName) {
return $annot;
}
}
return null;
}
/**
* {@inheritDoc}
*/
public function getPropertyAnnotation(ReflectionProperty $property, $annotationName)
{
foreach ($this->getPropertyAnnotations($property) as $annot) {
if ($annot instanceof $annotationName) {
return $annot;
}
}
return null;
}
}

View File

@@ -0,0 +1,174 @@
<?php
namespace ps_metrics_module_v4_0_5\Doctrine\Common\Annotations;
use function array_merge;
use function count;
use function explode;
use function strtolower;
use function token_get_all;
use const PHP_VERSION_ID;
use const T_AS;
use const T_COMMENT;
use const T_DOC_COMMENT;
use const T_NAME_FULLY_QUALIFIED;
use const T_NAME_QUALIFIED;
use const T_NAMESPACE;
use const T_NS_SEPARATOR;
use const T_STRING;
use const T_USE;
use const T_WHITESPACE;
/**
* Parses a file for namespaces/use/class declarations.
*/
class TokenParser
{
/**
* The token list.
*
* @phpstan-var list<mixed[]>
*/
private $tokens;
/**
* The number of tokens.
*
* @var int
*/
private $numTokens;
/**
* The current array pointer.
*
* @var int
*/
private $pointer = 0;
/** @param string $contents */
public function __construct($contents)
{
$this->tokens = token_get_all($contents);
// The PHP parser sets internal compiler globals for certain things. Annoyingly, the last docblock comment it
// saw gets stored in doc_comment. When it comes to compile the next thing to be include()d this stored
// doc_comment becomes owned by the first thing the compiler sees in the file that it considers might have a
// docblock. If the first thing in the file is a class without a doc block this would cause calls to
// getDocBlock() on said class to return our long lost doc_comment. Argh.
// To workaround, cause the parser to parse an empty docblock. Sure getDocBlock() will return this, but at least
// it's harmless to us.
token_get_all("<?php\n/**\n *\n */");
$this->numTokens = count($this->tokens);
}
/**
* Gets the next non whitespace and non comment token.
*
* @param bool $docCommentIsComment If TRUE then a doc comment is considered a comment and skipped.
* If FALSE then only whitespace and normal comments are skipped.
*
* @return mixed[]|string|null The token if exists, null otherwise.
*/
public function next($docCommentIsComment = \true)
{
for ($i = $this->pointer; $i < $this->numTokens; $i++) {
$this->pointer++;
if ($this->tokens[$i][0] === T_WHITESPACE || $this->tokens[$i][0] === T_COMMENT || $docCommentIsComment && $this->tokens[$i][0] === T_DOC_COMMENT) {
continue;
}
return $this->tokens[$i];
}
return null;
}
/**
* Parses a single use statement.
*
* @return array<string, string> A list with all found class names for a use statement.
*/
public function parseUseStatement()
{
$groupRoot = '';
$class = '';
$alias = '';
$statements = [];
$explicitAlias = \false;
while ($token = $this->next()) {
if (!$explicitAlias && $token[0] === T_STRING) {
$class .= $token[1];
$alias = $token[1];
} elseif ($explicitAlias && $token[0] === T_STRING) {
$alias = $token[1];
} elseif (PHP_VERSION_ID >= 80000 && ($token[0] === T_NAME_QUALIFIED || $token[0] === T_NAME_FULLY_QUALIFIED)) {
$class .= $token[1];
$classSplit = explode('\\', $token[1]);
$alias = $classSplit[count($classSplit) - 1];
} elseif ($token[0] === T_NS_SEPARATOR) {
$class .= '\\';
$alias = '';
} elseif ($token[0] === T_AS) {
$explicitAlias = \true;
$alias = '';
} elseif ($token === ',') {
$statements[strtolower($alias)] = $groupRoot . $class;
$class = '';
$alias = '';
$explicitAlias = \false;
} elseif ($token === ';') {
$statements[strtolower($alias)] = $groupRoot . $class;
break;
} elseif ($token === '{') {
$groupRoot = $class;
$class = '';
} elseif ($token === '}') {
continue;
} else {
break;
}
}
return $statements;
}
/**
* Gets all use statements.
*
* @param string $namespaceName The namespace name of the reflected class.
*
* @return array<string, string> A list with all found use statements.
*/
public function parseUseStatements($namespaceName)
{
$statements = [];
while ($token = $this->next()) {
if ($token[0] === T_USE) {
$statements = array_merge($statements, $this->parseUseStatement());
continue;
}
if ($token[0] !== T_NAMESPACE || $this->parseNamespace() !== $namespaceName) {
continue;
}
// Get fresh array for new namespace. This is to prevent the parser to collect the use statements
// for a previous namespace with the same name. This is the case if a namespace is defined twice
// or if a namespace with the same name is commented out.
$statements = [];
}
return $statements;
}
/**
* Gets the namespace.
*
* @return string The found namespace.
*/
public function parseNamespace()
{
$name = '';
while (($token = $this->next()) && ($token[0] === T_STRING || $token[0] === T_NS_SEPARATOR || PHP_VERSION_ID >= 80000 && ($token[0] === T_NAME_QUALIFIED || $token[0] === T_NAME_FULLY_QUALIFIED))) {
$name .= $token[1];
}
return $name;
}
/**
* Gets the class name.
*
* @return string The found class name.
*/
public function parseClass()
{
// Namespaces and class names are tokenized the same: T_STRINGs
// separated by T_NS_SEPARATOR so we can use one function to provide
// both.
return $this->parseNamespace();
}
}

View File

@@ -0,0 +1,11 @@
<?php
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,11 @@
<?php
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,11 @@
<?php
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;