Vendor lock

This commit is contained in:
2023-06-16 02:08:47 +00:00
parent 7933e70e90
commit 3351b92dd6
4099 changed files with 345789 additions and 0 deletions

View File

@ -0,0 +1,7 @@
# .gitattributes
tests/ export-ignore
phpunit.xml.dist export-ignore
.travis.yml export-ignore
# Auto detect text files and perform LF normalization
* text=auto

View File

@ -0,0 +1,5 @@
.DS_Store
.idea/*
vendor/*
composer.phar
composer.lock

16
vendor/php-di/phpdoc-reader/LICENSE vendored Normal file
View File

@ -0,0 +1,16 @@
Copyright (C) 2015 Matthieu Napoli
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

58
vendor/php-di/phpdoc-reader/README.md vendored Normal file
View File

@ -0,0 +1,58 @@
# PhpDocReader
[![Build Status](https://img.shields.io/travis/PHP-DI/PhpDocReader.svg)](https://travis-ci.org/mnapoli/PhpDocReader)
![](https://img.shields.io/packagist/dt/PHP-DI/phpdoc-reader.svg)
This project is used by:
- [PHP-DI](http://php-di.org/)
- [phockito-unit-php-di](https://github.com/balihoo/phockito-unit-php-di)
Fork the README to add your project here.
## Features
PhpDocReader parses `@var` and `@param` values in PHP docblocks:
```php
use My\Cache\Backend;
class Cache
{
/**
* @var Backend
*/
protected $backend;
/**
* @param Backend $backend
*/
public function __construct($backend)
{
}
}
```
It supports namespaced class names with the same resolution rules as PHP:
- fully qualified name (starting with `\`)
- imported class name (eg. `use My\Cache\Backend;`)
- relative class name (from the current namespace, like `SubNamespace\MyClass`)
- aliased class name (eg. `use My\Cache\Backend as FooBar;`)
Primitive types (`@var string`) are ignored (returns null), only valid class names are returned.
## Usage
```php
$reader = new PhpDocReader();
// Read a property type (@var phpdoc)
$property = new ReflectionProperty($className, $propertyName);
$propertyClass = $reader->getPropertyClass($property);
// Read a parameter type (@param phpdoc)
$parameter = new ReflectionParameter(array($className, $methodName), $parameterName);
$parameterClass = $reader->getParameterClass($parameter);
```

View File

@ -0,0 +1,23 @@
{
"name": "php-di/phpdoc-reader",
"type": "library",
"description": "PhpDocReader parses @var and @param values in PHP docblocks (supports namespaced class names with the same resolution rules as PHP)",
"keywords": ["phpdoc", "reflection"],
"license": "MIT",
"autoload": {
"psr-4": {
"PhpDocReader\\": "src/PhpDocReader"
}
},
"autoload-dev": {
"psr-4": {
"UnitTest\\PhpDocReader\\": "tests/"
}
},
"require": {
"php": ">=5.4.0"
},
"require-dev": {
"phpunit/phpunit": "~4.6"
}
}

View File

@ -0,0 +1,10 @@
<?php
namespace PhpDocReader;
/**
* @author Matthieu Napoli <matthieu@mnapoli.fr>
*/
class AnnotationException extends \Exception
{
}

View File

@ -0,0 +1,312 @@
<?php
namespace PhpDocReader;
use PhpDocReader\PhpParser\UseStatementParser;
use ReflectionClass;
use ReflectionMethod;
use ReflectionParameter;
use ReflectionProperty;
use Reflector;
/**
* PhpDoc reader
*
* @author Matthieu Napoli <matthieu@mnapoli.fr>
*/
class PhpDocReader
{
/**
* @var UseStatementParser
*/
private $parser;
private $ignoredTypes = array(
'bool',
'boolean',
'string',
'int',
'integer',
'float',
'double',
'array',
'object',
'callable',
'resource',
'mixed',
'iterable',
);
/**
* Enable or disable throwing errors when PhpDoc Errors occur (when parsing annotations)
*
* @var bool
*/
private $ignorePhpDocErrors;
/**
*
* @param bool $ignorePhpDocErrors
*/
public function __construct($ignorePhpDocErrors = false)
{
$this->parser = new UseStatementParser();
$this->ignorePhpDocErrors = $ignorePhpDocErrors;
}
/**
* Parse the docblock of the property to get the class of the var annotation.
*
* @param ReflectionProperty $property
*
* @throws AnnotationException
* @return string|null Type of the property (content of var annotation)
*
* @deprecated Use getPropertyClass instead.
*/
public function getPropertyType(ReflectionProperty $property)
{
return $this->getPropertyClass($property);
}
/**
* Parse the docblock of the property to get the class of the var annotation.
*
* @param ReflectionProperty $property
*
* @throws AnnotationException
* @return string|null Type of the property (content of var annotation)
*/
public function getPropertyClass(ReflectionProperty $property)
{
// Get the content of the @var annotation
if (preg_match('/@var\s+([^\s]+)/', $property->getDocComment(), $matches)) {
list(, $type) = $matches;
} else {
return null;
}
// Ignore primitive types
if (in_array($type, $this->ignoredTypes)) {
return null;
}
// Ignore types containing special characters ([], <> ...)
if (! preg_match('/^[a-zA-Z0-9\\\\_]+$/', $type)) {
return null;
}
$class = $property->getDeclaringClass();
// If the class name is not fully qualified (i.e. doesn't start with a \)
if ($type[0] !== '\\') {
// Try to resolve the FQN using the class context
$resolvedType = $this->tryResolveFqn($type, $class, $property);
if (!$resolvedType && !$this->ignorePhpDocErrors) {
throw new AnnotationException(sprintf(
'The @var annotation on %s::%s contains a non existent class "%s". '
. 'Did you maybe forget to add a "use" statement for this annotation?',
$class->name,
$property->getName(),
$type
));
}
$type = $resolvedType;
}
if (!$this->classExists($type) && !$this->ignorePhpDocErrors) {
throw new AnnotationException(sprintf(
'The @var annotation on %s::%s contains a non existent class "%s"',
$class->name,
$property->getName(),
$type
));
}
// Remove the leading \ (FQN shouldn't contain it)
$type = ltrim($type, '\\');
return $type;
}
/**
* Parse the docblock of the property to get the class of the param annotation.
*
* @param ReflectionParameter $parameter
*
* @throws AnnotationException
* @return string|null Type of the property (content of var annotation)
*
* @deprecated Use getParameterClass instead.
*/
public function getParameterType(ReflectionParameter $parameter)
{
return $this->getParameterClass($parameter);
}
/**
* Parse the docblock of the property to get the class of the param annotation.
*
* @param ReflectionParameter $parameter
*
* @throws AnnotationException
* @return string|null Type of the property (content of var annotation)
*/
public function getParameterClass(ReflectionParameter $parameter)
{
// Use reflection
$parameterClass = $parameter->getClass();
if ($parameterClass !== null) {
return $parameterClass->name;
}
$parameterName = $parameter->name;
// Get the content of the @param annotation
$method = $parameter->getDeclaringFunction();
if (preg_match('/@param\s+([^\s]+)\s+\$' . $parameterName . '/', $method->getDocComment(), $matches)) {
list(, $type) = $matches;
} else {
return null;
}
// Ignore primitive types
if (in_array($type, $this->ignoredTypes)) {
return null;
}
// Ignore types containing special characters ([], <> ...)
if (! preg_match('/^[a-zA-Z0-9\\\\_]+$/', $type)) {
return null;
}
$class = $parameter->getDeclaringClass();
// If the class name is not fully qualified (i.e. doesn't start with a \)
if ($type[0] !== '\\') {
// Try to resolve the FQN using the class context
$resolvedType = $this->tryResolveFqn($type, $class, $parameter);
if (!$resolvedType && !$this->ignorePhpDocErrors) {
throw new AnnotationException(sprintf(
'The @param annotation for parameter "%s" of %s::%s contains a non existent class "%s". '
. 'Did you maybe forget to add a "use" statement for this annotation?',
$parameterName,
$class->name,
$method->name,
$type
));
}
$type = $resolvedType;
}
if (!$this->classExists($type) && !$this->ignorePhpDocErrors) {
throw new AnnotationException(sprintf(
'The @param annotation for parameter "%s" of %s::%s contains a non existent class "%s"',
$parameterName,
$class->name,
$method->name,
$type
));
}
// Remove the leading \ (FQN shouldn't contain it)
$type = ltrim($type, '\\');
return $type;
}
/**
* Attempts to resolve the FQN of the provided $type based on the $class and $member context.
*
* @param string $type
* @param ReflectionClass $class
* @param Reflector $member
*
* @return string|null Fully qualified name of the type, or null if it could not be resolved
*/
private function tryResolveFqn($type, ReflectionClass $class, Reflector $member)
{
$alias = ($pos = strpos($type, '\\')) === false ? $type : substr($type, 0, $pos);
$loweredAlias = strtolower($alias);
// Retrieve "use" statements
$uses = $this->parser->parseUseStatements($class);
if (isset($uses[$loweredAlias])) {
// Imported classes
if ($pos !== false) {
return $uses[$loweredAlias] . substr($type, $pos);
} else {
return $uses[$loweredAlias];
}
} elseif ($this->classExists($class->getNamespaceName() . '\\' . $type)) {
return $class->getNamespaceName() . '\\' . $type;
} elseif (isset($uses['__NAMESPACE__']) && $this->classExists($uses['__NAMESPACE__'] . '\\' . $type)) {
// Class namespace
return $uses['__NAMESPACE__'] . '\\' . $type;
} elseif ($this->classExists($type)) {
// No namespace
return $type;
}
if (version_compare(phpversion(), '5.4.0', '<')) {
return null;
} else {
// If all fail, try resolving through related traits
return $this->tryResolveFqnInTraits($type, $class, $member);
}
}
/**
* Attempts to resolve the FQN of the provided $type based on the $class and $member context, specifically searching
* through the traits that are used by the provided $class.
*
* @param string $type
* @param ReflectionClass $class
* @param Reflector $member
*
* @return string|null Fully qualified name of the type, or null if it could not be resolved
*/
private function tryResolveFqnInTraits($type, ReflectionClass $class, Reflector $member)
{
/** @var ReflectionClass[] $traits */
$traits = array();
// Get traits for the class and its parents
while ($class) {
$traits = array_merge($traits, $class->getTraits());
$class = $class->getParentClass();
}
foreach ($traits as $trait) {
// Eliminate traits that don't have the property/method/parameter
if ($member instanceof ReflectionProperty && !$trait->hasProperty($member->name)) {
continue;
} elseif ($member instanceof ReflectionMethod && !$trait->hasMethod($member->name)) {
continue;
} elseif ($member instanceof ReflectionParameter && !$trait->hasMethod($member->getDeclaringFunction()->name)) {
continue;
}
// Run the resolver again with the ReflectionClass instance for the trait
$resolvedType = $this->tryResolveFqn($type, $trait, $member);
if ($resolvedType) {
return $resolvedType;
}
}
return null;
}
/**
* @param string $class
* @return bool
*/
private function classExists($class)
{
return class_exists($class) || interface_exists($class);
}
}

View File

@ -0,0 +1,159 @@
<?php
namespace PhpDocReader\PhpParser;
/**
* Parses a file for namespaces/use/class declarations.
*
* Class taken and adapted from doctrine/annotations to avoid pulling the whole package.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Christian Kaps <christian.kaps@mohiva.com>
*/
class TokenParser
{
/**
* The token list.
*
* @var array
*/
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 all use statements.
*
* @param string $namespaceName The namespace name of the reflected class.
*
* @return array A list with all found use statements.
*/
public function parseUseStatements($namespaceName)
{
$statements = array();
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 = array();
}
return $statements;
}
/**
* Gets the next non whitespace and non comment token.
*
* @param boolean $docCommentIsComment If TRUE then a doc comment is considered a comment and skipped.
* If FALSE then only whitespace and normal comments are skipped.
*
* @return array|null The token if exists, null otherwise.
*/
private 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 A list with all found class names for a use statement.
*/
private function parseUseStatement()
{
$class = '';
$alias = '';
$statements = array();
$explicitAlias = false;
while (($token = $this->next())) {
$isNameToken = $token[0] === T_STRING || $token[0] === T_NS_SEPARATOR;
if (!$explicitAlias && $isNameToken) {
$class .= $token[1];
$alias = $token[1];
} elseif ($explicitAlias && $isNameToken) {
$alias .= $token[1];
} elseif ($token[0] === T_AS) {
$explicitAlias = true;
$alias = '';
} elseif ($token === ',') {
$statements[strtolower($alias)] = $class;
$class = '';
$alias = '';
$explicitAlias = false;
} elseif ($token === ';') {
$statements[strtolower($alias)] = $class;
break;
} else {
break;
}
}
return $statements;
}
/**
* Gets the namespace.
*
* @return string The found namespace.
*/
private function parseNamespace()
{
$name = '';
while (($token = $this->next()) && ($token[0] === T_STRING || $token[0] === T_NS_SEPARATOR)) {
$name .= $token[1];
}
return $name;
}
}

View File

@ -0,0 +1,68 @@
<?php
namespace PhpDocReader\PhpParser;
use SplFileObject;
/**
* Parses a file for "use" declarations.
*
* Class taken and adapted from doctrine/annotations to avoid pulling the whole package.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Christian Kaps <christian.kaps@mohiva.com>
*/
class UseStatementParser
{
/**
* @return array A list with use statements in the form (Alias => FQN).
*/
public function parseUseStatements(\ReflectionClass $class)
{
if (false === $filename = $class->getFilename()) {
return array();
}
$content = $this->getFileContent($filename, $class->getStartLine());
if (null === $content) {
return array();
}
$namespace = preg_quote($class->getNamespaceName());
$content = preg_replace('/^.*?(\bnamespace\s+' . $namespace . '\s*[;{].*)$/s', '\\1', $content);
$tokenizer = new TokenParser('<?php ' . $content);
$statements = $tokenizer->parseUseStatements($class->getNamespaceName());
return $statements;
}
/**
* Gets the content of the file right up to the given line number.
*
* @param string $filename The name of the file to load.
* @param integer $lineNumber The number of lines to read from file.
*
* @return string The content of the file.
*/
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;
}
}