Initial Drupal 11 with DDEV setup
This commit is contained in:
19
vendor/doctrine/annotations/LICENSE
vendored
Normal file
19
vendor/doctrine/annotations/LICENSE
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2006-2013 Doctrine Project
|
||||
|
||||
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.
|
||||
31
vendor/doctrine/annotations/README.md
vendored
Normal file
31
vendor/doctrine/annotations/README.md
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
⚠️ PHP 8 introduced
|
||||
[attributes](https://www.php.net/manual/en/language.attributes.overview.php),
|
||||
which are a native replacement for annotations. As such, this library is
|
||||
considered feature complete, and should receive exclusively bugfixes and
|
||||
security fixes.
|
||||
|
||||
We do not recommend using this library in new projects and encourage authors
|
||||
of downstream libraries to offer support for attributes as an alternative to
|
||||
Doctrine Annotations.
|
||||
|
||||
Have a look at [our blog](https://www.doctrine-project.org/2022/11/04/annotations-to-attributes.html)
|
||||
to learn more.
|
||||
|
||||
# Doctrine Annotations
|
||||
|
||||
[](https://github.com/doctrine/persistence/actions)
|
||||
[](https://www.versioneye.com/package/php--doctrine--annotations)
|
||||
[](https://www.versioneye.com/php/doctrine:annotations/references)
|
||||
[](https://packagist.org/packages/doctrine/annotations)
|
||||
[](https://packagist.org/packages/doctrine/annotations)
|
||||
|
||||
Docblock Annotations Parser library (extracted from [Doctrine Common](https://github.com/doctrine/common)).
|
||||
|
||||
## Documentation
|
||||
|
||||
See the [doctrine-project website](https://www.doctrine-project.org/projects/doctrine-annotations/en/stable/index.html).
|
||||
|
||||
## Contributing
|
||||
|
||||
When making a pull request, make sure your changes follow the
|
||||
[Coding Standard Guidelines](https://www.doctrine-project.org/projects/doctrine-coding-standard/en/current/reference/index.html#introduction).
|
||||
18
vendor/doctrine/annotations/UPGRADE.md
vendored
Normal file
18
vendor/doctrine/annotations/UPGRADE.md
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
# Upgrade from 1.0.x to 2.0.x
|
||||
|
||||
- The `NamedArgumentConstructorAnnotation` has been removed. Use the `@NamedArgumentConstructor`
|
||||
annotation instead.
|
||||
- `SimpleAnnotationReader` has been removed.
|
||||
- `DocLexer::peek()` and `DocLexer::glimpse` now return
|
||||
`Doctrine\Common\Lexer\Token` objects. When using `doctrine/lexer` 2, these
|
||||
implement `ArrayAccess` as a way for you to still be able to treat them as
|
||||
arrays in some ways.
|
||||
- `CachedReader` and `FileCacheReader` have been removed use `PsrCachedReader` instead.
|
||||
- `AnnotationRegistry` methods related to registering annotations instead of
|
||||
using autoloading have been removed.
|
||||
- Parameter type declarations have been added to all methods of all classes. If
|
||||
you have classes inheriting from classes inside this package, you should add
|
||||
parameter and return type declarations.
|
||||
- Support for PHP < 7.2 has been removed
|
||||
- `PhpParser::parseClass()` has been removed. Use
|
||||
`PhpParser::parseUseStatements()` instead.
|
||||
72
vendor/doctrine/annotations/composer.json
vendored
Normal file
72
vendor/doctrine/annotations/composer.json
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
{
|
||||
"name": "doctrine/annotations",
|
||||
"description": "Docblock Annotations Parser",
|
||||
"license": "MIT",
|
||||
"type": "library",
|
||||
"keywords": [
|
||||
"annotations",
|
||||
"docblock",
|
||||
"parser"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Guilherme Blanco",
|
||||
"email": "guilhermeblanco@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Roman Borschel",
|
||||
"email": "roman@code-factory.org"
|
||||
},
|
||||
{
|
||||
"name": "Benjamin Eberlei",
|
||||
"email": "kontakt@beberlei.de"
|
||||
},
|
||||
{
|
||||
"name": "Jonathan Wage",
|
||||
"email": "jonwage@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Johannes Schmitt",
|
||||
"email": "schmittjoh@gmail.com"
|
||||
}
|
||||
],
|
||||
"homepage": "https://www.doctrine-project.org/projects/annotations.html",
|
||||
"require": {
|
||||
"php": "^7.2 || ^8.0",
|
||||
"ext-tokenizer": "*",
|
||||
"doctrine/lexer": "^2 || ^3",
|
||||
"psr/cache": "^1 || ^2 || ^3"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/cache": "^2.0",
|
||||
"doctrine/coding-standard": "^10",
|
||||
"phpstan/phpstan": "^1.10.28",
|
||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
|
||||
"symfony/cache": "^5.4 || ^6.4 || ^7",
|
||||
"vimeo/psalm": "^4.30 || ^5.14"
|
||||
},
|
||||
"suggest": {
|
||||
"php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Performance\\Common\\Annotations\\": "tests/Doctrine/Performance/Common/Annotations",
|
||||
"Doctrine\\Tests\\Common\\Annotations\\": "tests/Doctrine/Tests/Common/Annotations"
|
||||
},
|
||||
"files": [
|
||||
"tests/Doctrine/Tests/Common/Annotations/Fixtures/functions.php",
|
||||
"tests/Doctrine/Tests/Common/Annotations/Fixtures/SingleClassLOC1000.php"
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": true
|
||||
},
|
||||
"sort-packages": true
|
||||
}
|
||||
}
|
||||
189
vendor/doctrine/annotations/docs/en/annotations.rst
vendored
Normal file
189
vendor/doctrine/annotations/docs/en/annotations.rst
vendored
Normal file
@ -0,0 +1,189 @@
|
||||
Handling Annotations
|
||||
====================
|
||||
|
||||
There are several different approaches to handling annotations in PHP.
|
||||
Doctrine Annotations maps docblock annotations to PHP classes. Because
|
||||
not all docblock annotations are used for metadata purposes a filter is
|
||||
applied to ignore or skip classes that are not Doctrine annotations.
|
||||
|
||||
Take a look at the following code snippet:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
namespace MyProject\Entities;
|
||||
|
||||
use Doctrine\ORM\Mapping AS ORM;
|
||||
use Symfony\Component\Validator\Constraints AS Assert;
|
||||
|
||||
/**
|
||||
* @author Benjamin Eberlei
|
||||
* @ORM\Entity
|
||||
* @MyProject\Annotations\Foobarable
|
||||
*/
|
||||
class User
|
||||
{
|
||||
/**
|
||||
* @ORM\Id @ORM\Column @ORM\GeneratedValue
|
||||
* @dummy
|
||||
* @var int
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string")
|
||||
* @Assert\NotEmpty
|
||||
* @Assert\Email
|
||||
* @var string
|
||||
*/
|
||||
private $email;
|
||||
}
|
||||
|
||||
In this snippet you can see a variety of different docblock annotations:
|
||||
|
||||
- Documentation annotations such as ``@var`` and ``@author``. These
|
||||
annotations are ignored and never considered for throwing an
|
||||
exception due to wrongly used annotations.
|
||||
- Annotations imported through use statements. The statement ``use
|
||||
Doctrine\ORM\Mapping AS ORM`` makes all classes under that namespace
|
||||
available as ``@ORM\ClassName``. Same goes for the import of
|
||||
``@Assert``.
|
||||
- The ``@dummy`` annotation. It is not a documentation annotation and
|
||||
not ignored. For Doctrine Annotations it is not entirely clear how
|
||||
to handle this annotation. Depending on the configuration an exception
|
||||
(unknown annotation) will be thrown when parsing this annotation.
|
||||
- The fully qualified annotation ``@MyProject\Annotations\Foobarable``.
|
||||
This is transformed directly into the given class name.
|
||||
|
||||
How are these annotations loaded? From looking at the code you could
|
||||
guess that the ORM Mapping, Assert Validation and the fully qualified
|
||||
annotation can just be loaded using
|
||||
the defined PHP autoloaders. This is not the case however: For error
|
||||
handling reasons every check for class existence inside the
|
||||
``AnnotationReader`` sets the second parameter $autoload
|
||||
of ``class_exists($name, $autoload)`` to false. To work flawlessly the
|
||||
``AnnotationReader`` requires silent autoloaders which many autoloaders are
|
||||
not. Silent autoloading is NOT part of the `PSR-0 specification
|
||||
<https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md>`_
|
||||
for autoloading.
|
||||
|
||||
This is why Doctrine Annotations uses its own autoloading mechanism
|
||||
through a global registry. If you are wondering about the annotation
|
||||
registry being global, there is no other way to solve the architectural
|
||||
problems of autoloading annotation classes in a straightforward fashion.
|
||||
Additionally if you think about PHP autoloading then you recognize it is
|
||||
a global as well.
|
||||
|
||||
To anticipate the configuration section, making the above PHP class work
|
||||
with Doctrine Annotations requires this setup:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use Doctrine\Common\Annotations\AnnotationReader;
|
||||
|
||||
$reader = new AnnotationReader();
|
||||
AnnotationReader::addGlobalIgnoredName('dummy');
|
||||
|
||||
We create the actual ``AnnotationReader`` instance.
|
||||
Note that we also add ``dummy`` to the global list of ignored
|
||||
annotations for which we do not throw exceptions. Setting this is
|
||||
necessary in our example case, otherwise ``@dummy`` would trigger an
|
||||
exception to be thrown during the parsing of the docblock of
|
||||
``MyProject\Entities\User#id``.
|
||||
|
||||
Setup and Configuration
|
||||
-----------------------
|
||||
|
||||
To use the annotations library is simple, you just need to create a new
|
||||
``AnnotationReader`` instance:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$reader = new \Doctrine\Common\Annotations\AnnotationReader();
|
||||
|
||||
This creates a simple annotation reader with no caching other than in
|
||||
memory (in php arrays). Since parsing docblocks can be expensive you
|
||||
should cache this process by using a caching reader.
|
||||
|
||||
To cache annotations, you can create a ``Doctrine\Common\Annotations\PsrCachedReader``.
|
||||
This reader decorates the original reader and stores all annotations in a PSR-6
|
||||
cache:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use Doctrine\Common\Annotations\AnnotationReader;
|
||||
use Doctrine\Common\Annotations\PsrCachedReader;
|
||||
|
||||
$cache = ... // instantiate a PSR-6 Cache pool
|
||||
|
||||
$reader = new PsrCachedReader(
|
||||
new AnnotationReader(),
|
||||
$cache,
|
||||
$debug = true
|
||||
);
|
||||
|
||||
The ``debug`` flag is used here as well to invalidate the cache files
|
||||
when the PHP class with annotations changed and should be used during
|
||||
development.
|
||||
|
||||
.. warning ::
|
||||
|
||||
The ``AnnotationReader`` works and caches under the
|
||||
assumption that all annotations of a doc-block are processed at
|
||||
once. That means that annotation classes that do not exist and
|
||||
aren't loaded and cannot be autoloaded (using the
|
||||
AnnotationRegistry) would never be visible and not accessible if a
|
||||
cache is used unless the cache is cleared and the annotations
|
||||
requested again, this time with all annotations defined.
|
||||
|
||||
By default the annotation reader returns a list of annotations with
|
||||
numeric indexes. If you want your annotations to be indexed by their
|
||||
class name you can wrap the reader in an ``IndexedReader``:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use Doctrine\Common\Annotations\AnnotationReader;
|
||||
use Doctrine\Common\Annotations\IndexedReader;
|
||||
|
||||
$reader = new IndexedReader(new AnnotationReader());
|
||||
|
||||
.. warning::
|
||||
|
||||
You should never wrap the indexed reader inside a cached reader,
|
||||
only the other way around. This way you can re-use the cache with
|
||||
indexed or numeric keys, otherwise your code may experience failures
|
||||
due to caching in a numerical or indexed format.
|
||||
|
||||
Ignoring missing exceptions
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
By default an exception is thrown from the ``AnnotationReader`` if an
|
||||
annotation was found that:
|
||||
|
||||
- is not part of the list of ignored "documentation annotations";
|
||||
- was not imported through a use statement;
|
||||
- is not a fully qualified class that exists.
|
||||
|
||||
You can disable this behavior for specific names if your docblocks do
|
||||
not follow strict requirements:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$reader = new \Doctrine\Common\Annotations\AnnotationReader();
|
||||
AnnotationReader::addGlobalIgnoredName('foo');
|
||||
|
||||
PHP Imports
|
||||
~~~~~~~~~~~
|
||||
|
||||
By default the annotation reader parses the use-statement of a php file
|
||||
to gain access to the import rules and register them for the annotation
|
||||
processing. Only if you are using PHP Imports can you validate the
|
||||
correct usage of annotations and throw exceptions if you misspelled an
|
||||
annotation. This mechanism is enabled by default.
|
||||
|
||||
To ease the upgrade path, we still allow you to disable this mechanism.
|
||||
Note however that we will remove this in future versions:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$reader = new \Doctrine\Common\Annotations\AnnotationReader();
|
||||
$reader->setEnabledPhpImports(false);
|
||||
443
vendor/doctrine/annotations/docs/en/custom.rst
vendored
Normal file
443
vendor/doctrine/annotations/docs/en/custom.rst
vendored
Normal file
@ -0,0 +1,443 @@
|
||||
Custom Annotation Classes
|
||||
=========================
|
||||
|
||||
If you want to define your own annotations, you just have to group them
|
||||
in a namespace.
|
||||
Annotation classes have to contain a class-level docblock with the text
|
||||
``@Annotation``:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
namespace MyCompany\Annotations;
|
||||
|
||||
/** @Annotation */
|
||||
class Bar
|
||||
{
|
||||
// some code
|
||||
}
|
||||
|
||||
Inject annotation values
|
||||
------------------------
|
||||
|
||||
The annotation parser checks if the annotation constructor has arguments,
|
||||
if so then it will pass the value array, otherwise it will try to inject
|
||||
values into public properties directly:
|
||||
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
namespace MyCompany\Annotations;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
*
|
||||
* Some Annotation using a constructor
|
||||
*/
|
||||
class Bar
|
||||
{
|
||||
private $foo;
|
||||
|
||||
public function __construct(array $values)
|
||||
{
|
||||
$this->foo = $values['foo'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
*
|
||||
* Some Annotation without a constructor
|
||||
*/
|
||||
class Foo
|
||||
{
|
||||
public $bar;
|
||||
}
|
||||
|
||||
Optional: Constructors with Named Parameters
|
||||
--------------------------------------------
|
||||
|
||||
Starting with Annotations v1.11 a new annotation instantiation strategy
|
||||
is available that aims at compatibility of Annotation classes with the PHP 8
|
||||
attribute feature. You need to declare a constructor with regular parameter
|
||||
names that match the named arguments in the annotation syntax.
|
||||
|
||||
To enable this feature, you can tag your annotation class with
|
||||
``@NamedArgumentConstructor`` (available from v1.12) or implement the
|
||||
``Doctrine\Common\Annotations\NamedArgumentConstructorAnnotation`` interface
|
||||
(available from v1.11 and deprecated as of v1.12).
|
||||
When using the ``@NamedArgumentConstructor`` tag, the first argument of the
|
||||
constructor is considered as the default one.
|
||||
|
||||
|
||||
Usage with the ``@NamedArgumentConstructor`` tag
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
namespace MyCompany\Annotations;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor
|
||||
*/
|
||||
class Bar implements NamedArgumentConstructorAnnotation
|
||||
{
|
||||
private $foo;
|
||||
|
||||
public function __construct(string $foo)
|
||||
{
|
||||
$this->foo = $foo;
|
||||
}
|
||||
}
|
||||
|
||||
/** Usable with @Bar(foo="baz") */
|
||||
/** Usable with @Bar("baz") */
|
||||
|
||||
In combination with PHP 8's constructor property promotion feature
|
||||
you can simplify this to:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
namespace MyCompany\Annotations;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor
|
||||
*/
|
||||
class Bar implements NamedArgumentConstructorAnnotation
|
||||
{
|
||||
public function __construct(private string $foo) {}
|
||||
}
|
||||
|
||||
|
||||
Usage with the
|
||||
``Doctrine\Common\Annotations\NamedArgumentConstructorAnnotation``
|
||||
interface (v1.11, deprecated as of v1.12):
|
||||
.. code-block:: php
|
||||
|
||||
namespace MyCompany\Annotations;
|
||||
|
||||
use Doctrine\Common\Annotations\NamedArgumentConstructorAnnotation;
|
||||
|
||||
/** @Annotation */
|
||||
class Bar implements NamedArgumentConstructorAnnotation
|
||||
{
|
||||
private $foo;
|
||||
|
||||
public function __construct(private string $foo) {}
|
||||
}
|
||||
|
||||
/** Usable with @Bar(foo="baz") */
|
||||
|
||||
Annotation Target
|
||||
-----------------
|
||||
|
||||
``@Target`` indicates the kinds of class elements to which an annotation
|
||||
type is applicable. Then you could define one or more targets:
|
||||
|
||||
- ``CLASS`` Allowed in class docblocks
|
||||
- ``PROPERTY`` Allowed in property docblocks
|
||||
- ``METHOD`` Allowed in the method docblocks
|
||||
- ``FUNCTION`` Allowed in function dockblocks
|
||||
- ``ALL`` Allowed in class, property, method and function docblocks
|
||||
- ``ANNOTATION`` Allowed inside other annotations
|
||||
|
||||
If the annotations is not allowed in the current context, an
|
||||
``AnnotationException`` is thrown.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
namespace MyCompany\Annotations;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target({"METHOD","PROPERTY"})
|
||||
*/
|
||||
class Bar
|
||||
{
|
||||
// some code
|
||||
}
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target("CLASS")
|
||||
*/
|
||||
class Foo
|
||||
{
|
||||
// some code
|
||||
}
|
||||
|
||||
Attribute types
|
||||
---------------
|
||||
|
||||
The annotation parser checks the given parameters using the phpdoc
|
||||
annotation ``@var``, The data type could be validated using the ``@var``
|
||||
annotation on the annotation properties or using the ``@Attributes`` and
|
||||
``@Attribute`` annotations.
|
||||
|
||||
If the data type does not match you get an ``AnnotationException``
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
namespace MyCompany\Annotations;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target({"METHOD","PROPERTY"})
|
||||
*/
|
||||
class Bar
|
||||
{
|
||||
/** @var mixed */
|
||||
public $mixed;
|
||||
|
||||
/** @var boolean */
|
||||
public $boolean;
|
||||
|
||||
/** @var bool */
|
||||
public $bool;
|
||||
|
||||
/** @var float */
|
||||
public $float;
|
||||
|
||||
/** @var string */
|
||||
public $string;
|
||||
|
||||
/** @var integer */
|
||||
public $integer;
|
||||
|
||||
/** @var array */
|
||||
public $array;
|
||||
|
||||
/** @var SomeAnnotationClass */
|
||||
public $annotation;
|
||||
|
||||
/** @var array<integer> */
|
||||
public $arrayOfIntegers;
|
||||
|
||||
/** @var array<SomeAnnotationClass> */
|
||||
public $arrayOfAnnotations;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target({"METHOD","PROPERTY"})
|
||||
* @Attributes({
|
||||
* @Attribute("stringProperty", type = "string"),
|
||||
* @Attribute("annotProperty", type = "SomeAnnotationClass"),
|
||||
* })
|
||||
*/
|
||||
class Foo
|
||||
{
|
||||
public function __construct(array $values)
|
||||
{
|
||||
$this->stringProperty = $values['stringProperty'];
|
||||
$this->annotProperty = $values['annotProperty'];
|
||||
}
|
||||
|
||||
// some code
|
||||
}
|
||||
|
||||
Annotation Required
|
||||
-------------------
|
||||
|
||||
``@Required`` indicates that the field must be specified when the
|
||||
annotation is used. If it is not used you get an ``AnnotationException``
|
||||
stating that this value can not be null.
|
||||
|
||||
Declaring a required field:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target("ALL")
|
||||
*/
|
||||
class Foo
|
||||
{
|
||||
/** @Required */
|
||||
public $requiredField;
|
||||
}
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
/** @Foo(requiredField="value") */
|
||||
public $direction; // Valid
|
||||
|
||||
/** @Foo */
|
||||
public $direction; // Required field missing, throws an AnnotationException
|
||||
|
||||
|
||||
Enumerated values
|
||||
-----------------
|
||||
|
||||
- An annotation property marked with ``@Enum`` is a field that accepts a
|
||||
fixed set of scalar values.
|
||||
- You should use ``@Enum`` fields any time you need to represent fixed
|
||||
values.
|
||||
- The annotation parser checks the given value and throws an
|
||||
``AnnotationException`` if the value does not match.
|
||||
|
||||
|
||||
Declaring an enumerated property:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target("ALL")
|
||||
*/
|
||||
class Direction
|
||||
{
|
||||
/**
|
||||
* @Enum({"NORTH", "SOUTH", "EAST", "WEST"})
|
||||
*/
|
||||
public $value;
|
||||
}
|
||||
|
||||
Annotation usage:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
/** @Direction("NORTH") */
|
||||
public $direction; // Valid value
|
||||
|
||||
/** @Direction("NORTHEAST") */
|
||||
public $direction; // Invalid value, throws an AnnotationException
|
||||
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
The use of constants and class constants is available on the annotations
|
||||
parser.
|
||||
|
||||
The following usages are allowed:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
namespace MyCompany\Entity;
|
||||
|
||||
use MyCompany\Annotations\Foo;
|
||||
use MyCompany\Annotations\Bar;
|
||||
use MyCompany\Entity\SomeClass;
|
||||
|
||||
/**
|
||||
* @Foo(PHP_EOL)
|
||||
* @Bar(Bar::FOO)
|
||||
* @Foo({SomeClass::FOO, SomeClass::BAR})
|
||||
* @Bar({SomeClass::FOO_KEY = SomeClass::BAR_VALUE})
|
||||
*/
|
||||
class User
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Be careful with constants and the cache !
|
||||
|
||||
.. note::
|
||||
|
||||
The cached reader will not re-evaluate each time an annotation is
|
||||
loaded from cache. When a constant is changed the cache must be
|
||||
cleaned.
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Using the library API is simple. Using the annotations described in the
|
||||
previous section, you can now annotate other classes with your
|
||||
annotations:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
namespace MyCompany\Entity;
|
||||
|
||||
use MyCompany\Annotations\Foo;
|
||||
use MyCompany\Annotations\Bar;
|
||||
|
||||
/**
|
||||
* @Foo(bar="foo")
|
||||
* @Bar(foo="bar")
|
||||
*/
|
||||
class User
|
||||
{
|
||||
}
|
||||
|
||||
Now we can write a script to get the annotations above:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$reflClass = new ReflectionClass('MyCompany\Entity\User');
|
||||
$classAnnotations = $reader->getClassAnnotations($reflClass);
|
||||
|
||||
foreach ($classAnnotations AS $annot) {
|
||||
if ($annot instanceof \MyCompany\Annotations\Foo) {
|
||||
echo $annot->bar; // prints "foo";
|
||||
} else if ($annot instanceof \MyCompany\Annotations\Bar) {
|
||||
echo $annot->foo; // prints "bar";
|
||||
}
|
||||
}
|
||||
|
||||
You have a complete API for retrieving annotation class instances from a
|
||||
class, property or method docblock:
|
||||
|
||||
|
||||
Reader API
|
||||
~~~~~~~~~~
|
||||
|
||||
Access all annotations of a class
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
public function getClassAnnotations(\ReflectionClass $class);
|
||||
|
||||
Access one annotation of a class
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
public function getClassAnnotation(\ReflectionClass $class, $annotationName);
|
||||
|
||||
Access all annotations of a method
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
public function getMethodAnnotations(\ReflectionMethod $method);
|
||||
|
||||
Access one annotation of a method
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
public function getMethodAnnotation(\ReflectionMethod $method, $annotationName);
|
||||
|
||||
Access all annotations of a property
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
public function getPropertyAnnotations(\ReflectionProperty $property);
|
||||
|
||||
Access one annotation of a property
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName);
|
||||
|
||||
Access all annotations of a function
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
public function getFunctionAnnotations(\ReflectionFunction $property);
|
||||
|
||||
Access one annotation of a function
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
public function getFunctionAnnotation(\ReflectionFunction $property, $annotationName);
|
||||
109
vendor/doctrine/annotations/docs/en/index.rst
vendored
Normal file
109
vendor/doctrine/annotations/docs/en/index.rst
vendored
Normal file
@ -0,0 +1,109 @@
|
||||
Deprecation notice
|
||||
==================
|
||||
|
||||
PHP 8 introduced `attributes
|
||||
<https://www.php.net/manual/en/language.attributes.overview.php>`_,
|
||||
which are a native replacement for annotations. As such, this library is
|
||||
considered feature complete, and should receive exclusively bugfixes and
|
||||
security fixes.
|
||||
|
||||
We do not recommend using this library in new projects and encourage authors
|
||||
of downstream libraries to offer support for attributes as an alternative to
|
||||
Doctrine Annotations.
|
||||
|
||||
Have a look at [our blog](https://www.doctrine-project.org/2022/11/04/annotations-to-attributes.html)
|
||||
to learn more.
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
Doctrine Annotations allows to implement custom annotation
|
||||
functionality for PHP classes and functions.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
class Foo
|
||||
{
|
||||
/**
|
||||
* @MyAnnotation(myProperty="value")
|
||||
*/
|
||||
private $bar;
|
||||
}
|
||||
|
||||
Annotations aren't implemented in PHP itself which is why this component
|
||||
offers a way to use the PHP doc-blocks as a place for the well known
|
||||
annotation syntax using the ``@`` char.
|
||||
|
||||
Annotations in Doctrine are used for the ORM configuration to build the
|
||||
class mapping, but it can be used in other projects for other purposes
|
||||
too.
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
You can install the Annotation component with composer:
|
||||
|
||||
.. code-block::
|
||||
|
||||
$ composer require doctrine/annotations
|
||||
|
||||
Create an annotation class
|
||||
==========================
|
||||
|
||||
An annotation class is a representation of the later used annotation
|
||||
configuration in classes. The annotation class of the previous example
|
||||
looks like this:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
*/
|
||||
final class MyAnnotation
|
||||
{
|
||||
public $myProperty;
|
||||
}
|
||||
|
||||
The annotation class is declared as an annotation by ``@Annotation``.
|
||||
|
||||
:ref:`Read more about custom annotations. <custom>`
|
||||
|
||||
Reading annotations
|
||||
===================
|
||||
|
||||
The access to the annotations happens by reflection of the class or function
|
||||
containing them. There are multiple reader-classes implementing the
|
||||
``Doctrine\Common\Annotations\Reader`` interface, that can access the
|
||||
annotations of a class. A common one is
|
||||
``Doctrine\Common\Annotations\AnnotationReader``:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
use Doctrine\Common\Annotations\AnnotationReader;
|
||||
|
||||
$reflectionClass = new ReflectionClass(Foo::class);
|
||||
$property = $reflectionClass->getProperty('bar');
|
||||
|
||||
$reader = new AnnotationReader();
|
||||
$myAnnotation = $reader->getPropertyAnnotation(
|
||||
$property,
|
||||
MyAnnotation::class
|
||||
);
|
||||
|
||||
echo $myAnnotation->myProperty; // result: "value"
|
||||
|
||||
A reader has multiple methods to access the annotations of a class or
|
||||
function.
|
||||
|
||||
:ref:`Read more about handling annotations. <annotations>`
|
||||
|
||||
IDE Support
|
||||
-----------
|
||||
|
||||
Some IDEs already provide support for annotations:
|
||||
|
||||
- Eclipse via the `Symfony2 Plugin <https://github.com/pulse00/Symfony-2-Eclipse-Plugin>`_
|
||||
- PhpStorm via the `PHP Annotations Plugin <https://plugins.jetbrains.com/plugin/7320-php-annotations>`_ or the `Symfony Plugin <https://plugins.jetbrains.com/plugin/7219-symfony-support>`_
|
||||
|
||||
.. _Read more about handling annotations.: annotations
|
||||
.. _Read more about custom annotations.: custom
|
||||
6
vendor/doctrine/annotations/docs/en/sidebar.rst
vendored
Normal file
6
vendor/doctrine/annotations/docs/en/sidebar.rst
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
.. toctree::
|
||||
:depth: 3
|
||||
|
||||
index
|
||||
annotations
|
||||
custom
|
||||
54
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation.php
vendored
Normal file
54
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation.php
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace 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. */
|
||||
final public function __construct(array $data)
|
||||
{
|
||||
foreach ($data as $key => $value) {
|
||||
$this->$key = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Error handler for unknown property accessor in Annotation class.
|
||||
*
|
||||
* @throws BadMethodCallException
|
||||
*/
|
||||
public function __get(string $name)
|
||||
{
|
||||
throw new BadMethodCallException(
|
||||
sprintf("Unknown property '%s' on annotation '%s'.", $name, static::class)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Error handler for unknown property mutator in Annotation class.
|
||||
*
|
||||
* @param mixed $value Property value.
|
||||
*
|
||||
* @throws BadMethodCallException
|
||||
*/
|
||||
public function __set(string $name, $value)
|
||||
{
|
||||
throw new BadMethodCallException(
|
||||
sprintf("Unknown property '%s' on annotation '%s'.", $name, static::class)
|
||||
);
|
||||
}
|
||||
}
|
||||
21
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attribute.php
vendored
Normal file
21
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attribute.php
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace 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;
|
||||
}
|
||||
15
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attributes.php
vendored
Normal file
15
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attributes.php
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace 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;
|
||||
}
|
||||
69
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Enum.php
vendored
Normal file
69
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Enum.php
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace 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'];
|
||||
}
|
||||
}
|
||||
43
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php
vendored
Normal file
43
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace 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'];
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace 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
|
||||
{
|
||||
}
|
||||
13
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Required.php
vendored
Normal file
13
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Required.php
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace 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
|
||||
{
|
||||
}
|
||||
101
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Target.php
vendored
Normal file
101
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Target.php
vendored
Normal file
@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
namespace 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);
|
||||
}
|
||||
}
|
||||
158
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php
vendored
Normal file
158
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php
vendored
Normal file
@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
namespace 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.
|
||||
*
|
||||
* @return AnnotationException
|
||||
*/
|
||||
public static function syntaxError(string $message)
|
||||
{
|
||||
return new self('[Syntax Error] ' . $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new AnnotationException describing a Semantical error.
|
||||
*
|
||||
* @return AnnotationException
|
||||
*/
|
||||
public static function semanticalError(string $message)
|
||||
{
|
||||
return new self('[Semantical Error] ' . $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new AnnotationException describing an error which occurred during
|
||||
* the creation of the annotation.
|
||||
*
|
||||
* @return AnnotationException
|
||||
*/
|
||||
public static function creationError(string $message, ?Throwable $previous = null)
|
||||
{
|
||||
return new self('[Creation Error] ' . $message, 0, $previous);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new AnnotationException describing a type error.
|
||||
*
|
||||
* @return AnnotationException
|
||||
*/
|
||||
public static function typeError(string $message)
|
||||
{
|
||||
return new self('[Type Error] ' . $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new AnnotationException describing a constant semantical error.
|
||||
*
|
||||
* @return AnnotationException
|
||||
*/
|
||||
public static function semanticalErrorConstants(string $identifier, ?string $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 mixed $actual
|
||||
*
|
||||
* @return AnnotationException
|
||||
*/
|
||||
public static function attributeTypeError(
|
||||
string $attributeName,
|
||||
string $annotationName,
|
||||
string $context,
|
||||
string $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.
|
||||
*
|
||||
* @return AnnotationException
|
||||
*/
|
||||
public static function requiredError(
|
||||
string $attributeName,
|
||||
string $annotationName,
|
||||
string $context,
|
||||
string $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 mixed $given
|
||||
* @phpstan-param list<string> $available
|
||||
*
|
||||
* @return AnnotationException
|
||||
*/
|
||||
public static function enumeratorError(
|
||||
string $attributeName,
|
||||
string $annotationName,
|
||||
string $context,
|
||||
array $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.'
|
||||
);
|
||||
}
|
||||
}
|
||||
392
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php
vendored
Normal file
392
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php
vendored
Normal file
@ -0,0 +1,392 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Common\Annotations;
|
||||
|
||||
use Doctrine\Common\Annotations\Annotation\IgnoreAnnotation;
|
||||
use 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 filter_var;
|
||||
use function ini_get;
|
||||
|
||||
use const FILTER_VALIDATE_BOOLEAN;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public static function addGlobalIgnoredName(string $name)
|
||||
{
|
||||
self::$globalIgnoredNames[$name] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new annotation to the globally ignored annotation namespaces with regard to exception handling.
|
||||
*/
|
||||
public static function addGlobalIgnoredNamespace(string $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+') &&
|
||||
(filter_var(ini_get('zend_optimizerplus.save_comments'), FILTER_VALIDATE_BOOLEAN) === false ||
|
||||
filter_var(ini_get('opcache.save_comments'), FILTER_VALIDATE_BOOLEAN) === false)
|
||||
) {
|
||||
throw AnnotationException::optimizerPlusSaveComments();
|
||||
}
|
||||
|
||||
if (
|
||||
extension_loaded('Zend OPcache') &&
|
||||
filter_var(ini_get('opcache.save_comments'), FILTER_VALIDATE_BOOLEAN) === false
|
||||
) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
43
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationRegistry.php
vendored
Normal file
43
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationRegistry.php
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Common\Annotations;
|
||||
|
||||
use function array_key_exists;
|
||||
use function class_exists;
|
||||
|
||||
final class AnnotationRegistry
|
||||
{
|
||||
/**
|
||||
* An array of classes which cannot be found
|
||||
*
|
||||
* @var null[] indexed by class name
|
||||
*/
|
||||
private static $failedToAutoload = [];
|
||||
|
||||
public static function reset(): void
|
||||
{
|
||||
self::$failedToAutoload = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
if (class_exists($class)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
self::$failedToAutoload[$class] = null;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
131
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocLexer.php
vendored
Normal file
131
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocLexer.php
vendored
Normal file
@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Common\Annotations;
|
||||
|
||||
use 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;
|
||||
}
|
||||
}
|
||||
1496
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php
vendored
Normal file
1496
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
178
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/ImplicitlyIgnoredAnnotationNames.php
vendored
Normal file
178
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/ImplicitlyIgnoredAnnotationNames.php
vendored
Normal file
@ -0,0 +1,178 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace 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()
|
||||
{
|
||||
}
|
||||
}
|
||||
99
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/IndexedReader.php
vendored
Normal file
99
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/IndexedReader.php
vendored
Normal file
@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace 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 mixed[] $args
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call(string $method, array $args)
|
||||
{
|
||||
return call_user_func_array([$this->delegate, $method], $args);
|
||||
}
|
||||
}
|
||||
78
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/PhpParser.php
vendored
Normal file
78
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/PhpParser.php
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace 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
|
||||
{
|
||||
/**
|
||||
* 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(string $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;
|
||||
}
|
||||
}
|
||||
233
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/PsrCachedReader.php
vendored
Normal file
233
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/PsrCachedReader.php
vendored
Normal file
@ -0,0 +1,233 @@
|
||||
<?php
|
||||
|
||||
namespace 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 is_file;
|
||||
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 !== false && is_file($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 !== false && is_file($fileName) ? filemtime($fileName) : 0],
|
||||
array_map(function (ReflectionClass $reflectionTrait): int {
|
||||
return $this->getTraitLastModificationTime($reflectionTrait);
|
||||
}, $reflectionTrait->getTraits())
|
||||
));
|
||||
|
||||
assert($lastModificationTime !== false);
|
||||
|
||||
return $this->loadedFilemtimes[$fileName] = $lastModificationTime;
|
||||
}
|
||||
}
|
||||
80
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Reader.php
vendored
Normal file
80
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Reader.php
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace 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);
|
||||
}
|
||||
205
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/TokenParser.php
vendored
Normal file
205
vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/TokenParser.php
vendored
Normal file
@ -0,0 +1,205 @@
|
||||
<?php
|
||||
|
||||
namespace 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;
|
||||
|
||||
public function __construct(string $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(bool $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(string $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();
|
||||
}
|
||||
}
|
||||
19
vendor/doctrine/common/LICENSE
vendored
Normal file
19
vendor/doctrine/common/LICENSE
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2006-2015 Doctrine Project
|
||||
|
||||
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.
|
||||
12
vendor/doctrine/common/README.md
vendored
Normal file
12
vendor/doctrine/common/README.md
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# Doctrine Common
|
||||
|
||||
[](https://github.com/doctrine/common/actions)
|
||||
[](https://codecov.io/gh/doctrine/common)
|
||||
|
||||
The Doctrine Common project is a library that provides extensions to core PHP functionality.
|
||||
|
||||
## More resources:
|
||||
|
||||
* [Website](https://www.doctrine-project.org/)
|
||||
* [Documentation](https://www.doctrine-project.org/projects/doctrine-common/en/current/)
|
||||
* [Downloads](https://github.com/doctrine/common/releases)
|
||||
39
vendor/doctrine/common/UPGRADE_TO_2_1
vendored
Normal file
39
vendor/doctrine/common/UPGRADE_TO_2_1
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
This document details all the possible changes that you should investigate when updating
|
||||
your project from Doctrine Common 2.0.x to 2.1
|
||||
|
||||
## AnnotationReader changes
|
||||
|
||||
The annotation reader was heavily refactored between 2.0 and 2.1-RC1. In theory the operation of the new reader should be backwards compatible, but it has to be setup differently to work that way:
|
||||
|
||||
$reader = new \Doctrine\Common\Annotations\AnnotationReader();
|
||||
$reader->setDefaultAnnotationNamespace('Doctrine\ORM\Mapping\\');
|
||||
// new code necessary starting here
|
||||
$reader->setIgnoreNotImportedAnnotations(true);
|
||||
$reader->setEnableParsePhpImports(false);
|
||||
$reader = new \Doctrine\Common\Annotations\CachedReader(
|
||||
new \Doctrine\Common\Annotations\IndexedReader($reader), new ArrayCache()
|
||||
);
|
||||
|
||||
## Annotation Base class or @Annotation
|
||||
|
||||
Beginning after 2.1-RC2 you have to either extend ``Doctrine\Common\Annotations\Annotation`` or add @Annotation to your annotations class-level docblock, otherwise the class will simply be ignored.
|
||||
|
||||
## Removed methods on AnnotationReader
|
||||
|
||||
* AnnotationReader::setAutoloadAnnotations()
|
||||
* AnnotationReader::getAutoloadAnnotations()
|
||||
* AnnotationReader::isAutoloadAnnotations()
|
||||
|
||||
## AnnotationRegistry
|
||||
|
||||
Autoloading through the PHP autoloader is removed from the 2.1 AnnotationReader. Instead you have to use the global AnnotationRegistry for loading purposes:
|
||||
|
||||
\Doctrine\Common\Annotations\AnnotationRegistry::registerFile($fileWithAnnotations);
|
||||
\Doctrine\Common\Annotations\AnnotationRegistry::registerAutoloadNamespace($namespace, $dirs = null);
|
||||
\Doctrine\Common\Annotations\AnnotationRegistry::registerAutoloadNamespaces($namespaces);
|
||||
\Doctrine\Common\Annotations\AnnotationRegistry::registerLoader($callable);
|
||||
|
||||
The $callable for registering a loader accepts a class as first and only parameter and must try to silently autoload it. On success true has to be returned.
|
||||
The registerAutoloadNamespace function registers a PSR-0 compatible silent autoloader for all classes with the given namespace in the given directories.
|
||||
If null is passed as directory the include path will be used.
|
||||
|
||||
61
vendor/doctrine/common/UPGRADE_TO_2_2
vendored
Normal file
61
vendor/doctrine/common/UPGRADE_TO_2_2
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
This document details all the possible changes that you should investigate when
|
||||
updating your project from Doctrine Common 2.1 to 2.2:
|
||||
|
||||
## Annotation Changes
|
||||
|
||||
- AnnotationReader::setIgnoreNotImportedAnnotations has been removed, you need to
|
||||
add ignore annotation names which are supposed to be ignored via
|
||||
AnnotationReader::addGlobalIgnoredName
|
||||
|
||||
- AnnotationReader::setAutoloadAnnotations was deprecated by the AnnotationRegistry
|
||||
in 2.1 and has been removed in 2.2
|
||||
|
||||
- AnnotationReader::setEnableParsePhpImports was added to ease transition to the new
|
||||
annotation mechanism in 2.1 and is removed in 2.2
|
||||
|
||||
- AnnotationReader::isParsePhpImportsEnabled is removed (see above)
|
||||
|
||||
- AnnotationReader::setDefaultAnnotationNamespace was deprecated in favor of explicit
|
||||
configuration in 2.1 and will be removed in 2.2 (for isolated projects where you
|
||||
have full-control over _all_ available annotations, we offer a dedicated reader
|
||||
class ``SimpleAnnotationReader``)
|
||||
|
||||
- AnnotationReader::setAnnotationCreationFunction was deprecated in 2.1 and will be
|
||||
removed in 2.2. We only offer two creation mechanisms which cannot be changed
|
||||
anymore to allow the same reader instance to work with all annotations regardless
|
||||
of which library they are coming from.
|
||||
|
||||
- AnnotationReader::setAnnotationNamespaceAlias was deprecated in 2.1 and will be
|
||||
removed in 2.2 (see setDefaultAnnotationNamespace)
|
||||
|
||||
- If you use a class as annotation which has not the @Annotation marker in it's
|
||||
class block, we will now throw an exception instead of silently ignoring it. You
|
||||
can however still achieve the previous behavior using the @IgnoreAnnotation, or
|
||||
AnnotationReader::addGlobalIgnoredName (the exception message will contain detailed
|
||||
instructions when you run into this problem).
|
||||
|
||||
## Cache Changes
|
||||
|
||||
- Renamed old AbstractCache to CacheProvider
|
||||
|
||||
- Dropped the support to the following functions of all cache providers:
|
||||
|
||||
- CacheProvider::deleteByWildcard
|
||||
|
||||
- CacheProvider::deleteByRegEx
|
||||
|
||||
- CacheProvider::deleteByPrefix
|
||||
|
||||
- CacheProvider::deleteBySuffix
|
||||
|
||||
- CacheProvider::deleteAll will not remove ALL entries, it will only mark them as invalid
|
||||
|
||||
- CacheProvider::flushAll will remove ALL entries, namespaced or not
|
||||
|
||||
- Added support to MemcachedCache
|
||||
|
||||
- Added support to WincacheCache
|
||||
|
||||
## ClassLoader Changes
|
||||
|
||||
- ClassLoader::fileExistsInIncludePath() no longer exists. Use the native stream_resolve_include_path() PHP function
|
||||
50
vendor/doctrine/common/composer.json
vendored
Normal file
50
vendor/doctrine/common/composer.json
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
{
|
||||
"name": "doctrine/common",
|
||||
"type": "library",
|
||||
"description": "PHP Doctrine Common project is a library that provides additional functionality that other Doctrine projects depend on such as better reflection support, proxies and much more.",
|
||||
"keywords": [
|
||||
"php",
|
||||
"common",
|
||||
"doctrine"
|
||||
],
|
||||
"homepage": "https://www.doctrine-project.org/projects/common.html",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"},
|
||||
{"name": "Roman Borschel", "email": "roman@code-factory.org"},
|
||||
{"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"},
|
||||
{"name": "Jonathan Wage", "email": "jonwage@gmail.com"},
|
||||
{"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"},
|
||||
{"name": "Marco Pivetta", "email": "ocramius@gmail.com"}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.1 || ^8.0",
|
||||
"doctrine/persistence": "^2.0 || ^3.0 || ^4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/collections": "^1",
|
||||
"phpstan/phpstan": "^1.4.1",
|
||||
"phpstan/phpstan-phpunit": "^1",
|
||||
"phpunit/phpunit": "^7.5.20 || ^8.5 || ^9.0",
|
||||
"doctrine/coding-standard": "^9.0 || ^10.0",
|
||||
"squizlabs/php_codesniffer": "^3.0",
|
||||
"symfony/phpunit-bridge": "^6.1",
|
||||
"vimeo/psalm": "^4.4"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Common\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Tests\\": "tests"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": true,
|
||||
"composer/package-versions-deprecated": true
|
||||
}
|
||||
}
|
||||
}
|
||||
10
vendor/doctrine/common/docs/en/index.rst
vendored
Normal file
10
vendor/doctrine/common/docs/en/index.rst
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
Common Documentation
|
||||
====================
|
||||
|
||||
Welcome to the Doctrine Common Library documentation.
|
||||
|
||||
.. toctree::
|
||||
:depth: 2
|
||||
:glob:
|
||||
|
||||
*
|
||||
241
vendor/doctrine/common/docs/en/reference/class-loading.rst
vendored
Normal file
241
vendor/doctrine/common/docs/en/reference/class-loading.rst
vendored
Normal file
@ -0,0 +1,241 @@
|
||||
Class Loading
|
||||
=============
|
||||
|
||||
Class loading is an essential part of any PHP application that
|
||||
makes heavy use of classes and interfaces. Unfortunately, a lot of
|
||||
people and projects spend a lot of time and effort on custom and
|
||||
specialized class loading strategies. It can quickly become a pain
|
||||
to understand what is going on when using multiple libraries and/or
|
||||
frameworks, each with its own way to do class loading. Class
|
||||
loading should be simple and it is an ideal candidate for
|
||||
convention over configuration.
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
The Doctrine Common ClassLoader implements a simple and efficient
|
||||
approach to class loading that is easy to understand and use. The
|
||||
implementation is based on the widely used and accepted convention
|
||||
of mapping namespace and class names to a directory structure. This
|
||||
approach is used for example by Symfony2, the Zend Framework and of
|
||||
course, Doctrine.
|
||||
|
||||
For example, the following class:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
namespace MyProject\Shipping;
|
||||
class ShippingStrategy { ... }
|
||||
|
||||
resides in the following directory structure:
|
||||
|
||||
::
|
||||
|
||||
src/
|
||||
/MyProject
|
||||
/Shipping
|
||||
ShippingStrategy.php
|
||||
|
||||
Note that the name of "src" or the structure above or beside this
|
||||
directory is completely arbitrary. "src" could be named "classes"
|
||||
or "lib" or whatever. The only convention to adhere to is to map
|
||||
namespaces to directories and classes to files named after the
|
||||
class name.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
To use a Doctrine Common ClassLoader, you first need to load the
|
||||
class file containing the ClassLoader. This is the only class file
|
||||
that actually needs to be loaded explicitly via ``require``. All
|
||||
other classes will be loaded on demand by the configured class
|
||||
loaders.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
use Doctrine\Common\ClassLoader;
|
||||
require '/path/to/Doctrine/Common/ClassLoader.php';
|
||||
$classLoader = new ClassLoader('MyProject', '/path/to/src');
|
||||
|
||||
A ``ClassLoader`` takes two constructor parameters, both optional.
|
||||
In the normal case both arguments are supplied. The first argument
|
||||
specifies the namespace prefix this class loader should be
|
||||
responsible for and the second parameter is the path to the root
|
||||
directory where the classes can be found according to the
|
||||
convention mentioned previously.
|
||||
|
||||
The class loader in the example above would thus be responsible for
|
||||
all classes under the 'MyProject' namespace and it would look for
|
||||
the class files starting at the directory '/path/to/src'.
|
||||
|
||||
Also note that the prefix supplied in the first argument need not
|
||||
be a root namespace but can be an arbitrarily nested namespace as
|
||||
well. This allows you to even have the sources of subnamespaces
|
||||
split across different directories. For example, all projects under
|
||||
the Doctrine umbrella reside in the Doctrine namespace, yet the
|
||||
sources for each project usually do not reside under a common root
|
||||
directory. The following is an example of configuring three class
|
||||
loaders, one for each used Doctrine project:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
use Doctrine\Common\ClassLoader;
|
||||
require '/path/to/Doctrine/Common/ClassLoader.php';
|
||||
$commonLoader = new ClassLoader('Doctrine\Common', '/path/to/common/lib');
|
||||
$dbalLoader = new ClassLoader('Doctrine\DBAL', '/path/to/dbal/lib');
|
||||
$ormLoader = new ClassLoader('Doctrine\ORM', '/path/to/orm/lib');
|
||||
$commonLoader->register();
|
||||
$dbalLoader->register();
|
||||
$ormLoader->register();
|
||||
|
||||
Do not be afraid of using multiple class loaders. Due to the
|
||||
efficient class loading design you will not incur much overhead
|
||||
from using many class loaders. Take a look at the implementation of
|
||||
``ClassLoader#loadClass`` to see how simple and efficient the class
|
||||
loading is. The iteration over the installed class loaders happens
|
||||
in C (with the exception of using ``ClassLoader::classExists``).
|
||||
|
||||
A ClassLoader can be used in the following other variations,
|
||||
however, these are rarely used/needed:
|
||||
|
||||
|
||||
- If only the second argument is not supplied, the class loader
|
||||
will be responsible for the namespace prefix given in the first
|
||||
argument and it will rely on the PHP include_path.
|
||||
|
||||
- If only the first argument is not supplied, the class loader
|
||||
will be responsible for *all* classes and it will try to look up
|
||||
*all* classes starting at the directory given as the second
|
||||
argument.
|
||||
|
||||
- If both arguments are not supplied, the class loader will be
|
||||
responsible for *all* classes and it will rely on the PHP
|
||||
include_path.
|
||||
|
||||
|
||||
File Extension
|
||||
--------------
|
||||
|
||||
By default, a ClassLoader uses the ``.php`` file extension for all
|
||||
class files. You can change this behavior, for example to use a
|
||||
ClassLoader to load classes from a library that uses the
|
||||
".class.php" convention (but it must nevertheless adhere to the
|
||||
directory structure convention!):
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
$customLoader = new ClassLoader('CustomLib', '/path/to/custom/lib');
|
||||
$customLoader->setFileExtension('.class.php');
|
||||
$customLoader->register();
|
||||
|
||||
Namespace Separator
|
||||
-------------------
|
||||
|
||||
By default, a ClassLoader uses the ``\`` namespace separator. You
|
||||
can change this behavior, for example to use a ClassLoader to load
|
||||
legacy Zend Framework classes that still use the underscore "_"
|
||||
separator:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
$zend1Loader = new ClassLoader('Zend', '/path/to/zend/lib');
|
||||
$zend1Loader->setNamespaceSeparator('_');
|
||||
$zend1Loader->register();
|
||||
|
||||
Failing Silently and class_exists
|
||||
----------------------------------
|
||||
|
||||
A lot of class/autoloaders these days try to fail silently when a
|
||||
class file is not found. For the most part this is necessary in
|
||||
order to support using ``class_exists('ClassName', true)`` which is
|
||||
supposed to return a boolean value but triggers autoloading. This
|
||||
is a bad thing as it basically forces class loaders to fail
|
||||
silently, which in turn requires costly file_exists or fopen calls
|
||||
for each class being loaded, even though in at least 99% of the
|
||||
cases this is not necessary (compare the number of
|
||||
class_exists(..., true) invocations to the total number of classes
|
||||
being loaded in a request).
|
||||
|
||||
The Doctrine Common ClassLoader does not fail silently, by design.
|
||||
It therefore does not need any costly checks for file existence. A
|
||||
ClassLoader is always responsible for all classes with a certain
|
||||
namespace prefix and if a class is requested to be loaded and can
|
||||
not be found this is considered to be a fatal error. This also
|
||||
means that using class_exists(..., true) to check for class
|
||||
existence when using a Doctrine Common ClassLoader is not possible
|
||||
but this is not a bad thing. What class\_exists(..., true) actually
|
||||
means is two things: 1) Check whether the class is already
|
||||
defined/exists (i.e. class_exists(..., false)) and if not 2) check
|
||||
whether a class file can be loaded for that class. In the Doctrine
|
||||
Common ClassLoader the two responsibilities of loading a class and
|
||||
checking for its existence are separated, which can be observed by
|
||||
the existence of the two methods ``loadClass`` and
|
||||
``canLoadClass``. Thereby ``loadClass`` does not invoke
|
||||
``canLoadClass`` internally, by design. However, you are free to
|
||||
use it yourself to check whether a class can be loaded and the
|
||||
following code snippet is thus equivalent to class\_exists(...,
|
||||
true):
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
// Equivalent to if (('Foo', true)) if there is only 1 class loader to check
|
||||
if (class_exists('Foo', false) || $classLoader->canLoadClass('Foo')) {
|
||||
// ...
|
||||
}
|
||||
|
||||
The only problem with this is that it is inconvenient as you need
|
||||
to have a reference to the class loaders around (and there are
|
||||
often multiple class loaders in use). Therefore, a simpler
|
||||
alternative exists for the cases in which you really want to ask
|
||||
all installed class loaders whether they can load the class:
|
||||
``ClassLoader::classExists($className)``:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
// Equivalent to if (class_exists('Foo', true))
|
||||
if (ClassLoader::classExists('Foo')) {
|
||||
// ...
|
||||
}
|
||||
|
||||
This static method can basically be used as a drop-in replacement
|
||||
for class_exists(..., true). It iterates over all installed class
|
||||
loaders and asks each of them via ``canLoadClass``, returning early
|
||||
(with TRUE) as soon as one class loader returns TRUE from
|
||||
``canLoadClass``. If this sounds like it can potentially be rather
|
||||
costly then because that is true but it is exactly the same thing
|
||||
that class_exists(..., true) does under the hood, it triggers a
|
||||
complete interaction of all class/auto loaders. Checking for class
|
||||
existence via invoking autoloading was never a cheap thing to do
|
||||
but now it is more obvious and more importantly, this check is no
|
||||
longer interleaved with regular class loading, which avoids having
|
||||
to check each and every class for existence prior to loading it.
|
||||
The vast majority of classes to be loaded are *not* optional and a
|
||||
failure to load such a class is, and should be, a fatal error. The
|
||||
ClassLoader design reflects this.
|
||||
|
||||
If you have code that requires the usage of class\_exists(...,
|
||||
true) or ClassLoader::classExists during normal runtime of the
|
||||
application (i.e. on each request) try to refactor your design to
|
||||
avoid it.
|
||||
|
||||
Summary
|
||||
-------
|
||||
|
||||
No matter which class loader you prefer to use (Doctrine classes do
|
||||
not care about how they are loaded), we kindly encourage you to
|
||||
adhere to the simple convention of mapping namespaces and class
|
||||
names to a directory structure.
|
||||
|
||||
Class loading should be simple, automated and uniform. Time is
|
||||
better invested in actual application development than in designing
|
||||
special directory structures, autoloaders and clever caching
|
||||
strategies for class loading.
|
||||
|
||||
|
||||
285
vendor/doctrine/common/src/ClassLoader.php
vendored
Normal file
285
vendor/doctrine/common/src/ClassLoader.php
vendored
Normal file
@ -0,0 +1,285 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Common;
|
||||
|
||||
use function class_exists;
|
||||
use function interface_exists;
|
||||
use function is_array;
|
||||
use function is_file;
|
||||
use function reset;
|
||||
use function spl_autoload_functions;
|
||||
use function spl_autoload_register;
|
||||
use function spl_autoload_unregister;
|
||||
use function str_replace;
|
||||
use function stream_resolve_include_path;
|
||||
use function strpos;
|
||||
use function trait_exists;
|
||||
use function trigger_error;
|
||||
|
||||
use const DIRECTORY_SEPARATOR;
|
||||
use const E_USER_DEPRECATED;
|
||||
|
||||
@trigger_error(ClassLoader::class . ' is deprecated.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* A <tt>ClassLoader</tt> is an autoloader for class files that can be
|
||||
* installed on the SPL autoload stack. It is a class loader that either loads only classes
|
||||
* of a specific namespace or all namespaces and it is suitable for working together
|
||||
* with other autoloaders in the SPL autoload stack.
|
||||
*
|
||||
* If no include path is configured through the constructor or {@link setIncludePath}, a ClassLoader
|
||||
* relies on the PHP <code>include_path</code>.
|
||||
*
|
||||
* @deprecated The ClassLoader is deprecated and will be removed in version 4.0 of doctrine/common.
|
||||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
/**
|
||||
* PHP file extension.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $fileExtension = '.php';
|
||||
|
||||
/**
|
||||
* Current namespace.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected $namespace;
|
||||
|
||||
/**
|
||||
* Current include path.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected $includePath;
|
||||
|
||||
/**
|
||||
* PHP namespace separator.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespaceSeparator = '\\';
|
||||
|
||||
/**
|
||||
* Creates a new <tt>ClassLoader</tt> that loads classes of the
|
||||
* specified namespace from the specified include path.
|
||||
*
|
||||
* If no include path is given, the ClassLoader relies on the PHP include_path.
|
||||
* If neither a namespace nor an include path is given, the ClassLoader will
|
||||
* be responsible for loading all classes, thereby relying on the PHP include_path.
|
||||
*
|
||||
* @param string|null $ns The namespace of the classes to load.
|
||||
* @param string|null $includePath The base include path to use.
|
||||
*/
|
||||
public function __construct($ns = null, $includePath = null)
|
||||
{
|
||||
$this->namespace = $ns;
|
||||
$this->includePath = $includePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the namespace separator used by classes in the namespace of this ClassLoader.
|
||||
*
|
||||
* @param string $sep The separator to use.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setNamespaceSeparator($sep)
|
||||
{
|
||||
$this->namespaceSeparator = $sep;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the namespace separator used by classes in the namespace of this ClassLoader.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getNamespaceSeparator()
|
||||
{
|
||||
return $this->namespaceSeparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the base include path for all class files in the namespace of this ClassLoader.
|
||||
*
|
||||
* @param string|null $includePath
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setIncludePath($includePath)
|
||||
{
|
||||
$this->includePath = $includePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the base include path for all class files in the namespace of this ClassLoader.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getIncludePath()
|
||||
{
|
||||
return $this->includePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the file extension of class files in the namespace of this ClassLoader.
|
||||
*
|
||||
* @param string $fileExtension
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setFileExtension($fileExtension)
|
||||
{
|
||||
$this->fileExtension = $fileExtension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the file extension of class files in the namespace of this ClassLoader.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFileExtension()
|
||||
{
|
||||
return $this->fileExtension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers this ClassLoader on the SPL autoload stack.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
spl_autoload_register([$this, 'loadClass']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes this ClassLoader from the SPL autoload stack.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unregister()
|
||||
{
|
||||
spl_autoload_unregister([$this, 'loadClass']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given class or interface.
|
||||
*
|
||||
* @param string $className The name of the class to load.
|
||||
* @psalm-param class-string $className
|
||||
*
|
||||
* @return bool TRUE if the class has been successfully loaded, FALSE otherwise.
|
||||
*/
|
||||
public function loadClass($className)
|
||||
{
|
||||
if (self::typeExists($className)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! $this->canLoadClass($className)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
require($this->includePath !== null ? $this->includePath . DIRECTORY_SEPARATOR : '')
|
||||
. str_replace($this->namespaceSeparator, DIRECTORY_SEPARATOR, $className)
|
||||
. $this->fileExtension;
|
||||
|
||||
return self::typeExists($className);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asks this ClassLoader whether it can potentially load the class (file) with
|
||||
* the given name.
|
||||
*
|
||||
* @param string $className The fully-qualified name of the class.
|
||||
* @psalm-param class-string $className
|
||||
*
|
||||
* @return bool TRUE if this ClassLoader can load the class, FALSE otherwise.
|
||||
*/
|
||||
public function canLoadClass($className)
|
||||
{
|
||||
if ($this->namespace !== null && strpos($className, $this->namespace . $this->namespaceSeparator) !== 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$file = str_replace($this->namespaceSeparator, DIRECTORY_SEPARATOR, $className) . $this->fileExtension;
|
||||
|
||||
if ($this->includePath !== null) {
|
||||
return is_file($this->includePath . DIRECTORY_SEPARATOR . $file);
|
||||
}
|
||||
|
||||
return stream_resolve_include_path($file) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a class with a given name exists. A class "exists" if it is either
|
||||
* already defined in the current request or if there is an autoloader on the SPL
|
||||
* autoload stack that is a) responsible for the class in question and b) is able to
|
||||
* load a class file in which the class definition resides.
|
||||
*
|
||||
* If the class is not already defined, each autoloader in the SPL autoload stack
|
||||
* is asked whether it is able to tell if the class exists. If the autoloader is
|
||||
* a <tt>ClassLoader</tt>, {@link canLoadClass} is used, otherwise the autoload
|
||||
* function of the autoloader is invoked and expected to return a value that
|
||||
* evaluates to TRUE if the class (file) exists. As soon as one autoloader reports
|
||||
* that the class exists, TRUE is returned.
|
||||
*
|
||||
* Note that, depending on what kinds of autoloaders are installed on the SPL
|
||||
* autoload stack, the class (file) might already be loaded as a result of checking
|
||||
* for its existence. This is not the case with a <tt>ClassLoader</tt>, who separates
|
||||
* these responsibilities.
|
||||
*
|
||||
* @param string $className The fully-qualified name of the class.
|
||||
* @psalm-param class-string $className
|
||||
*
|
||||
* @return bool TRUE if the class exists as per the definition given above, FALSE otherwise.
|
||||
*/
|
||||
public static function classExists($className)
|
||||
{
|
||||
return self::typeExists($className, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the <tt>ClassLoader</tt> from the SPL autoload stack that is responsible
|
||||
* for (and is able to load) the class with the given name.
|
||||
*
|
||||
* @param string $className The name of the class.
|
||||
* @psalm-param class-string $className
|
||||
*
|
||||
* @return ClassLoader|null The <tt>ClassLoader</tt> for the class or NULL if no such <tt>ClassLoader</tt> exists.
|
||||
*/
|
||||
public static function getClassLoader($className)
|
||||
{
|
||||
foreach (spl_autoload_functions() as $loader) {
|
||||
if (! is_array($loader)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$classLoader = reset($loader);
|
||||
|
||||
if ($classLoader instanceof ClassLoader && $classLoader->canLoadClass($className)) {
|
||||
return $classLoader;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a given type exists
|
||||
*
|
||||
* @param string $type
|
||||
* @param bool $autoload
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private static function typeExists($type, $autoload = false)
|
||||
{
|
||||
return class_exists($type, $autoload)
|
||||
|| interface_exists($type, $autoload)
|
||||
|| trait_exists($type, $autoload);
|
||||
}
|
||||
}
|
||||
14
vendor/doctrine/common/src/CommonException.php
vendored
Normal file
14
vendor/doctrine/common/src/CommonException.php
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Common;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Base exception class for package Doctrine\Common.
|
||||
*
|
||||
* @deprecated The doctrine/common package is deprecated, please use specific packages and their exceptions instead.
|
||||
*/
|
||||
class CommonException extends Exception
|
||||
{
|
||||
}
|
||||
26
vendor/doctrine/common/src/Comparable.php
vendored
Normal file
26
vendor/doctrine/common/src/Comparable.php
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Common;
|
||||
|
||||
/**
|
||||
* Comparable interface that allows to compare two value objects to each other for similarity.
|
||||
*
|
||||
* @link www.doctrine-project.org
|
||||
*/
|
||||
interface Comparable
|
||||
{
|
||||
/**
|
||||
* Compares the current object to the passed $other.
|
||||
*
|
||||
* Returns 0 if they are semantically equal, 1 if the other object
|
||||
* is less than the current one, or -1 if its more than the current one.
|
||||
*
|
||||
* This method should not check for identity using ===, only for semantical equality for example
|
||||
* when two different DateTime instances point to the exact same Date + TZ.
|
||||
*
|
||||
* @param mixed $other
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function compareTo($other);
|
||||
}
|
||||
246
vendor/doctrine/common/src/Proxy/AbstractProxyFactory.php
vendored
Normal file
246
vendor/doctrine/common/src/Proxy/AbstractProxyFactory.php
vendored
Normal file
@ -0,0 +1,246 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Common\Proxy;
|
||||
|
||||
use Doctrine\Common\Proxy\Exception\InvalidArgumentException;
|
||||
use Doctrine\Common\Proxy\Exception\OutOfBoundsException;
|
||||
use Doctrine\Common\Util\ClassUtils;
|
||||
use Doctrine\Persistence\Mapping\ClassMetadata;
|
||||
use Doctrine\Persistence\Mapping\ClassMetadataFactory;
|
||||
|
||||
use function class_exists;
|
||||
use function file_exists;
|
||||
use function filemtime;
|
||||
use function in_array;
|
||||
|
||||
/**
|
||||
* Abstract factory for proxy objects.
|
||||
*
|
||||
* @deprecated The AbstractProxyFactory class is deprecated since doctrine/common 3.5.
|
||||
*/
|
||||
abstract class AbstractProxyFactory
|
||||
{
|
||||
/**
|
||||
* Never autogenerate a proxy and rely that it was generated by some
|
||||
* process before deployment.
|
||||
*/
|
||||
public const AUTOGENERATE_NEVER = 0;
|
||||
|
||||
/**
|
||||
* Always generates a new proxy in every request.
|
||||
*
|
||||
* This is only sane during development.
|
||||
*/
|
||||
public const AUTOGENERATE_ALWAYS = 1;
|
||||
|
||||
/**
|
||||
* Autogenerate the proxy class when the proxy file does not exist.
|
||||
*
|
||||
* This strategy causes a file_exists() call whenever any proxy is used the
|
||||
* first time in a request.
|
||||
*/
|
||||
public const AUTOGENERATE_FILE_NOT_EXISTS = 2;
|
||||
|
||||
/**
|
||||
* Generate the proxy classes using eval().
|
||||
*
|
||||
* This strategy is only sane for development, and even then it gives me
|
||||
* the creeps a little.
|
||||
*/
|
||||
public const AUTOGENERATE_EVAL = 3;
|
||||
|
||||
/**
|
||||
* Autogenerate the proxy class when the proxy file does not exist or
|
||||
* when the proxied file changed.
|
||||
*
|
||||
* This strategy causes a file_exists() call whenever any proxy is used the
|
||||
* first time in a request. When the proxied file is changed, the proxy will
|
||||
* be updated.
|
||||
*/
|
||||
public const AUTOGENERATE_FILE_NOT_EXISTS_OR_CHANGED = 4;
|
||||
|
||||
private const AUTOGENERATE_MODES = [
|
||||
self::AUTOGENERATE_NEVER,
|
||||
self::AUTOGENERATE_ALWAYS,
|
||||
self::AUTOGENERATE_FILE_NOT_EXISTS,
|
||||
self::AUTOGENERATE_EVAL,
|
||||
self::AUTOGENERATE_FILE_NOT_EXISTS_OR_CHANGED,
|
||||
];
|
||||
|
||||
/** @var ClassMetadataFactory */
|
||||
private $metadataFactory;
|
||||
|
||||
/** @var ProxyGenerator the proxy generator responsible for creating the proxy classes/files. */
|
||||
private $proxyGenerator;
|
||||
|
||||
/** @var int Whether to automatically (re)generate proxy classes. */
|
||||
private $autoGenerate;
|
||||
|
||||
/** @var ProxyDefinition[] */
|
||||
private $definitions = [];
|
||||
|
||||
/**
|
||||
* @param bool|int $autoGenerate
|
||||
*
|
||||
* @throws InvalidArgumentException When auto generate mode is not valid.
|
||||
*/
|
||||
public function __construct(ProxyGenerator $proxyGenerator, ClassMetadataFactory $metadataFactory, $autoGenerate)
|
||||
{
|
||||
$this->proxyGenerator = $proxyGenerator;
|
||||
$this->metadataFactory = $metadataFactory;
|
||||
$this->autoGenerate = (int) $autoGenerate;
|
||||
|
||||
if (! in_array($this->autoGenerate, self::AUTOGENERATE_MODES, true)) {
|
||||
throw InvalidArgumentException::invalidAutoGenerateMode($autoGenerate);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a reference proxy instance for the entity of the given type and identified by
|
||||
* the given identifier.
|
||||
*
|
||||
* @param string $className
|
||||
* @param array<mixed> $identifier
|
||||
*
|
||||
* @return Proxy
|
||||
*
|
||||
* @throws OutOfBoundsException
|
||||
*/
|
||||
public function getProxy($className, array $identifier)
|
||||
{
|
||||
$definition = $this->definitions[$className] ?? $this->getProxyDefinition($className);
|
||||
$fqcn = $definition->proxyClassName;
|
||||
$proxy = new $fqcn($definition->initializer, $definition->cloner);
|
||||
|
||||
foreach ($definition->identifierFields as $idField) {
|
||||
if (! isset($identifier[$idField])) {
|
||||
throw OutOfBoundsException::missingPrimaryKeyValue($className, $idField);
|
||||
}
|
||||
|
||||
$definition->reflectionFields[$idField]->setValue($proxy, $identifier[$idField]);
|
||||
}
|
||||
|
||||
return $proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates proxy classes for all given classes.
|
||||
*
|
||||
* @param ClassMetadata[] $classes The classes (ClassMetadata instances)
|
||||
* for which to generate proxies.
|
||||
* @param string $proxyDir The target directory of the proxy classes. If not specified, the
|
||||
* directory configured on the Configuration of the EntityManager used
|
||||
* by this factory is used.
|
||||
*
|
||||
* @return int Number of generated proxies.
|
||||
*/
|
||||
public function generateProxyClasses(array $classes, $proxyDir = null)
|
||||
{
|
||||
$generated = 0;
|
||||
|
||||
foreach ($classes as $class) {
|
||||
if ($this->skipClass($class)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$proxyFileName = $this->proxyGenerator->getProxyFileName($class->getName(), $proxyDir);
|
||||
|
||||
$this->proxyGenerator->generateProxyClass($class, $proxyFileName);
|
||||
|
||||
$generated += 1;
|
||||
}
|
||||
|
||||
return $generated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset initialization/cloning logic for an un-initialized proxy
|
||||
*
|
||||
* @return Proxy
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function resetUninitializedProxy(Proxy $proxy)
|
||||
{
|
||||
if ($proxy->__isInitialized()) {
|
||||
throw InvalidArgumentException::unitializedProxyExpected($proxy);
|
||||
}
|
||||
|
||||
$className = ClassUtils::getClass($proxy);
|
||||
$definition = $this->definitions[$className] ?? $this->getProxyDefinition($className);
|
||||
|
||||
$proxy->__setInitializer($definition->initializer);
|
||||
$proxy->__setCloner($definition->cloner);
|
||||
|
||||
return $proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a proxy definition for the given class name.
|
||||
*
|
||||
* @param string $className
|
||||
* @psalm-param class-string $className
|
||||
*
|
||||
* @return ProxyDefinition
|
||||
*/
|
||||
private function getProxyDefinition($className)
|
||||
{
|
||||
$classMetadata = $this->metadataFactory->getMetadataFor($className);
|
||||
$className = $classMetadata->getName(); // aliases and case sensitivity
|
||||
|
||||
$this->definitions[$className] = $this->createProxyDefinition($className);
|
||||
$proxyClassName = $this->definitions[$className]->proxyClassName;
|
||||
|
||||
if (! class_exists($proxyClassName, false)) {
|
||||
$fileName = $this->proxyGenerator->getProxyFileName($className);
|
||||
|
||||
switch ($this->autoGenerate) {
|
||||
case self::AUTOGENERATE_NEVER:
|
||||
require $fileName;
|
||||
break;
|
||||
|
||||
case self::AUTOGENERATE_FILE_NOT_EXISTS:
|
||||
if (! file_exists($fileName)) {
|
||||
$this->proxyGenerator->generateProxyClass($classMetadata, $fileName);
|
||||
}
|
||||
|
||||
require $fileName;
|
||||
break;
|
||||
|
||||
case self::AUTOGENERATE_ALWAYS:
|
||||
$this->proxyGenerator->generateProxyClass($classMetadata, $fileName);
|
||||
require $fileName;
|
||||
break;
|
||||
|
||||
case self::AUTOGENERATE_EVAL:
|
||||
$this->proxyGenerator->generateProxyClass($classMetadata, false);
|
||||
break;
|
||||
|
||||
case self::AUTOGENERATE_FILE_NOT_EXISTS_OR_CHANGED:
|
||||
if (! file_exists($fileName) || filemtime($fileName) < filemtime($classMetadata->getReflectionClass()->getFileName())) {
|
||||
$this->proxyGenerator->generateProxyClass($classMetadata, $fileName);
|
||||
}
|
||||
|
||||
require $fileName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->definitions[$className];
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if this class should be skipped during proxy generation.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
abstract protected function skipClass(ClassMetadata $metadata);
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
* @psalm-param class-string $className
|
||||
*
|
||||
* @return ProxyDefinition
|
||||
*/
|
||||
abstract protected function createProxyDefinition($className);
|
||||
}
|
||||
100
vendor/doctrine/common/src/Proxy/Autoloader.php
vendored
Normal file
100
vendor/doctrine/common/src/Proxy/Autoloader.php
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Common\Proxy;
|
||||
|
||||
use Closure;
|
||||
use Doctrine\Common\Proxy\Exception\InvalidArgumentException;
|
||||
|
||||
use function call_user_func;
|
||||
use function file_exists;
|
||||
use function is_callable;
|
||||
use function ltrim;
|
||||
use function spl_autoload_register;
|
||||
use function str_replace;
|
||||
use function strlen;
|
||||
use function strpos;
|
||||
use function substr;
|
||||
|
||||
use const DIRECTORY_SEPARATOR;
|
||||
|
||||
/**
|
||||
* Special Autoloader for Proxy classes, which are not PSR-0 compliant.
|
||||
*
|
||||
* @internal
|
||||
* @deprecated The Autoloader class is deprecated since doctrine/common 3.5.
|
||||
*/
|
||||
class Autoloader
|
||||
{
|
||||
/**
|
||||
* Resolves proxy class name to a filename based on the following pattern.
|
||||
*
|
||||
* 1. Remove Proxy namespace from class name.
|
||||
* 2. Remove namespace separators from remaining class name.
|
||||
* 3. Return PHP filename from proxy-dir with the result from 2.
|
||||
*
|
||||
* @param string $proxyDir
|
||||
* @param string $proxyNamespace
|
||||
* @param string $className
|
||||
* @psalm-param class-string $className
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public static function resolveFile($proxyDir, $proxyNamespace, $className)
|
||||
{
|
||||
if (strpos($className, $proxyNamespace) !== 0) {
|
||||
throw InvalidArgumentException::notProxyClass($className, $proxyNamespace);
|
||||
}
|
||||
|
||||
// remove proxy namespace from class name
|
||||
$classNameRelativeToProxyNamespace = substr($className, strlen($proxyNamespace));
|
||||
|
||||
// remove namespace separators from remaining class name
|
||||
$fileName = str_replace('\\', '', $classNameRelativeToProxyNamespace);
|
||||
|
||||
return $proxyDir . DIRECTORY_SEPARATOR . $fileName . '.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers and returns autoloader callback for the given proxy dir and namespace.
|
||||
*
|
||||
* @param string $proxyDir
|
||||
* @param string $proxyNamespace
|
||||
* @param callable|null $notFoundCallback Invoked when the proxy file is not found.
|
||||
*
|
||||
* @return Closure
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public static function register($proxyDir, $proxyNamespace, $notFoundCallback = null)
|
||||
{
|
||||
$proxyNamespace = ltrim($proxyNamespace, '\\');
|
||||
|
||||
if ($notFoundCallback !== null && ! is_callable($notFoundCallback)) {
|
||||
throw InvalidArgumentException::invalidClassNotFoundCallback($notFoundCallback);
|
||||
}
|
||||
|
||||
$autoloader = static function ($className) use ($proxyDir, $proxyNamespace, $notFoundCallback) {
|
||||
if ($proxyNamespace === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (strpos($className, $proxyNamespace) !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$file = Autoloader::resolveFile($proxyDir, $proxyNamespace, $className);
|
||||
|
||||
if ($notFoundCallback && ! file_exists($file)) {
|
||||
call_user_func($notFoundCallback, $proxyDir, $proxyNamespace, $className);
|
||||
}
|
||||
|
||||
require $file;
|
||||
};
|
||||
|
||||
spl_autoload_register($autoloader);
|
||||
|
||||
return $autoloader;
|
||||
}
|
||||
}
|
||||
110
vendor/doctrine/common/src/Proxy/Exception/InvalidArgumentException.php
vendored
Normal file
110
vendor/doctrine/common/src/Proxy/Exception/InvalidArgumentException.php
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Common\Proxy\Exception;
|
||||
|
||||
use Doctrine\Persistence\Proxy;
|
||||
use InvalidArgumentException as BaseInvalidArgumentException;
|
||||
|
||||
use function get_class;
|
||||
use function gettype;
|
||||
use function is_object;
|
||||
use function sprintf;
|
||||
|
||||
/**
|
||||
* Proxy Invalid Argument Exception.
|
||||
*
|
||||
* @deprecated The InvalidArgumentException class is deprecated since doctrine/common 3.5.
|
||||
*/
|
||||
class InvalidArgumentException extends BaseInvalidArgumentException implements ProxyException
|
||||
{
|
||||
/** @return self */
|
||||
public static function proxyDirectoryRequired()
|
||||
{
|
||||
return new self('You must configure a proxy directory. See docs for details');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
* @param string $proxyNamespace
|
||||
* @psalm-param class-string $className
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public static function notProxyClass($className, $proxyNamespace)
|
||||
{
|
||||
return new self(sprintf('The class "%s" is not part of the proxy namespace "%s"', $className, $proxyNamespace));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public static function invalidPlaceholder($name)
|
||||
{
|
||||
return new self(sprintf('Provided placeholder for "%s" must be either a string or a valid callable', $name));
|
||||
}
|
||||
|
||||
/** @return self */
|
||||
public static function proxyNamespaceRequired()
|
||||
{
|
||||
return new self('You must configure a proxy namespace');
|
||||
}
|
||||
|
||||
/** @return self */
|
||||
public static function unitializedProxyExpected(Proxy $proxy)
|
||||
{
|
||||
return new self(sprintf('Provided proxy of type "%s" must not be initialized.', get_class($proxy)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $callback
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public static function invalidClassNotFoundCallback($callback)
|
||||
{
|
||||
$type = is_object($callback) ? get_class($callback) : gettype($callback);
|
||||
|
||||
return new self(sprintf('Invalid \$notFoundCallback given: must be a callable, "%s" given', $type));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
* @psalm-param class-string $className
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public static function classMustNotBeAbstract($className)
|
||||
{
|
||||
return new self(sprintf('Unable to create a proxy for an abstract class "%s".', $className));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
* @psalm-param class-string $className
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public static function classMustNotBeFinal($className)
|
||||
{
|
||||
return new self(sprintf('Unable to create a proxy for a final class "%s".', $className));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
* @psalm-param class-string $className
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public static function classMustNotBeReadOnly($className)
|
||||
{
|
||||
return new self(sprintf('Unable to create a proxy for a readonly class "%s".', $className));
|
||||
}
|
||||
|
||||
/** @param mixed $value */
|
||||
public static function invalidAutoGenerateMode($value): self
|
||||
{
|
||||
return new self(sprintf('Invalid auto generate mode "%s" given.', $value));
|
||||
}
|
||||
}
|
||||
27
vendor/doctrine/common/src/Proxy/Exception/OutOfBoundsException.php
vendored
Normal file
27
vendor/doctrine/common/src/Proxy/Exception/OutOfBoundsException.php
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Common\Proxy\Exception;
|
||||
|
||||
use OutOfBoundsException as BaseOutOfBoundsException;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
/**
|
||||
* Proxy Invalid Argument Exception.
|
||||
*
|
||||
* @deprecated The OutOfBoundsException class is deprecated since doctrine/common 3.5.
|
||||
*/
|
||||
class OutOfBoundsException extends BaseOutOfBoundsException implements ProxyException
|
||||
{
|
||||
/**
|
||||
* @param string $className
|
||||
* @param string $idField
|
||||
* @psalm-param class-string $className
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public static function missingPrimaryKeyValue($className, $idField)
|
||||
{
|
||||
return new self(sprintf('Missing value for primary key %s on %s', $idField, $className));
|
||||
}
|
||||
}
|
||||
12
vendor/doctrine/common/src/Proxy/Exception/ProxyException.php
vendored
Normal file
12
vendor/doctrine/common/src/Proxy/Exception/ProxyException.php
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Common\Proxy\Exception;
|
||||
|
||||
/**
|
||||
* Base exception interface for proxy exceptions.
|
||||
*
|
||||
* @deprecated The ProxyException interface is deprecated since doctrine/common 3.5.
|
||||
*/
|
||||
interface ProxyException
|
||||
{
|
||||
}
|
||||
72
vendor/doctrine/common/src/Proxy/Exception/UnexpectedValueException.php
vendored
Normal file
72
vendor/doctrine/common/src/Proxy/Exception/UnexpectedValueException.php
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Common\Proxy\Exception;
|
||||
|
||||
use Throwable;
|
||||
use UnexpectedValueException as BaseUnexpectedValueException;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
/**
|
||||
* Proxy Unexpected Value Exception.
|
||||
*
|
||||
* @deprecated The UnexpectedValueException class is deprecated since doctrine/common 3.5.
|
||||
*/
|
||||
class UnexpectedValueException extends BaseUnexpectedValueException implements ProxyException
|
||||
{
|
||||
/**
|
||||
* @param string $proxyDirectory
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public static function proxyDirectoryNotWritable($proxyDirectory)
|
||||
{
|
||||
return new self(sprintf('Your proxy directory "%s" must be writable', $proxyDirectory));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
* @param string $methodName
|
||||
* @param string $parameterName
|
||||
* @psalm-param class-string $className
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public static function invalidParameterTypeHint(
|
||||
$className,
|
||||
$methodName,
|
||||
$parameterName,
|
||||
?Throwable $previous = null
|
||||
) {
|
||||
return new self(
|
||||
sprintf(
|
||||
'The type hint of parameter "%s" in method "%s" in class "%s" is invalid.',
|
||||
$parameterName,
|
||||
$methodName,
|
||||
$className
|
||||
),
|
||||
0,
|
||||
$previous
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
* @param string $methodName
|
||||
* @psalm-param class-string $className
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public static function invalidReturnTypeHint($className, $methodName, ?Throwable $previous = null)
|
||||
{
|
||||
return new self(
|
||||
sprintf(
|
||||
'The return type of method "%s" in class "%s" is invalid.',
|
||||
$methodName,
|
||||
$className
|
||||
),
|
||||
0,
|
||||
$previous
|
||||
);
|
||||
}
|
||||
}
|
||||
70
vendor/doctrine/common/src/Proxy/Proxy.php
vendored
Normal file
70
vendor/doctrine/common/src/Proxy/Proxy.php
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Common\Proxy;
|
||||
|
||||
use Closure;
|
||||
use Doctrine\Persistence\Proxy as BaseProxy;
|
||||
|
||||
/**
|
||||
* Interface for proxy classes.
|
||||
*
|
||||
* @deprecated The Proxy interface is deprecated since doctrine/common 3.5.
|
||||
*
|
||||
* @template T of object
|
||||
* @template-extends BaseProxy<T>
|
||||
*/
|
||||
interface Proxy extends BaseProxy
|
||||
{
|
||||
/**
|
||||
* Marks the proxy as initialized or not.
|
||||
*
|
||||
* @param bool $initialized
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __setInitialized($initialized);
|
||||
|
||||
/**
|
||||
* Sets the initializer callback to be used when initializing the proxy. That
|
||||
* initializer should accept 3 parameters: $proxy, $method and $params. Those
|
||||
* are respectively the proxy object that is being initialized, the method name
|
||||
* that triggered initialization and the parameters passed to that method.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __setInitializer(?Closure $initializer = null);
|
||||
|
||||
/**
|
||||
* Retrieves the initializer callback used to initialize the proxy.
|
||||
*
|
||||
* @see __setInitializer
|
||||
*
|
||||
* @return Closure|null
|
||||
*/
|
||||
public function __getInitializer();
|
||||
|
||||
/**
|
||||
* Sets the callback to be used when cloning the proxy. That initializer should accept
|
||||
* a single parameter, which is the cloned proxy instance itself.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __setCloner(?Closure $cloner = null);
|
||||
|
||||
/**
|
||||
* Retrieves the callback to be used when cloning the proxy.
|
||||
*
|
||||
* @see __setCloner
|
||||
*
|
||||
* @return Closure|null
|
||||
*/
|
||||
public function __getCloner();
|
||||
|
||||
/**
|
||||
* Retrieves the list of lazy loaded properties for a given proxy
|
||||
*
|
||||
* @return array<string, mixed> Keys are the property names, and values are the default values
|
||||
* for those properties.
|
||||
*/
|
||||
public function __getLazyProperties();
|
||||
}
|
||||
44
vendor/doctrine/common/src/Proxy/ProxyDefinition.php
vendored
Normal file
44
vendor/doctrine/common/src/Proxy/ProxyDefinition.php
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Common\Proxy;
|
||||
|
||||
use ReflectionProperty;
|
||||
|
||||
/**
|
||||
* Definition structure how to create a proxy.
|
||||
*
|
||||
* @deprecated The ProxyDefinition class is deprecated since doctrine/common 3.5.
|
||||
*/
|
||||
class ProxyDefinition
|
||||
{
|
||||
/** @var string */
|
||||
public $proxyClassName;
|
||||
|
||||
/** @var array<string> */
|
||||
public $identifierFields;
|
||||
|
||||
/** @var ReflectionProperty[] */
|
||||
public $reflectionFields;
|
||||
|
||||
/** @var callable */
|
||||
public $initializer;
|
||||
|
||||
/** @var callable */
|
||||
public $cloner;
|
||||
|
||||
/**
|
||||
* @param string $proxyClassName
|
||||
* @param array<string> $identifierFields
|
||||
* @param array<string, ReflectionProperty> $reflectionFields
|
||||
* @param callable $initializer
|
||||
* @param callable $cloner
|
||||
*/
|
||||
public function __construct($proxyClassName, array $identifierFields, array $reflectionFields, $initializer, $cloner)
|
||||
{
|
||||
$this->proxyClassName = $proxyClassName;
|
||||
$this->identifierFields = $identifierFields;
|
||||
$this->reflectionFields = $reflectionFields;
|
||||
$this->initializer = $initializer;
|
||||
$this->cloner = $cloner;
|
||||
}
|
||||
}
|
||||
1293
vendor/doctrine/common/src/Proxy/ProxyGenerator.php
vendored
Normal file
1293
vendor/doctrine/common/src/Proxy/ProxyGenerator.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
113
vendor/doctrine/common/src/Util/ClassUtils.php
vendored
Normal file
113
vendor/doctrine/common/src/Util/ClassUtils.php
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Common\Util;
|
||||
|
||||
use Doctrine\Persistence\Proxy;
|
||||
use ReflectionClass;
|
||||
|
||||
use function get_class;
|
||||
use function get_parent_class;
|
||||
use function ltrim;
|
||||
use function rtrim;
|
||||
use function strrpos;
|
||||
use function substr;
|
||||
|
||||
/**
|
||||
* Class and reflection related functionality for objects that
|
||||
* might or not be proxy objects at the moment.
|
||||
*/
|
||||
class ClassUtils
|
||||
{
|
||||
/**
|
||||
* Gets the real class name of a class name that could be a proxy.
|
||||
*
|
||||
* @param string $className
|
||||
* @psalm-param class-string<Proxy<T>>|class-string<T> $className
|
||||
*
|
||||
* @return string
|
||||
* @psalm-return class-string<T>
|
||||
*
|
||||
* @template T of object
|
||||
*/
|
||||
public static function getRealClass($className)
|
||||
{
|
||||
$pos = strrpos($className, '\\' . Proxy::MARKER . '\\');
|
||||
|
||||
if ($pos === false) {
|
||||
/** @psalm-var class-string<T> */
|
||||
return $className;
|
||||
}
|
||||
|
||||
return substr($className, $pos + Proxy::MARKER_LENGTH + 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the real class name of an object (even if its a proxy).
|
||||
*
|
||||
* @param object $object
|
||||
* @psalm-param Proxy<T>|T $object
|
||||
*
|
||||
* @return string
|
||||
* @psalm-return class-string<T>
|
||||
*
|
||||
* @template T of object
|
||||
*/
|
||||
public static function getClass($object)
|
||||
{
|
||||
return self::getRealClass(get_class($object));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the real parent class name of a class or object.
|
||||
*
|
||||
* @param string $className
|
||||
* @psalm-param class-string $className
|
||||
*
|
||||
* @return string
|
||||
* @psalm-return class-string
|
||||
*/
|
||||
public static function getParentClass($className)
|
||||
{
|
||||
return get_parent_class(self::getRealClass($className));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new reflection class.
|
||||
*
|
||||
* @param string $className
|
||||
* @psalm-param class-string $className
|
||||
*
|
||||
* @return ReflectionClass
|
||||
*/
|
||||
public static function newReflectionClass($className)
|
||||
{
|
||||
return new ReflectionClass(self::getRealClass($className));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new reflection object.
|
||||
*
|
||||
* @param object $object
|
||||
*
|
||||
* @return ReflectionClass
|
||||
*/
|
||||
public static function newReflectionObject($object)
|
||||
{
|
||||
return self::newReflectionClass(self::getClass($object));
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a class name and a proxy namespace returns the proxy name.
|
||||
*
|
||||
* @param string $className
|
||||
* @param string $proxyNamespace
|
||||
* @psalm-param class-string $className
|
||||
*
|
||||
* @return string
|
||||
* @psalm-return class-string
|
||||
*/
|
||||
public static function generateProxyClassName($className, $proxyNamespace)
|
||||
{
|
||||
return rtrim($proxyNamespace, '\\') . '\\' . Proxy::MARKER . '\\' . ltrim($className, '\\');
|
||||
}
|
||||
}
|
||||
185
vendor/doctrine/common/src/Util/Debug.php
vendored
Normal file
185
vendor/doctrine/common/src/Util/Debug.php
vendored
Normal file
@ -0,0 +1,185 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Common\Util;
|
||||
|
||||
use ArrayIterator;
|
||||
use ArrayObject;
|
||||
use DateTimeInterface;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\Persistence\Proxy;
|
||||
use stdClass;
|
||||
|
||||
use function array_keys;
|
||||
use function count;
|
||||
use function end;
|
||||
use function explode;
|
||||
use function extension_loaded;
|
||||
use function get_class;
|
||||
use function html_entity_decode;
|
||||
use function ini_get;
|
||||
use function ini_set;
|
||||
use function is_array;
|
||||
use function is_object;
|
||||
use function method_exists;
|
||||
use function ob_end_clean;
|
||||
use function ob_get_contents;
|
||||
use function ob_start;
|
||||
use function spl_object_hash;
|
||||
use function strip_tags;
|
||||
use function var_dump;
|
||||
|
||||
/**
|
||||
* Static class containing most used debug methods.
|
||||
*
|
||||
* @deprecated The Debug class is deprecated, please use symfony/var-dumper instead.
|
||||
*
|
||||
* @link www.doctrine-project.org
|
||||
*/
|
||||
final class Debug
|
||||
{
|
||||
/**
|
||||
* Private constructor (prevents instantiation).
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a dump of the public, protected and private properties of $var.
|
||||
*
|
||||
* @link https://xdebug.org/
|
||||
*
|
||||
* @param mixed $var The variable to dump.
|
||||
* @param int $maxDepth The maximum nesting level for object properties.
|
||||
* @param bool $stripTags Whether output should strip HTML tags.
|
||||
* @param bool $echo Send the dumped value to the output buffer
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function dump($var, $maxDepth = 2, $stripTags = true, $echo = true)
|
||||
{
|
||||
$html = ini_get('html_errors');
|
||||
|
||||
if ($html !== true) {
|
||||
ini_set('html_errors', 'on');
|
||||
}
|
||||
|
||||
if (extension_loaded('xdebug')) {
|
||||
ini_set('xdebug.var_display_max_depth', $maxDepth);
|
||||
}
|
||||
|
||||
$var = self::export($var, $maxDepth);
|
||||
|
||||
ob_start();
|
||||
var_dump($var);
|
||||
|
||||
$dump = ob_get_contents();
|
||||
|
||||
ob_end_clean();
|
||||
|
||||
$dumpText = ($stripTags ? strip_tags(html_entity_decode($dump)) : $dump);
|
||||
|
||||
ini_set('html_errors', $html);
|
||||
|
||||
if ($echo) {
|
||||
echo $dumpText;
|
||||
}
|
||||
|
||||
return $dumpText;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $var
|
||||
* @param int $maxDepth
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function export($var, $maxDepth)
|
||||
{
|
||||
$return = null;
|
||||
$isObj = is_object($var);
|
||||
|
||||
if ($var instanceof Collection) {
|
||||
$var = $var->toArray();
|
||||
}
|
||||
|
||||
if (! $maxDepth) {
|
||||
return is_object($var) ? get_class($var)
|
||||
: (is_array($var) ? 'Array(' . count($var) . ')' : $var);
|
||||
}
|
||||
|
||||
if (is_array($var)) {
|
||||
$return = [];
|
||||
|
||||
foreach ($var as $k => $v) {
|
||||
$return[$k] = self::export($v, $maxDepth - 1);
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
if (! $isObj) {
|
||||
return $var;
|
||||
}
|
||||
|
||||
$return = new stdClass();
|
||||
if ($var instanceof DateTimeInterface) {
|
||||
$return->__CLASS__ = get_class($var);
|
||||
$return->date = $var->format('c');
|
||||
$return->timezone = $var->getTimezone()->getName();
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
$return->__CLASS__ = ClassUtils::getClass($var);
|
||||
|
||||
if ($var instanceof Proxy) {
|
||||
$return->__IS_PROXY__ = true;
|
||||
$return->__PROXY_INITIALIZED__ = $var->__isInitialized();
|
||||
}
|
||||
|
||||
if ($var instanceof ArrayObject || $var instanceof ArrayIterator) {
|
||||
$return->__STORAGE__ = self::export($var->getArrayCopy(), $maxDepth - 1);
|
||||
}
|
||||
|
||||
return self::fillReturnWithClassAttributes($var, $return, $maxDepth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill the $return variable with class attributes
|
||||
* Based on obj2array function from {@see https://secure.php.net/manual/en/function.get-object-vars.php#47075}
|
||||
*
|
||||
* @param object $var
|
||||
* @param int $maxDepth
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
private static function fillReturnWithClassAttributes($var, stdClass $return, $maxDepth)
|
||||
{
|
||||
$clone = (array) $var;
|
||||
|
||||
foreach (array_keys($clone) as $key) {
|
||||
$aux = explode("\0", $key);
|
||||
$name = end($aux);
|
||||
if ($aux[0] === '') {
|
||||
$name .= ':' . ($aux[1] === '*' ? 'protected' : $aux[1] . ':private');
|
||||
}
|
||||
|
||||
$return->$name = self::export($clone[$key], $maxDepth - 1);
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of an object.
|
||||
*
|
||||
* @param object $obj
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function toString($obj)
|
||||
{
|
||||
return method_exists($obj, '__toString') ? (string) $obj : get_class($obj) . '@' . spl_object_hash($obj);
|
||||
}
|
||||
}
|
||||
19
vendor/doctrine/deprecations/LICENSE
vendored
Normal file
19
vendor/doctrine/deprecations/LICENSE
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2020-2021 Doctrine Project
|
||||
|
||||
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.
|
||||
218
vendor/doctrine/deprecations/README.md
vendored
Normal file
218
vendor/doctrine/deprecations/README.md
vendored
Normal file
@ -0,0 +1,218 @@
|
||||
# Doctrine Deprecations
|
||||
|
||||
A small (side-effect free by default) layer on top of
|
||||
`trigger_error(E_USER_DEPRECATED)` or PSR-3 logging.
|
||||
|
||||
- no side-effects by default, making it a perfect fit for libraries that don't know how the error handler works they operate under
|
||||
- options to avoid having to rely on error handlers global state by using PSR-3 logging
|
||||
- deduplicate deprecation messages to avoid excessive triggering and reduce overhead
|
||||
|
||||
We recommend to collect Deprecations using a PSR logger instead of relying on
|
||||
the global error handler.
|
||||
|
||||
## Usage from consumer perspective:
|
||||
|
||||
Enable Doctrine deprecations to be sent to a PSR3 logger:
|
||||
|
||||
```php
|
||||
\Doctrine\Deprecations\Deprecation::enableWithPsrLogger($logger);
|
||||
```
|
||||
|
||||
Enable Doctrine deprecations to be sent as `@trigger_error($message, E_USER_DEPRECATED)`
|
||||
messages by setting the `DOCTRINE_DEPRECATIONS` environment variable to `trigger`.
|
||||
Alternatively, call:
|
||||
|
||||
```php
|
||||
\Doctrine\Deprecations\Deprecation::enableWithTriggerError();
|
||||
```
|
||||
|
||||
If you only want to enable deprecation tracking, without logging or calling `trigger_error`
|
||||
then set the `DOCTRINE_DEPRECATIONS` environment variable to `track`.
|
||||
Alternatively, call:
|
||||
|
||||
```php
|
||||
\Doctrine\Deprecations\Deprecation::enableTrackingDeprecations();
|
||||
```
|
||||
|
||||
Tracking is enabled with all three modes and provides access to all triggered
|
||||
deprecations and their individual count:
|
||||
|
||||
```php
|
||||
$deprecations = \Doctrine\Deprecations\Deprecation::getTriggeredDeprecations();
|
||||
|
||||
foreach ($deprecations as $identifier => $count) {
|
||||
echo $identifier . " was triggered " . $count . " times\n";
|
||||
}
|
||||
```
|
||||
|
||||
### Suppressing Specific Deprecations
|
||||
|
||||
Disable triggering about specific deprecations:
|
||||
|
||||
```php
|
||||
\Doctrine\Deprecations\Deprecation::ignoreDeprecations("https://link/to/deprecations-description-identifier");
|
||||
```
|
||||
|
||||
Disable all deprecations from a package
|
||||
|
||||
```php
|
||||
\Doctrine\Deprecations\Deprecation::ignorePackage("doctrine/orm");
|
||||
```
|
||||
|
||||
### Other Operations
|
||||
|
||||
When used within PHPUnit or other tools that could collect multiple instances of the same deprecations
|
||||
the deduplication can be disabled:
|
||||
|
||||
```php
|
||||
\Doctrine\Deprecations\Deprecation::withoutDeduplication();
|
||||
```
|
||||
|
||||
Disable deprecation tracking again:
|
||||
|
||||
```php
|
||||
\Doctrine\Deprecations\Deprecation::disable();
|
||||
```
|
||||
|
||||
## Usage from a library/producer perspective:
|
||||
|
||||
When you want to unconditionally trigger a deprecation even when called
|
||||
from the library itself then the `trigger` method is the way to go:
|
||||
|
||||
```php
|
||||
\Doctrine\Deprecations\Deprecation::trigger(
|
||||
"doctrine/orm",
|
||||
"https://link/to/deprecations-description",
|
||||
"message"
|
||||
);
|
||||
```
|
||||
|
||||
If variable arguments are provided at the end, they are used with `sprintf` on
|
||||
the message.
|
||||
|
||||
```php
|
||||
\Doctrine\Deprecations\Deprecation::trigger(
|
||||
"doctrine/orm",
|
||||
"https://github.com/doctrine/orm/issue/1234",
|
||||
"message %s %d",
|
||||
"foo",
|
||||
1234
|
||||
);
|
||||
```
|
||||
|
||||
When you want to trigger a deprecation only when it is called by a function
|
||||
outside of the current package, but not trigger when the package itself is the cause,
|
||||
then use:
|
||||
|
||||
```php
|
||||
\Doctrine\Deprecations\Deprecation::triggerIfCalledFromOutside(
|
||||
"doctrine/orm",
|
||||
"https://link/to/deprecations-description",
|
||||
"message"
|
||||
);
|
||||
```
|
||||
|
||||
Based on the issue link each deprecation message is only triggered once per
|
||||
request.
|
||||
|
||||
A limited stacktrace is included in the deprecation message to find the
|
||||
offending location.
|
||||
|
||||
Note: A producer/library should never call `Deprecation::enableWith` methods
|
||||
and leave the decision how to handle deprecations to application and
|
||||
frameworks.
|
||||
|
||||
## Usage in PHPUnit tests
|
||||
|
||||
There is a `VerifyDeprecations` trait that you can use to make assertions on
|
||||
the occurrence of deprecations within a test.
|
||||
|
||||
```php
|
||||
use Doctrine\Deprecations\PHPUnit\VerifyDeprecations;
|
||||
|
||||
class MyTest extends TestCase
|
||||
{
|
||||
use VerifyDeprecations;
|
||||
|
||||
public function testSomethingDeprecation()
|
||||
{
|
||||
$this->expectDeprecationWithIdentifier('https://github.com/doctrine/orm/issue/1234');
|
||||
|
||||
triggerTheCodeWithDeprecation();
|
||||
}
|
||||
|
||||
public function testSomethingDeprecationFixed()
|
||||
{
|
||||
$this->expectNoDeprecationWithIdentifier('https://github.com/doctrine/orm/issue/1234');
|
||||
|
||||
triggerTheCodeWithoutDeprecation();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Displaying deprecations after running a PHPUnit test suite
|
||||
|
||||
It is possible to integrate this library with PHPUnit to display all
|
||||
deprecations triggered during the test suite execution.
|
||||
|
||||
```xml
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
|
||||
colors="true"
|
||||
bootstrap="vendor/autoload.php"
|
||||
displayDetailsOnTestsThatTriggerDeprecations="true"
|
||||
failOnDeprecation="true"
|
||||
>
|
||||
<!-- one attribute to display the deprecations, the other to fail the test suite -->
|
||||
|
||||
<php>
|
||||
<!-- ensures native PHP deprecations are used -->
|
||||
<server name="DOCTRINE_DEPRECATIONS" value="trigger"/>
|
||||
</php>
|
||||
|
||||
<!-- ensures the @ operator in @trigger_error is ignored -->
|
||||
<source ignoreSuppressionOfDeprecations="true">
|
||||
<include>
|
||||
<directory>src</directory>
|
||||
</include>
|
||||
</source>
|
||||
</phpunit>
|
||||
```
|
||||
|
||||
Note that you can still trigger Deprecations in your code, provided you use the
|
||||
`#[WithoutErrorHandler]` attribute to disable PHPUnit's error handler for tests
|
||||
that call it. Be wary that this will disable all error handling, meaning it
|
||||
will mask any warnings or errors that would otherwise be caught by PHPUnit.
|
||||
|
||||
At the moment, it is not possible to disable deduplication with an environment
|
||||
variable, but you can use a bootstrap file to achieve that:
|
||||
|
||||
```php
|
||||
// tests/bootstrap.php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
use Doctrine\Deprecations\Deprecation;
|
||||
|
||||
Deprecation::withoutDeduplication();
|
||||
```
|
||||
|
||||
Then, reference that file in your PHPUnit configuration:
|
||||
|
||||
```xml
|
||||
<phpunit …
|
||||
bootstrap="tests/bootstrap.php"
|
||||
…
|
||||
>
|
||||
…
|
||||
</phpunit>
|
||||
```
|
||||
|
||||
## What is a deprecation identifier?
|
||||
|
||||
An identifier for deprecations is just a link to any resource, most often a
|
||||
Github Issue or Pull Request explaining the deprecation and potentially its
|
||||
alternative.
|
||||
39
vendor/doctrine/deprecations/composer.json
vendored
Normal file
39
vendor/doctrine/deprecations/composer.json
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
{
|
||||
"name": "doctrine/deprecations",
|
||||
"description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.",
|
||||
"license": "MIT",
|
||||
"type": "library",
|
||||
"homepage": "https://www.doctrine-project.org/",
|
||||
"require": {
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^9 || ^12 || ^13",
|
||||
"phpstan/phpstan": "1.4.10 || 2.1.11",
|
||||
"phpstan/phpstan-phpunit": "^1.0 || ^2",
|
||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12",
|
||||
"psr/log": "^1 || ^2 || ^3"
|
||||
},
|
||||
"conflict": {
|
||||
"phpunit/phpunit": "<=7.5 || >=13"
|
||||
},
|
||||
"suggest": {
|
||||
"psr/log": "Allows logging deprecations via PSR-3 logger implementation"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Deprecations\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"DeprecationTests\\": "test_fixtures/src",
|
||||
"Doctrine\\Foo\\": "test_fixtures/vendor/doctrine/foo"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": true
|
||||
}
|
||||
}
|
||||
}
|
||||
309
vendor/doctrine/deprecations/src/Deprecation.php
vendored
Normal file
309
vendor/doctrine/deprecations/src/Deprecation.php
vendored
Normal file
@ -0,0 +1,309 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Deprecations;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
use function array_key_exists;
|
||||
use function array_reduce;
|
||||
use function assert;
|
||||
use function debug_backtrace;
|
||||
use function sprintf;
|
||||
use function str_replace;
|
||||
use function strpos;
|
||||
use function strrpos;
|
||||
use function substr;
|
||||
use function trigger_error;
|
||||
|
||||
use const DEBUG_BACKTRACE_IGNORE_ARGS;
|
||||
use const DIRECTORY_SEPARATOR;
|
||||
use const E_USER_DEPRECATED;
|
||||
|
||||
/**
|
||||
* Manages Deprecation logging in different ways.
|
||||
*
|
||||
* By default triggered exceptions are not logged.
|
||||
*
|
||||
* To enable different deprecation logging mechanisms you can call the
|
||||
* following methods:
|
||||
*
|
||||
* - Minimal collection of deprecations via getTriggeredDeprecations()
|
||||
* \Doctrine\Deprecations\Deprecation::enableTrackingDeprecations();
|
||||
*
|
||||
* - Uses @trigger_error with E_USER_DEPRECATED
|
||||
* \Doctrine\Deprecations\Deprecation::enableWithTriggerError();
|
||||
*
|
||||
* - Sends deprecation messages via a PSR-3 logger
|
||||
* \Doctrine\Deprecations\Deprecation::enableWithPsrLogger($logger);
|
||||
*
|
||||
* Packages that trigger deprecations should use the `trigger()` or
|
||||
* `triggerIfCalledFromOutside()` methods.
|
||||
*/
|
||||
class Deprecation
|
||||
{
|
||||
private const TYPE_NONE = 0;
|
||||
private const TYPE_TRACK_DEPRECATIONS = 1;
|
||||
private const TYPE_TRIGGER_ERROR = 2;
|
||||
private const TYPE_PSR_LOGGER = 4;
|
||||
|
||||
/** @var int-mask-of<self::TYPE_*>|null */
|
||||
private static $type;
|
||||
|
||||
/** @var LoggerInterface|null */
|
||||
private static $logger;
|
||||
|
||||
/** @var array<string,bool> */
|
||||
private static $ignoredPackages = [];
|
||||
|
||||
/** @var array<string,int> */
|
||||
private static $triggeredDeprecations = [];
|
||||
|
||||
/** @var array<string,bool> */
|
||||
private static $ignoredLinks = [];
|
||||
|
||||
/** @var bool */
|
||||
private static $deduplication = true;
|
||||
|
||||
/**
|
||||
* Trigger a deprecation for the given package and identfier.
|
||||
*
|
||||
* The link should point to a Github issue or Wiki entry detailing the
|
||||
* deprecation. It is additionally used to de-duplicate the trigger of the
|
||||
* same deprecation during a request.
|
||||
*
|
||||
* @param float|int|string $args
|
||||
*/
|
||||
public static function trigger(string $package, string $link, string $message, ...$args): void
|
||||
{
|
||||
$type = self::$type ?? self::getTypeFromEnv();
|
||||
|
||||
if ($type === self::TYPE_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset(self::$ignoredLinks[$link])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (array_key_exists($link, self::$triggeredDeprecations)) {
|
||||
self::$triggeredDeprecations[$link]++;
|
||||
} else {
|
||||
self::$triggeredDeprecations[$link] = 1;
|
||||
}
|
||||
|
||||
if (self::$deduplication === true && self::$triggeredDeprecations[$link] > 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset(self::$ignoredPackages[$package])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
|
||||
|
||||
$message = sprintf($message, ...$args);
|
||||
|
||||
self::delegateTriggerToBackend($message, $backtrace, $link, $package);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger a deprecation for the given package and identifier when called from outside.
|
||||
*
|
||||
* "Outside" means we assume that $package is currently installed as a
|
||||
* dependency and the caller is not a file in that package. When $package
|
||||
* is installed as a root package then deprecations triggered from the
|
||||
* tests folder are also considered "outside".
|
||||
*
|
||||
* This deprecation method assumes that you are using Composer to install
|
||||
* the dependency and are using the default /vendor/ folder and not a
|
||||
* Composer plugin to change the install location. The assumption is also
|
||||
* that $package is the exact composer packge name.
|
||||
*
|
||||
* Compared to {@link trigger()} this method causes some overhead when
|
||||
* deprecation tracking is enabled even during deduplication, because it
|
||||
* needs to call {@link debug_backtrace()}
|
||||
*
|
||||
* @param float|int|string $args
|
||||
*/
|
||||
public static function triggerIfCalledFromOutside(string $package, string $link, string $message, ...$args): void
|
||||
{
|
||||
$type = self::$type ?? self::getTypeFromEnv();
|
||||
|
||||
if ($type === self::TYPE_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
|
||||
|
||||
// first check that the caller is not from a tests folder, in which case we always let deprecations pass
|
||||
if (isset($backtrace[1]['file'], $backtrace[0]['file']) && strpos($backtrace[1]['file'], DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR) === false) {
|
||||
$path = DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $package) . DIRECTORY_SEPARATOR;
|
||||
|
||||
if (strpos($backtrace[0]['file'], $path) === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (strpos($backtrace[1]['file'], $path) !== false) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset(self::$ignoredLinks[$link])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (array_key_exists($link, self::$triggeredDeprecations)) {
|
||||
self::$triggeredDeprecations[$link]++;
|
||||
} else {
|
||||
self::$triggeredDeprecations[$link] = 1;
|
||||
}
|
||||
|
||||
if (self::$deduplication === true && self::$triggeredDeprecations[$link] > 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset(self::$ignoredPackages[$package])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$message = sprintf($message, ...$args);
|
||||
|
||||
self::delegateTriggerToBackend($message, $backtrace, $link, $package);
|
||||
}
|
||||
|
||||
/** @param list<array{function: string, line?: int, file?: string, class?: class-string, type?: string, args?: mixed[], object?: object}> $backtrace */
|
||||
private static function delegateTriggerToBackend(string $message, array $backtrace, string $link, string $package): void
|
||||
{
|
||||
$type = self::$type ?? self::getTypeFromEnv();
|
||||
|
||||
if (($type & self::TYPE_PSR_LOGGER) > 0) {
|
||||
$context = [
|
||||
'file' => $backtrace[0]['file'] ?? null,
|
||||
'line' => $backtrace[0]['line'] ?? null,
|
||||
'package' => $package,
|
||||
'link' => $link,
|
||||
];
|
||||
|
||||
assert(self::$logger !== null);
|
||||
|
||||
self::$logger->notice($message, $context);
|
||||
}
|
||||
|
||||
if (! (($type & self::TYPE_TRIGGER_ERROR) > 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$message .= sprintf(
|
||||
' (%s:%d called by %s:%d, %s, package %s)',
|
||||
self::basename($backtrace[0]['file'] ?? 'native code'),
|
||||
$backtrace[0]['line'] ?? 0,
|
||||
self::basename($backtrace[1]['file'] ?? 'native code'),
|
||||
$backtrace[1]['line'] ?? 0,
|
||||
$link,
|
||||
$package
|
||||
);
|
||||
|
||||
@trigger_error($message, E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
/**
|
||||
* A non-local-aware version of PHPs basename function.
|
||||
*/
|
||||
private static function basename(string $filename): string
|
||||
{
|
||||
$pos = strrpos($filename, DIRECTORY_SEPARATOR);
|
||||
|
||||
if ($pos === false) {
|
||||
return $filename;
|
||||
}
|
||||
|
||||
return substr($filename, $pos + 1);
|
||||
}
|
||||
|
||||
public static function enableTrackingDeprecations(): void
|
||||
{
|
||||
self::$type = self::$type ?? self::getTypeFromEnv();
|
||||
self::$type |= self::TYPE_TRACK_DEPRECATIONS;
|
||||
}
|
||||
|
||||
public static function enableWithTriggerError(): void
|
||||
{
|
||||
self::$type = self::$type ?? self::getTypeFromEnv();
|
||||
self::$type |= self::TYPE_TRIGGER_ERROR;
|
||||
}
|
||||
|
||||
public static function enableWithPsrLogger(LoggerInterface $logger): void
|
||||
{
|
||||
self::$type = self::$type ?? self::getTypeFromEnv();
|
||||
self::$type |= self::TYPE_PSR_LOGGER;
|
||||
self::$logger = $logger;
|
||||
}
|
||||
|
||||
public static function withoutDeduplication(): void
|
||||
{
|
||||
self::$deduplication = false;
|
||||
}
|
||||
|
||||
public static function disable(): void
|
||||
{
|
||||
self::$type = self::TYPE_NONE;
|
||||
self::$logger = null;
|
||||
self::$deduplication = true;
|
||||
self::$ignoredLinks = [];
|
||||
|
||||
foreach (self::$triggeredDeprecations as $link => $count) {
|
||||
self::$triggeredDeprecations[$link] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static function ignorePackage(string $packageName): void
|
||||
{
|
||||
self::$ignoredPackages[$packageName] = true;
|
||||
}
|
||||
|
||||
public static function ignoreDeprecations(string ...$links): void
|
||||
{
|
||||
foreach ($links as $link) {
|
||||
self::$ignoredLinks[$link] = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static function getUniqueTriggeredDeprecationsCount(): int
|
||||
{
|
||||
return array_reduce(self::$triggeredDeprecations, static function (int $carry, int $count) {
|
||||
return $carry + $count;
|
||||
}, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns each triggered deprecation link identifier and the amount of occurrences.
|
||||
*
|
||||
* @return array<string,int>
|
||||
*/
|
||||
public static function getTriggeredDeprecations(): array
|
||||
{
|
||||
return self::$triggeredDeprecations;
|
||||
}
|
||||
|
||||
/** @return int-mask-of<self::TYPE_*> */
|
||||
private static function getTypeFromEnv(): int
|
||||
{
|
||||
switch ($_SERVER['DOCTRINE_DEPRECATIONS'] ?? $_ENV['DOCTRINE_DEPRECATIONS'] ?? null) {
|
||||
case 'trigger':
|
||||
self::$type = self::TYPE_TRIGGER_ERROR;
|
||||
break;
|
||||
|
||||
case 'track':
|
||||
self::$type = self::TYPE_TRACK_DEPRECATIONS;
|
||||
break;
|
||||
|
||||
default:
|
||||
self::$type = self::TYPE_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
return self::$type;
|
||||
}
|
||||
}
|
||||
66
vendor/doctrine/deprecations/src/PHPUnit/VerifyDeprecations.php
vendored
Normal file
66
vendor/doctrine/deprecations/src/PHPUnit/VerifyDeprecations.php
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Deprecations\PHPUnit;
|
||||
|
||||
use Doctrine\Deprecations\Deprecation;
|
||||
use PHPUnit\Framework\Attributes\After;
|
||||
use PHPUnit\Framework\Attributes\Before;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
trait VerifyDeprecations
|
||||
{
|
||||
/** @var array<string,int> */
|
||||
private $doctrineDeprecationsExpectations = [];
|
||||
|
||||
/** @var array<string,int> */
|
||||
private $doctrineNoDeprecationsExpectations = [];
|
||||
|
||||
public function expectDeprecationWithIdentifier(string $identifier): void
|
||||
{
|
||||
$this->doctrineDeprecationsExpectations[$identifier] = Deprecation::getTriggeredDeprecations()[$identifier] ?? 0;
|
||||
}
|
||||
|
||||
public function expectNoDeprecationWithIdentifier(string $identifier): void
|
||||
{
|
||||
$this->doctrineNoDeprecationsExpectations[$identifier] = Deprecation::getTriggeredDeprecations()[$identifier] ?? 0;
|
||||
}
|
||||
|
||||
/** @before */
|
||||
#[Before]
|
||||
public function enableDeprecationTracking(): void
|
||||
{
|
||||
Deprecation::enableTrackingDeprecations();
|
||||
}
|
||||
|
||||
/** @after */
|
||||
#[After]
|
||||
public function verifyDeprecationsAreTriggered(): void
|
||||
{
|
||||
foreach ($this->doctrineDeprecationsExpectations as $identifier => $expectation) {
|
||||
$actualCount = Deprecation::getTriggeredDeprecations()[$identifier] ?? 0;
|
||||
|
||||
$this->assertTrue(
|
||||
$actualCount > $expectation,
|
||||
sprintf(
|
||||
"Expected deprecation with identifier '%s' was not triggered by code executed in test.",
|
||||
$identifier
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($this->doctrineNoDeprecationsExpectations as $identifier => $expectation) {
|
||||
$actualCount = Deprecation::getTriggeredDeprecations()[$identifier] ?? 0;
|
||||
|
||||
$this->assertTrue(
|
||||
$actualCount === $expectation,
|
||||
sprintf(
|
||||
"Expected deprecation with identifier '%s' was triggered by code executed in test, but expected not to.",
|
||||
$identifier
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
19
vendor/doctrine/event-manager/LICENSE
vendored
Normal file
19
vendor/doctrine/event-manager/LICENSE
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2006-2015 Doctrine Project
|
||||
|
||||
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.
|
||||
13
vendor/doctrine/event-manager/README.md
vendored
Normal file
13
vendor/doctrine/event-manager/README.md
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
# Doctrine Event Manager
|
||||
|
||||
[](https://github.com/doctrine/event-manager/actions)
|
||||
[](https://scrutinizer-ci.com/g/doctrine/event-manager/?branch=1.2.x)
|
||||
[](https://scrutinizer-ci.com/g/doctrine/event-manager/?branch=1.2.x)
|
||||
|
||||
The Doctrine Event Manager is a library that provides a simple event system.
|
||||
|
||||
## More resources:
|
||||
|
||||
* [Website](https://www.doctrine-project.org/)
|
||||
* [Documentation](https://www.doctrine-project.org/projects/doctrine-event-manager/en/latest/)
|
||||
* [Downloads](https://github.com/doctrine/event-manager/releases)
|
||||
15
vendor/doctrine/event-manager/UPGRADE.md
vendored
Normal file
15
vendor/doctrine/event-manager/UPGRADE.md
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
# Upgrade to 2.0
|
||||
|
||||
## Made the `$event` parameter of `EventManager::getListeners()` mandatory
|
||||
|
||||
When calling `EventManager::getListeners()` you need to specify the event that
|
||||
you want to fetch the listeners for. Call `getAllListeners()` instead if you
|
||||
want to access the listeners of all events.
|
||||
|
||||
# Upgrade to 1.2
|
||||
|
||||
## Deprecated calling `EventManager::getListeners()` without an event name
|
||||
|
||||
When calling `EventManager::getListeners()` without an event name, all
|
||||
listeners were returned, keyed by event name. A new method `getAllListeners()`
|
||||
has been added to provide this functionality. It should be used instead.
|
||||
68
vendor/doctrine/event-manager/composer.json
vendored
Normal file
68
vendor/doctrine/event-manager/composer.json
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
{
|
||||
"name": "doctrine/event-manager",
|
||||
"description": "The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.",
|
||||
"license": "MIT",
|
||||
"type": "library",
|
||||
"keywords": [
|
||||
"events",
|
||||
"event",
|
||||
"event dispatcher",
|
||||
"event manager",
|
||||
"event system"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Guilherme Blanco",
|
||||
"email": "guilhermeblanco@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Roman Borschel",
|
||||
"email": "roman@code-factory.org"
|
||||
},
|
||||
{
|
||||
"name": "Benjamin Eberlei",
|
||||
"email": "kontakt@beberlei.de"
|
||||
},
|
||||
{
|
||||
"name": "Jonathan Wage",
|
||||
"email": "jonwage@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Johannes Schmitt",
|
||||
"email": "schmittjoh@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Marco Pivetta",
|
||||
"email": "ocramius@gmail.com"
|
||||
}
|
||||
],
|
||||
"homepage": "https://www.doctrine-project.org/projects/event-manager.html",
|
||||
"require": {
|
||||
"php": "^8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^12",
|
||||
"phpstan/phpstan": "^1.8.8",
|
||||
"phpunit/phpunit": "^10.5",
|
||||
"vimeo/psalm": "^5.24"
|
||||
},
|
||||
"conflict": {
|
||||
"doctrine/common": "<2.9"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Common\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Tests\\Common\\": "tests"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": true
|
||||
},
|
||||
"sort-packages": true
|
||||
}
|
||||
}
|
||||
8
vendor/doctrine/event-manager/psalm-baseline.xml
vendored
Normal file
8
vendor/doctrine/event-manager/psalm-baseline.xml
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<files psalm-version="5.24.0@462c80e31c34e58cc4f750c656be3927e80e550e">
|
||||
<file src="src/EventManager.php">
|
||||
<RiskyTruthyFalsyComparison>
|
||||
<code><![CDATA[empty($this->listeners[$event])]]></code>
|
||||
</RiskyTruthyFalsyComparison>
|
||||
</file>
|
||||
</files>
|
||||
37
vendor/doctrine/event-manager/src/EventArgs.php
vendored
Normal file
37
vendor/doctrine/event-manager/src/EventArgs.php
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Common;
|
||||
|
||||
/**
|
||||
* EventArgs is the base class for classes containing event data.
|
||||
*
|
||||
* This class contains no event data. It is used by events that do not pass state
|
||||
* information to an event handler when an event is raised. The single empty EventArgs
|
||||
* instance can be obtained through {@link getEmptyInstance}.
|
||||
*/
|
||||
class EventArgs
|
||||
{
|
||||
/**
|
||||
* Single instance of EventArgs.
|
||||
*/
|
||||
private static EventArgs|null $emptyEventArgsInstance = null;
|
||||
|
||||
/**
|
||||
* Gets the single, empty and immutable EventArgs instance.
|
||||
*
|
||||
* This instance will be used when events are dispatched without any parameter,
|
||||
* like this: EventManager::dispatchEvent('eventname');
|
||||
*
|
||||
* The benefit from this is that only one empty instance is instantiated and shared
|
||||
* (otherwise there would be instances for every dispatched in the abovementioned form).
|
||||
*
|
||||
* @link https://msdn.microsoft.com/en-us/library/system.eventargs.aspx
|
||||
* @see EventManager::dispatchEvent
|
||||
*/
|
||||
public static function getEmptyInstance(): EventArgs
|
||||
{
|
||||
return self::$emptyEventArgsInstance ??= new EventArgs();
|
||||
}
|
||||
}
|
||||
129
vendor/doctrine/event-manager/src/EventManager.php
vendored
Normal file
129
vendor/doctrine/event-manager/src/EventManager.php
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Common;
|
||||
|
||||
use function spl_object_hash;
|
||||
|
||||
/**
|
||||
* The EventManager is the central point of Doctrine's event listener system.
|
||||
* Listeners are registered on the manager and events are dispatched through the
|
||||
* manager.
|
||||
*/
|
||||
class EventManager
|
||||
{
|
||||
/**
|
||||
* Map of registered listeners.
|
||||
* <event> => <listeners>
|
||||
*
|
||||
* @var array<string, object[]>
|
||||
*/
|
||||
private array $listeners = [];
|
||||
|
||||
/**
|
||||
* Dispatches an event to all registered listeners.
|
||||
*
|
||||
* @param string $eventName The name of the event to dispatch. The name of the event is
|
||||
* the name of the method that is invoked on listeners.
|
||||
* @param EventArgs|null $eventArgs The event arguments to pass to the event handlers/listeners.
|
||||
* If not supplied, the single empty EventArgs instance is used.
|
||||
*/
|
||||
public function dispatchEvent(string $eventName, EventArgs|null $eventArgs = null): void
|
||||
{
|
||||
if (! isset($this->listeners[$eventName])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$eventArgs ??= EventArgs::getEmptyInstance();
|
||||
|
||||
foreach ($this->listeners[$eventName] as $listener) {
|
||||
$listener->$eventName($eventArgs);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the listeners of a specific event.
|
||||
*
|
||||
* @param string $event The name of the event.
|
||||
*
|
||||
* @return object[]
|
||||
*/
|
||||
public function getListeners(string $event): array
|
||||
{
|
||||
return $this->listeners[$event] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all listeners keyed by event name.
|
||||
*
|
||||
* @return array<string, object[]> The event listeners for the specified event, or all event listeners.
|
||||
*/
|
||||
public function getAllListeners(): array
|
||||
{
|
||||
return $this->listeners;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether an event has any registered listeners.
|
||||
*/
|
||||
public function hasListeners(string $event): bool
|
||||
{
|
||||
return ! empty($this->listeners[$event]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an event listener that listens on the specified events.
|
||||
*
|
||||
* @param string|string[] $events The event(s) to listen on.
|
||||
* @param object $listener The listener object.
|
||||
*/
|
||||
public function addEventListener(string|array $events, object $listener): void
|
||||
{
|
||||
// Picks the hash code related to that listener
|
||||
$hash = spl_object_hash($listener);
|
||||
|
||||
foreach ((array) $events as $event) {
|
||||
// Overrides listener if a previous one was associated already
|
||||
// Prevents duplicate listeners on same event (same instance only)
|
||||
$this->listeners[$event][$hash] = $listener;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an event listener from the specified events.
|
||||
*
|
||||
* @param string|string[] $events
|
||||
*/
|
||||
public function removeEventListener(string|array $events, object $listener): void
|
||||
{
|
||||
// Picks the hash code related to that listener
|
||||
$hash = spl_object_hash($listener);
|
||||
|
||||
foreach ((array) $events as $event) {
|
||||
unset($this->listeners[$event][$hash]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an EventSubscriber.
|
||||
*
|
||||
* The subscriber is asked for all the events it is interested in and added
|
||||
* as a listener for these events.
|
||||
*/
|
||||
public function addEventSubscriber(EventSubscriber $subscriber): void
|
||||
{
|
||||
$this->addEventListener($subscriber->getSubscribedEvents(), $subscriber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an EventSubscriber.
|
||||
*
|
||||
* The subscriber is asked for all the events it is interested in and removed
|
||||
* as a listener for these events.
|
||||
*/
|
||||
public function removeEventSubscriber(EventSubscriber $subscriber): void
|
||||
{
|
||||
$this->removeEventListener($subscriber->getSubscribedEvents(), $subscriber);
|
||||
}
|
||||
}
|
||||
21
vendor/doctrine/event-manager/src/EventSubscriber.php
vendored
Normal file
21
vendor/doctrine/event-manager/src/EventSubscriber.php
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Common;
|
||||
|
||||
/**
|
||||
* An EventSubscriber knows what events it is interested in.
|
||||
* If an EventSubscriber is added to an EventManager, the manager invokes
|
||||
* {@link getSubscribedEvents} and registers the subscriber as a listener for all
|
||||
* returned events.
|
||||
*/
|
||||
interface EventSubscriber
|
||||
{
|
||||
/**
|
||||
* Returns an array of events this subscriber wants to listen to.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getSubscribedEvents();
|
||||
}
|
||||
19
vendor/doctrine/lexer/LICENSE
vendored
Normal file
19
vendor/doctrine/lexer/LICENSE
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2006-2018 Doctrine Project
|
||||
|
||||
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.
|
||||
9
vendor/doctrine/lexer/README.md
vendored
Normal file
9
vendor/doctrine/lexer/README.md
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
# Doctrine Lexer
|
||||
|
||||
[](https://github.com/doctrine/lexer/actions)
|
||||
|
||||
Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.
|
||||
|
||||
This lexer is used in Doctrine Annotations and in Doctrine ORM (DQL).
|
||||
|
||||
https://www.doctrine-project.org/projects/lexer.html
|
||||
14
vendor/doctrine/lexer/UPGRADE.md
vendored
Normal file
14
vendor/doctrine/lexer/UPGRADE.md
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
Note about upgrading: Doctrine uses static and runtime mechanisms to raise
|
||||
awareness about deprecated code.
|
||||
|
||||
- Use of `@deprecated` docblock that is detected by IDEs (like PHPStorm) or
|
||||
Static Analysis tools (like Psalm, phpstan)
|
||||
- Use of our low-overhead runtime deprecation API, details:
|
||||
https://github.com/doctrine/deprecations/
|
||||
|
||||
# Upgrade to 2.0.0
|
||||
|
||||
`AbstractLexer::glimpse()` and `AbstractLexer::peek()` now return
|
||||
instances of `Doctrine\Common\Lexer\Token`, which is an array-like class
|
||||
Using it as an array is deprecated in favor of using properties of that class.
|
||||
Using `count()` on it is deprecated with no replacement.
|
||||
56
vendor/doctrine/lexer/composer.json
vendored
Normal file
56
vendor/doctrine/lexer/composer.json
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
{
|
||||
"name": "doctrine/lexer",
|
||||
"description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.",
|
||||
"license": "MIT",
|
||||
"type": "library",
|
||||
"keywords": [
|
||||
"php",
|
||||
"parser",
|
||||
"lexer",
|
||||
"annotations",
|
||||
"docblock"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Guilherme Blanco",
|
||||
"email": "guilhermeblanco@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Roman Borschel",
|
||||
"email": "roman@code-factory.org"
|
||||
},
|
||||
{
|
||||
"name": "Johannes Schmitt",
|
||||
"email": "schmittjoh@gmail.com"
|
||||
}
|
||||
],
|
||||
"homepage": "https://www.doctrine-project.org/projects/lexer.html",
|
||||
"require": {
|
||||
"php": "^7.1 || ^8.0",
|
||||
"doctrine/deprecations": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^9 || ^12",
|
||||
"phpstan/phpstan": "^1.3",
|
||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.6",
|
||||
"psalm/plugin-phpunit": "^0.18.3",
|
||||
"vimeo/psalm": "^4.11 || ^5.21"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Common\\Lexer\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Tests\\Common\\Lexer\\": "tests"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"composer/package-versions-deprecated": true,
|
||||
"dealerdirect/phpcodesniffer-composer-installer": true
|
||||
},
|
||||
"sort-packages": true
|
||||
}
|
||||
}
|
||||
342
vendor/doctrine/lexer/src/AbstractLexer.php
vendored
Normal file
342
vendor/doctrine/lexer/src/AbstractLexer.php
vendored
Normal file
@ -0,0 +1,342 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Common\Lexer;
|
||||
|
||||
use ReflectionClass;
|
||||
use UnitEnum;
|
||||
|
||||
use function get_class;
|
||||
use function implode;
|
||||
use function preg_split;
|
||||
use function sprintf;
|
||||
use function substr;
|
||||
|
||||
use const PREG_SPLIT_DELIM_CAPTURE;
|
||||
use const PREG_SPLIT_NO_EMPTY;
|
||||
use const PREG_SPLIT_OFFSET_CAPTURE;
|
||||
|
||||
/**
|
||||
* Base class for writing simple lexers, i.e. for creating small DSLs.
|
||||
*
|
||||
* @template T of UnitEnum|string|int
|
||||
* @template V of string|int
|
||||
*/
|
||||
abstract class AbstractLexer
|
||||
{
|
||||
/**
|
||||
* Lexer original input string.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $input;
|
||||
|
||||
/**
|
||||
* Array of scanned tokens.
|
||||
*
|
||||
* @var list<Token<T, V>>
|
||||
*/
|
||||
private $tokens = [];
|
||||
|
||||
/**
|
||||
* Current lexer position in input string.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $position = 0;
|
||||
|
||||
/**
|
||||
* Current peek of current lexer position.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $peek = 0;
|
||||
|
||||
/**
|
||||
* The next token in the input.
|
||||
*
|
||||
* @var Token<T, V>|null
|
||||
*/
|
||||
public $lookahead;
|
||||
|
||||
/**
|
||||
* The last matched/seen token.
|
||||
*
|
||||
* @var Token<T, V>|null
|
||||
*/
|
||||
public $token;
|
||||
|
||||
/**
|
||||
* Composed regex for input parsing.
|
||||
*
|
||||
* @var non-empty-string|null
|
||||
*/
|
||||
private $regex;
|
||||
|
||||
/**
|
||||
* Sets the input data to be tokenized.
|
||||
*
|
||||
* The Lexer is immediately reset and the new input tokenized.
|
||||
* Any unprocessed tokens from any previous input are lost.
|
||||
*
|
||||
* @param string $input The input to be tokenized.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setInput($input)
|
||||
{
|
||||
$this->input = $input;
|
||||
$this->tokens = [];
|
||||
|
||||
$this->reset();
|
||||
$this->scan($input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the lexer.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
$this->lookahead = null;
|
||||
$this->token = null;
|
||||
$this->peek = 0;
|
||||
$this->position = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the peek pointer to 0.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function resetPeek()
|
||||
{
|
||||
$this->peek = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the lexer position on the input to the given position.
|
||||
*
|
||||
* @param int $position Position to place the lexical scanner.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function resetPosition($position = 0)
|
||||
{
|
||||
$this->position = $position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the original lexer's input until a given position.
|
||||
*
|
||||
* @param int $position
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getInputUntilPosition($position)
|
||||
{
|
||||
return substr($this->input, 0, $position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a given token matches the current lookahead.
|
||||
*
|
||||
* @param T $type
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @psalm-assert-if-true !=null $this->lookahead
|
||||
*/
|
||||
public function isNextToken($type)
|
||||
{
|
||||
return $this->lookahead !== null && $this->lookahead->isA($type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether any of the given tokens matches the current lookahead.
|
||||
*
|
||||
* @param list<T> $types
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @psalm-assert-if-true !=null $this->lookahead
|
||||
*/
|
||||
public function isNextTokenAny(array $types)
|
||||
{
|
||||
return $this->lookahead !== null && $this->lookahead->isA(...$types);
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves to the next token in the input string.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @psalm-assert-if-true !null $this->lookahead
|
||||
*/
|
||||
public function moveNext()
|
||||
{
|
||||
$this->peek = 0;
|
||||
$this->token = $this->lookahead;
|
||||
$this->lookahead = isset($this->tokens[$this->position])
|
||||
? $this->tokens[$this->position++] : null;
|
||||
|
||||
return $this->lookahead !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the lexer to skip input tokens until it sees a token with the given value.
|
||||
*
|
||||
* @param T $type The token type to skip until.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function skipUntil($type)
|
||||
{
|
||||
while ($this->lookahead !== null && ! $this->lookahead->isA($type)) {
|
||||
$this->moveNext();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if given value is identical to the given token.
|
||||
*
|
||||
* @param string $value
|
||||
* @param int|string $token
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isA($value, $token)
|
||||
{
|
||||
return $this->getType($value) === $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the lookahead token forward.
|
||||
*
|
||||
* @return Token<T, V>|null The next token or NULL if there are no more tokens ahead.
|
||||
*/
|
||||
public function peek()
|
||||
{
|
||||
if (isset($this->tokens[$this->position + $this->peek])) {
|
||||
return $this->tokens[$this->position + $this->peek++];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Peeks at the next token, returns it and immediately resets the peek.
|
||||
*
|
||||
* @return Token<T, V>|null The next token or NULL if there are no more tokens ahead.
|
||||
*/
|
||||
public function glimpse()
|
||||
{
|
||||
$peek = $this->peek();
|
||||
$this->peek = 0;
|
||||
|
||||
return $peek;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans the input string for tokens.
|
||||
*
|
||||
* @param string $input A query string.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function scan($input)
|
||||
{
|
||||
if (! isset($this->regex)) {
|
||||
$this->regex = sprintf(
|
||||
'/(%s)|%s/%s',
|
||||
implode(')|(', $this->getCatchablePatterns()),
|
||||
implode('|', $this->getNonCatchablePatterns()),
|
||||
$this->getModifiers()
|
||||
);
|
||||
}
|
||||
|
||||
$flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE;
|
||||
$matches = preg_split($this->regex, $input, -1, $flags);
|
||||
|
||||
if ($matches === false) {
|
||||
// Work around https://bugs.php.net/78122
|
||||
$matches = [[$input, 0]];
|
||||
}
|
||||
|
||||
foreach ($matches as $match) {
|
||||
// Must remain before 'value' assignment since it can change content
|
||||
$firstMatch = $match[0];
|
||||
$type = $this->getType($firstMatch);
|
||||
|
||||
$this->tokens[] = new Token(
|
||||
$firstMatch,
|
||||
$type,
|
||||
$match[1]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the literal for a given token.
|
||||
*
|
||||
* @param T $token
|
||||
*
|
||||
* @return int|string
|
||||
*/
|
||||
public function getLiteral($token)
|
||||
{
|
||||
if ($token instanceof UnitEnum) {
|
||||
return get_class($token) . '::' . $token->name;
|
||||
}
|
||||
|
||||
$className = static::class;
|
||||
|
||||
$reflClass = new ReflectionClass($className);
|
||||
$constants = $reflClass->getConstants();
|
||||
|
||||
foreach ($constants as $name => $value) {
|
||||
if ($value === $token) {
|
||||
return $className . '::' . $name;
|
||||
}
|
||||
}
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Regex modifiers
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getModifiers()
|
||||
{
|
||||
return 'iu';
|
||||
}
|
||||
|
||||
/**
|
||||
* Lexical catchable patterns.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
abstract protected function getCatchablePatterns();
|
||||
|
||||
/**
|
||||
* Lexical non-catchable patterns.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
abstract protected function getNonCatchablePatterns();
|
||||
|
||||
/**
|
||||
* Retrieve token type. Also processes the token value if necessary.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return T|null
|
||||
*
|
||||
* @param-out V $value
|
||||
*/
|
||||
abstract protected function getType(&$value);
|
||||
}
|
||||
145
vendor/doctrine/lexer/src/Token.php
vendored
Normal file
145
vendor/doctrine/lexer/src/Token.php
vendored
Normal file
@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Common\Lexer;
|
||||
|
||||
use ArrayAccess;
|
||||
use Doctrine\Deprecations\Deprecation;
|
||||
use ReturnTypeWillChange;
|
||||
use UnitEnum;
|
||||
|
||||
use function in_array;
|
||||
|
||||
/**
|
||||
* @template T of UnitEnum|string|int
|
||||
* @template V of string|int
|
||||
* @implements ArrayAccess<string,mixed>
|
||||
*/
|
||||
final class Token implements ArrayAccess
|
||||
{
|
||||
/**
|
||||
* The string value of the token in the input string
|
||||
*
|
||||
* @readonly
|
||||
* @var V
|
||||
*/
|
||||
public $value;
|
||||
|
||||
/**
|
||||
* The type of the token (identifier, numeric, string, input parameter, none)
|
||||
*
|
||||
* @readonly
|
||||
* @var T|null
|
||||
*/
|
||||
public $type;
|
||||
|
||||
/**
|
||||
* The position of the token in the input string
|
||||
*
|
||||
* @readonly
|
||||
* @var int
|
||||
*/
|
||||
public $position;
|
||||
|
||||
/**
|
||||
* @param V $value
|
||||
* @param T|null $type
|
||||
*/
|
||||
public function __construct($value, $type, int $position)
|
||||
{
|
||||
$this->value = $value;
|
||||
$this->type = $type;
|
||||
$this->position = $position;
|
||||
}
|
||||
|
||||
/** @param T ...$types */
|
||||
public function isA(...$types): bool
|
||||
{
|
||||
return in_array($this->type, $types, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use the value, type or position property instead
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function offsetExists($offset): bool
|
||||
{
|
||||
Deprecation::trigger(
|
||||
'doctrine/lexer',
|
||||
'https://github.com/doctrine/lexer/pull/79',
|
||||
'Accessing %s properties via ArrayAccess is deprecated, use the value, type or position property instead',
|
||||
self::class
|
||||
);
|
||||
|
||||
return in_array($offset, ['value', 'type', 'position'], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use the value, type or position property instead
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @param O $offset
|
||||
*
|
||||
* @return mixed
|
||||
* @psalm-return (
|
||||
* O is 'value'
|
||||
* ? V
|
||||
* : (
|
||||
* O is 'type'
|
||||
* ? T|null
|
||||
* : (
|
||||
* O is 'position'
|
||||
* ? int
|
||||
* : mixed
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* @template O of array-key
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
Deprecation::trigger(
|
||||
'doctrine/lexer',
|
||||
'https://github.com/doctrine/lexer/pull/79',
|
||||
'Accessing %s properties via ArrayAccess is deprecated, use the value, type or position property instead',
|
||||
self::class
|
||||
);
|
||||
|
||||
return $this->$offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated no replacement planned
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function offsetSet($offset, $value): void
|
||||
{
|
||||
Deprecation::trigger(
|
||||
'doctrine/lexer',
|
||||
'https://github.com/doctrine/lexer/pull/79',
|
||||
'Setting %s properties via ArrayAccess is deprecated',
|
||||
self::class
|
||||
);
|
||||
|
||||
$this->$offset = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated no replacement planned
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function offsetUnset($offset): void
|
||||
{
|
||||
Deprecation::trigger(
|
||||
'doctrine/lexer',
|
||||
'https://github.com/doctrine/lexer/pull/79',
|
||||
'Setting %s properties via ArrayAccess is deprecated',
|
||||
self::class
|
||||
);
|
||||
|
||||
$this->$offset = null;
|
||||
}
|
||||
}
|
||||
19
vendor/doctrine/persistence/LICENSE
vendored
Normal file
19
vendor/doctrine/persistence/LICENSE
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2006-2015 Doctrine Project
|
||||
|
||||
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.
|
||||
17
vendor/doctrine/persistence/README.md
vendored
Normal file
17
vendor/doctrine/persistence/README.md
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
# Doctrine Persistence
|
||||
|
||||
[![GitHub Actions][GA 4.0 image]][GA 4.0]
|
||||
[![Code Coverage][Coverage 4.0 image]][CodeCov 4.0]
|
||||
|
||||
The Doctrine Persistence project is a library that provides common abstractions for object mapper persistence.
|
||||
|
||||
## More resources:
|
||||
|
||||
* [Website](https://www.doctrine-project.org/)
|
||||
* [Documentation](https://www.doctrine-project.org/projects/doctrine-persistence/en/latest/index.html)
|
||||
* [Downloads](https://github.com/doctrine/persistence/releases)
|
||||
|
||||
[Coverage 4.0 image]: https://codecov.io/gh/doctrine/persistence/branch/4.0.x/graph/badge.svg
|
||||
[CodeCov 4.0]: https://codecov.io/gh/doctrine/persistence/branch/4.0.x
|
||||
[GA 4.0 image]: https://github.com/doctrine/persistence/actions/workflows/continuous-integration.yml/badge.svg?branch=4.0.x
|
||||
[GA 4.0]: https://github.com/doctrine/persistence/actions/workflows/continuous-integration.yml?branch=4.0.x
|
||||
195
vendor/doctrine/persistence/UPGRADE.md
vendored
Normal file
195
vendor/doctrine/persistence/UPGRADE.md
vendored
Normal file
@ -0,0 +1,195 @@
|
||||
Note about upgrading: Doctrine uses static and runtime mechanisms to raise
|
||||
awareness about deprecated code.
|
||||
|
||||
- Use of `@deprecated` docblock that is detected by IDEs (like PHPStorm) or
|
||||
Static Analysis tools (like Psalm, phpstan)
|
||||
- Use of our low-overhead runtime deprecation API, details:
|
||||
https://github.com/doctrine/deprecations/
|
||||
|
||||
# Upgrade to 4.0
|
||||
|
||||
## BC Break: Removed `StaticReflectionService`
|
||||
|
||||
The class `Doctrine\Persistence\Mapping\StaticReflectionService` is removed
|
||||
without replacement.
|
||||
|
||||
## BC Break: Narrowed `ReflectionService::getClass()` return type
|
||||
|
||||
The return type of `ReflectionService::getClass()` has been narrowed so that
|
||||
`null` is no longer a valid return value.
|
||||
|
||||
## BC Break: Added `ObjectManager::isUninitializedObject()`
|
||||
|
||||
Classes implementing `Doctrine\Persistence\ObjectManager` must implement this
|
||||
new method.
|
||||
|
||||
## BC Break: Added type declarations
|
||||
|
||||
The code base is now fully typed, meaning properties, parameters and return
|
||||
type declarations have been added to all types.
|
||||
|
||||
## BC Break: Dropped support for Common proxies
|
||||
|
||||
Proxy objects implementing the `Doctrine\Common\Proxy\Proxy` interface are not
|
||||
supported anymore. Implement `Doctrine\Persistence\Proxy` instead.
|
||||
|
||||
## BC Break: Removed deprecated ReflectionProperty overrides
|
||||
|
||||
Deprecated classes have been removed:
|
||||
|
||||
- `Doctrine\Persistence\Reflection\RuntimePublicReflectionProperty`
|
||||
- `Doctrine\Persistence\Reflection\TypedNoDefaultRuntimePublicReflectionProperty`
|
||||
|
||||
# Upgrade to 3.4
|
||||
|
||||
## Deprecated `StaticReflectionService`
|
||||
|
||||
The class `Doctrine\Persistence\Mapping\StaticReflectionService` is deprecated
|
||||
without replacement.
|
||||
|
||||
# Upgrade to 3.3
|
||||
|
||||
## Added method `ObjectManager::isUninitializedObject()`
|
||||
|
||||
Classes implementing `Doctrine\Persistence\ObjectManager` should implement the new
|
||||
method. This method will be added to the interface in 4.0.
|
||||
|
||||
# Upgrade to 3.1
|
||||
|
||||
## Deprecated `RuntimePublicReflectionProperty`
|
||||
|
||||
Use `RuntimeReflectionProperty` instead.
|
||||
|
||||
# Upgrade to 3.0
|
||||
|
||||
## Removed `OnClearEventArgs::clearsAllEntities()` and `OnClearEventArgs::getEntityClass()`
|
||||
|
||||
These methods only make sense when partially clearing the object manager, which
|
||||
is no longer possible.
|
||||
The second argument of the constructor of `OnClearEventArgs` is removed as well.
|
||||
|
||||
## BC Break: removed `ObjectManagerAware`
|
||||
|
||||
Implement active record style functionality directly in your application, by
|
||||
using a `postLoad` event.
|
||||
|
||||
## BC Break: removed `AnnotationDriver`
|
||||
|
||||
Use `ColocatedMappingDriver` instead.
|
||||
|
||||
## BC Break: Removed `MappingException::pathRequired()`
|
||||
|
||||
Use `MappingException::pathRequiredForDriver()` instead.
|
||||
|
||||
## BC Break: removed `LifecycleEventArgs::getEntity()`
|
||||
|
||||
Use `LifecycleEventArgs::getObject()` instead.
|
||||
|
||||
## BC Break: removed support for short namespace aliases
|
||||
|
||||
- `AbstractClassMetadataFactory::getFqcnFromAlias()` is removed.
|
||||
- `ClassMetadataFactory` methods now require their `$className` argument to be an
|
||||
actual FQCN.
|
||||
|
||||
## BC Break: removed `ObjectManager::merge()`
|
||||
|
||||
`ObjectManagerDecorator::merge()` is removed without replacement.
|
||||
|
||||
## BC Break: removed support for `doctrine/cache`
|
||||
|
||||
Removed support for using doctrine/cache for metadata caching. The
|
||||
`setCacheDriver` and `getCacheDriver` methods have been removed from
|
||||
`Doctrine\Persistence\Mapping\AbstractMetadata`. Please use `getCache` and
|
||||
`setCache` with a PSR-6 implementation instead.
|
||||
|
||||
## BC Break: changed signatures
|
||||
|
||||
`$objectName` has been dropped from the signature of `ObjectManager::clear()`.
|
||||
|
||||
```diff
|
||||
- public function clear($objectName = null)
|
||||
+ public function clear(): void
|
||||
```
|
||||
|
||||
Also, native parameter type declarations have been added on all public APIs.
|
||||
Native return type declarations have not been added so that it is possible to
|
||||
implement types compatible with both 2.x and 3.x.
|
||||
|
||||
## BC Break: Removed `PersistentObject`
|
||||
|
||||
Please implement this functionality directly in your application if you want
|
||||
ActiveRecord style functionality.
|
||||
|
||||
# Upgrade to 2.5
|
||||
|
||||
## Deprecated `OnClearEventArgs::clearsAllEntities()` and `OnClearEventArgs::getEntityClass()`
|
||||
|
||||
These methods only make sense when partially clearing the object manager, which
|
||||
is deprecated.
|
||||
Passing a second argument to the constructor of `OnClearEventArgs` is
|
||||
deprecated as well.
|
||||
|
||||
## Deprecated `ObjectManagerAware`
|
||||
|
||||
Along with deprecating `PersistentObject`, deprecating `ObjectManagerAware`
|
||||
means deprecating support for active record, which already came with a word of
|
||||
warning. Please implement this directly in your application with a `postLoad`
|
||||
event if you need active record style functionality.
|
||||
|
||||
## Deprecated `MappingException::pathRequired()`
|
||||
|
||||
`MappingException::pathRequiredForDriver()` should be used instead.
|
||||
|
||||
# Upgrade to 2.4
|
||||
|
||||
## Deprecated `AnnotationDriver`
|
||||
|
||||
Since attributes were introduced in PHP 8.0, annotations are deprecated.
|
||||
`AnnotationDriver` is an abstract class that is used when implementing concrete
|
||||
annotation drivers in dependent packages. It is deprecated in favor of using
|
||||
`ColocatedMappingDriver` to implement both annotation and attribute based
|
||||
drivers. This will involve implementing `isTransient()` as well as
|
||||
`__construct()` and `getReader()` to retain backward compatibility.
|
||||
|
||||
# Upgrade to 2.3
|
||||
|
||||
## Deprecated using short namespace alias syntax in favor of `::class` syntax.
|
||||
|
||||
Before:
|
||||
|
||||
```php
|
||||
$objectManager->find('MyPackage:MyClass', $id);
|
||||
$objectManager->createQuery('SELECT u FROM MyPackage:MyClass');
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```php
|
||||
$objectManager->find(MyClass::class, $id);
|
||||
$objectManager->createQuery('SELECT u FROM '. MyClass::class);
|
||||
```
|
||||
|
||||
# Upgrade to 2.2
|
||||
|
||||
## Deprecated `doctrine/cache` usage for metadata caching
|
||||
|
||||
The `setCacheDriver` and `getCacheDriver` methods in
|
||||
`Doctrine\Persistence\Mapping\AbstractMetadata` have been deprecated. Please
|
||||
use `getCache` and `setCache` with a PSR-6 implementation instead. Note that
|
||||
even after switching to PSR-6, `getCacheDriver` will return a cache instance
|
||||
that wraps the PSR-6 cache. Note that if you use a custom implementation of
|
||||
doctrine/cache, the library may not be able to provide a forward compatibility
|
||||
layer. The cache implementation MUST extend the
|
||||
`Doctrine\Common\Cache\CacheProvider` class.
|
||||
|
||||
# Upgrade to 1.2
|
||||
|
||||
## Deprecated `ObjectManager::merge()` and `ObjectManager::detach()`
|
||||
|
||||
Please handle merge operations in your application, and use
|
||||
`ObjectManager::clear()` instead.
|
||||
|
||||
## Deprecated `PersistentObject`
|
||||
|
||||
Please implement this functionality directly in your application if you want
|
||||
ActiveRecord style functionality.
|
||||
52
vendor/doctrine/persistence/composer.json
vendored
Normal file
52
vendor/doctrine/persistence/composer.json
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
{
|
||||
"name": "doctrine/persistence",
|
||||
"type": "library",
|
||||
"description": "The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.",
|
||||
"keywords": [
|
||||
"persistence",
|
||||
"object",
|
||||
"mapper",
|
||||
"orm",
|
||||
"odm"
|
||||
],
|
||||
"homepage": "https://www.doctrine-project.org/projects/persistence.html",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"},
|
||||
{"name": "Roman Borschel", "email": "roman@code-factory.org"},
|
||||
{"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"},
|
||||
{"name": "Jonathan Wage", "email": "jonwage@gmail.com"},
|
||||
{"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"},
|
||||
{"name": "Marco Pivetta", "email": "ocramius@gmail.com"}
|
||||
],
|
||||
"require": {
|
||||
"php": "^8.1",
|
||||
"doctrine/event-manager": "^1 || ^2",
|
||||
"psr/cache": "^1.0 || ^2.0 || ^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "1.12.7",
|
||||
"phpstan/phpstan-phpunit": "^1",
|
||||
"phpstan/phpstan-strict-rules": "^1.6",
|
||||
"doctrine/coding-standard": "^12",
|
||||
"phpunit/phpunit": "^9.6",
|
||||
"symfony/cache": "^4.4 || ^5.4 || ^6.0 || ^7.0",
|
||||
"symfony/finder": "^4.4 || ^5.4 || ^6.0 || ^7.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Persistence\\": "src/Persistence"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Tests\\": "tests"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": true,
|
||||
"composer/package-versions-deprecated": true
|
||||
}
|
||||
}
|
||||
}
|
||||
218
vendor/doctrine/persistence/src/Persistence/AbstractManagerRegistry.php
vendored
Normal file
218
vendor/doctrine/persistence/src/Persistence/AbstractManagerRegistry.php
vendored
Normal file
@ -0,0 +1,218 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Persistence;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use ReflectionClass;
|
||||
|
||||
use function assert;
|
||||
use function sprintf;
|
||||
|
||||
/**
|
||||
* Abstract implementation of the ManagerRegistry contract.
|
||||
*/
|
||||
abstract class AbstractManagerRegistry implements ManagerRegistry
|
||||
{
|
||||
/**
|
||||
* @param array<string, string> $connections
|
||||
* @param array<string, string> $managers
|
||||
* @phpstan-param class-string $proxyInterfaceName
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly string $name,
|
||||
private array $connections,
|
||||
private array $managers,
|
||||
private readonly string $defaultConnection,
|
||||
private readonly string $defaultManager,
|
||||
private readonly string $proxyInterfaceName,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches/creates the given services.
|
||||
*
|
||||
* A service in this context is connection or a manager instance.
|
||||
*
|
||||
* @param string $name The name of the service.
|
||||
*
|
||||
* @return object The instance of the given service.
|
||||
*/
|
||||
abstract protected function getService(string $name): object;
|
||||
|
||||
/**
|
||||
* Resets the given services.
|
||||
*
|
||||
* A service in this context is connection or a manager instance.
|
||||
*
|
||||
* @param string $name The name of the service.
|
||||
*/
|
||||
abstract protected function resetService(string $name): void;
|
||||
|
||||
/** Gets the name of the registry. */
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function getConnection(string|null $name = null): object
|
||||
{
|
||||
if ($name === null) {
|
||||
$name = $this->defaultConnection;
|
||||
}
|
||||
|
||||
if (! isset($this->connections[$name])) {
|
||||
throw new InvalidArgumentException(
|
||||
sprintf('Doctrine %s Connection named "%s" does not exist.', $this->name, $name),
|
||||
);
|
||||
}
|
||||
|
||||
return $this->getService($this->connections[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getConnectionNames(): array
|
||||
{
|
||||
return $this->connections;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getConnections(): array
|
||||
{
|
||||
$connections = [];
|
||||
foreach ($this->connections as $name => $id) {
|
||||
$connections[$name] = $this->getService($id);
|
||||
}
|
||||
|
||||
return $connections;
|
||||
}
|
||||
|
||||
public function getDefaultConnectionName(): string
|
||||
{
|
||||
return $this->defaultConnection;
|
||||
}
|
||||
|
||||
public function getDefaultManagerName(): string
|
||||
{
|
||||
return $this->defaultManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function getManager(string|null $name = null): ObjectManager
|
||||
{
|
||||
if ($name === null) {
|
||||
$name = $this->defaultManager;
|
||||
}
|
||||
|
||||
if (! isset($this->managers[$name])) {
|
||||
throw new InvalidArgumentException(
|
||||
sprintf('Doctrine %s Manager named "%s" does not exist.', $this->name, $name),
|
||||
);
|
||||
}
|
||||
|
||||
$service = $this->getService($this->managers[$name]);
|
||||
assert($service instanceof ObjectManager);
|
||||
|
||||
return $service;
|
||||
}
|
||||
|
||||
public function getManagerForClass(string $class): ObjectManager|null
|
||||
{
|
||||
$proxyClass = new ReflectionClass($class);
|
||||
if ($proxyClass->isAnonymous()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($proxyClass->implementsInterface($this->proxyInterfaceName)) {
|
||||
$parentClass = $proxyClass->getParentClass();
|
||||
|
||||
if ($parentClass === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$class = $parentClass->getName();
|
||||
}
|
||||
|
||||
foreach ($this->managers as $id) {
|
||||
$manager = $this->getService($id);
|
||||
assert($manager instanceof ObjectManager);
|
||||
|
||||
if (! $manager->getMetadataFactory()->isTransient($class)) {
|
||||
return $manager;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getManagerNames(): array
|
||||
{
|
||||
return $this->managers;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getManagers(): array
|
||||
{
|
||||
$managers = [];
|
||||
|
||||
foreach ($this->managers as $name => $id) {
|
||||
$manager = $this->getService($id);
|
||||
assert($manager instanceof ObjectManager);
|
||||
$managers[$name] = $manager;
|
||||
}
|
||||
|
||||
return $managers;
|
||||
}
|
||||
|
||||
public function getRepository(
|
||||
string $persistentObject,
|
||||
string|null $persistentManagerName = null,
|
||||
): ObjectRepository {
|
||||
return $this
|
||||
->selectManager($persistentObject, $persistentManagerName)
|
||||
->getRepository($persistentObject);
|
||||
}
|
||||
|
||||
public function resetManager(string|null $name = null): ObjectManager
|
||||
{
|
||||
if ($name === null) {
|
||||
$name = $this->defaultManager;
|
||||
}
|
||||
|
||||
if (! isset($this->managers[$name])) {
|
||||
throw new InvalidArgumentException(sprintf('Doctrine %s Manager named "%s" does not exist.', $this->name, $name));
|
||||
}
|
||||
|
||||
// force the creation of a new document manager
|
||||
// if the current one is closed
|
||||
$this->resetService($this->managers[$name]);
|
||||
|
||||
return $this->getManager($name);
|
||||
}
|
||||
|
||||
/** @phpstan-param class-string $persistentObject */
|
||||
private function selectManager(
|
||||
string $persistentObject,
|
||||
string|null $persistentManagerName = null,
|
||||
): ObjectManager {
|
||||
if ($persistentManagerName !== null) {
|
||||
return $this->getManager($persistentManagerName);
|
||||
}
|
||||
|
||||
return $this->getManagerForClass($persistentObject) ?? $this->getManager();
|
||||
}
|
||||
}
|
||||
39
vendor/doctrine/persistence/src/Persistence/ConnectionRegistry.php
vendored
Normal file
39
vendor/doctrine/persistence/src/Persistence/ConnectionRegistry.php
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Persistence;
|
||||
|
||||
/**
|
||||
* Contract covering connection for a Doctrine persistence layer ManagerRegistry class to implement.
|
||||
*/
|
||||
interface ConnectionRegistry
|
||||
{
|
||||
/**
|
||||
* Gets the default connection name.
|
||||
*
|
||||
* @return string The default connection name.
|
||||
*/
|
||||
public function getDefaultConnectionName(): string;
|
||||
|
||||
/**
|
||||
* Gets the named connection.
|
||||
*
|
||||
* @param string|null $name The connection name (null for the default one).
|
||||
*/
|
||||
public function getConnection(string|null $name = null): object;
|
||||
|
||||
/**
|
||||
* Gets an array of all registered connections.
|
||||
*
|
||||
* @return array<string, object> An array of Connection instances.
|
||||
*/
|
||||
public function getConnections(): array;
|
||||
|
||||
/**
|
||||
* Gets all connection names.
|
||||
*
|
||||
* @return array<string, string> An array of connection names.
|
||||
*/
|
||||
public function getConnectionNames(): array;
|
||||
}
|
||||
40
vendor/doctrine/persistence/src/Persistence/Event/LifecycleEventArgs.php
vendored
Normal file
40
vendor/doctrine/persistence/src/Persistence/Event/LifecycleEventArgs.php
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Persistence\Event;
|
||||
|
||||
use Doctrine\Common\EventArgs;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
|
||||
/**
|
||||
* Lifecycle Events are triggered by the UnitOfWork during lifecycle transitions
|
||||
* of entities.
|
||||
*
|
||||
* @template-covariant TObjectManager of ObjectManager
|
||||
*/
|
||||
class LifecycleEventArgs extends EventArgs
|
||||
{
|
||||
/** @phpstan-param TObjectManager $objectManager */
|
||||
public function __construct(
|
||||
private readonly object $object,
|
||||
private readonly ObjectManager $objectManager,
|
||||
) {
|
||||
}
|
||||
|
||||
/** Retrieves the associated object. */
|
||||
public function getObject(): object
|
||||
{
|
||||
return $this->object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the associated ObjectManager.
|
||||
*
|
||||
* @phpstan-return TObjectManager
|
||||
*/
|
||||
public function getObjectManager(): ObjectManager
|
||||
{
|
||||
return $this->objectManager;
|
||||
}
|
||||
}
|
||||
48
vendor/doctrine/persistence/src/Persistence/Event/LoadClassMetadataEventArgs.php
vendored
Normal file
48
vendor/doctrine/persistence/src/Persistence/Event/LoadClassMetadataEventArgs.php
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Persistence\Event;
|
||||
|
||||
use Doctrine\Common\EventArgs;
|
||||
use Doctrine\Persistence\Mapping\ClassMetadata;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
|
||||
/**
|
||||
* Class that holds event arguments for a loadMetadata event.
|
||||
*
|
||||
* @template-covariant TClassMetadata of ClassMetadata<object>
|
||||
* @template-covariant TObjectManager of ObjectManager
|
||||
*/
|
||||
class LoadClassMetadataEventArgs extends EventArgs
|
||||
{
|
||||
/**
|
||||
* @phpstan-param TClassMetadata $classMetadata
|
||||
* @phpstan-param TObjectManager $objectManager
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly ClassMetadata $classMetadata,
|
||||
private readonly ObjectManager $objectManager,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the associated ClassMetadata.
|
||||
*
|
||||
* @phpstan-return TClassMetadata
|
||||
*/
|
||||
public function getClassMetadata(): ClassMetadata
|
||||
{
|
||||
return $this->classMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the associated ObjectManager.
|
||||
*
|
||||
* @phpstan-return TObjectManager
|
||||
*/
|
||||
public function getObjectManager(): ObjectManager
|
||||
{
|
||||
return $this->objectManager;
|
||||
}
|
||||
}
|
||||
32
vendor/doctrine/persistence/src/Persistence/Event/ManagerEventArgs.php
vendored
Normal file
32
vendor/doctrine/persistence/src/Persistence/Event/ManagerEventArgs.php
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Persistence\Event;
|
||||
|
||||
use Doctrine\Common\EventArgs;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
|
||||
/**
|
||||
* Provides event arguments for the preFlush event.
|
||||
*
|
||||
* @template-covariant TObjectManager of ObjectManager
|
||||
*/
|
||||
class ManagerEventArgs extends EventArgs
|
||||
{
|
||||
/** @phpstan-param TObjectManager $objectManager */
|
||||
public function __construct(
|
||||
private readonly ObjectManager $objectManager,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the associated ObjectManager.
|
||||
*
|
||||
* @phpstan-return TObjectManager
|
||||
*/
|
||||
public function getObjectManager(): ObjectManager
|
||||
{
|
||||
return $this->objectManager;
|
||||
}
|
||||
}
|
||||
34
vendor/doctrine/persistence/src/Persistence/Event/OnClearEventArgs.php
vendored
Normal file
34
vendor/doctrine/persistence/src/Persistence/Event/OnClearEventArgs.php
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Persistence\Event;
|
||||
|
||||
use Doctrine\Common\EventArgs;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
|
||||
/**
|
||||
* Provides event arguments for the onClear event.
|
||||
*
|
||||
* @template-covariant TObjectManager of ObjectManager
|
||||
*/
|
||||
class OnClearEventArgs extends EventArgs
|
||||
{
|
||||
/**
|
||||
* @param ObjectManager $objectManager The object manager.
|
||||
* @phpstan-param TObjectManager $objectManager
|
||||
*/
|
||||
public function __construct(private readonly ObjectManager $objectManager)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the associated ObjectManager.
|
||||
*
|
||||
* @phpstan-return TObjectManager
|
||||
*/
|
||||
public function getObjectManager(): ObjectManager
|
||||
{
|
||||
return $this->objectManager;
|
||||
}
|
||||
}
|
||||
89
vendor/doctrine/persistence/src/Persistence/Event/PreUpdateEventArgs.php
vendored
Normal file
89
vendor/doctrine/persistence/src/Persistence/Event/PreUpdateEventArgs.php
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Persistence\Event;
|
||||
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
use InvalidArgumentException;
|
||||
|
||||
use function sprintf;
|
||||
|
||||
/**
|
||||
* Class that holds event arguments for a preUpdate event.
|
||||
*
|
||||
* @template-covariant TObjectManager of ObjectManager
|
||||
* @extends LifecycleEventArgs<TObjectManager>
|
||||
*/
|
||||
class PreUpdateEventArgs extends LifecycleEventArgs
|
||||
{
|
||||
/** @var array<string, array<int, mixed>> */
|
||||
private array $entityChangeSet;
|
||||
|
||||
/**
|
||||
* @param array<string, array<int, mixed>> $changeSet
|
||||
* @phpstan-param TObjectManager $objectManager
|
||||
*/
|
||||
public function __construct(object $entity, ObjectManager $objectManager, array &$changeSet)
|
||||
{
|
||||
parent::__construct($entity, $objectManager);
|
||||
|
||||
$this->entityChangeSet = &$changeSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the entity changeset.
|
||||
*
|
||||
* @return array<string, array<int, mixed>>
|
||||
*/
|
||||
public function getEntityChangeSet(): array
|
||||
{
|
||||
return $this->entityChangeSet;
|
||||
}
|
||||
|
||||
/** Checks if field has a changeset. */
|
||||
public function hasChangedField(string $field): bool
|
||||
{
|
||||
return isset($this->entityChangeSet[$field]);
|
||||
}
|
||||
|
||||
/** Gets the old value of the changeset of the changed field. */
|
||||
public function getOldValue(string $field): mixed
|
||||
{
|
||||
$this->assertValidField($field);
|
||||
|
||||
return $this->entityChangeSet[$field][0];
|
||||
}
|
||||
|
||||
/** Gets the new value of the changeset of the changed field. */
|
||||
public function getNewValue(string $field): mixed
|
||||
{
|
||||
$this->assertValidField($field);
|
||||
|
||||
return $this->entityChangeSet[$field][1];
|
||||
}
|
||||
|
||||
/** Sets the new value of this field. */
|
||||
public function setNewValue(string $field, mixed $value): void
|
||||
{
|
||||
$this->assertValidField($field);
|
||||
|
||||
$this->entityChangeSet[$field][1] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts the field exists in changeset.
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
private function assertValidField(string $field): void
|
||||
{
|
||||
if (! isset($this->entityChangeSet[$field])) {
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'Field "%s" is not a valid field of the entity "%s" in PreUpdateEventArgs.',
|
||||
$field,
|
||||
$this->getObject()::class,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
82
vendor/doctrine/persistence/src/Persistence/ManagerRegistry.php
vendored
Normal file
82
vendor/doctrine/persistence/src/Persistence/ManagerRegistry.php
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Persistence;
|
||||
|
||||
/**
|
||||
* Contract covering object managers for a Doctrine persistence layer ManagerRegistry class to implement.
|
||||
*/
|
||||
interface ManagerRegistry extends ConnectionRegistry
|
||||
{
|
||||
/**
|
||||
* Gets the default object manager name.
|
||||
*
|
||||
* @return string The default object manager name.
|
||||
*/
|
||||
public function getDefaultManagerName(): string;
|
||||
|
||||
/**
|
||||
* Gets a named object manager.
|
||||
*
|
||||
* @param string|null $name The object manager name (null for the default one).
|
||||
*/
|
||||
public function getManager(string|null $name = null): ObjectManager;
|
||||
|
||||
/**
|
||||
* Gets an array of all registered object managers.
|
||||
*
|
||||
* @return array<string, ObjectManager> An array of ObjectManager instances
|
||||
*/
|
||||
public function getManagers(): array;
|
||||
|
||||
/**
|
||||
* Resets a named object manager.
|
||||
*
|
||||
* This method is useful when an object manager has been closed
|
||||
* because of a rollbacked transaction AND when you think that
|
||||
* it makes sense to get a new one to replace the closed one.
|
||||
*
|
||||
* Be warned that you will get a brand new object manager as
|
||||
* the existing one is not useable anymore. This means that any
|
||||
* other object with a dependency on this object manager will
|
||||
* hold an obsolete reference. You can inject the registry instead
|
||||
* to avoid this problem.
|
||||
*
|
||||
* @param string|null $name The object manager name (null for the default one).
|
||||
*/
|
||||
public function resetManager(string|null $name = null): ObjectManager;
|
||||
|
||||
/**
|
||||
* Gets all object manager names and associated service IDs. A service ID
|
||||
* is a string that allows to obtain an object manager, typically from a
|
||||
* PSR-11 container.
|
||||
*
|
||||
* @return array<string,string> An array with object manager names as keys,
|
||||
* and service IDs as values.
|
||||
*/
|
||||
public function getManagerNames(): array;
|
||||
|
||||
/**
|
||||
* Gets the ObjectRepository for a persistent object.
|
||||
*
|
||||
* @param string $persistentObject The name of the persistent object.
|
||||
* @param string|null $persistentManagerName The object manager name (null for the default one).
|
||||
* @phpstan-param class-string<T> $persistentObject
|
||||
*
|
||||
* @phpstan-return ObjectRepository<T>
|
||||
*
|
||||
* @template T of object
|
||||
*/
|
||||
public function getRepository(
|
||||
string $persistentObject,
|
||||
string|null $persistentManagerName = null,
|
||||
): ObjectRepository;
|
||||
|
||||
/**
|
||||
* Gets the object manager associated with a given class.
|
||||
*
|
||||
* @param class-string $class A persistent object class name.
|
||||
*/
|
||||
public function getManagerForClass(string $class): ObjectManager|null;
|
||||
}
|
||||
460
vendor/doctrine/persistence/src/Persistence/Mapping/AbstractClassMetadataFactory.php
vendored
Normal file
460
vendor/doctrine/persistence/src/Persistence/Mapping/AbstractClassMetadataFactory.php
vendored
Normal file
@ -0,0 +1,460 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Persistence\Mapping;
|
||||
|
||||
use Doctrine\Persistence\Mapping\Driver\MappingDriver;
|
||||
use Doctrine\Persistence\Proxy;
|
||||
use Psr\Cache\CacheItemPoolInterface;
|
||||
use ReflectionClass;
|
||||
use ReflectionException;
|
||||
|
||||
use function array_combine;
|
||||
use function array_keys;
|
||||
use function array_map;
|
||||
use function array_reverse;
|
||||
use function array_unshift;
|
||||
use function assert;
|
||||
use function class_exists;
|
||||
use function ltrim;
|
||||
use function str_contains;
|
||||
use function str_replace;
|
||||
use function strrpos;
|
||||
use function substr;
|
||||
|
||||
/**
|
||||
* The ClassMetadataFactory is used to create ClassMetadata objects that contain all the
|
||||
* metadata mapping informations of a class which describes how a class should be mapped
|
||||
* to a relational database.
|
||||
*
|
||||
* This class was abstracted from the ORM ClassMetadataFactory.
|
||||
*
|
||||
* @template CMTemplate of ClassMetadata
|
||||
* @template-implements ClassMetadataFactory<CMTemplate>
|
||||
*/
|
||||
abstract class AbstractClassMetadataFactory implements ClassMetadataFactory
|
||||
{
|
||||
/** Salt used by specific Object Manager implementation. */
|
||||
protected string $cacheSalt = '__CLASSMETADATA__';
|
||||
|
||||
private CacheItemPoolInterface|null $cache = null;
|
||||
|
||||
/**
|
||||
* @var array<string, ClassMetadata>
|
||||
* @phpstan-var CMTemplate[]
|
||||
*/
|
||||
private array $loadedMetadata = [];
|
||||
|
||||
protected bool $initialized = false;
|
||||
|
||||
private ReflectionService|null $reflectionService = null;
|
||||
|
||||
private ProxyClassNameResolver|null $proxyClassNameResolver = null;
|
||||
|
||||
public function setCache(CacheItemPoolInterface $cache): void
|
||||
{
|
||||
$this->cache = $cache;
|
||||
}
|
||||
|
||||
final protected function getCache(): CacheItemPoolInterface|null
|
||||
{
|
||||
return $this->cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all the loaded metadata currently in memory.
|
||||
*
|
||||
* @return ClassMetadata[]
|
||||
* @phpstan-return CMTemplate[]
|
||||
*/
|
||||
public function getLoadedMetadata(): array
|
||||
{
|
||||
return $this->loadedMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getAllMetadata(): array
|
||||
{
|
||||
if (! $this->initialized) {
|
||||
$this->initialize();
|
||||
}
|
||||
|
||||
$driver = $this->getDriver();
|
||||
$metadata = [];
|
||||
foreach ($driver->getAllClassNames() as $className) {
|
||||
$metadata[] = $this->getMetadataFor($className);
|
||||
}
|
||||
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
public function setProxyClassNameResolver(ProxyClassNameResolver $resolver): void
|
||||
{
|
||||
$this->proxyClassNameResolver = $resolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazy initialization of this stuff, especially the metadata driver,
|
||||
* since these are not needed at all when a metadata cache is active.
|
||||
*/
|
||||
abstract protected function initialize(): void;
|
||||
|
||||
/** Returns the mapping driver implementation. */
|
||||
abstract protected function getDriver(): MappingDriver;
|
||||
|
||||
/**
|
||||
* Wakes up reflection after ClassMetadata gets unserialized from cache.
|
||||
*
|
||||
* @phpstan-param CMTemplate $class
|
||||
*/
|
||||
abstract protected function wakeupReflection(
|
||||
ClassMetadata $class,
|
||||
ReflectionService $reflService,
|
||||
): void;
|
||||
|
||||
/**
|
||||
* Initializes Reflection after ClassMetadata was constructed.
|
||||
*
|
||||
* @phpstan-param CMTemplate $class
|
||||
*/
|
||||
abstract protected function initializeReflection(
|
||||
ClassMetadata $class,
|
||||
ReflectionService $reflService,
|
||||
): void;
|
||||
|
||||
/**
|
||||
* Checks whether the class metadata is an entity.
|
||||
*
|
||||
* This method should return false for mapped superclasses or embedded classes.
|
||||
*
|
||||
* @phpstan-param CMTemplate $class
|
||||
*/
|
||||
abstract protected function isEntity(ClassMetadata $class): bool;
|
||||
|
||||
/**
|
||||
* Removes the prepended backslash of a class string to conform with how php outputs class names
|
||||
*
|
||||
* @phpstan-param class-string $className
|
||||
*
|
||||
* @phpstan-return class-string
|
||||
*/
|
||||
private function normalizeClassName(string $className): string
|
||||
{
|
||||
return ltrim($className, '\\');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @throws ReflectionException
|
||||
* @throws MappingException
|
||||
*/
|
||||
public function getMetadataFor(string $className): ClassMetadata
|
||||
{
|
||||
$className = $this->normalizeClassName($className);
|
||||
|
||||
if (isset($this->loadedMetadata[$className])) {
|
||||
return $this->loadedMetadata[$className];
|
||||
}
|
||||
|
||||
if (class_exists($className, false) && (new ReflectionClass($className))->isAnonymous()) {
|
||||
throw MappingException::classIsAnonymous($className);
|
||||
}
|
||||
|
||||
if (! class_exists($className, false) && str_contains($className, ':')) {
|
||||
throw MappingException::nonExistingClass($className);
|
||||
}
|
||||
|
||||
$realClassName = $this->getRealClass($className);
|
||||
|
||||
if (isset($this->loadedMetadata[$realClassName])) {
|
||||
// We do not have the alias name in the map, include it
|
||||
return $this->loadedMetadata[$className] = $this->loadedMetadata[$realClassName];
|
||||
}
|
||||
|
||||
try {
|
||||
if ($this->cache !== null) {
|
||||
$cached = $this->cache->getItem($this->getCacheKey($realClassName))->get();
|
||||
if ($cached instanceof ClassMetadata) {
|
||||
/** @phpstan-var CMTemplate $cached */
|
||||
$this->loadedMetadata[$realClassName] = $cached;
|
||||
|
||||
$this->wakeupReflection($cached, $this->getReflectionService());
|
||||
} else {
|
||||
$loadedMetadata = $this->loadMetadata($realClassName);
|
||||
$classNames = array_combine(
|
||||
array_map($this->getCacheKey(...), $loadedMetadata),
|
||||
$loadedMetadata,
|
||||
);
|
||||
|
||||
foreach ($this->cache->getItems(array_keys($classNames)) as $item) {
|
||||
if (! isset($classNames[$item->getKey()])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$item->set($this->loadedMetadata[$classNames[$item->getKey()]]);
|
||||
$this->cache->saveDeferred($item);
|
||||
}
|
||||
|
||||
$this->cache->commit();
|
||||
}
|
||||
} else {
|
||||
$this->loadMetadata($realClassName);
|
||||
}
|
||||
} catch (MappingException $loadingException) {
|
||||
$fallbackMetadataResponse = $this->onNotFoundMetadata($realClassName);
|
||||
|
||||
if ($fallbackMetadataResponse === null) {
|
||||
throw $loadingException;
|
||||
}
|
||||
|
||||
$this->loadedMetadata[$realClassName] = $fallbackMetadataResponse;
|
||||
}
|
||||
|
||||
if ($className !== $realClassName) {
|
||||
// We do not have the alias name in the map, include it
|
||||
$this->loadedMetadata[$className] = $this->loadedMetadata[$realClassName];
|
||||
}
|
||||
|
||||
return $this->loadedMetadata[$className];
|
||||
}
|
||||
|
||||
public function hasMetadataFor(string $className): bool
|
||||
{
|
||||
$className = $this->normalizeClassName($className);
|
||||
|
||||
return isset($this->loadedMetadata[$className]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the metadata descriptor for a specific class.
|
||||
*
|
||||
* NOTE: This is only useful in very special cases, like when generating proxy classes.
|
||||
*
|
||||
* @phpstan-param class-string $className
|
||||
* @phpstan-param CMTemplate $class
|
||||
*/
|
||||
public function setMetadataFor(string $className, ClassMetadata $class): void
|
||||
{
|
||||
$this->loadedMetadata[$this->normalizeClassName($className)] = $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array of parent classes for the given entity class.
|
||||
*
|
||||
* @phpstan-param class-string $name
|
||||
*
|
||||
* @return string[]
|
||||
* @phpstan-return list<class-string>
|
||||
*/
|
||||
protected function getParentClasses(string $name): array
|
||||
{
|
||||
// Collect parent classes, ignoring transient (not-mapped) classes.
|
||||
$parentClasses = [];
|
||||
|
||||
foreach (array_reverse($this->getReflectionService()->getParentClasses($name)) as $parentClass) {
|
||||
if ($this->getDriver()->isTransient($parentClass)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$parentClasses[] = $parentClass;
|
||||
}
|
||||
|
||||
return $parentClasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the metadata of the class in question and all it's ancestors whose metadata
|
||||
* is still not loaded.
|
||||
*
|
||||
* Important: The class $name does not necessarily exist at this point here.
|
||||
* Scenarios in a code-generation setup might have access to XML/YAML
|
||||
* Mapping files without the actual PHP code existing here. That is why the
|
||||
* {@see \Doctrine\Persistence\Mapping\ReflectionService} interface
|
||||
* should be used for reflection.
|
||||
*
|
||||
* @param string $name The name of the class for which the metadata should get loaded.
|
||||
* @phpstan-param class-string $name
|
||||
*
|
||||
* @return array<int, string>
|
||||
* @phpstan-return list<string>
|
||||
*/
|
||||
protected function loadMetadata(string $name): array
|
||||
{
|
||||
if (! $this->initialized) {
|
||||
$this->initialize();
|
||||
}
|
||||
|
||||
$loaded = [];
|
||||
|
||||
$parentClasses = $this->getParentClasses($name);
|
||||
$parentClasses[] = $name;
|
||||
|
||||
// Move down the hierarchy of parent classes, starting from the topmost class
|
||||
$parent = null;
|
||||
$rootEntityFound = false;
|
||||
$visited = [];
|
||||
$reflService = $this->getReflectionService();
|
||||
|
||||
foreach ($parentClasses as $className) {
|
||||
if (isset($this->loadedMetadata[$className])) {
|
||||
$parent = $this->loadedMetadata[$className];
|
||||
|
||||
if ($this->isEntity($parent)) {
|
||||
$rootEntityFound = true;
|
||||
|
||||
array_unshift($visited, $className);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$class = $this->newClassMetadataInstance($className);
|
||||
$this->initializeReflection($class, $reflService);
|
||||
|
||||
$this->doLoadMetadata($class, $parent, $rootEntityFound, $visited);
|
||||
|
||||
$this->loadedMetadata[$className] = $class;
|
||||
|
||||
$parent = $class;
|
||||
|
||||
if ($this->isEntity($class)) {
|
||||
$rootEntityFound = true;
|
||||
|
||||
array_unshift($visited, $className);
|
||||
}
|
||||
|
||||
$this->wakeupReflection($class, $reflService);
|
||||
|
||||
$loaded[] = $className;
|
||||
}
|
||||
|
||||
return $loaded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a fallback hook for loading metadata when loading failed due to reflection/mapping exceptions
|
||||
*
|
||||
* Override this method to implement a fallback strategy for failed metadata loading
|
||||
*
|
||||
* @phpstan-return CMTemplate|null
|
||||
*/
|
||||
protected function onNotFoundMetadata(string $className): ClassMetadata|null
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Actually loads the metadata from the underlying metadata.
|
||||
*
|
||||
* @param bool $rootEntityFound True when there is another entity (non-mapped superclass) class above the current class in the PHP class hierarchy.
|
||||
* @param list<class-string> $nonSuperclassParents All parent class names that are not marked as mapped superclasses, with the direct parent class being the first and the root entity class the last element.
|
||||
* @phpstan-param CMTemplate $class
|
||||
* @phpstan-param CMTemplate|null $parent
|
||||
*/
|
||||
abstract protected function doLoadMetadata(
|
||||
ClassMetadata $class,
|
||||
ClassMetadata|null $parent,
|
||||
bool $rootEntityFound,
|
||||
array $nonSuperclassParents,
|
||||
): void;
|
||||
|
||||
/**
|
||||
* Creates a new ClassMetadata instance for the given class name.
|
||||
*
|
||||
* @phpstan-param class-string<T> $className
|
||||
*
|
||||
* @return ClassMetadata<T>
|
||||
* @phpstan-return CMTemplate
|
||||
*
|
||||
* @template T of object
|
||||
*/
|
||||
abstract protected function newClassMetadataInstance(string $className): ClassMetadata;
|
||||
|
||||
public function isTransient(string $className): bool
|
||||
{
|
||||
if (! $this->initialized) {
|
||||
$this->initialize();
|
||||
}
|
||||
|
||||
if (class_exists($className, false) && (new ReflectionClass($className))->isAnonymous()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! class_exists($className, false) && str_contains($className, ':')) {
|
||||
throw MappingException::nonExistingClass($className);
|
||||
}
|
||||
|
||||
/** @phpstan-var class-string $className */
|
||||
return $this->getDriver()->isTransient($className);
|
||||
}
|
||||
|
||||
/** Sets the reflectionService. */
|
||||
public function setReflectionService(ReflectionService $reflectionService): void
|
||||
{
|
||||
$this->reflectionService = $reflectionService;
|
||||
}
|
||||
|
||||
/** Gets the reflection service associated with this metadata factory. */
|
||||
public function getReflectionService(): ReflectionService
|
||||
{
|
||||
if ($this->reflectionService === null) {
|
||||
$this->reflectionService = new RuntimeReflectionService();
|
||||
}
|
||||
|
||||
return $this->reflectionService;
|
||||
}
|
||||
|
||||
protected function getCacheKey(string $realClassName): string
|
||||
{
|
||||
return str_replace('\\', '__', $realClassName) . $this->cacheSalt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the real class name of a class name that could be a proxy.
|
||||
*
|
||||
* @phpstan-param class-string<Proxy<T>>|class-string<T> $class
|
||||
*
|
||||
* @phpstan-return class-string<T>
|
||||
*
|
||||
* @template T of object
|
||||
*/
|
||||
private function getRealClass(string $class): string
|
||||
{
|
||||
if ($this->proxyClassNameResolver === null) {
|
||||
$this->createDefaultProxyClassNameResolver();
|
||||
}
|
||||
|
||||
assert($this->proxyClassNameResolver !== null);
|
||||
|
||||
return $this->proxyClassNameResolver->resolveClassName($class);
|
||||
}
|
||||
|
||||
private function createDefaultProxyClassNameResolver(): void
|
||||
{
|
||||
$this->proxyClassNameResolver = new class implements ProxyClassNameResolver {
|
||||
/**
|
||||
* @phpstan-param class-string<Proxy<T>>|class-string<T> $className
|
||||
*
|
||||
* @phpstan-return class-string<T>
|
||||
*
|
||||
* @template T of object
|
||||
*/
|
||||
public function resolveClassName(string $className): string
|
||||
{
|
||||
$pos = strrpos($className, '\\' . Proxy::MARKER . '\\');
|
||||
|
||||
if ($pos === false) {
|
||||
/** @phpstan-var class-string<T> */
|
||||
return $className;
|
||||
}
|
||||
|
||||
/** @phpstan-var class-string<T> */
|
||||
return substr($className, $pos + Proxy::MARKER_LENGTH + 2);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
109
vendor/doctrine/persistence/src/Persistence/Mapping/ClassMetadata.php
vendored
Normal file
109
vendor/doctrine/persistence/src/Persistence/Mapping/ClassMetadata.php
vendored
Normal file
@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Persistence\Mapping;
|
||||
|
||||
use ReflectionClass;
|
||||
|
||||
/**
|
||||
* Contract for a Doctrine persistence layer ClassMetadata class to implement.
|
||||
*
|
||||
* @template-covariant T of object
|
||||
*/
|
||||
interface ClassMetadata
|
||||
{
|
||||
/**
|
||||
* Gets the fully-qualified class name of this persistent class.
|
||||
*
|
||||
* @phpstan-return class-string<T>
|
||||
*/
|
||||
public function getName(): string;
|
||||
|
||||
/**
|
||||
* Gets the mapped identifier field name.
|
||||
*
|
||||
* The returned structure is an array of the identifier field names.
|
||||
*
|
||||
* @return array<int, string>
|
||||
* @phpstan-return list<string>
|
||||
*/
|
||||
public function getIdentifier(): array;
|
||||
|
||||
/**
|
||||
* Gets the ReflectionClass instance for this mapped class.
|
||||
*
|
||||
* @return ReflectionClass<T>
|
||||
*/
|
||||
public function getReflectionClass(): ReflectionClass;
|
||||
|
||||
/** Checks if the given field name is a mapped identifier for this class. */
|
||||
public function isIdentifier(string $fieldName): bool;
|
||||
|
||||
/** Checks if the given field is a mapped property for this class. */
|
||||
public function hasField(string $fieldName): bool;
|
||||
|
||||
/** Checks if the given field is a mapped association for this class. */
|
||||
public function hasAssociation(string $fieldName): bool;
|
||||
|
||||
/** Checks if the given field is a mapped single valued association for this class. */
|
||||
public function isSingleValuedAssociation(string $fieldName): bool;
|
||||
|
||||
/** Checks if the given field is a mapped collection valued association for this class. */
|
||||
public function isCollectionValuedAssociation(string $fieldName): bool;
|
||||
|
||||
/**
|
||||
* A numerically indexed list of field names of this persistent class.
|
||||
*
|
||||
* This array includes identifier fields if present on this class.
|
||||
*
|
||||
* @return array<int, string>
|
||||
*/
|
||||
public function getFieldNames(): array;
|
||||
|
||||
/**
|
||||
* Returns an array of identifier field names numerically indexed.
|
||||
*
|
||||
* @return array<int, string>
|
||||
*/
|
||||
public function getIdentifierFieldNames(): array;
|
||||
|
||||
/**
|
||||
* Returns a numerically indexed list of association names of this persistent class.
|
||||
*
|
||||
* This array includes identifier associations if present on this class.
|
||||
*
|
||||
* @return array<int, string>
|
||||
*/
|
||||
public function getAssociationNames(): array;
|
||||
|
||||
/**
|
||||
* Returns a type name of this field.
|
||||
*
|
||||
* This type names can be implementation specific but should at least include the php types:
|
||||
* integer, string, boolean, float/double, datetime.
|
||||
*/
|
||||
public function getTypeOfField(string $fieldName): string|null;
|
||||
|
||||
/**
|
||||
* Returns the target class name of the given association.
|
||||
*
|
||||
* @phpstan-return class-string|null
|
||||
*/
|
||||
public function getAssociationTargetClass(string $assocName): string|null;
|
||||
|
||||
/** Checks if the association is the inverse side of a bidirectional association. */
|
||||
public function isAssociationInverseSide(string $assocName): bool;
|
||||
|
||||
/** Returns the target field of the owning side of the association. */
|
||||
public function getAssociationMappedByTargetField(string $assocName): string;
|
||||
|
||||
/**
|
||||
* Returns the identifier of this object as an array with field name as key.
|
||||
*
|
||||
* Has to return an empty array if no identifier isset.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function getIdentifierValues(object $object): array;
|
||||
}
|
||||
56
vendor/doctrine/persistence/src/Persistence/Mapping/ClassMetadataFactory.php
vendored
Normal file
56
vendor/doctrine/persistence/src/Persistence/Mapping/ClassMetadataFactory.php
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Persistence\Mapping;
|
||||
|
||||
/**
|
||||
* Contract for a Doctrine persistence layer ClassMetadata class to implement.
|
||||
*
|
||||
* @template T of ClassMetadata
|
||||
*/
|
||||
interface ClassMetadataFactory
|
||||
{
|
||||
/**
|
||||
* Forces the factory to load the metadata of all classes known to the underlying
|
||||
* mapping driver.
|
||||
*
|
||||
* @return ClassMetadata[] The ClassMetadata instances of all mapped classes.
|
||||
* @phpstan-return list<T>
|
||||
*/
|
||||
public function getAllMetadata(): array;
|
||||
|
||||
/**
|
||||
* Gets the class metadata descriptor for a class.
|
||||
*
|
||||
* @param class-string $className The name of the class.
|
||||
*
|
||||
* @phpstan-return T
|
||||
*/
|
||||
public function getMetadataFor(string $className): ClassMetadata;
|
||||
|
||||
/**
|
||||
* Checks whether the factory has the metadata for a class loaded already.
|
||||
*
|
||||
* @param class-string $className
|
||||
*
|
||||
* @return bool TRUE if the metadata of the class in question is already loaded, FALSE otherwise.
|
||||
*/
|
||||
public function hasMetadataFor(string $className): bool;
|
||||
|
||||
/**
|
||||
* Sets the metadata descriptor for a specific class.
|
||||
*
|
||||
* @param class-string $className
|
||||
* @phpstan-param T $class
|
||||
*/
|
||||
public function setMetadataFor(string $className, ClassMetadata $class): void;
|
||||
|
||||
/**
|
||||
* Returns whether the class with the specified name should have its metadata loaded.
|
||||
* This is only the case if it is either mapped directly or as a MappedSuperclass.
|
||||
*
|
||||
* @phpstan-param class-string $className
|
||||
*/
|
||||
public function isTransient(string $className): bool;
|
||||
}
|
||||
14
vendor/doctrine/persistence/src/Persistence/Mapping/Driver/ClassLocator.php
vendored
Normal file
14
vendor/doctrine/persistence/src/Persistence/Mapping/Driver/ClassLocator.php
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Persistence\Mapping\Driver;
|
||||
|
||||
/**
|
||||
* ClassLocator is an interface for classes that can provide a list of class names.
|
||||
*/
|
||||
interface ClassLocator
|
||||
{
|
||||
/** @return list<class-string> */
|
||||
public function getClassNames(): array;
|
||||
}
|
||||
23
vendor/doctrine/persistence/src/Persistence/Mapping/Driver/ClassNames.php
vendored
Normal file
23
vendor/doctrine/persistence/src/Persistence/Mapping/Driver/ClassNames.php
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Persistence\Mapping\Driver;
|
||||
|
||||
/**
|
||||
* Basic implementation of ClassLocator that passes a list of class names.
|
||||
*/
|
||||
final class ClassNames implements ClassLocator
|
||||
{
|
||||
/** @param list<class-string> $classNames */
|
||||
public function __construct(
|
||||
private array $classNames,
|
||||
) {
|
||||
}
|
||||
|
||||
/** @return list<class-string> */
|
||||
public function getClassNames(): array
|
||||
{
|
||||
return $this->classNames;
|
||||
}
|
||||
}
|
||||
138
vendor/doctrine/persistence/src/Persistence/Mapping/Driver/ColocatedMappingDriver.php
vendored
Normal file
138
vendor/doctrine/persistence/src/Persistence/Mapping/Driver/ColocatedMappingDriver.php
vendored
Normal file
@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Persistence\Mapping\Driver;
|
||||
|
||||
use Doctrine\Persistence\Mapping\MappingException;
|
||||
|
||||
use function array_filter;
|
||||
use function array_merge;
|
||||
use function array_unique;
|
||||
use function array_values;
|
||||
|
||||
/**
|
||||
* The ColocatedMappingDriver reads the mapping metadata located near the code.
|
||||
*/
|
||||
trait ColocatedMappingDriver
|
||||
{
|
||||
private ClassLocator|null $classLocator = null;
|
||||
|
||||
/**
|
||||
* The directory paths where to look for mapping files.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected array $paths = [];
|
||||
|
||||
/**
|
||||
* The paths excluded from path where to look for mapping files.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected array $excludePaths = [];
|
||||
|
||||
/** The file extension of mapping documents. */
|
||||
protected string $fileExtension = '.php';
|
||||
|
||||
/**
|
||||
* Cache for {@see getAllClassNames()}.
|
||||
*
|
||||
* @var array<int, string>|null
|
||||
* @phpstan-var list<class-string>|null
|
||||
*/
|
||||
protected array|null $classNames = null;
|
||||
|
||||
/**
|
||||
* Appends lookup paths to metadata driver.
|
||||
*
|
||||
* @param array<int, string> $paths
|
||||
*/
|
||||
public function addPaths(array $paths): void
|
||||
{
|
||||
$this->paths = array_unique(array_merge($this->paths, $paths));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the defined metadata lookup paths.
|
||||
*
|
||||
* @return array<int, string>
|
||||
*/
|
||||
public function getPaths(): array
|
||||
{
|
||||
return $this->paths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append exclude lookup paths to a metadata driver.
|
||||
*
|
||||
* @param string[] $paths
|
||||
*/
|
||||
public function addExcludePaths(array $paths): void
|
||||
{
|
||||
$this->excludePaths = array_unique(array_merge($this->excludePaths, $paths));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the defined metadata lookup exclude paths.
|
||||
*
|
||||
* @return array<int, string>
|
||||
*/
|
||||
public function getExcludePaths(): array
|
||||
{
|
||||
return $this->excludePaths;
|
||||
}
|
||||
|
||||
/** Gets the file extension used to look for mapping files under. */
|
||||
public function getFileExtension(): string
|
||||
{
|
||||
return $this->fileExtension;
|
||||
}
|
||||
|
||||
/** Sets the file extension used to look for mapping files under. */
|
||||
public function setFileExtension(string $fileExtension): void
|
||||
{
|
||||
$this->fileExtension = $fileExtension;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* Returns whether the class with the specified name is transient. Only non-transient
|
||||
* classes, that is entities and mapped superclasses, should have their metadata loaded.
|
||||
*
|
||||
* @phpstan-param class-string $className
|
||||
*/
|
||||
abstract public function isTransient(string $className): bool;
|
||||
|
||||
/**
|
||||
* Gets the names of all mapped classes known to this driver.
|
||||
*
|
||||
* @return string[] The names of all mapped classes known to this driver.
|
||||
* @phpstan-return list<class-string>
|
||||
*/
|
||||
public function getAllClassNames(): array
|
||||
{
|
||||
if ($this->classNames !== null) {
|
||||
return $this->classNames;
|
||||
}
|
||||
|
||||
if ($this->paths === [] && $this->classLocator === null) {
|
||||
throw MappingException::pathRequiredForDriver(static::class);
|
||||
}
|
||||
|
||||
$classNames = $this->classLocator?->getClassNames() ?? [];
|
||||
|
||||
if ($this->paths !== []) {
|
||||
$classNames = array_unique([
|
||||
...FileClassLocator::createFromDirectories($this->paths, $this->excludePaths, $this->fileExtension)->getClassNames(),
|
||||
...$classNames,
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->classNames = array_values(array_filter(
|
||||
$classNames,
|
||||
fn (string $className): bool => ! $this->isTransient($className),
|
||||
));
|
||||
}
|
||||
}
|
||||
156
vendor/doctrine/persistence/src/Persistence/Mapping/Driver/DefaultFileLocator.php
vendored
Normal file
156
vendor/doctrine/persistence/src/Persistence/Mapping/Driver/DefaultFileLocator.php
vendored
Normal file
@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Persistence\Mapping\Driver;
|
||||
|
||||
use Doctrine\Persistence\Mapping\MappingException;
|
||||
use RecursiveDirectoryIterator;
|
||||
use RecursiveIteratorIterator;
|
||||
|
||||
use function array_unique;
|
||||
use function assert;
|
||||
use function is_dir;
|
||||
use function is_file;
|
||||
use function is_string;
|
||||
use function str_replace;
|
||||
|
||||
use const DIRECTORY_SEPARATOR;
|
||||
|
||||
/**
|
||||
* Locates the file that contains the metadata information for a given class name.
|
||||
*
|
||||
* This behavior is independent of the actual content of the file. It just detects
|
||||
* the file which is responsible for the given class name.
|
||||
*/
|
||||
class DefaultFileLocator implements FileLocator
|
||||
{
|
||||
/**
|
||||
* The paths where to look for mapping files.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected array $paths = [];
|
||||
|
||||
/** The file extension of mapping documents. */
|
||||
protected string|null $fileExtension;
|
||||
|
||||
/**
|
||||
* Initializes a new FileDriver that looks in the given path(s) for mapping
|
||||
* documents and operates in the specified operating mode.
|
||||
*
|
||||
* @param string|array<int, string> $paths One or multiple paths where mapping documents
|
||||
* can be found.
|
||||
* @param string|null $fileExtension The file extension of mapping documents,
|
||||
* usually prefixed with a dot.
|
||||
*/
|
||||
public function __construct(string|array $paths, string|null $fileExtension = null)
|
||||
{
|
||||
$this->addPaths((array) $paths);
|
||||
$this->fileExtension = $fileExtension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends lookup paths to metadata driver.
|
||||
*
|
||||
* @param array<int, string> $paths
|
||||
*/
|
||||
public function addPaths(array $paths): void
|
||||
{
|
||||
$this->paths = array_unique([...$this->paths, ...$paths]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the defined metadata lookup paths.
|
||||
*
|
||||
* @return array<int, string>
|
||||
*/
|
||||
public function getPaths(): array
|
||||
{
|
||||
return $this->paths;
|
||||
}
|
||||
|
||||
/** Gets the file extension used to look for mapping files under. */
|
||||
public function getFileExtension(): string|null
|
||||
{
|
||||
return $this->fileExtension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the file extension used to look for mapping files under.
|
||||
*
|
||||
* @param string|null $fileExtension The file extension to set.
|
||||
*/
|
||||
public function setFileExtension(string|null $fileExtension): void
|
||||
{
|
||||
$this->fileExtension = $fileExtension;
|
||||
}
|
||||
|
||||
public function findMappingFile(string $className): string
|
||||
{
|
||||
$fileName = str_replace('\\', '.', $className) . $this->fileExtension;
|
||||
|
||||
// Check whether file exists
|
||||
foreach ($this->paths as $path) {
|
||||
if (is_file($path . DIRECTORY_SEPARATOR . $fileName)) {
|
||||
return $path . DIRECTORY_SEPARATOR . $fileName;
|
||||
}
|
||||
}
|
||||
|
||||
throw MappingException::mappingFileNotFound($className, $fileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getAllClassNames(string $globalBasename): array
|
||||
{
|
||||
if ($this->paths === []) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$classes = [];
|
||||
|
||||
foreach ($this->paths as $path) {
|
||||
if (! is_dir($path)) {
|
||||
throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path);
|
||||
}
|
||||
|
||||
$iterator = new RecursiveIteratorIterator(
|
||||
new RecursiveDirectoryIterator($path),
|
||||
RecursiveIteratorIterator::LEAVES_ONLY,
|
||||
);
|
||||
|
||||
foreach ($iterator as $file) {
|
||||
$fileName = $file->getBasename($this->fileExtension);
|
||||
|
||||
if ($fileName === $file->getBasename() || $fileName === $globalBasename) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// NOTE: All files found here means classes are not transient!
|
||||
|
||||
assert(is_string($fileName));
|
||||
/** @phpstan-var class-string */
|
||||
$class = str_replace('.', '\\', $fileName);
|
||||
$classes[] = $class;
|
||||
}
|
||||
}
|
||||
|
||||
return $classes;
|
||||
}
|
||||
|
||||
public function fileExists(string $className): bool
|
||||
{
|
||||
$fileName = str_replace('\\', '.', $className) . $this->fileExtension;
|
||||
|
||||
// Check whether file exists
|
||||
foreach ($this->paths as $path) {
|
||||
if (is_file($path . DIRECTORY_SEPARATOR . $fileName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
143
vendor/doctrine/persistence/src/Persistence/Mapping/Driver/FileClassLocator.php
vendored
Normal file
143
vendor/doctrine/persistence/src/Persistence/Mapping/Driver/FileClassLocator.php
vendored
Normal file
@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Persistence\Mapping\Driver;
|
||||
|
||||
use AppendIterator;
|
||||
use CallbackFilterIterator;
|
||||
use Doctrine\Persistence\Mapping\MappingException;
|
||||
use FilesystemIterator;
|
||||
use InvalidArgumentException;
|
||||
use Iterator;
|
||||
use RecursiveDirectoryIterator;
|
||||
use RecursiveIteratorIterator;
|
||||
use ReflectionClass;
|
||||
use RegexIterator;
|
||||
use SplFileInfo;
|
||||
|
||||
use function array_key_exists;
|
||||
use function array_map;
|
||||
use function assert;
|
||||
use function get_debug_type;
|
||||
use function get_declared_classes;
|
||||
use function is_dir;
|
||||
use function preg_quote;
|
||||
use function realpath;
|
||||
use function sprintf;
|
||||
use function str_replace;
|
||||
use function str_starts_with;
|
||||
|
||||
/**
|
||||
* ClassLocator implementation that uses a list of file names to locate PHP files
|
||||
* and extract class names from them.
|
||||
*
|
||||
* It is compatible with the Symfony Finder component, but does not require it.
|
||||
*/
|
||||
final class FileClassLocator implements ClassLocator
|
||||
{
|
||||
/** @param iterable<SplFileInfo> $files An iterable of files to include. */
|
||||
public function __construct(
|
||||
private iterable $files,
|
||||
) {
|
||||
}
|
||||
|
||||
/** @return list<class-string> */
|
||||
public function getClassNames(): array
|
||||
{
|
||||
$includedFiles = [];
|
||||
|
||||
foreach ($this->files as $file) {
|
||||
// @phpstan-ignore function.alreadyNarrowedType, instanceof.alwaysTrue
|
||||
assert($file instanceof SplFileInfo, new InvalidArgumentException(sprintf('Expected an iterable of SplFileInfo, got %s', get_debug_type($file))));
|
||||
|
||||
// Skip non-files
|
||||
if (! $file->isFile()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// getRealPath() returns false if the file is in a phar archive
|
||||
// @phpstan-ignore ternary.shortNotAllowed (false is the only falsy value getRealPath() may return)
|
||||
$fileName = $file->getRealPath() ?: $file->getPathname();
|
||||
|
||||
$includedFiles[$fileName] = true;
|
||||
require_once $fileName;
|
||||
}
|
||||
|
||||
$classes = [];
|
||||
foreach (get_declared_classes() as $className) {
|
||||
$fileName = (new ReflectionClass($className))->getFileName();
|
||||
|
||||
if ($fileName === false || ! array_key_exists($fileName, $includedFiles)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$classes[] = $className;
|
||||
}
|
||||
|
||||
return $classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a FileClassLocator from an array of directories.
|
||||
*
|
||||
* @param list<string> $directories
|
||||
* @param list<string> $excludedDirectories Directories to exclude from the search.
|
||||
* @param string $fileExtension The file extension to look for (default is '.php').
|
||||
*
|
||||
* @throws MappingException if any of the directories are not valid.
|
||||
*/
|
||||
public static function createFromDirectories(
|
||||
array $directories,
|
||||
array $excludedDirectories = [],
|
||||
string $fileExtension = '.php',
|
||||
): self {
|
||||
$filesIterator = new AppendIterator();
|
||||
|
||||
foreach ($directories as $directory) {
|
||||
if (! is_dir($directory)) {
|
||||
throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($directory);
|
||||
}
|
||||
|
||||
/** @var Iterator<array-key,SplFileInfo> $iterator */
|
||||
$iterator = new RegexIterator(
|
||||
new RecursiveIteratorIterator(
|
||||
new RecursiveDirectoryIterator($directory, FilesystemIterator::SKIP_DOTS),
|
||||
RecursiveIteratorIterator::LEAVES_ONLY,
|
||||
),
|
||||
sprintf('/%s$/', preg_quote($fileExtension, '/')),
|
||||
RegexIterator::MATCH,
|
||||
);
|
||||
|
||||
$filesIterator->append($iterator);
|
||||
}
|
||||
|
||||
if ($excludedDirectories !== []) {
|
||||
$excludedDirectories = array_map(
|
||||
// realpath() returns false if the file is in a phar archive
|
||||
// @phpstan-ignore ternary.shortNotAllowed (false is the only falsy value realpath() may return)
|
||||
static fn (string $dir): string => str_replace('\\', '/', realpath($dir) ?: $dir),
|
||||
$excludedDirectories,
|
||||
);
|
||||
|
||||
$filesIterator = new CallbackFilterIterator(
|
||||
$filesIterator,
|
||||
static function (SplFileInfo $file) use ($excludedDirectories): bool {
|
||||
// getRealPath() returns false if the file is in a phar archive
|
||||
// @phpstan-ignore ternary.shortNotAllowed (false is the only falsy value getRealPath() may return)
|
||||
$sourceFile = str_replace('\\', '/', $file->getRealPath() ?: $file->getPathname());
|
||||
|
||||
foreach ($excludedDirectories as $excludedDirectory) {
|
||||
if (str_starts_with($sourceFile, $excludedDirectory)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return new self($filesIterator);
|
||||
}
|
||||
}
|
||||
182
vendor/doctrine/persistence/src/Persistence/Mapping/Driver/FileDriver.php
vendored
Normal file
182
vendor/doctrine/persistence/src/Persistence/Mapping/Driver/FileDriver.php
vendored
Normal file
@ -0,0 +1,182 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Persistence\Mapping\Driver;
|
||||
|
||||
use Doctrine\Persistence\Mapping\ClassMetadata;
|
||||
use Doctrine\Persistence\Mapping\MappingException;
|
||||
|
||||
use function array_keys;
|
||||
use function array_unique;
|
||||
use function array_values;
|
||||
use function is_file;
|
||||
use function str_replace;
|
||||
|
||||
/**
|
||||
* Base driver for file-based metadata drivers.
|
||||
*
|
||||
* A file driver operates in a mode where it loads the mapping files of individual
|
||||
* classes on demand. This requires the user to adhere to the convention of 1 mapping
|
||||
* file per class and the file names of the mapping files must correspond to the full
|
||||
* class name, including namespace, with the namespace delimiters '\', replaced by dots '.'.
|
||||
*
|
||||
* @template T
|
||||
*/
|
||||
abstract class FileDriver implements MappingDriver
|
||||
{
|
||||
protected FileLocator $locator;
|
||||
|
||||
/**
|
||||
* @var mixed[]|null
|
||||
* @phpstan-var array<class-string, T>|null
|
||||
*/
|
||||
protected array|null $classCache = null;
|
||||
protected string $globalBasename = '';
|
||||
|
||||
/**
|
||||
* Initializes a new FileDriver that looks in the given path(s) for mapping
|
||||
* documents and operates in the specified operating mode.
|
||||
*
|
||||
* @param string|array<int, string>|FileLocator $locator A FileLocator or one/multiple paths
|
||||
* where mapping documents can be found.
|
||||
*/
|
||||
public function __construct(string|array|FileLocator $locator, string|null $fileExtension = null)
|
||||
{
|
||||
if ($locator instanceof FileLocator) {
|
||||
$this->locator = $locator;
|
||||
} else {
|
||||
$this->locator = new DefaultFileLocator((array) $locator, $fileExtension);
|
||||
}
|
||||
}
|
||||
|
||||
/** Sets the global basename. */
|
||||
public function setGlobalBasename(string $file): void
|
||||
{
|
||||
$this->globalBasename = $file;
|
||||
}
|
||||
|
||||
/** Retrieves the global basename. */
|
||||
public function getGlobalBasename(): string
|
||||
{
|
||||
return $this->globalBasename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the element of schema meta data for the class from the mapping file.
|
||||
* This will lazily load the mapping file if it is not loaded yet.
|
||||
*
|
||||
* @phpstan-param class-string $className
|
||||
*
|
||||
* @return T The element of schema meta data.
|
||||
*
|
||||
* @throws MappingException
|
||||
*/
|
||||
public function getElement(string $className): mixed
|
||||
{
|
||||
if ($this->classCache === null) {
|
||||
$this->initialize();
|
||||
}
|
||||
|
||||
if (isset($this->classCache[$className])) {
|
||||
return $this->classCache[$className];
|
||||
}
|
||||
|
||||
$result = $this->loadMappingFile($this->locator->findMappingFile($className));
|
||||
|
||||
if (! isset($result[$className])) {
|
||||
throw MappingException::invalidMappingFile(
|
||||
$className,
|
||||
str_replace('\\', '.', $className) . $this->locator->getFileExtension(),
|
||||
);
|
||||
}
|
||||
|
||||
$this->classCache[$className] = $result[$className];
|
||||
|
||||
return $result[$className];
|
||||
}
|
||||
|
||||
public function isTransient(string $className): bool
|
||||
{
|
||||
if ($this->classCache === null) {
|
||||
$this->initialize();
|
||||
}
|
||||
|
||||
if (isset($this->classCache[$className])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ! $this->locator->fileExists($className);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getAllClassNames(): array
|
||||
{
|
||||
if ($this->classCache === null) {
|
||||
$this->initialize();
|
||||
}
|
||||
|
||||
if ($this->classCache === []) {
|
||||
return $this->locator->getAllClassNames($this->globalBasename);
|
||||
}
|
||||
|
||||
/** @phpstan-var array<class-string, ClassMetadata<object>> $classCache */
|
||||
$classCache = $this->classCache;
|
||||
|
||||
/** @var list<class-string> $keys */
|
||||
$keys = array_keys($classCache);
|
||||
|
||||
return array_values(array_unique([...$keys, ...$this->locator->getAllClassNames($this->globalBasename)]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a mapping file with the given name and returns a map
|
||||
* from class/entity names to their corresponding file driver elements.
|
||||
*
|
||||
* @param string $file The mapping file to load.
|
||||
*
|
||||
* @return mixed[]
|
||||
* @phpstan-return array<class-string, T>
|
||||
*/
|
||||
abstract protected function loadMappingFile(string $file): array;
|
||||
|
||||
/**
|
||||
* Initializes the class cache from all the global files.
|
||||
*
|
||||
* Using this feature adds a substantial performance hit to file drivers as
|
||||
* more metadata has to be loaded into memory than might actually be
|
||||
* necessary. This may not be relevant to scenarios where caching of
|
||||
* metadata is in place, however hits very hard in scenarios where no
|
||||
* caching is used.
|
||||
*/
|
||||
protected function initialize(): void
|
||||
{
|
||||
$this->classCache = [];
|
||||
if ($this->globalBasename === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($this->locator->getPaths() as $path) {
|
||||
$file = $path . '/' . $this->globalBasename . $this->locator->getFileExtension();
|
||||
if (! is_file($file)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->classCache = [...$this->classCache, ...$this->loadMappingFile($file)];
|
||||
}
|
||||
}
|
||||
|
||||
/** Retrieves the locator used to discover mapping files by className. */
|
||||
public function getLocator(): FileLocator
|
||||
{
|
||||
return $this->locator;
|
||||
}
|
||||
|
||||
/** Sets the locator used to discover mapping files by className. */
|
||||
public function setLocator(FileLocator $locator): void
|
||||
{
|
||||
$this->locator = $locator;
|
||||
}
|
||||
}
|
||||
40
vendor/doctrine/persistence/src/Persistence/Mapping/Driver/FileLocator.php
vendored
Normal file
40
vendor/doctrine/persistence/src/Persistence/Mapping/Driver/FileLocator.php
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Persistence\Mapping\Driver;
|
||||
|
||||
/**
|
||||
* Locates the file that contains the metadata information for a given class name.
|
||||
*
|
||||
* This behavior is independent of the actual content of the file. It just detects
|
||||
* the file which is responsible for the given class name.
|
||||
*/
|
||||
interface FileLocator
|
||||
{
|
||||
/** Locates mapping file for the given class name. */
|
||||
public function findMappingFile(string $className): string;
|
||||
|
||||
/**
|
||||
* Gets all class names that are found with this file locator.
|
||||
*
|
||||
* @param string $globalBasename Passed to allow excluding the basename.
|
||||
*
|
||||
* @return array<int, string>
|
||||
* @phpstan-return list<class-string>
|
||||
*/
|
||||
public function getAllClassNames(string $globalBasename): array;
|
||||
|
||||
/** Checks if a file can be found for this class name. */
|
||||
public function fileExists(string $className): bool;
|
||||
|
||||
/**
|
||||
* Gets all the paths that this file locator looks for mapping files.
|
||||
*
|
||||
* @return array<int, string>
|
||||
*/
|
||||
public function getPaths(): array;
|
||||
|
||||
/** Gets the file extension that mapping files are suffixed with. */
|
||||
public function getFileExtension(): string|null;
|
||||
}
|
||||
39
vendor/doctrine/persistence/src/Persistence/Mapping/Driver/MappingDriver.php
vendored
Normal file
39
vendor/doctrine/persistence/src/Persistence/Mapping/Driver/MappingDriver.php
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Persistence\Mapping\Driver;
|
||||
|
||||
use Doctrine\Persistence\Mapping\ClassMetadata;
|
||||
|
||||
/**
|
||||
* Contract for metadata drivers.
|
||||
*/
|
||||
interface MappingDriver
|
||||
{
|
||||
/**
|
||||
* Loads the metadata for the specified class into the provided container.
|
||||
*
|
||||
* @phpstan-param class-string<T> $className
|
||||
* @phpstan-param ClassMetadata<T> $metadata
|
||||
*
|
||||
* @template T of object
|
||||
*/
|
||||
public function loadMetadataForClass(string $className, ClassMetadata $metadata): void;
|
||||
|
||||
/**
|
||||
* Gets the names of all mapped classes known to this driver.
|
||||
*
|
||||
* @return array<int, string> The names of all mapped classes known to this driver.
|
||||
* @phpstan-return list<class-string>
|
||||
*/
|
||||
public function getAllClassNames(): array;
|
||||
|
||||
/**
|
||||
* Returns whether the class with the specified name should have its metadata loaded.
|
||||
* This is only the case if it is either mapped as an Entity or a MappedSuperclass.
|
||||
*
|
||||
* @phpstan-param class-string $className
|
||||
*/
|
||||
public function isTransient(string $className): bool;
|
||||
}
|
||||
122
vendor/doctrine/persistence/src/Persistence/Mapping/Driver/MappingDriverChain.php
vendored
Normal file
122
vendor/doctrine/persistence/src/Persistence/Mapping/Driver/MappingDriverChain.php
vendored
Normal file
@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Persistence\Mapping\Driver;
|
||||
|
||||
use Doctrine\Persistence\Mapping\ClassMetadata;
|
||||
use Doctrine\Persistence\Mapping\MappingException;
|
||||
|
||||
use function array_keys;
|
||||
use function spl_object_id;
|
||||
use function str_starts_with;
|
||||
|
||||
/**
|
||||
* The DriverChain allows you to add multiple other mapping drivers for
|
||||
* certain namespaces.
|
||||
*/
|
||||
class MappingDriverChain implements MappingDriver
|
||||
{
|
||||
/**
|
||||
* The default driver.
|
||||
*/
|
||||
private MappingDriver|null $defaultDriver = null;
|
||||
|
||||
/** @var array<string, MappingDriver> */
|
||||
private array $drivers = [];
|
||||
|
||||
/** Gets the default driver. */
|
||||
public function getDefaultDriver(): MappingDriver|null
|
||||
{
|
||||
return $this->defaultDriver;
|
||||
}
|
||||
|
||||
/** Set the default driver. */
|
||||
public function setDefaultDriver(MappingDriver $driver): void
|
||||
{
|
||||
$this->defaultDriver = $driver;
|
||||
}
|
||||
|
||||
/** Adds a nested driver. */
|
||||
public function addDriver(MappingDriver $nestedDriver, string $namespace): void
|
||||
{
|
||||
$this->drivers[$namespace] = $nestedDriver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the array of nested drivers.
|
||||
*
|
||||
* @return array<string, MappingDriver> $drivers
|
||||
*/
|
||||
public function getDrivers(): array
|
||||
{
|
||||
return $this->drivers;
|
||||
}
|
||||
|
||||
public function loadMetadataForClass(string $className, ClassMetadata $metadata): void
|
||||
{
|
||||
foreach ($this->drivers as $namespace => $driver) {
|
||||
if (str_starts_with($className, $namespace)) {
|
||||
$driver->loadMetadataForClass($className, $metadata);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->defaultDriver !== null) {
|
||||
$this->defaultDriver->loadMetadataForClass($className, $metadata);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
throw MappingException::classNotFoundInNamespaces($className, array_keys($this->drivers));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getAllClassNames(): array
|
||||
{
|
||||
$classNames = [];
|
||||
$driverClasses = [];
|
||||
|
||||
foreach ($this->drivers as $namespace => $driver) {
|
||||
$oid = spl_object_id($driver);
|
||||
|
||||
if (! isset($driverClasses[$oid])) {
|
||||
$driverClasses[$oid] = $driver->getAllClassNames();
|
||||
}
|
||||
|
||||
foreach ($driverClasses[$oid] as $className) {
|
||||
if (! str_starts_with($className, $namespace)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$classNames[$className] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->defaultDriver !== null) {
|
||||
foreach ($this->defaultDriver->getAllClassNames() as $className) {
|
||||
$classNames[$className] = true;
|
||||
}
|
||||
}
|
||||
|
||||
return array_keys($classNames);
|
||||
}
|
||||
|
||||
public function isTransient(string $className): bool
|
||||
{
|
||||
foreach ($this->drivers as $namespace => $driver) {
|
||||
if (str_starts_with($className, $namespace)) {
|
||||
return $driver->isTransient($className);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->defaultDriver !== null) {
|
||||
return $this->defaultDriver->isTransient($className);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
43
vendor/doctrine/persistence/src/Persistence/Mapping/Driver/PHPDriver.php
vendored
Normal file
43
vendor/doctrine/persistence/src/Persistence/Mapping/Driver/PHPDriver.php
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Persistence\Mapping\Driver;
|
||||
|
||||
use Doctrine\Persistence\Mapping\ClassMetadata;
|
||||
|
||||
/**
|
||||
* The PHPDriver includes php files which just populate ClassMetadataInfo
|
||||
* instances with plain PHP code.
|
||||
*
|
||||
* @template-extends FileDriver<ClassMetadata<object>>
|
||||
*/
|
||||
class PHPDriver extends FileDriver
|
||||
{
|
||||
/** @phpstan-var ClassMetadata<object> */
|
||||
protected ClassMetadata $metadata;
|
||||
|
||||
/** @param string|array<int, string>|FileLocator $locator */
|
||||
public function __construct(string|array|FileLocator $locator)
|
||||
{
|
||||
parent::__construct($locator, '.php');
|
||||
}
|
||||
|
||||
public function loadMetadataForClass(string $className, ClassMetadata $metadata): void
|
||||
{
|
||||
$this->metadata = $metadata;
|
||||
|
||||
$this->loadMappingFile($this->locator->findMappingFile($className));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function loadMappingFile(string $file): array
|
||||
{
|
||||
$metadata = $this->metadata;
|
||||
include $file;
|
||||
|
||||
return [$metadata->getName() => $metadata];
|
||||
}
|
||||
}
|
||||
121
vendor/doctrine/persistence/src/Persistence/Mapping/Driver/StaticPHPDriver.php
vendored
Normal file
121
vendor/doctrine/persistence/src/Persistence/Mapping/Driver/StaticPHPDriver.php
vendored
Normal file
@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Persistence\Mapping\Driver;
|
||||
|
||||
use Doctrine\Persistence\Mapping\ClassMetadata;
|
||||
use Doctrine\Persistence\Mapping\MappingException;
|
||||
use RecursiveDirectoryIterator;
|
||||
use RecursiveIteratorIterator;
|
||||
use ReflectionClass;
|
||||
|
||||
use function array_unique;
|
||||
use function get_declared_classes;
|
||||
use function in_array;
|
||||
use function is_dir;
|
||||
use function method_exists;
|
||||
use function realpath;
|
||||
|
||||
/**
|
||||
* The StaticPHPDriver calls a static loadMetadata() method on your entity
|
||||
* classes where you can manually populate the ClassMetadata instance.
|
||||
*/
|
||||
class StaticPHPDriver implements MappingDriver
|
||||
{
|
||||
/**
|
||||
* Paths of entity directories.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
private array $paths = [];
|
||||
|
||||
/**
|
||||
* Map of all class names.
|
||||
*
|
||||
* @var array<int, string>
|
||||
* @phpstan-var list<class-string>
|
||||
*/
|
||||
private array|null $classNames = null;
|
||||
|
||||
/** @param array<int, string>|string $paths */
|
||||
public function __construct(array|string $paths)
|
||||
{
|
||||
$this->addPaths((array) $paths);
|
||||
}
|
||||
|
||||
/** @param array<int, string> $paths */
|
||||
public function addPaths(array $paths): void
|
||||
{
|
||||
$this->paths = array_unique([...$this->paths, ...$paths]);
|
||||
}
|
||||
|
||||
public function loadMetadataForClass(string $className, ClassMetadata $metadata): void
|
||||
{
|
||||
$className::loadMetadata($metadata);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @todo Same code exists in ColocatedMappingDriver, should we re-use it
|
||||
* somehow or not worry about it?
|
||||
*/
|
||||
public function getAllClassNames(): array
|
||||
{
|
||||
if ($this->classNames !== null) {
|
||||
return $this->classNames;
|
||||
}
|
||||
|
||||
if ($this->paths === []) {
|
||||
throw MappingException::pathRequiredForDriver(static::class);
|
||||
}
|
||||
|
||||
$classes = [];
|
||||
$includedFiles = [];
|
||||
|
||||
foreach ($this->paths as $path) {
|
||||
if (! is_dir($path)) {
|
||||
throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path);
|
||||
}
|
||||
|
||||
$iterator = new RecursiveIteratorIterator(
|
||||
new RecursiveDirectoryIterator($path),
|
||||
RecursiveIteratorIterator::LEAVES_ONLY,
|
||||
);
|
||||
|
||||
foreach ($iterator as $file) {
|
||||
if ($file->getBasename('.php') === $file->getBasename()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$sourceFile = realpath($file->getPathName());
|
||||
require_once $sourceFile;
|
||||
$includedFiles[] = $sourceFile;
|
||||
}
|
||||
}
|
||||
|
||||
$declared = get_declared_classes();
|
||||
|
||||
foreach ($declared as $className) {
|
||||
$rc = new ReflectionClass($className);
|
||||
|
||||
$sourceFile = $rc->getFileName();
|
||||
|
||||
if (! in_array($sourceFile, $includedFiles, true) || $this->isTransient($className)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$classes[] = $className;
|
||||
}
|
||||
|
||||
$this->classNames = $classes;
|
||||
|
||||
return $classes;
|
||||
}
|
||||
|
||||
public function isTransient(string $className): bool
|
||||
{
|
||||
return ! method_exists($className, 'loadMetadata');
|
||||
}
|
||||
}
|
||||
245
vendor/doctrine/persistence/src/Persistence/Mapping/Driver/SymfonyFileLocator.php
vendored
Normal file
245
vendor/doctrine/persistence/src/Persistence/Mapping/Driver/SymfonyFileLocator.php
vendored
Normal file
@ -0,0 +1,245 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Persistence\Mapping\Driver;
|
||||
|
||||
use Doctrine\Persistence\Mapping\MappingException;
|
||||
use InvalidArgumentException;
|
||||
use RecursiveDirectoryIterator;
|
||||
use RecursiveIteratorIterator;
|
||||
use RuntimeException;
|
||||
|
||||
use function array_keys;
|
||||
use function assert;
|
||||
use function is_dir;
|
||||
use function is_file;
|
||||
use function is_int;
|
||||
use function realpath;
|
||||
use function sprintf;
|
||||
use function str_replace;
|
||||
use function str_starts_with;
|
||||
use function strlen;
|
||||
use function strrpos;
|
||||
use function strtr;
|
||||
use function substr;
|
||||
|
||||
use const DIRECTORY_SEPARATOR;
|
||||
|
||||
/**
|
||||
* The Symfony File Locator makes a simplifying assumptions compared
|
||||
* to the DefaultFileLocator. By assuming paths only contain entities of a certain
|
||||
* namespace the mapping files consists of the short classname only.
|
||||
*/
|
||||
class SymfonyFileLocator implements FileLocator
|
||||
{
|
||||
/**
|
||||
* The paths where to look for mapping files.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected array $paths = [];
|
||||
|
||||
/**
|
||||
* A map of mapping directory path to namespace prefix used to expand class shortnames.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected array $prefixes = [];
|
||||
|
||||
/** File extension that is searched for. */
|
||||
protected string|null $fileExtension;
|
||||
|
||||
/**
|
||||
* Represents PHP namespace delimiters when looking for files
|
||||
*/
|
||||
private readonly string $nsSeparator;
|
||||
|
||||
/**
|
||||
* @param array<string, string> $prefixes
|
||||
* @param string $nsSeparator String which would be used when converting FQCN
|
||||
* to filename and vice versa. Should not be empty
|
||||
*/
|
||||
public function __construct(
|
||||
array $prefixes,
|
||||
string $fileExtension = '',
|
||||
string $nsSeparator = '.',
|
||||
) {
|
||||
$this->addNamespacePrefixes($prefixes);
|
||||
$this->fileExtension = $fileExtension;
|
||||
|
||||
if ($nsSeparator === '') {
|
||||
throw new InvalidArgumentException('Namespace separator should not be empty');
|
||||
}
|
||||
|
||||
$this->nsSeparator = $nsSeparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds Namespace Prefixes.
|
||||
*
|
||||
* @param array<string, string> $prefixes
|
||||
*/
|
||||
public function addNamespacePrefixes(array $prefixes): void
|
||||
{
|
||||
$this->prefixes = [...$this->prefixes, ...$prefixes];
|
||||
$this->paths = [...$this->paths, ...array_keys($prefixes)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets Namespace Prefixes.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getNamespacePrefixes(): array
|
||||
{
|
||||
return $this->prefixes;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getPaths(): array
|
||||
{
|
||||
return $this->paths;
|
||||
}
|
||||
|
||||
public function getFileExtension(): string|null
|
||||
{
|
||||
return $this->fileExtension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the file extension used to look for mapping files under.
|
||||
*
|
||||
* @param string $fileExtension The file extension to set.
|
||||
*/
|
||||
public function setFileExtension(string $fileExtension): void
|
||||
{
|
||||
$this->fileExtension = $fileExtension;
|
||||
}
|
||||
|
||||
public function fileExists(string $className): bool
|
||||
{
|
||||
$defaultFileName = str_replace('\\', $this->nsSeparator, $className) . $this->fileExtension;
|
||||
foreach ($this->paths as $path) {
|
||||
if (! isset($this->prefixes[$path])) {
|
||||
// global namespace class
|
||||
if (is_file($path . DIRECTORY_SEPARATOR . $defaultFileName)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$prefix = $this->prefixes[$path];
|
||||
|
||||
if (! str_starts_with($className, $prefix . '\\')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$filename = $path . '/' . strtr(substr($className, strlen($prefix) + 1), '\\', $this->nsSeparator) . $this->fileExtension;
|
||||
|
||||
if (is_file($filename)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getAllClassNames(string|null $globalBasename = null): array
|
||||
{
|
||||
if ($this->paths === []) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$classes = [];
|
||||
|
||||
foreach ($this->paths as $path) {
|
||||
if (! is_dir($path)) {
|
||||
throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path);
|
||||
}
|
||||
|
||||
$iterator = new RecursiveIteratorIterator(
|
||||
new RecursiveDirectoryIterator($path),
|
||||
RecursiveIteratorIterator::LEAVES_ONLY,
|
||||
);
|
||||
|
||||
foreach ($iterator as $file) {
|
||||
$fileName = $file->getBasename($this->fileExtension);
|
||||
|
||||
if ($fileName === $file->getBasename() || $fileName === $globalBasename) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// NOTE: All files found here means classes are not transient!
|
||||
if (isset($this->prefixes[$path])) {
|
||||
// Calculate namespace suffix for given prefix as a relative path from basepath to file path
|
||||
$nsSuffix = strtr(
|
||||
substr($this->realpath($file->getPath()), strlen($this->realpath($path))),
|
||||
$this->nsSeparator,
|
||||
'\\',
|
||||
);
|
||||
|
||||
/** @phpstan-var class-string */
|
||||
$class = $this->prefixes[$path] . str_replace(DIRECTORY_SEPARATOR, '\\', $nsSuffix) . '\\' . str_replace($this->nsSeparator, '\\', $fileName);
|
||||
} else {
|
||||
/** @phpstan-var class-string */
|
||||
$class = str_replace($this->nsSeparator, '\\', $fileName);
|
||||
}
|
||||
|
||||
$classes[] = $class;
|
||||
}
|
||||
}
|
||||
|
||||
return $classes;
|
||||
}
|
||||
|
||||
public function findMappingFile(string $className): string
|
||||
{
|
||||
$defaultFileName = str_replace('\\', $this->nsSeparator, $className) . $this->fileExtension;
|
||||
foreach ($this->paths as $path) {
|
||||
if (! isset($this->prefixes[$path])) {
|
||||
if (is_file($path . DIRECTORY_SEPARATOR . $defaultFileName)) {
|
||||
return $path . DIRECTORY_SEPARATOR . $defaultFileName;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$prefix = $this->prefixes[$path];
|
||||
|
||||
if (! str_starts_with($className, $prefix . '\\')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$filename = $path . '/' . strtr(substr($className, strlen($prefix) + 1), '\\', $this->nsSeparator) . $this->fileExtension;
|
||||
if (is_file($filename)) {
|
||||
return $filename;
|
||||
}
|
||||
}
|
||||
|
||||
$pos = strrpos($className, '\\');
|
||||
assert(is_int($pos));
|
||||
|
||||
throw MappingException::mappingFileNotFound(
|
||||
$className,
|
||||
substr($className, $pos + 1) . $this->fileExtension,
|
||||
);
|
||||
}
|
||||
|
||||
private function realpath(string $path): string
|
||||
{
|
||||
$realpath = realpath($path);
|
||||
|
||||
if ($realpath === false) {
|
||||
throw new RuntimeException(sprintf('Could not get realpath for %s', $path));
|
||||
}
|
||||
|
||||
return $realpath;
|
||||
}
|
||||
}
|
||||
80
vendor/doctrine/persistence/src/Persistence/Mapping/MappingException.php
vendored
Normal file
80
vendor/doctrine/persistence/src/Persistence/Mapping/MappingException.php
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Persistence\Mapping;
|
||||
|
||||
use Exception;
|
||||
|
||||
use function implode;
|
||||
use function sprintf;
|
||||
|
||||
/**
|
||||
* A MappingException indicates that something is wrong with the mapping setup.
|
||||
*/
|
||||
class MappingException extends Exception
|
||||
{
|
||||
/** @param array<int, string> $namespaces */
|
||||
public static function classNotFoundInNamespaces(
|
||||
string $className,
|
||||
array $namespaces,
|
||||
): self {
|
||||
return new self(sprintf(
|
||||
"The class '%s' was not found in the chain configured namespaces %s",
|
||||
$className,
|
||||
implode(', ', $namespaces),
|
||||
));
|
||||
}
|
||||
|
||||
/** @param class-string $driverClassName */
|
||||
public static function pathRequiredForDriver(string $driverClassName): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
'Specifying source file paths to your entities is required when using %s to retrieve all class names.',
|
||||
$driverClassName,
|
||||
));
|
||||
}
|
||||
|
||||
public static function fileMappingDriversRequireConfiguredDirectoryPath(
|
||||
string|null $path = null,
|
||||
): self {
|
||||
if ($path !== null) {
|
||||
$path = '[' . $path . ']';
|
||||
}
|
||||
|
||||
return new self(sprintf(
|
||||
'File mapping drivers must have a valid directory path, ' .
|
||||
'however the given path %s seems to be incorrect!',
|
||||
(string) $path,
|
||||
));
|
||||
}
|
||||
|
||||
public static function mappingFileNotFound(string $entityName, string $fileName): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
"No mapping file found named '%s' for class '%s'.",
|
||||
$fileName,
|
||||
$entityName,
|
||||
));
|
||||
}
|
||||
|
||||
public static function invalidMappingFile(string $entityName, string $fileName): self
|
||||
{
|
||||
return new self(sprintf(
|
||||
"Invalid mapping file '%s' for class '%s'.",
|
||||
$fileName,
|
||||
$entityName,
|
||||
));
|
||||
}
|
||||
|
||||
public static function nonExistingClass(string $className): self
|
||||
{
|
||||
return new self(sprintf("Class '%s' does not exist", $className));
|
||||
}
|
||||
|
||||
/** @param class-string $className */
|
||||
public static function classIsAnonymous(string $className): self
|
||||
{
|
||||
return new self(sprintf('Class "%s" is anonymous', $className));
|
||||
}
|
||||
}
|
||||
19
vendor/doctrine/persistence/src/Persistence/Mapping/ProxyClassNameResolver.php
vendored
Normal file
19
vendor/doctrine/persistence/src/Persistence/Mapping/ProxyClassNameResolver.php
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Persistence\Mapping;
|
||||
|
||||
use Doctrine\Persistence\Proxy;
|
||||
|
||||
interface ProxyClassNameResolver
|
||||
{
|
||||
/**
|
||||
* @phpstan-param class-string<Proxy<T>>|class-string<T> $className
|
||||
*
|
||||
* @phpstan-return class-string<T>
|
||||
*
|
||||
* @template T of object
|
||||
*/
|
||||
public function resolveClassName(string $className): string;
|
||||
}
|
||||
64
vendor/doctrine/persistence/src/Persistence/Mapping/ReflectionService.php
vendored
Normal file
64
vendor/doctrine/persistence/src/Persistence/Mapping/ReflectionService.php
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Persistence\Mapping;
|
||||
|
||||
use ReflectionClass;
|
||||
use ReflectionProperty;
|
||||
|
||||
/**
|
||||
* Very simple reflection service abstraction.
|
||||
*
|
||||
* This is required inside metadata layers that may require either
|
||||
* static or runtime reflection.
|
||||
*/
|
||||
interface ReflectionService
|
||||
{
|
||||
/**
|
||||
* Returns an array of the parent classes (not interfaces) for the given class.
|
||||
*
|
||||
* @phpstan-param class-string $class
|
||||
*
|
||||
* @return string[]
|
||||
* @phpstan-return class-string[]
|
||||
*
|
||||
* @throws MappingException
|
||||
*/
|
||||
public function getParentClasses(string $class): array;
|
||||
|
||||
/**
|
||||
* Returns the shortname of a class.
|
||||
*
|
||||
* @phpstan-param class-string $class
|
||||
*/
|
||||
public function getClassShortName(string $class): string;
|
||||
|
||||
/** @phpstan-param class-string $class */
|
||||
public function getClassNamespace(string $class): string;
|
||||
|
||||
/**
|
||||
* Returns a reflection class instance or null.
|
||||
*
|
||||
* @phpstan-param class-string<T> $class
|
||||
*
|
||||
* @phpstan-return ReflectionClass<T>
|
||||
*
|
||||
* @template T of object
|
||||
*/
|
||||
public function getClass(string $class): ReflectionClass;
|
||||
|
||||
/**
|
||||
* Returns an accessible property or null.
|
||||
*
|
||||
* @phpstan-param class-string $class
|
||||
*/
|
||||
public function getAccessibleProperty(string $class, string $property): ReflectionProperty|null;
|
||||
|
||||
/**
|
||||
* Checks if the class have a public method with the given name.
|
||||
*
|
||||
* @phpstan-param class-string $class
|
||||
*/
|
||||
public function hasPublicMethod(string $class, string $method): bool;
|
||||
}
|
||||
95
vendor/doctrine/persistence/src/Persistence/Mapping/RuntimeReflectionService.php
vendored
Normal file
95
vendor/doctrine/persistence/src/Persistence/Mapping/RuntimeReflectionService.php
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Persistence\Mapping;
|
||||
|
||||
use Doctrine\Persistence\Reflection\RuntimeReflectionProperty;
|
||||
use Doctrine\Persistence\Reflection\TypedNoDefaultReflectionProperty;
|
||||
use ReflectionClass;
|
||||
use ReflectionException;
|
||||
use ReflectionMethod;
|
||||
|
||||
use function array_key_exists;
|
||||
use function assert;
|
||||
use function class_exists;
|
||||
use function class_parents;
|
||||
use function phpversion;
|
||||
use function version_compare;
|
||||
|
||||
/**
|
||||
* PHP Runtime Reflection Service.
|
||||
*/
|
||||
class RuntimeReflectionService implements ReflectionService
|
||||
{
|
||||
private readonly bool $supportsTypedPropertiesWorkaround;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->supportsTypedPropertiesWorkaround = version_compare(phpversion(), '7.4.0') >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getParentClasses(string $class): array
|
||||
{
|
||||
if (! class_exists($class)) {
|
||||
throw MappingException::nonExistingClass($class);
|
||||
}
|
||||
|
||||
$parents = class_parents($class);
|
||||
|
||||
assert($parents !== false);
|
||||
|
||||
return $parents;
|
||||
}
|
||||
|
||||
public function getClassShortName(string $class): string
|
||||
{
|
||||
$reflectionClass = new ReflectionClass($class);
|
||||
|
||||
return $reflectionClass->getShortName();
|
||||
}
|
||||
|
||||
public function getClassNamespace(string $class): string
|
||||
{
|
||||
$reflectionClass = new ReflectionClass($class);
|
||||
|
||||
return $reflectionClass->getNamespaceName();
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-param class-string<T> $class
|
||||
*
|
||||
* @phpstan-return ReflectionClass<T>
|
||||
*
|
||||
* @template T of object
|
||||
*/
|
||||
public function getClass(string $class): ReflectionClass
|
||||
{
|
||||
return new ReflectionClass($class);
|
||||
}
|
||||
|
||||
public function getAccessibleProperty(string $class, string $property): RuntimeReflectionProperty
|
||||
{
|
||||
$reflectionProperty = new RuntimeReflectionProperty($class, $property);
|
||||
|
||||
if ($this->supportsTypedPropertiesWorkaround && ! array_key_exists($property, $this->getClass($class)->getDefaultProperties())) {
|
||||
$reflectionProperty = new TypedNoDefaultReflectionProperty($class, $property);
|
||||
}
|
||||
|
||||
return $reflectionProperty;
|
||||
}
|
||||
|
||||
public function hasPublicMethod(string $class, string $method): bool
|
||||
{
|
||||
try {
|
||||
$reflectionMethod = new ReflectionMethod($class, $method);
|
||||
} catch (ReflectionException) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $reflectionMethod->isPublic();
|
||||
}
|
||||
}
|
||||
18
vendor/doctrine/persistence/src/Persistence/NotifyPropertyChanged.php
vendored
Normal file
18
vendor/doctrine/persistence/src/Persistence/NotifyPropertyChanged.php
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Persistence;
|
||||
|
||||
/**
|
||||
* Interface for classes that notify event listeners of changes to their managed properties.
|
||||
*
|
||||
* This interface is implemented by objects that manually want to notify their object manager or
|
||||
* other listeners when properties change, instead of relying on the object manager to compute
|
||||
* property changes itself when changes are to be persisted.
|
||||
*/
|
||||
interface NotifyPropertyChanged
|
||||
{
|
||||
/** Adds a listener that wants to be notified about property changes. */
|
||||
public function addPropertyChangedListener(PropertyChangedListener $listener): void;
|
||||
}
|
||||
128
vendor/doctrine/persistence/src/Persistence/ObjectManager.php
vendored
Normal file
128
vendor/doctrine/persistence/src/Persistence/ObjectManager.php
vendored
Normal file
@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Doctrine\Persistence;
|
||||
|
||||
use Doctrine\Persistence\Mapping\ClassMetadata;
|
||||
use Doctrine\Persistence\Mapping\ClassMetadataFactory;
|
||||
|
||||
/** Contract for a Doctrine persistence layer ObjectManager class to implement. */
|
||||
interface ObjectManager
|
||||
{
|
||||
/**
|
||||
* Finds an object by its identifier.
|
||||
*
|
||||
* This is just a convenient shortcut for getRepository($className)->find($id).
|
||||
*
|
||||
* @param string $className The class name of the object to find.
|
||||
* @param mixed $id The identity of the object to find.
|
||||
* @phpstan-param class-string<T> $className
|
||||
*
|
||||
* @return object|null The found object.
|
||||
* @phpstan-return T|null
|
||||
*
|
||||
* @template T of object
|
||||
*/
|
||||
public function find(string $className, mixed $id): object|null;
|
||||
|
||||
/**
|
||||
* Tells the ObjectManager to make an instance managed and persistent.
|
||||
*
|
||||
* The object will be entered into the database as a result of the flush operation.
|
||||
*
|
||||
* NOTE: The persist operation always considers objects that are not yet known to
|
||||
* this ObjectManager as NEW. Do not pass detached objects to the persist operation.
|
||||
*
|
||||
* @param object $object The instance to make managed and persistent.
|
||||
*/
|
||||
public function persist(object $object): void;
|
||||
|
||||
/**
|
||||
* Removes an object instance.
|
||||
*
|
||||
* A removed object will be removed from the database as a result of the flush operation.
|
||||
*
|
||||
* @param object $object The object instance to remove.
|
||||
*/
|
||||
public function remove(object $object): void;
|
||||
|
||||
/**
|
||||
* Clears the ObjectManager. All objects that are currently managed
|
||||
* by this ObjectManager become detached.
|
||||
*/
|
||||
public function clear(): void;
|
||||
|
||||
/**
|
||||
* Detaches an object from the ObjectManager, causing a managed object to
|
||||
* become detached. Unflushed changes made to the object if any
|
||||
* (including removal of the object), will not be synchronized to the database.
|
||||
* Objects which previously referenced the detached object will continue to
|
||||
* reference it.
|
||||
*
|
||||
* @param object $object The object to detach.
|
||||
*/
|
||||
public function detach(object $object): void;
|
||||
|
||||
/**
|
||||
* Refreshes the persistent state of an object from the database,
|
||||
* overriding any local changes that have not yet been persisted.
|
||||
*
|
||||
* @param object $object The object to refresh.
|
||||
*/
|
||||
public function refresh(object $object): void;
|
||||
|
||||
/**
|
||||
* Flushes all changes to objects that have been queued up to now to the database.
|
||||
* This effectively synchronizes the in-memory state of managed objects with the
|
||||
* database.
|
||||
*/
|
||||
public function flush(): void;
|
||||
|
||||
/**
|
||||
* Gets the repository for a class.
|
||||
*
|
||||
* @phpstan-param class-string<T> $className
|
||||
*
|
||||
* @phpstan-return ObjectRepository<T>
|
||||
*
|
||||
* @template T of object
|
||||
*/
|
||||
public function getRepository(string $className): ObjectRepository;
|
||||
|
||||
/**
|
||||
* Returns the ClassMetadata descriptor for a class.
|
||||
*
|
||||
* The class name must be the fully-qualified class name without a leading backslash
|
||||
* (as it is returned by get_class($obj)).
|
||||
*
|
||||
* @phpstan-param class-string<T> $className
|
||||
*
|
||||
* @phpstan-return ClassMetadata<T>
|
||||
*
|
||||
* @template T of object
|
||||
*/
|
||||
public function getClassMetadata(string $className): ClassMetadata;
|
||||
|
||||
/**
|
||||
* Gets the metadata factory used to gather the metadata of classes.
|
||||
*
|
||||
* @phpstan-return ClassMetadataFactory<ClassMetadata<object>>
|
||||
*/
|
||||
public function getMetadataFactory(): ClassMetadataFactory;
|
||||
|
||||
/**
|
||||
* Helper method to initialize a lazy loading proxy or persistent collection.
|
||||
*
|
||||
* This method is a no-op for other objects.
|
||||
*/
|
||||
public function initializeObject(object $obj): void;
|
||||
|
||||
/** Helper method to check whether a lazy loading proxy or persistent collection has been initialized. */
|
||||
public function isUninitializedObject(mixed $value): bool;
|
||||
|
||||
/**
|
||||
* Checks if the object is part of the current UnitOfWork and therefore managed.
|
||||
*/
|
||||
public function contains(object $object): bool;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user