Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove deprecated APIs #468

Merged
merged 1 commit into from Dec 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 4 additions & 1 deletion UPGRADE.md
@@ -1,6 +1,9 @@
# Upgrade from 1.0.x to 2.0.x

`DocLexer::peek()` and `DocLexer::glimpse` now return
- `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.
- `AnnotationRegistry` method related to registering annotations instead of
using autoloading have been removed.
65 changes: 1 addition & 64 deletions docs/en/annotations.rst
Expand Up @@ -79,23 +79,11 @@ with Doctrine Annotations requires this setup:
.. code-block:: php

use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\AnnotationRegistry;

AnnotationRegistry::registerFile("/path/to/doctrine/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php");
AnnotationRegistry::registerAutoloadNamespace("Symfony\Component\Validator\Constraint", "/path/to/symfony/src");
AnnotationRegistry::registerAutoloadNamespace("MyProject\Annotations", "/path/to/myproject/src");

$reader = new AnnotationReader();
AnnotationReader::addGlobalIgnoredName('dummy');

The second block with the annotation registry calls registers all the
three different annotation namespaces that are used.
Doctrine Annotations saves all its annotations in a single file, that is
why ``AnnotationRegistry#registerFile`` is used in contrast to
``AnnotationRegistry#registerAutoloadNamespace`` which creates a PSR-0
compatible loading mechanism for class to file names.

In the third block, we create the actual ``AnnotationReader`` instance.
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
Expand Down Expand Up @@ -165,57 +153,6 @@ class name you can wrap the reader in an ``IndexedReader``:
indexed or numeric keys, otherwise your code may experience failures
due to caching in a numerical or indexed format.

Registering Annotations
~~~~~~~~~~~~~~~~~~~~~~~

As explained in the introduction, Doctrine Annotations uses its own
autoloading mechanism to determine if a given annotation has a
corresponding PHP class that can be autoloaded. For annotation
autoloading you have to configure the
``Doctrine\Common\Annotations\AnnotationRegistry``. There are three
different mechanisms to configure annotation autoloading:

- Calling ``AnnotationRegistry#registerFile($file)`` to register a file
that contains one or more annotation classes.
- Calling ``AnnotationRegistry#registerNamespace($namespace, $dirs =
null)`` to register that the given namespace contains annotations and
that their base directory is located at the given $dirs or in the
include path if ``NULL`` is passed. The given directories should *NOT*
be the directory where classes of the namespace are in, but the base
directory of the root namespace. The AnnotationRegistry uses a
namespace to directory separator approach to resolve the correct path.
- Calling ``AnnotationRegistry#registerLoader($callable)`` to register
an autoloader callback. The callback accepts the class as first and
only parameter and has to return ``true`` if the corresponding file
was found and included.

.. note::

Loaders have to fail silently, if a class is not found even if it
matches for example the namespace prefix of that loader. Never is a
loader to throw a warning or exception if the loading failed
otherwise parsing doc block annotations will become a huge pain.

A sample loader callback could look like:

.. code-block:: php

use Doctrine\Common\Annotations\AnnotationRegistry;
use Symfony\Component\ClassLoader\UniversalClassLoader;

AnnotationRegistry::registerLoader(function($class) {
$file = str_replace("\\", DIRECTORY_SEPARATOR, $class) . ".php";

if (file_exists("/my/base/path/" . $file)) {
// file_exists() makes sure that the loader fails silently
require "/my/base/path/" . $file;
}
});

$loader = new UniversalClassLoader();
AnnotationRegistry::registerLoader(array($loader, "loadClass"));


Ignoring missing exceptions
~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
16 changes: 8 additions & 8 deletions docs/en/custom.rst
Expand Up @@ -2,7 +2,7 @@ Custom Annotation Classes
=========================

If you want to define your own annotations, you just have to group them
in a namespace and register this namespace in the ``AnnotationRegistry``.
in a namespace.
Annotation classes have to contain a class-level docblock with the text
``@Annotation``:

Expand Down Expand Up @@ -58,10 +58,10 @@ 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
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
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).
Expand All @@ -75,8 +75,8 @@ Usage with the ``@NamedArgumentConstructor`` tag

namespace MyCompany\Annotations;

/**
* @Annotation
/**
* @Annotation
* @NamedArgumentConstructor
*/
class Bar implements NamedArgumentConstructorAnnotation
Expand All @@ -99,8 +99,8 @@ you can simplify this to:

namespace MyCompany\Annotations;

/**
* @Annotation
/**
* @Annotation
* @NamedArgumentConstructor
*/
class Bar implements NamedArgumentConstructorAnnotation
Expand All @@ -109,7 +109,7 @@ you can simplify this to:
}


Usage with the
Usage with the
``Doctrine\Common\Annotations\NamedArgumentConstructorAnnotation``
interface (v1.11, deprecated as of v1.12):
.. code-block:: php
Expand Down
8 changes: 0 additions & 8 deletions docs/en/index.rst
Expand Up @@ -73,10 +73,6 @@ annotations of a class. A common one is
.. code-block:: php

use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\AnnotationRegistry;

// Deprecated and will be removed in 2.0 but currently needed
AnnotationRegistry::registerLoader('class_exists');

$reflectionClass = new ReflectionClass(Foo::class);
$property = $reflectionClass->getProperty('bar');
Expand All @@ -89,10 +85,6 @@ annotations of a class. A common one is

echo $myAnnotation->myProperty; // result: "value"

Note that ``AnnotationRegistry::registerLoader('class_exists')`` only works
if you already have an autoloader configured (i.e. composer autoloader).
Otherwise, :ref:`please take a look to the other annotation autoload mechanisms <annotations>`.

A reader has multiple methods to access the annotations of a class or
function.

Expand Down
149 changes: 1 addition & 148 deletions lib/Doctrine/Common/Annotations/AnnotationRegistry.php
Expand Up @@ -3,131 +3,20 @@
namespace Doctrine\Common\Annotations;

use function array_key_exists;
use function array_merge;
use function class_exists;
use function in_array;
use function is_file;
use function str_replace;
use function stream_resolve_include_path;
use function strpos;

use const DIRECTORY_SEPARATOR;

final class AnnotationRegistry
{
/**
* A map of namespaces to use for autoloading purposes based on a PSR-0 convention.
*
* Contains the namespace as key and an array of directories as value. If the value is NULL
* the include path is used for checking for the corresponding file.
*
* This autoloading mechanism does not utilize the PHP autoloading but implements autoloading on its own.
*
* @var string[][]|string[]|null[]
*/
private static $autoloadNamespaces = [];

/**
* A map of autoloader callables.
*
* @var callable[]
*/
private static $loaders = [];

/**
* An array of classes which cannot be found
*
* @var null[] indexed by class name
*/
private static $failedToAutoload = [];

/**
* Whenever registerFile() was used. Disables use of standard autoloader.
*
* @var bool
*/
private static $registerFileUsed = false;

public static function reset(): void
{
self::$autoloadNamespaces = [];
self::$loaders = [];
self::$failedToAutoload = [];
self::$registerFileUsed = false;
}

/**
* Registers file.
*
* @deprecated This method is deprecated and will be removed in
* doctrine/annotations 2.0. Annotations will be autoloaded in 2.0.
*/
public static function registerFile(string $file): void
{
self::$registerFileUsed = true;

require_once $file;
}

/**
* Adds a namespace with one or many directories to look for files or null for the include path.
*
* Loading of this namespaces will be done with a PSR-0 namespace loading algorithm.
*
* @deprecated This method is deprecated and will be removed in
* doctrine/annotations 2.0. Annotations will be autoloaded in 2.0.
*
* @phpstan-param string|list<string>|null $dirs
*/
public static function registerAutoloadNamespace(string $namespace, $dirs = null): void
{
self::$autoloadNamespaces[$namespace] = $dirs;
}

/**
* Registers multiple namespaces.
*
* Loading of this namespaces will be done with a PSR-0 namespace loading algorithm.
*
* @deprecated This method is deprecated and will be removed in
* doctrine/annotations 2.0. Annotations will be autoloaded in 2.0.
*
* @param string[][]|string[]|null[] $namespaces indexed by namespace name
*/
public static function registerAutoloadNamespaces(array $namespaces): void
{
self::$autoloadNamespaces = array_merge(self::$autoloadNamespaces, $namespaces);
}

/**
* Registers an autoloading callable for annotations, much like spl_autoload_register().
*
* NOTE: These class loaders HAVE to be silent when a class was not found!
* IMPORTANT: Loaders have to return true if they loaded a class that could contain the searched annotation class.
*
* @deprecated This method is deprecated and will be removed in
* doctrine/annotations 2.0. Annotations will be autoloaded in 2.0.
*/
public static function registerLoader(callable $callable): void
{
// Reset our static cache now that we have a new loader to work with
self::$failedToAutoload = [];
self::$loaders[] = $callable;
}

/**
* Registers an autoloading callable for annotations, if it is not already registered
*
* @deprecated This method is deprecated and will be removed in
* doctrine/annotations 2.0. Annotations will be autoloaded in 2.0.
*/
public static function registerUniqueLoader(callable $callable): void
{
if (in_array($callable, self::$loaders, true)) {
return;
}

self::registerLoader($callable);
}

/**
Expand All @@ -143,43 +32,7 @@ public static function loadAnnotationClass(string $class): bool
return false;
}

foreach (self::$autoloadNamespaces as $namespace => $dirs) {
if (strpos($class, $namespace) !== 0) {
continue;
}

$file = str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';

if ($dirs === null) {
$path = stream_resolve_include_path($file);
if ($path) {
require $path;

return true;
}
} else {
foreach ((array) $dirs as $dir) {
if (is_file($dir . DIRECTORY_SEPARATOR . $file)) {
require $dir . DIRECTORY_SEPARATOR . $file;

return true;
}
}
}
}

foreach (self::$loaders as $loader) {
if ($loader($class) === true) {
return true;
}
}

if (
self::$loaders === [] &&
self::$autoloadNamespaces === [] &&
self::$registerFileUsed === false &&
class_exists($class)
) {
if (class_exists($class)) {
return true;
}

Expand Down