Server IP : 213.176.29.180  /  Your IP : 3.133.110.37
Web Server : Apache
System : Linux 213.176.29.180.hostiran.name 4.18.0-553.22.1.el8_10.x86_64 #1 SMP Tue Sep 24 05:16:59 EDT 2024 x86_64
User : webtaragh ( 1001)
PHP Version : 8.3.14
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON
Directory (0750) :  /home/webtaragh/public_html/

[  Home  ][  C0mmand  ][  Upload File  ]

Current File : /home/webtaragh/public_html/doctrine.zip
PKb�$Z�ﻦinstantiator/CONTRIBUTING.mdnu�[���# Contributing

 * Follow the [Doctrine Coding Standard](https://github.com/doctrine/coding-standard)
 * The project will follow strict [object calisthenics](http://www.slideshare.net/guilhermeblanco/object-calisthenics-applied-to-php)
 * Any contribution must provide tests for additional introduced conditions
 * Any un-confirmed issue needs a failing test case before being accepted
 * Pull requests must be sent from a new hotfix/feature branch, not from `master`.

## Installation

To install the project and run the tests, you need to clone it first:

```sh
$ git clone git://github.com/doctrine/instantiator.git
```

You will then need to run a composer installation:

```sh
$ cd Instantiator
$ curl -s https://getcomposer.org/installer | php
$ php composer.phar update
```

## Testing

The PHPUnit version to be used is the one installed as a dev- dependency via composer:

```sh
$ ./vendor/bin/phpunit
```

Accepted coverage for new contributions is 80%. Any contribution not satisfying this requirement 
won't be merged.

PKb�$ZS�ǚ""instantiator/.travis.install.shnu�[���#!/bin/sh
set -x
if [ "$TRAVIS_PHP_VERSION" = 'hhvm' ] || [ "$TRAVIS_PHP_VERSION" = 'hhvm-nightly' ] ; then
    curl -sS https://getcomposer.org/installer > composer-installer.php
    hhvm composer-installer.php
    hhvm -v ResourceLimit.SocketDefaultTimeout=30 -v Http.SlowQueryThreshold=30000 composer.phar update --prefer-source
elif [ "$TRAVIS_PHP_VERSION" = '5.3.3' ] ; then
    composer self-update
    composer update --prefer-source --no-dev
    composer dump-autoload
else
    composer self-update
    composer update --prefer-source
fi
PKb�$Z��Q==instantiator/phpmd.xml.distnu�[���<?xml version="1.0" encoding="UTF-8" ?>
<ruleset
    name="Instantiator rules"
    xmlns="http://pmd.sf.net/ruleset/1.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
    xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd"
>
    <rule ref="rulesets/cleancode.xml">
        <!-- static access is used for caching purposes -->
        <exclude name="StaticAccess"/>
    </rule>
    <rule ref="rulesets/codesize.xml"/>
    <rule ref="rulesets/controversial.xml"/>
    <rule ref="rulesets/design.xml"/>
    <rule ref="rulesets/naming.xml"/>
    <rule ref="rulesets/unusedcode.xml"/>
    <rule
        name="NPathComplexity"
        message="The {0} {1}() has an NPath complexity of {2}. The configured NPath complexity threshold is {3}."
        class="PHP_PMD_Rule_Design_NpathComplexity"
    >
        <properties>
            <property name="minimum" description="The npath reporting threshold" value="10"/>
        </properties>
    </rule>
</ruleset>
PKb�$Z��.U��@instantiator/src/Doctrine/Instantiator/InstantiatorInterface.phpnu�[���<?php

namespace Doctrine\Instantiator;

use Doctrine\Instantiator\Exception\ExceptionInterface;

/**
 * Instantiator provides utility methods to build objects without invoking their constructors
 */
interface InstantiatorInterface
{
    /**
     * @param string $className
     * @phpstan-param class-string<T> $className
     *
     * @return object
     * @phpstan-return T
     *
     * @throws ExceptionInterface
     *
     * @template T of object
     */
    public function instantiate($className);
}
PKb�$Z�z.�WWMinstantiator/src/Doctrine/Instantiator/Exception/UnexpectedValueException.phpnu�[���<?php

namespace Doctrine\Instantiator\Exception;

use Exception;
use ReflectionClass;
use UnexpectedValueException as BaseUnexpectedValueException;

use function sprintf;

/**
 * Exception for given parameters causing invalid/unexpected state on instantiation
 */
class UnexpectedValueException extends BaseUnexpectedValueException implements ExceptionInterface
{
    /**
     * @phpstan-param ReflectionClass<T> $reflectionClass
     *
     * @template T of object
     */
    public static function fromSerializationTriggeredException(
        ReflectionClass $reflectionClass,
        Exception $exception
    ): self {
        return new self(
            sprintf(
                'An exception was raised while trying to instantiate an instance of "%s" via un-serialization',
                $reflectionClass->getName()
            ),
            0,
            $exception
        );
    }

    /**
     * @phpstan-param ReflectionClass<T> $reflectionClass
     *
     * @template T of object
     */
    public static function fromUncleanUnSerialization(
        ReflectionClass $reflectionClass,
        string $errorString,
        int $errorCode,
        string $errorFile,
        int $errorLine
    ): self {
        return new self(
            sprintf(
                'Could not produce an instance of "%s" via un-serialization, since an error was triggered '
                . 'in file "%s" at line "%d"',
                $reflectionClass->getName(),
                $errorFile,
                $errorLine
            ),
            0,
            new Exception($errorString, $errorCode)
        );
    }
}
PKb�$Z�f���Ginstantiator/src/Doctrine/Instantiator/Exception/ExceptionInterface.phpnu�[���<?php

namespace Doctrine\Instantiator\Exception;

use Throwable;

/**
 * Base exception marker interface for the instantiator component
 */
interface ExceptionInterface extends Throwable
{
}
PKb�$Z$�8���Minstantiator/src/Doctrine/Instantiator/Exception/InvalidArgumentException.phpnu�[���<?php

namespace Doctrine\Instantiator\Exception;

use InvalidArgumentException as BaseInvalidArgumentException;
use ReflectionClass;

use function interface_exists;
use function sprintf;
use function trait_exists;

/**
 * Exception for invalid arguments provided to the instantiator
 */
class InvalidArgumentException extends BaseInvalidArgumentException implements ExceptionInterface
{
    public static function fromNonExistingClass(string $className): self
    {
        if (interface_exists($className)) {
            return new self(sprintf('The provided type "%s" is an interface, and cannot be instantiated', $className));
        }

        if (trait_exists($className)) {
            return new self(sprintf('The provided type "%s" is a trait, and cannot be instantiated', $className));
        }

        return new self(sprintf('The provided class "%s" does not exist', $className));
    }

    /**
     * @phpstan-param ReflectionClass<T> $reflectionClass
     *
     * @template T of object
     */
    public static function fromAbstractClass(ReflectionClass $reflectionClass): self
    {
        return new self(sprintf(
            'The provided class "%s" is abstract, and cannot be instantiated',
            $reflectionClass->getName()
        ));
    }

    public static function fromEnum(string $className): self
    {
        return new self(sprintf(
            'The provided class "%s" is an enum, and cannot be instantiated',
            $className
        ));
    }
}
PKb�$Z��447instantiator/src/Doctrine/Instantiator/Instantiator.phpnu�[���<?php

namespace Doctrine\Instantiator;

use ArrayIterator;
use Doctrine\Instantiator\Exception\ExceptionInterface;
use Doctrine\Instantiator\Exception\InvalidArgumentException;
use Doctrine\Instantiator\Exception\UnexpectedValueException;
use Exception;
use ReflectionClass;
use ReflectionException;
use Serializable;

use function class_exists;
use function enum_exists;
use function is_subclass_of;
use function restore_error_handler;
use function set_error_handler;
use function sprintf;
use function strlen;
use function unserialize;

use const PHP_VERSION_ID;

final class Instantiator implements InstantiatorInterface
{
    /**
     * Markers used internally by PHP to define whether {@see \unserialize} should invoke
     * the method {@see \Serializable::unserialize()} when dealing with classes implementing
     * the {@see \Serializable} interface.
     */
    public const SERIALIZATION_FORMAT_USE_UNSERIALIZER   = 'C';
    public const SERIALIZATION_FORMAT_AVOID_UNSERIALIZER = 'O';

    /**
     * Used to instantiate specific classes, indexed by class name.
     *
     * @var callable[]
     */
    private static $cachedInstantiators = [];

    /**
     * Array of objects that can directly be cloned, indexed by class name.
     *
     * @var object[]
     */
    private static $cachedCloneables = [];

    /**
     * @param string $className
     * @phpstan-param class-string<T> $className
     *
     * @return object
     * @phpstan-return T
     *
     * @throws ExceptionInterface
     *
     * @template T of object
     */
    public function instantiate($className)
    {
        if (isset(self::$cachedCloneables[$className])) {
            /**
             * @phpstan-var T
             */
            $cachedCloneable = self::$cachedCloneables[$className];

            return clone $cachedCloneable;
        }

        if (isset(self::$cachedInstantiators[$className])) {
            $factory = self::$cachedInstantiators[$className];

            return $factory();
        }

        return $this->buildAndCacheFromFactory($className);
    }

    /**
     * Builds the requested object and caches it in static properties for performance
     *
     * @phpstan-param class-string<T> $className
     *
     * @return object
     * @phpstan-return T
     *
     * @template T of object
     */
    private function buildAndCacheFromFactory(string $className)
    {
        $factory  = self::$cachedInstantiators[$className] = $this->buildFactory($className);
        $instance = $factory();

        if ($this->isSafeToClone(new ReflectionClass($instance))) {
            self::$cachedCloneables[$className] = clone $instance;
        }

        return $instance;
    }

    /**
     * Builds a callable capable of instantiating the given $className without
     * invoking its constructor.
     *
     * @phpstan-param class-string<T> $className
     *
     * @phpstan-return callable(): T
     *
     * @throws InvalidArgumentException
     * @throws UnexpectedValueException
     * @throws ReflectionException
     *
     * @template T of object
     */
    private function buildFactory(string $className): callable
    {
        $reflectionClass = $this->getReflectionClass($className);

        if ($this->isInstantiableViaReflection($reflectionClass)) {
            return [$reflectionClass, 'newInstanceWithoutConstructor'];
        }

        $serializedString = sprintf(
            '%s:%d:"%s":0:{}',
            is_subclass_of($className, Serializable::class) ? self::SERIALIZATION_FORMAT_USE_UNSERIALIZER : self::SERIALIZATION_FORMAT_AVOID_UNSERIALIZER,
            strlen($className),
            $className
        );

        $this->checkIfUnSerializationIsSupported($reflectionClass, $serializedString);

        return static function () use ($serializedString) {
            return unserialize($serializedString);
        };
    }

    /**
     * @phpstan-param class-string<T> $className
     *
     * @phpstan-return ReflectionClass<T>
     *
     * @throws InvalidArgumentException
     * @throws ReflectionException
     *
     * @template T of object
     */
    private function getReflectionClass(string $className): ReflectionClass
    {
        if (! class_exists($className)) {
            throw InvalidArgumentException::fromNonExistingClass($className);
        }

        if (PHP_VERSION_ID >= 80100 && enum_exists($className, false)) {
            throw InvalidArgumentException::fromEnum($className);
        }

        $reflection = new ReflectionClass($className);

        if ($reflection->isAbstract()) {
            throw InvalidArgumentException::fromAbstractClass($reflection);
        }

        return $reflection;
    }

    /**
     * @phpstan-param ReflectionClass<T> $reflectionClass
     *
     * @throws UnexpectedValueException
     *
     * @template T of object
     */
    private function checkIfUnSerializationIsSupported(ReflectionClass $reflectionClass, string $serializedString): void
    {
        set_error_handler(static function (int $code, string $message, string $file, int $line) use ($reflectionClass, &$error): bool {
            $error = UnexpectedValueException::fromUncleanUnSerialization(
                $reflectionClass,
                $message,
                $code,
                $file,
                $line
            );

            return true;
        });

        try {
            $this->attemptInstantiationViaUnSerialization($reflectionClass, $serializedString);
        } finally {
            restore_error_handler();
        }

        if ($error) {
            throw $error;
        }
    }

    /**
     * @phpstan-param ReflectionClass<T> $reflectionClass
     *
     * @throws UnexpectedValueException
     *
     * @template T of object
     */
    private function attemptInstantiationViaUnSerialization(ReflectionClass $reflectionClass, string $serializedString): void
    {
        try {
            unserialize($serializedString);
        } catch (Exception $exception) {
            throw UnexpectedValueException::fromSerializationTriggeredException($reflectionClass, $exception);
        }
    }

    /**
     * @phpstan-param ReflectionClass<T> $reflectionClass
     *
     * @template T of object
     */
    private function isInstantiableViaReflection(ReflectionClass $reflectionClass): bool
    {
        return ! ($this->hasInternalAncestors($reflectionClass) && $reflectionClass->isFinal());
    }

    /**
     * Verifies whether the given class is to be considered internal
     *
     * @phpstan-param ReflectionClass<T> $reflectionClass
     *
     * @template T of object
     */
    private function hasInternalAncestors(ReflectionClass $reflectionClass): bool
    {
        do {
            if ($reflectionClass->isInternal()) {
                return true;
            }

            $reflectionClass = $reflectionClass->getParentClass();
        } while ($reflectionClass);

        return false;
    }

    /**
     * Checks if a class is cloneable
     *
     * Classes implementing `__clone` cannot be safely cloned, as that may cause side-effects.
     *
     * @phpstan-param ReflectionClass<T> $reflectionClass
     *
     * @template T of object
     */
    private function isSafeToClone(ReflectionClass $reflectionClass): bool
    {
        return $reflectionClass->isCloneable()
            && ! $reflectionClass->hasMethod('__clone')
            && ! $reflectionClass->isSubclassOf(ArrayIterator::class);
    }
}
PKb�$Za��w==instantiator/README.mdnu�[���# Instantiator

This library provides a way of avoiding usage of constructors when instantiating PHP classes.

[![Build Status](https://travis-ci.org/doctrine/instantiator.svg?branch=master)](https://travis-ci.org/doctrine/instantiator)
[![Code Coverage](https://codecov.io/gh/doctrine/instantiator/branch/master/graph/badge.svg)](https://codecov.io/gh/doctrine/instantiator/branch/master)
[![Dependency Status](https://www.versioneye.com/package/php--doctrine--instantiator/badge.svg)](https://www.versioneye.com/package/php--doctrine--instantiator)

[![Latest Stable Version](https://poser.pugx.org/doctrine/instantiator/v/stable.png)](https://packagist.org/packages/doctrine/instantiator)
[![Latest Unstable Version](https://poser.pugx.org/doctrine/instantiator/v/unstable.png)](https://packagist.org/packages/doctrine/instantiator)

## Installation

The suggested installation method is via [composer](https://getcomposer.org/):

```sh
php composer.phar require "doctrine/instantiator:~1.0.3"
```

## Usage

The instantiator is able to create new instances of any class without using the constructor or any API of the class
itself:

```php
$instantiator = new \Doctrine\Instantiator\Instantiator();

$instance = $instantiator->instantiate(\My\ClassName\Here::class);
```

## Contributing

Please read the [CONTRIBUTING.md](CONTRIBUTING.md) contents if you wish to help out!

## Credits

This library was migrated from [ocramius/instantiator](https://github.com/Ocramius/Instantiator), which
has been donated to the doctrine organization, and which is now deprecated in favour of this package.
PKb�$Zxxd#instantiator/.doctrine-project.jsonnu�[���{
    "active": true,
    "name": "Instantiator",
    "slug": "instantiator",
    "docsSlug": "doctrine-instantiator",
    "codePath": "/src",
    "versions": [
        {
            "name": "1.5",
            "branchName": "1.5.x",
            "slug": "latest",
            "upcoming": true
        },
        {
            "name": "1.4",
            "branchName": "1.4.x",
            "slug": "1.4",
            "aliases": [
                "current",
                "stable"
            ],
            "maintained": true,
            "current": true
        },
        {
            "name": "1.3",
            "branchName": "1.3.x",
            "slug": "1.3",
            "maintained": false
        },
        {
            "name": "1.2",
            "branchName": "1.2.x",
            "slug": "1.2"
        },
        {
            "name": "1.1",
            "branchName": "1.1.x",
            "slug": "1.1"
        },
        {
            "name": "1.0",
            "branchName": "1.0.x",
            "slug": "1.0"
        }
    ]
}
PKb�$Z
͂�$$instantiator/LICENSEnu�[���Copyright (c) 2014 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.
PKb�$Z�
!ffinflector/README.mdnu�[���# Doctrine Inflector

Doctrine Inflector is a small library that can perform string manipulations
with regard to uppercase/lowercase and singular/plural forms of words.

[![Build Status](https://travis-ci.org/doctrine/inflector.svg)](https://travis-ci.org/doctrine/inflector)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/doctrine/inflector/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/doctrine/inflector/?branch=master)
[![Code Coverage](https://scrutinizer-ci.com/g/doctrine/inflector/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/doctrine/inflector/?branch=master)
PKb�$Z�mY�� inflector/.doctrine-project.jsonnu�[���{
    "active": true,
    "name": "Inflector",
    "slug": "inflector",
    "docsSlug": "doctrine-inflector",
    "versions": [
        {
            "name": "1.3",
            "branchName": "1.3.x",
            "slug": "1.3",
            "current": true,
            "aliases": [
                "current",
                "stable"
            ]
        },
        {
            "name": "2.0",
            "branchName": "master",
            "slug": "2.0",
            "upcoming": true
        }
    ]
}
PKb�$Z��bu8282.inflector/lib/Doctrine/Inflector/Inflector.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector;

use RuntimeException;
use function chr;
use function function_exists;
use function lcfirst;
use function mb_strtolower;
use function ord;
use function preg_match;
use function preg_replace;
use function sprintf;
use function str_replace;
use function strlen;
use function strtolower;
use function strtr;
use function trim;
use function ucwords;

class Inflector
{
    private const ACCENTED_CHARACTERS = [
        'À' => 'A',
        'Á' => 'A',
        'Â' => 'A',
        'Ã' => 'A',
        'Ä' => 'Ae',
        'Æ' => 'Ae',
        'Å' => 'Aa',
        'æ' => 'a',
        'Ç' => 'C',
        'È' => 'E',
        'É' => 'E',
        'Ê' => 'E',
        'Ë' => 'E',
        'Ì' => 'I',
        'Í' => 'I',
        'Î' => 'I',
        'Ï' => 'I',
        'Ñ' => 'N',
        'Ò' => 'O',
        'Ó' => 'O',
        'Ô' => 'O',
        'Õ' => 'O',
        'Ö' => 'Oe',
        'Ù' => 'U',
        'Ú' => 'U',
        'Û' => 'U',
        'Ü' => 'Ue',
        'Ý' => 'Y',
        'ß' => 'ss',
        'à' => 'a',
        'á' => 'a',
        'â' => 'a',
        'ã' => 'a',
        'ä' => 'ae',
        'å' => 'aa',
        'ç' => 'c',
        'è' => 'e',
        'é' => 'e',
        'ê' => 'e',
        'ë' => 'e',
        'ì' => 'i',
        'í' => 'i',
        'î' => 'i',
        'ï' => 'i',
        'ñ' => 'n',
        'ò' => 'o',
        'ó' => 'o',
        'ô' => 'o',
        'õ' => 'o',
        'ö' => 'oe',
        'ù' => 'u',
        'ú' => 'u',
        'û' => 'u',
        'ü' => 'ue',
        'ý' => 'y',
        'ÿ' => 'y',
        'Ā' => 'A',
        'ā' => 'a',
        'Ă' => 'A',
        'ă' => 'a',
        'Ą' => 'A',
        'ą' => 'a',
        'Ć' => 'C',
        'ć' => 'c',
        'Ĉ' => 'C',
        'ĉ' => 'c',
        'Ċ' => 'C',
        'ċ' => 'c',
        'Č' => 'C',
        'č' => 'c',
        'Ď' => 'D',
        'ď' => 'd',
        'Đ' => 'D',
        'đ' => 'd',
        'Ē' => 'E',
        'ē' => 'e',
        'Ĕ' => 'E',
        'ĕ' => 'e',
        'Ė' => 'E',
        'ė' => 'e',
        'Ę' => 'E',
        'ę' => 'e',
        'Ě' => 'E',
        'ě' => 'e',
        'Ĝ' => 'G',
        'ĝ' => 'g',
        'Ğ' => 'G',
        'ğ' => 'g',
        'Ġ' => 'G',
        'ġ' => 'g',
        'Ģ' => 'G',
        'ģ' => 'g',
        'Ĥ' => 'H',
        'ĥ' => 'h',
        'Ħ' => 'H',
        'ħ' => 'h',
        'Ĩ' => 'I',
        'ĩ' => 'i',
        'Ī' => 'I',
        'ī' => 'i',
        'Ĭ' => 'I',
        'ĭ' => 'i',
        'Į' => 'I',
        'į' => 'i',
        'İ' => 'I',
        'ı' => 'i',
        'IJ' => 'IJ',
        'ij' => 'ij',
        'Ĵ' => 'J',
        'ĵ' => 'j',
        'Ķ' => 'K',
        'ķ' => 'k',
        'ĸ' => 'k',
        'Ĺ' => 'L',
        'ĺ' => 'l',
        'Ļ' => 'L',
        'ļ' => 'l',
        'Ľ' => 'L',
        'ľ' => 'l',
        'Ŀ' => 'L',
        'ŀ' => 'l',
        'Ł' => 'L',
        'ł' => 'l',
        'Ń' => 'N',
        'ń' => 'n',
        'Ņ' => 'N',
        'ņ' => 'n',
        'Ň' => 'N',
        'ň' => 'n',
        'ʼn' => 'N',
        'Ŋ' => 'n',
        'ŋ' => 'N',
        'Ō' => 'O',
        'ō' => 'o',
        'Ŏ' => 'O',
        'ŏ' => 'o',
        'Ő' => 'O',
        'ő' => 'o',
        'Œ' => 'OE',
        'œ' => 'oe',
        'Ø' => 'O',
        'ø' => 'o',
        'Ŕ' => 'R',
        'ŕ' => 'r',
        'Ŗ' => 'R',
        'ŗ' => 'r',
        'Ř' => 'R',
        'ř' => 'r',
        'Ś' => 'S',
        'ś' => 's',
        'Ŝ' => 'S',
        'ŝ' => 's',
        'Ş' => 'S',
        'ş' => 's',
        'Š' => 'S',
        'š' => 's',
        'Ţ' => 'T',
        'ţ' => 't',
        'Ť' => 'T',
        'ť' => 't',
        'Ŧ' => 'T',
        'ŧ' => 't',
        'Ũ' => 'U',
        'ũ' => 'u',
        'Ū' => 'U',
        'ū' => 'u',
        'Ŭ' => 'U',
        'ŭ' => 'u',
        'Ů' => 'U',
        'ů' => 'u',
        'Ű' => 'U',
        'ű' => 'u',
        'Ų' => 'U',
        'ų' => 'u',
        'Ŵ' => 'W',
        'ŵ' => 'w',
        'Ŷ' => 'Y',
        'ŷ' => 'y',
        'Ÿ' => 'Y',
        'Ź' => 'Z',
        'ź' => 'z',
        'Ż' => 'Z',
        'ż' => 'z',
        'Ž' => 'Z',
        'ž' => 'z',
        'ſ' => 's',
        '€' => 'E',
        '£' => '',
    ];

    /** @var WordInflector */
    private $singularizer;

    /** @var WordInflector */
    private $pluralizer;

    public function __construct(WordInflector $singularizer, WordInflector $pluralizer)
    {
        $this->singularizer = $singularizer;
        $this->pluralizer   = $pluralizer;
    }

    /**
     * Converts a word into the format for a Doctrine table name. Converts 'ModelName' to 'model_name'.
     */
    public function tableize(string $word) : string
    {
        $tableized = preg_replace('~(?<=\\w)([A-Z])~u', '_$1', $word);

        if ($tableized === null) {
            throw new RuntimeException(sprintf(
                'preg_replace returned null for value "%s"',
                $word
            ));
        }

        return mb_strtolower($tableized);
    }

    /**
     * Converts a word into the format for a Doctrine class name. Converts 'table_name' to 'TableName'.
     */
    public function classify(string $word) : string
    {
        return str_replace([' ', '_', '-'], '', ucwords($word, ' _-'));
    }

    /**
     * Camelizes a word. This uses the classify() method and turns the first character to lowercase.
     */
    public function camelize(string $word) : string
    {
        return lcfirst($this->classify($word));
    }

    /**
     * Uppercases words with configurable delimiters between words.
     *
     * Takes a string and capitalizes all of the words, like PHP's built-in
     * ucwords function. This extends that behavior, however, by allowing the
     * word delimiters to be configured, rather than only separating on
     * whitespace.
     *
     * Here is an example:
     * <code>
     * <?php
     * $string = 'top-o-the-morning to all_of_you!';
     * echo $inflector->capitalize($string);
     * // Top-O-The-Morning To All_of_you!
     *
     * echo $inflector->capitalize($string, '-_ ');
     * // Top-O-The-Morning To All_Of_You!
     * ?>
     * </code>
     *
     * @param string $string     The string to operate on.
     * @param string $delimiters A list of word separators.
     *
     * @return string The string with all delimiter-separated words capitalized.
     */
    public function capitalize(string $string, string $delimiters = " \n\t\r\0\x0B-") : string
    {
        return ucwords($string, $delimiters);
    }

    /**
     * Checks if the given string seems like it has utf8 characters in it.
     *
     * @param string $string The string to check for utf8 characters in.
     */
    public function seemsUtf8(string $string) : bool
    {
        for ($i = 0; $i < strlen($string); $i++) {
            if (ord($string[$i]) < 0x80) {
                continue; // 0bbbbbbb
            }

            if ((ord($string[$i]) & 0xE0) === 0xC0) {
                $n = 1; // 110bbbbb
            } elseif ((ord($string[$i]) & 0xF0) === 0xE0) {
                $n = 2; // 1110bbbb
            } elseif ((ord($string[$i]) & 0xF8) === 0xF0) {
                $n = 3; // 11110bbb
            } elseif ((ord($string[$i]) & 0xFC) === 0xF8) {
                $n = 4; // 111110bb
            } elseif ((ord($string[$i]) & 0xFE) === 0xFC) {
                $n = 5; // 1111110b
            } else {
                return false; // Does not match any model
            }

            for ($j = 0; $j < $n; $j++) { // n bytes matching 10bbbbbb follow ?
                if (++$i === strlen($string) || ((ord($string[$i]) & 0xC0) !== 0x80)) {
                    return false;
                }
            }
        }

        return true;
    }

    /**
     * Remove any illegal characters, accents, etc.
     *
     * @param  string $string String to unaccent
     *
     * @return string Unaccented string
     */
    public function unaccent(string $string) : string
    {
        if (preg_match('/[\x80-\xff]/', $string) === false) {
            return $string;
        }

        if ($this->seemsUtf8($string)) {
            $string = strtr($string, self::ACCENTED_CHARACTERS);
        } else {
            $characters = [];

            // Assume ISO-8859-1 if not UTF-8
            $characters['in'] =
                  chr(128)
                . chr(131)
                . chr(138)
                . chr(142)
                . chr(154)
                . chr(158)
                . chr(159)
                . chr(162)
                . chr(165)
                . chr(181)
                . chr(192)
                . chr(193)
                . chr(194)
                . chr(195)
                . chr(196)
                . chr(197)
                . chr(199)
                . chr(200)
                . chr(201)
                . chr(202)
                . chr(203)
                . chr(204)
                . chr(205)
                . chr(206)
                . chr(207)
                . chr(209)
                . chr(210)
                . chr(211)
                . chr(212)
                . chr(213)
                . chr(214)
                . chr(216)
                . chr(217)
                . chr(218)
                . chr(219)
                . chr(220)
                . chr(221)
                . chr(224)
                . chr(225)
                . chr(226)
                . chr(227)
                . chr(228)
                . chr(229)
                . chr(231)
                . chr(232)
                . chr(233)
                . chr(234)
                . chr(235)
                . chr(236)
                . chr(237)
                . chr(238)
                . chr(239)
                . chr(241)
                . chr(242)
                . chr(243)
                . chr(244)
                . chr(245)
                . chr(246)
                . chr(248)
                . chr(249)
                . chr(250)
                . chr(251)
                . chr(252)
                . chr(253)
                . chr(255);

            $characters['out'] = 'EfSZszYcYuAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy';

            $string = strtr($string, $characters['in'], $characters['out']);

            $doubleChars = [];

            $doubleChars['in'] = [
                chr(140),
                chr(156),
                chr(198),
                chr(208),
                chr(222),
                chr(223),
                chr(230),
                chr(240),
                chr(254),
            ];

            $doubleChars['out'] = ['OE', 'oe', 'AE', 'DH', 'TH', 'ss', 'ae', 'dh', 'th'];

            $string = str_replace($doubleChars['in'], $doubleChars['out'], $string);
        }

        return $string;
    }

    /**
     * Convert any passed string to a url friendly string.
     * Converts 'My first blog post' to 'my-first-blog-post'
     *
     * @param  string $string String to urlize.
     *
     * @return string Urlized string.
     */
    public function urlize(string $string) : string
    {
        // Remove all non url friendly characters with the unaccent function
        $unaccented = $this->unaccent($string);

        if (function_exists('mb_strtolower')) {
            $lowered = mb_strtolower($unaccented);
        } else {
            $lowered = strtolower($unaccented);
        }

        $replacements = [
            '/\W/' => ' ',
            '/([A-Z]+)([A-Z][a-z])/' => '\1_\2',
            '/([a-z\d])([A-Z])/' => '\1_\2',
            '/[^A-Z^a-z^0-9^\/]+/' => '-',
        ];

        $urlized = $lowered;

        foreach ($replacements as $pattern => $replacement) {
            $replaced = preg_replace($pattern, $replacement, $urlized);

            if ($replaced === null) {
                throw new RuntimeException(sprintf(
                    'preg_replace returned null for value "%s"',
                    $urlized
                ));
            }

            $urlized = $replaced;
        }

        return trim($urlized, '-');
    }

    /**
     * Returns a word in singular form.
     *
     * @param string $word The word in plural form.
     *
     * @return string The word in singular form.
     */
    public function singularize(string $word) : string
    {
        return $this->singularizer->inflect($word);
    }

    /**
     * Returns a word in plural form.
     *
     * @param string $word The word in singular form.
     *
     * @return string The word in plural form.
     */
    public function pluralize(string $word) : string
    {
        return $this->pluralizer->inflect($word);
    }
}
PKb�$Z�f�w��6inflector/lib/Doctrine/Inflector/NoopWordInflector.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector;

class NoopWordInflector implements WordInflector
{
    public function inflect(string $word) : string
    {
        return $word;
    }
}
PKb�$Z4��5inflector/lib/Doctrine/Inflector/RulesetInflector.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector;

use Doctrine\Inflector\Rules\Ruleset;
use function array_merge;

/**
 * Inflects based on multiple rulesets.
 *
 * Rules:
 * - If the word matches any uninflected word pattern, it is not inflected
 * - The first ruleset that returns a different value for an irregular word wins
 * - The first ruleset that returns a different value for a regular word wins
 * - If none of the above match, the word is left as-is
 */
class RulesetInflector implements WordInflector
{
    /** @var Ruleset[] */
    private $rulesets;

    public function __construct(Ruleset $ruleset, Ruleset ...$rulesets)
    {
        $this->rulesets = array_merge([$ruleset], $rulesets);
    }

    public function inflect(string $word) : string
    {
        if ($word === '') {
            return '';
        }

        foreach ($this->rulesets as $ruleset) {
            if ($ruleset->getUninflected()->matches($word)) {
                return $word;
            }
        }

        foreach ($this->rulesets as $ruleset) {
            $inflected = $ruleset->getIrregular()->inflect($word);

            if ($inflected !== $word) {
                return $inflected;
            }
        }

        foreach ($this->rulesets as $ruleset) {
            $inflected = $ruleset->getRegular()->inflect($word);

            if ($inflected !== $word) {
                return $inflected;
            }
        }

        return $word;
    }
}
PKb�$Z�U��>inflector/lib/Doctrine/Inflector/Rules/Turkish/Uninflected.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Turkish;

use Doctrine\Inflector\Rules\Pattern;

final class Uninflected
{
    /**
     * @return Pattern[]
     */
    public static function getSingular() : iterable
    {
        yield from self::getDefault();
    }

    /**
     * @return Pattern[]
     */
    public static function getPlural() : iterable
    {
        yield from self::getDefault();
    }

    /**
     * @return Pattern[]
     */
    private static function getDefault() : iterable
    {
        yield new Pattern('lunes');
        yield new Pattern('rompecabezas');
        yield new Pattern('crisis');
    }
}
PKb�$Z��U>inflector/lib/Doctrine/Inflector/Rules/Turkish/Inflectible.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Turkish;

use Doctrine\Inflector\Rules\Pattern;
use Doctrine\Inflector\Rules\Substitution;
use Doctrine\Inflector\Rules\Transformation;
use Doctrine\Inflector\Rules\Word;

class Inflectible
{
    /**
     * @return Transformation[]
     */
    public static function getSingular() : iterable
    {
        yield new Transformation(new Pattern('/l[ae]r$/i'), '');
    }

    /**
     * @return Transformation[]
     */
    public static function getPlural() : iterable
    {
        yield new Transformation(new Pattern('/([eöiü][^aoıueöiü]{0,6})$/u'), '\1ler');
        yield new Transformation(new Pattern('/([aoıu][^aoıueöiü]{0,6})$/u'), '\1lar');
    }

    /**
     * @return Substitution[]
     */
    public static function getIrregular() : iterable
    {
        yield new Substitution(new Word('ben'), new Word('biz'));
        yield new Substitution(new Word('sen'), new Word('siz'));
        yield new Substitution(new Word('o'), new Word('onlar'));
    }
}
PKb�$ZӇ4xll8inflector/lib/Doctrine/Inflector/Rules/Turkish/Rules.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Turkish;

use Doctrine\Inflector\Rules\Patterns;
use Doctrine\Inflector\Rules\Ruleset;
use Doctrine\Inflector\Rules\Substitutions;
use Doctrine\Inflector\Rules\Transformations;

final class Rules
{
    public static function getSingularRuleset() : Ruleset
    {
        return new Ruleset(
            new Transformations(...Inflectible::getSingular()),
            new Patterns(...Uninflected::getSingular()),
            (new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
        );
    }

    public static function getPluralRuleset() : Ruleset
    {
        return new Ruleset(
            new Transformations(...Inflectible::getPlural()),
            new Patterns(...Uninflected::getPlural()),
            new Substitutions(...Inflectible::getIrregular())
        );
    }
}
PKb�$ZԬ7��Cinflector/lib/Doctrine/Inflector/Rules/Turkish/InflectorFactory.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Turkish;

use Doctrine\Inflector\GenericLanguageInflectorFactory;
use Doctrine\Inflector\Rules\Ruleset;

final class InflectorFactory extends GenericLanguageInflectorFactory
{
    protected function getSingularRuleset() : Ruleset
    {
        return Rules::getSingularRuleset();
    }

    protected function getPluralRuleset() : Ruleset
    {
        return Rules::getPluralRuleset();
    }
}
PKb�$Z��}0��:inflector/lib/Doctrine/Inflector/Rules/Transformations.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules;

use Doctrine\Inflector\WordInflector;

class Transformations implements WordInflector
{
    /** @var Transformation[] */
    private $transformations;

    public function __construct(Transformation ...$transformations)
    {
        $this->transformations = $transformations;
    }

    public function inflect(string $word) : string
    {
        foreach ($this->transformations as $transformation) {
            if ($transformation->getPattern()->matches($word)) {
                return $transformation->inflect($word);
            }
        }

        return $word;
    }
}
PKb�$Z�}�9inflector/lib/Doctrine/Inflector/Rules/Transformation.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules;

use Doctrine\Inflector\WordInflector;
use function preg_replace;

final class Transformation implements WordInflector
{
    /** @var Pattern */
    private $pattern;

    /** @var string */
    private $replacement;

    public function __construct(Pattern $pattern, string $replacement)
    {
        $this->pattern     = $pattern;
        $this->replacement = $replacement;
    }

    public function getPattern() : Pattern
    {
        return $this->pattern;
    }

    public function getReplacement() : string
    {
        return $this->replacement;
    }

    public function inflect(string $word) : string
    {
        return (string) preg_replace($this->pattern->getRegex(), $this->replacement, $word);
    }
}
PKb�$Z
�� ��Finflector/lib/Doctrine/Inflector/Rules/NorwegianBokmal/Uninflected.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\NorwegianBokmal;

use Doctrine\Inflector\Rules\Pattern;

final class Uninflected
{
    /**
     * @return Pattern[]
     */
    public static function getSingular() : iterable
    {
        yield from self::getDefault();
    }

    /**
     * @return Pattern[]
     */
    public static function getPlural() : iterable
    {
        yield from self::getDefault();
    }

    /**
     * @return Pattern[]
     */
    private static function getDefault() : iterable
    {
        yield new Pattern('barn');
        yield new Pattern('fjell');
        yield new Pattern('hus');
    }
}
PKb�$Zs�0b��Finflector/lib/Doctrine/Inflector/Rules/NorwegianBokmal/Inflectible.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\NorwegianBokmal;

use Doctrine\Inflector\Rules\Pattern;
use Doctrine\Inflector\Rules\Substitution;
use Doctrine\Inflector\Rules\Transformation;
use Doctrine\Inflector\Rules\Word;

class Inflectible
{
    /**
     * @return Transformation[]
     */
    public static function getSingular() : iterable
    {
        yield new Transformation(new Pattern('/re$/i'), 'r');
        yield new Transformation(new Pattern('/er$/i'), '');
    }

    /**
     * @return Transformation[]
     */
    public static function getPlural() : iterable
    {
        yield new Transformation(new Pattern('/e$/i'), 'er');
        yield new Transformation(new Pattern('/r$/i'), 're');
        yield new Transformation(new Pattern('/$/'), 'er');
    }

    /**
     * @return Substitution[]
     */
    public static function getIrregular() : iterable
    {
        yield new Substitution(new Word('konto'), new Word('konti'));
    }
}
PKb�$Z�';�tt@inflector/lib/Doctrine/Inflector/Rules/NorwegianBokmal/Rules.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\NorwegianBokmal;

use Doctrine\Inflector\Rules\Patterns;
use Doctrine\Inflector\Rules\Ruleset;
use Doctrine\Inflector\Rules\Substitutions;
use Doctrine\Inflector\Rules\Transformations;

final class Rules
{
    public static function getSingularRuleset() : Ruleset
    {
        return new Ruleset(
            new Transformations(...Inflectible::getSingular()),
            new Patterns(...Uninflected::getSingular()),
            (new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
        );
    }

    public static function getPluralRuleset() : Ruleset
    {
        return new Ruleset(
            new Transformations(...Inflectible::getPlural()),
            new Patterns(...Uninflected::getPlural()),
            new Substitutions(...Inflectible::getIrregular())
        );
    }
}
PKb�$Z�C���Kinflector/lib/Doctrine/Inflector/Rules/NorwegianBokmal/InflectorFactory.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\NorwegianBokmal;

use Doctrine\Inflector\GenericLanguageInflectorFactory;
use Doctrine\Inflector\Rules\Ruleset;

final class InflectorFactory extends GenericLanguageInflectorFactory
{
    protected function getSingularRuleset() : Ruleset
    {
        return Rules::getSingularRuleset();
    }

    protected function getPluralRuleset() : Ruleset
    {
        return Rules::getPluralRuleset();
    }
}
PKb�$Z��٣2inflector/lib/Doctrine/Inflector/Rules/Ruleset.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules;

class Ruleset
{
    /** @var Transformations */
    private $regular;

    /** @var Patterns */
    private $uninflected;

    /** @var Substitutions */
    private $irregular;

    public function __construct(Transformations $regular, Patterns $uninflected, Substitutions $irregular)
    {
        $this->regular     = $regular;
        $this->uninflected = $uninflected;
        $this->irregular   = $irregular;
    }

    public function getRegular() : Transformations
    {
        return $this->regular;
    }

    public function getUninflected() : Patterns
    {
        return $this->uninflected;
    }

    public function getIrregular() : Substitutions
    {
        return $this->irregular;
    }
}
PKb�$ZG�iv''/inflector/lib/Doctrine/Inflector/Rules/Word.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules;

class Word
{
    /** @var string */
    private $word;

    public function __construct(string $word)
    {
        $this->word = $word;
    }

    public function getWord() : string
    {
        return $this->word;
    }
}
PKb�$Z��L<��Ainflector/lib/Doctrine/Inflector/Rules/Portuguese/Uninflected.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Portuguese;

use Doctrine\Inflector\Rules\Pattern;

final class Uninflected
{
    /**
     * @return Pattern[]
     */
    public static function getSingular() : iterable
    {
        yield from self::getDefault();
    }

    /**
     * @return Pattern[]
     */
    public static function getPlural() : iterable
    {
        yield from self::getDefault();
    }

    /**
     * @return Pattern[]
     */
    private static function getDefault() : iterable
    {
        yield new Pattern('tórax');
        yield new Pattern('tênis');
        yield new Pattern('ônibus');
        yield new Pattern('lápis');
        yield new Pattern('fênix');
    }
}
PKb�$Z���77Ainflector/lib/Doctrine/Inflector/Rules/Portuguese/Inflectible.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Portuguese;

use Doctrine\Inflector\Rules\Pattern;
use Doctrine\Inflector\Rules\Substitution;
use Doctrine\Inflector\Rules\Transformation;
use Doctrine\Inflector\Rules\Word;

class Inflectible
{
    /**
     * @return Transformation[]
     */
    public static function getSingular() : iterable
    {
        yield new Transformation(new Pattern('/^(g|)ases$/i'), '\1ás');
        yield new Transformation(new Pattern('/(japon|escoc|ingl|dinamarqu|fregu|portugu)eses$/i'), '\1ês');
        yield new Transformation(new Pattern('/(ae|ao|oe)s$/'), 'ao');
        yield new Transformation(new Pattern('/(ãe|ão|õe)s$/'), 'ão');
        yield new Transformation(new Pattern('/^(.*[^s]s)es$/i'), '\1');
        yield new Transformation(new Pattern('/sses$/i'), 'sse');
        yield new Transformation(new Pattern('/ns$/i'), 'm');
        yield new Transformation(new Pattern('/(r|t|f|v)is$/i'), '\1il');
        yield new Transformation(new Pattern('/uis$/i'), 'ul');
        yield new Transformation(new Pattern('/ois$/i'), 'ol');
        yield new Transformation(new Pattern('/eis$/i'), 'ei');
        yield new Transformation(new Pattern('/éis$/i'), 'el');
        yield new Transformation(new Pattern('/([^p])ais$/i'), '\1al');
        yield new Transformation(new Pattern('/(r|z)es$/i'), '\1');
        yield new Transformation(new Pattern('/^(á|gá)s$/i'), '\1s');
        yield new Transformation(new Pattern('/([^ê])s$/i'), '\1');
    }

    /**
     * @return Transformation[]
     */
    public static function getPlural() : iterable
    {
        yield new Transformation(new Pattern('/^(alem|c|p)ao$/i'), '\1aes');
        yield new Transformation(new Pattern('/^(irm|m)ao$/i'), '\1aos');
        yield new Transformation(new Pattern('/ao$/i'), 'oes');
        yield new Transformation(new Pattern('/^(alem|c|p)ão$/i'), '\1ães');
        yield new Transformation(new Pattern('/^(irm|m)ão$/i'), '\1ãos');
        yield new Transformation(new Pattern('/ão$/i'), 'ões');
        yield new Transformation(new Pattern('/^(|g)ás$/i'), '\1ases');
        yield new Transformation(new Pattern('/^(japon|escoc|ingl|dinamarqu|fregu|portugu)ês$/i'), '\1eses');
        yield new Transformation(new Pattern('/m$/i'), 'ns');
        yield new Transformation(new Pattern('/([^aeou])il$/i'), '\1is');
        yield new Transformation(new Pattern('/ul$/i'), 'uis');
        yield new Transformation(new Pattern('/ol$/i'), 'ois');
        yield new Transformation(new Pattern('/el$/i'), 'eis');
        yield new Transformation(new Pattern('/al$/i'), 'ais');
        yield new Transformation(new Pattern('/(z|r)$/i'), '\1es');
        yield new Transformation(new Pattern('/(s)$/i'), '\1');
        yield new Transformation(new Pattern('/$/'), 's');
    }

    /**
     * @return Substitution[]
     */
    public static function getIrregular() : iterable
    {
        yield new Substitution(new Word('abdomen'), new Word('abdomens'));
        yield new Substitution(new Word('alemão'), new Word('alemães'));
        yield new Substitution(new Word('artesã'), new Word('artesãos'));
        yield new Substitution(new Word('álcool'), new Word('álcoois'));
        yield new Substitution(new Word('árvore'), new Word('árvores'));
        yield new Substitution(new Word('bencão'), new Word('bencãos'));
        yield new Substitution(new Word('cão'), new Word('cães'));
        yield new Substitution(new Word('campus'), new Word('campi'));
        yield new Substitution(new Word('cadáver'), new Word('cadáveres'));
        yield new Substitution(new Word('capelão'), new Word('capelães'));
        yield new Substitution(new Word('capitão'), new Word('capitães'));
        yield new Substitution(new Word('chão'), new Word('chãos'));
        yield new Substitution(new Word('charlatão'), new Word('charlatães'));
        yield new Substitution(new Word('cidadão'), new Word('cidadãos'));
        yield new Substitution(new Word('consul'), new Word('consules'));
        yield new Substitution(new Word('cristão'), new Word('cristãos'));
        yield new Substitution(new Word('difícil'), new Word('difíceis'));
        yield new Substitution(new Word('email'), new Word('emails'));
        yield new Substitution(new Word('escrivão'), new Word('escrivães'));
        yield new Substitution(new Word('fóssil'), new Word('fósseis'));
        yield new Substitution(new Word('gás'), new Word('gases'));
        yield new Substitution(new Word('germens'), new Word('germen'));
        yield new Substitution(new Word('grão'), new Word('grãos'));
        yield new Substitution(new Word('hífen'), new Word('hífens'));
        yield new Substitution(new Word('irmão'), new Word('irmãos'));
        yield new Substitution(new Word('liquens'), new Word('liquen'));
        yield new Substitution(new Word('mal'), new Word('males'));
        yield new Substitution(new Word('mão'), new Word('mãos'));
        yield new Substitution(new Word('orfão'), new Word('orfãos'));
        yield new Substitution(new Word('país'), new Word('países'));
        yield new Substitution(new Word('pai'), new Word('pais'));
        yield new Substitution(new Word('pão'), new Word('pães'));
        yield new Substitution(new Word('projétil'), new Word('projéteis'));
        yield new Substitution(new Word('réptil'), new Word('répteis'));
        yield new Substitution(new Word('sacristão'), new Word('sacristães'));
        yield new Substitution(new Word('sotão'), new Word('sotãos'));
        yield new Substitution(new Word('tabelião'), new Word('tabeliães'));
    }
}
PKb�$Z1w�oo;inflector/lib/Doctrine/Inflector/Rules/Portuguese/Rules.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Portuguese;

use Doctrine\Inflector\Rules\Patterns;
use Doctrine\Inflector\Rules\Ruleset;
use Doctrine\Inflector\Rules\Substitutions;
use Doctrine\Inflector\Rules\Transformations;

final class Rules
{
    public static function getSingularRuleset() : Ruleset
    {
        return new Ruleset(
            new Transformations(...Inflectible::getSingular()),
            new Patterns(...Uninflected::getSingular()),
            (new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
        );
    }

    public static function getPluralRuleset() : Ruleset
    {
        return new Ruleset(
            new Transformations(...Inflectible::getPlural()),
            new Patterns(...Uninflected::getPlural()),
            new Substitutions(...Inflectible::getIrregular())
        );
    }
}
PKb�$Z�t!���Finflector/lib/Doctrine/Inflector/Rules/Portuguese/InflectorFactory.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Portuguese;

use Doctrine\Inflector\GenericLanguageInflectorFactory;
use Doctrine\Inflector\Rules\Ruleset;

final class InflectorFactory extends GenericLanguageInflectorFactory
{
    protected function getSingularRuleset() : Ruleset
    {
        return Rules::getSingularRuleset();
    }

    protected function getPluralRuleset() : Ruleset
    {
        return Rules::getPluralRuleset();
    }
}
PKb�$ZaZ�}��>inflector/lib/Doctrine/Inflector/Rules/Spanish/Uninflected.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Spanish;

use Doctrine\Inflector\Rules\Pattern;

final class Uninflected
{
    /**
     * @return Pattern[]
     */
    public static function getSingular() : iterable
    {
        yield from self::getDefault();
    }

    /**
     * @return Pattern[]
     */
    public static function getPlural() : iterable
    {
        yield from self::getDefault();
    }

    /**
     * @return Pattern[]
     */
    private static function getDefault() : iterable
    {
        yield new Pattern('lunes');
        yield new Pattern('rompecabezas');
        yield new Pattern('crisis');
    }
}
PKb�$Z6DK�``>inflector/lib/Doctrine/Inflector/Rules/Spanish/Inflectible.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Spanish;

use Doctrine\Inflector\Rules\Pattern;
use Doctrine\Inflector\Rules\Substitution;
use Doctrine\Inflector\Rules\Transformation;
use Doctrine\Inflector\Rules\Word;

class Inflectible
{
    /**
     * @return Transformation[]
     */
    public static function getSingular() : iterable
    {
        yield new Transformation(new Pattern('/ereses$/'), 'erés');
        yield new Transformation(new Pattern('/iones$/'), 'ión');
        yield new Transformation(new Pattern('/ces$/'), 'z');
        yield new Transformation(new Pattern('/es$/'), '');
        yield new Transformation(new Pattern('/s$/'), '');
    }

    /**
     * @return Transformation[]
     */
    public static function getPlural() : iterable
    {
        yield new Transformation(new Pattern('/ú([sn])$/i'), 'u\1es');
        yield new Transformation(new Pattern('/ó([sn])$/i'), 'o\1es');
        yield new Transformation(new Pattern('/í([sn])$/i'), 'i\1es');
        yield new Transformation(new Pattern('/é([sn])$/i'), 'e\1es');
        yield new Transformation(new Pattern('/á([sn])$/i'), 'a\1es');
        yield new Transformation(new Pattern('/z$/i'), 'ces');
        yield new Transformation(new Pattern('/([aeiou]s)$/i'), '\1');
        yield new Transformation(new Pattern('/([^aeéiou])$/i'), '\1es');
        yield new Transformation(new Pattern('/$/'), 's');
    }

    /**
     * @return Substitution[]
     */
    public static function getIrregular() : iterable
    {
        yield new Substitution(new Word('el'), new Word('los'));
        yield new Substitution(new Word('papá'), new Word('papás'));
        yield new Substitution(new Word('mamá'), new Word('mamás'));
        yield new Substitution(new Word('sofá'), new Word('sofás'));
        yield new Substitution(new Word('mes'), new Word('meses'));
    }
}
PKb�$Z-��ll8inflector/lib/Doctrine/Inflector/Rules/Spanish/Rules.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Spanish;

use Doctrine\Inflector\Rules\Patterns;
use Doctrine\Inflector\Rules\Ruleset;
use Doctrine\Inflector\Rules\Substitutions;
use Doctrine\Inflector\Rules\Transformations;

final class Rules
{
    public static function getSingularRuleset() : Ruleset
    {
        return new Ruleset(
            new Transformations(...Inflectible::getSingular()),
            new Patterns(...Uninflected::getSingular()),
            (new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
        );
    }

    public static function getPluralRuleset() : Ruleset
    {
        return new Ruleset(
            new Transformations(...Inflectible::getPlural()),
            new Patterns(...Uninflected::getPlural()),
            new Substitutions(...Inflectible::getIrregular())
        );
    }
}
PKb�$Z�L���Cinflector/lib/Doctrine/Inflector/Rules/Spanish/InflectorFactory.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\Spanish;

use Doctrine\Inflector\GenericLanguageInflectorFactory;
use Doctrine\Inflector\Rules\Ruleset;

final class InflectorFactory extends GenericLanguageInflectorFactory
{
    protected function getSingularRuleset() : Ruleset
    {
        return Rules::getSingularRuleset();
    }

    protected function getPluralRuleset() : Ruleset
    {
        return Rules::getPluralRuleset();
    }
}
PKb�$Z���+]]8inflector/lib/Doctrine/Inflector/Rules/Substitutions.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules;

use Doctrine\Inflector\WordInflector;
use function strtolower;
use function strtoupper;
use function substr;

class Substitutions implements WordInflector
{
    /** @var Substitution[] */
    private $substitutions;

    public function __construct(Substitution ...$substitutions)
    {
        foreach ($substitutions as $substitution) {
            $this->substitutions[$substitution->getFrom()->getWord()] = $substitution;
        }
    }

    public function getFlippedSubstitutions() : Substitutions
    {
        $substitutions = [];

        foreach ($this->substitutions as $substitution) {
            $substitutions[] = new Substitution(
                $substitution->getTo(),
                $substitution->getFrom()
            );
        }

        return new Substitutions(...$substitutions);
    }

    public function inflect(string $word) : string
    {
        $lowerWord = strtolower($word);

        if (isset($this->substitutions[$lowerWord])) {
            $firstLetterUppercase = $lowerWord[0] !== $word[0];

            $toWord = $this->substitutions[$lowerWord]->getTo()->getWord();

            if ($firstLetterUppercase) {
                return strtoupper($toWord[0]) . substr($toWord, 1);
            }

            return $toWord;
        }

        return $word;
    }
}
PKb�$Z��"ƻ�>inflector/lib/Doctrine/Inflector/Rules/English/Uninflected.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\English;

use Doctrine\Inflector\Rules\Pattern;

final class Uninflected
{
    /**
     * @return Pattern[]
     */
    public static function getSingular() : iterable
    {
        yield from self::getDefault();

        yield new Pattern('.*ss');
        yield new Pattern('clothes');
        yield new Pattern('data');
        yield new Pattern('fascia');
        yield new Pattern('fuchsia');
        yield new Pattern('galleria');
        yield new Pattern('mafia');
        yield new Pattern('militia');
        yield new Pattern('pants');
        yield new Pattern('petunia');
        yield new Pattern('sepia');
        yield new Pattern('trivia');
        yield new Pattern('utopia');
    }

    /**
     * @return Pattern[]
     */
    public static function getPlural() : iterable
    {
        yield from self::getDefault();

        yield new Pattern('people');
        yield new Pattern('trivia');
        yield new Pattern('\w+ware$');
        yield new Pattern('media');
    }

    /**
     * @return Pattern[]
     */
    private static function getDefault() : iterable
    {
        yield new Pattern('\w+media');
        yield new Pattern('advice');
        yield new Pattern('aircraft');
        yield new Pattern('amoyese');
        yield new Pattern('art');
        yield new Pattern('audio');
        yield new Pattern('baggage');
        yield new Pattern('bison');
        yield new Pattern('borghese');
        yield new Pattern('bream');
        yield new Pattern('breeches');
        yield new Pattern('britches');
        yield new Pattern('buffalo');
        yield new Pattern('butter');
        yield new Pattern('cantus');
        yield new Pattern('carp');
        yield new Pattern('chassis');
        yield new Pattern('clippers');
        yield new Pattern('clothing');
        yield new Pattern('coal');
        yield new Pattern('cod');
        yield new Pattern('coitus');
        yield new Pattern('compensation');
        yield new Pattern('congoese');
        yield new Pattern('contretemps');
        yield new Pattern('coreopsis');
        yield new Pattern('corps');
        yield new Pattern('cotton');
        yield new Pattern('data');
        yield new Pattern('debris');
        yield new Pattern('deer');
        yield new Pattern('diabetes');
        yield new Pattern('djinn');
        yield new Pattern('education');
        yield new Pattern('eland');
        yield new Pattern('elk');
        yield new Pattern('emoji');
        yield new Pattern('equipment');
        yield new Pattern('evidence');
        yield new Pattern('experience');
        yield new Pattern('faroese');
        yield new Pattern('feedback');
        yield new Pattern('fish');
        yield new Pattern('flounder');
        yield new Pattern('flour');
        yield new Pattern('foochowese');
        yield new Pattern('food');
        yield new Pattern('furniture');
        yield new Pattern('gallows');
        yield new Pattern('genevese');
        yield new Pattern('genoese');
        yield new Pattern('gilbertese');
        yield new Pattern('gold');
        yield new Pattern('headquarters');
        yield new Pattern('herpes');
        yield new Pattern('hijinks');
        yield new Pattern('homework');
        yield new Pattern('hottentotese');
        yield new Pattern('impatience');
        yield new Pattern('information');
        yield new Pattern('innings');
        yield new Pattern('jackanapes');
        yield new Pattern('jeans');
        yield new Pattern('jedi');
        yield new Pattern('kiplingese');
        yield new Pattern('knowledge');
        yield new Pattern('kongoese');
        yield new Pattern('leather');
        yield new Pattern('love');
        yield new Pattern('lucchese');
        yield new Pattern('luggage');
        yield new Pattern('mackerel');
        yield new Pattern('Maltese');
        yield new Pattern('management');
        yield new Pattern('metadata');
        yield new Pattern('mews');
        yield new Pattern('money');
        yield new Pattern('moose');
        yield new Pattern('mumps');
        yield new Pattern('music');
        yield new Pattern('nankingese');
        yield new Pattern('news');
        yield new Pattern('nexus');
        yield new Pattern('niasese');
        yield new Pattern('nutrition');
        yield new Pattern('offspring');
        yield new Pattern('oil');
        yield new Pattern('patience');
        yield new Pattern('pekingese');
        yield new Pattern('piedmontese');
        yield new Pattern('pincers');
        yield new Pattern('pistoiese');
        yield new Pattern('plankton');
        yield new Pattern('pliers');
        yield new Pattern('pokemon');
        yield new Pattern('police');
        yield new Pattern('polish');
        yield new Pattern('portuguese');
        yield new Pattern('proceedings');
        yield new Pattern('progress');
        yield new Pattern('rabies');
        yield new Pattern('rain');
        yield new Pattern('research');
        yield new Pattern('rhinoceros');
        yield new Pattern('rice');
        yield new Pattern('salmon');
        yield new Pattern('sand');
        yield new Pattern('sarawakese');
        yield new Pattern('scissors');
        yield new Pattern('sea[- ]bass');
        yield new Pattern('series');
        yield new Pattern('shavese');
        yield new Pattern('shears');
        yield new Pattern('sheep');
        yield new Pattern('siemens');
        yield new Pattern('silk');
        yield new Pattern('sms');
        yield new Pattern('soap');
        yield new Pattern('social media');
        yield new Pattern('spam');
        yield new Pattern('species');
        yield new Pattern('staff');
        yield new Pattern('sugar');
        yield new Pattern('swine');
        yield new Pattern('talent');
        yield new Pattern('toothpaste');
        yield new Pattern('traffic');
        yield new Pattern('travel');
        yield new Pattern('trousers');
        yield new Pattern('trout');
        yield new Pattern('tuna');
        yield new Pattern('us');
        yield new Pattern('vermontese');
        yield new Pattern('vinegar');
        yield new Pattern('weather');
        yield new Pattern('wenchowese');
        yield new Pattern('wheat');
        yield new Pattern('whiting');
        yield new Pattern('wildebeest');
        yield new Pattern('wood');
        yield new Pattern('wool');
        yield new Pattern('work');
        yield new Pattern('yengeese');
    }
}
PKb�$Z���+�+>inflector/lib/Doctrine/Inflector/Rules/English/Inflectible.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\English;

use Doctrine\Inflector\Rules\Pattern;
use Doctrine\Inflector\Rules\Substitution;
use Doctrine\Inflector\Rules\Transformation;
use Doctrine\Inflector\Rules\Word;

class Inflectible
{
    /**
     * @return Transformation[]
     */
    public static function getSingular() : iterable
    {
        yield new Transformation(new Pattern('(s)tatuses$'), '\1\2tatus');
        yield new Transformation(new Pattern('(s)tatus$'), '\1\2tatus');
        yield new Transformation(new Pattern('^(.*)(menu)s$'), '\1\2');
        yield new Transformation(new Pattern('(quiz)zes$'), '\\1');
        yield new Transformation(new Pattern('(matr)ices$'), '\1ix');
        yield new Transformation(new Pattern('(vert|ind)ices$'), '\1ex');
        yield new Transformation(new Pattern('^(ox)en'), '\1');
        yield new Transformation(new Pattern('(alias)(es)*$'), '\1');
        yield new Transformation(new Pattern('(buffal|her|potat|tomat|volcan)oes$'), '\1o');
        yield new Transformation(new Pattern('(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin|viri?)i$'), '\1us');
        yield new Transformation(new Pattern('([ftw]ax)es'), '\1');
        yield new Transformation(new Pattern('(analys|ax|cris|test|thes)es$'), '\1is');
        yield new Transformation(new Pattern('(shoe|slave)s$'), '\1');
        yield new Transformation(new Pattern('(o)es$'), '\1');
        yield new Transformation(new Pattern('ouses$'), 'ouse');
        yield new Transformation(new Pattern('([^a])uses$'), '\1us');
        yield new Transformation(new Pattern('([m|l])ice$'), '\1ouse');
        yield new Transformation(new Pattern('(x|ch|ss|sh)es$'), '\1');
        yield new Transformation(new Pattern('(m)ovies$'), '\1\2ovie');
        yield new Transformation(new Pattern('(s)eries$'), '\1\2eries');
        yield new Transformation(new Pattern('([^aeiouy]|qu)ies$'), '\1y');
        yield new Transformation(new Pattern('([lr])ves$'), '\1f');
        yield new Transformation(new Pattern('(tive)s$'), '\1');
        yield new Transformation(new Pattern('(hive)s$'), '\1');
        yield new Transformation(new Pattern('(drive)s$'), '\1');
        yield new Transformation(new Pattern('(dive)s$'), '\1');
        yield new Transformation(new Pattern('(olive)s$'), '\1');
        yield new Transformation(new Pattern('([^fo])ves$'), '\1fe');
        yield new Transformation(new Pattern('(^analy)ses$'), '\1sis');
        yield new Transformation(new Pattern('(analy|diagno|^ba|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$'), '\1\2sis');
        yield new Transformation(new Pattern('(tax)a$'), '\1on');
        yield new Transformation(new Pattern('(c)riteria$'), '\1riterion');
        yield new Transformation(new Pattern('([ti])a$'), '\1um');
        yield new Transformation(new Pattern('(p)eople$'), '\1\2erson');
        yield new Transformation(new Pattern('(m)en$'), '\1an');
        yield new Transformation(new Pattern('(c)hildren$'), '\1\2hild');
        yield new Transformation(new Pattern('(f)eet$'), '\1oot');
        yield new Transformation(new Pattern('(n)ews$'), '\1\2ews');
        yield new Transformation(new Pattern('eaus$'), 'eau');
        yield new Transformation(new Pattern('s$'), '');
    }

    /**
     * @return Transformation[]
     */
    public static function getPlural() : iterable
    {
        yield new Transformation(new Pattern('(s)tatus$'), '\1\2tatuses');
        yield new Transformation(new Pattern('(quiz)$'), '\1zes');
        yield new Transformation(new Pattern('^(ox)$'), '\1\2en');
        yield new Transformation(new Pattern('([m|l])ouse$'), '\1ice');
        yield new Transformation(new Pattern('(matr|vert|ind)(ix|ex)$'), '\1ices');
        yield new Transformation(new Pattern('(x|ch|ss|sh)$'), '\1es');
        yield new Transformation(new Pattern('([^aeiouy]|qu)y$'), '\1ies');
        yield new Transformation(new Pattern('(hive|gulf)$'), '\1s');
        yield new Transformation(new Pattern('(?:([^f])fe|([lr])f)$'), '\1\2ves');
        yield new Transformation(new Pattern('sis$'), 'ses');
        yield new Transformation(new Pattern('([ti])um$'), '\1a');
        yield new Transformation(new Pattern('(tax)on$'), '\1a');
        yield new Transformation(new Pattern('(c)riterion$'), '\1riteria');
        yield new Transformation(new Pattern('(p)erson$'), '\1eople');
        yield new Transformation(new Pattern('(m)an$'), '\1en');
        yield new Transformation(new Pattern('(c)hild$'), '\1hildren');
        yield new Transformation(new Pattern('(f)oot$'), '\1eet');
        yield new Transformation(new Pattern('(buffal|her|potat|tomat|volcan)o$'), '\1\2oes');
        yield new Transformation(new Pattern('(alumn|bacill|cact|foc|fung|nucle|radi|stimul|syllab|termin|vir)us$'), '\1i');
        yield new Transformation(new Pattern('us$'), 'uses');
        yield new Transformation(new Pattern('(alias)$'), '\1es');
        yield new Transformation(new Pattern('(analys|ax|cris|test|thes)is$'), '\1es');
        yield new Transformation(new Pattern('s$'), 's');
        yield new Transformation(new Pattern('^$'), '');
        yield new Transformation(new Pattern('$'), 's');
    }

    /**
     * @return Substitution[]
     */
    public static function getIrregular() : iterable
    {
        yield new Substitution(new Word('atlas'), new Word('atlases'));
        yield new Substitution(new Word('axe'), new Word('axes'));
        yield new Substitution(new Word('beef'), new Word('beefs'));
        yield new Substitution(new Word('brother'), new Word('brothers'));
        yield new Substitution(new Word('cafe'), new Word('cafes'));
        yield new Substitution(new Word('chateau'), new Word('chateaux'));
        yield new Substitution(new Word('niveau'), new Word('niveaux'));
        yield new Substitution(new Word('child'), new Word('children'));
        yield new Substitution(new Word('canvas'), new Word('canvases'));
        yield new Substitution(new Word('cookie'), new Word('cookies'));
        yield new Substitution(new Word('corpus'), new Word('corpuses'));
        yield new Substitution(new Word('cow'), new Word('cows'));
        yield new Substitution(new Word('criterion'), new Word('criteria'));
        yield new Substitution(new Word('curriculum'), new Word('curricula'));
        yield new Substitution(new Word('demo'), new Word('demos'));
        yield new Substitution(new Word('domino'), new Word('dominoes'));
        yield new Substitution(new Word('echo'), new Word('echoes'));
        yield new Substitution(new Word('foot'), new Word('feet'));
        yield new Substitution(new Word('fungus'), new Word('fungi'));
        yield new Substitution(new Word('ganglion'), new Word('ganglions'));
        yield new Substitution(new Word('gas'), new Word('gases'));
        yield new Substitution(new Word('genie'), new Word('genies'));
        yield new Substitution(new Word('genus'), new Word('genera'));
        yield new Substitution(new Word('goose'), new Word('geese'));
        yield new Substitution(new Word('graffito'), new Word('graffiti'));
        yield new Substitution(new Word('hippopotamus'), new Word('hippopotami'));
        yield new Substitution(new Word('hoof'), new Word('hoofs'));
        yield new Substitution(new Word('human'), new Word('humans'));
        yield new Substitution(new Word('iris'), new Word('irises'));
        yield new Substitution(new Word('larva'), new Word('larvae'));
        yield new Substitution(new Word('leaf'), new Word('leaves'));
        yield new Substitution(new Word('lens'), new Word('lenses'));
        yield new Substitution(new Word('loaf'), new Word('loaves'));
        yield new Substitution(new Word('man'), new Word('men'));
        yield new Substitution(new Word('medium'), new Word('media'));
        yield new Substitution(new Word('memorandum'), new Word('memoranda'));
        yield new Substitution(new Word('money'), new Word('monies'));
        yield new Substitution(new Word('mongoose'), new Word('mongooses'));
        yield new Substitution(new Word('motto'), new Word('mottoes'));
        yield new Substitution(new Word('move'), new Word('moves'));
        yield new Substitution(new Word('mythos'), new Word('mythoi'));
        yield new Substitution(new Word('niche'), new Word('niches'));
        yield new Substitution(new Word('nucleus'), new Word('nuclei'));
        yield new Substitution(new Word('numen'), new Word('numina'));
        yield new Substitution(new Word('occiput'), new Word('occiputs'));
        yield new Substitution(new Word('octopus'), new Word('octopuses'));
        yield new Substitution(new Word('opus'), new Word('opuses'));
        yield new Substitution(new Word('ox'), new Word('oxen'));
        yield new Substitution(new Word('passerby'), new Word('passersby'));
        yield new Substitution(new Word('penis'), new Word('penises'));
        yield new Substitution(new Word('person'), new Word('people'));
        yield new Substitution(new Word('plateau'), new Word('plateaux'));
        yield new Substitution(new Word('runner-up'), new Word('runners-up'));
        yield new Substitution(new Word('safe'), new Word('safes'));
        yield new Substitution(new Word('sex'), new Word('sexes'));
        yield new Substitution(new Word('soliloquy'), new Word('soliloquies'));
        yield new Substitution(new Word('son-in-law'), new Word('sons-in-law'));
        yield new Substitution(new Word('syllabus'), new Word('syllabi'));
        yield new Substitution(new Word('testis'), new Word('testes'));
        yield new Substitution(new Word('thief'), new Word('thieves'));
        yield new Substitution(new Word('tooth'), new Word('teeth'));
        yield new Substitution(new Word('tornado'), new Word('tornadoes'));
        yield new Substitution(new Word('trilby'), new Word('trilbys'));
        yield new Substitution(new Word('turf'), new Word('turfs'));
        yield new Substitution(new Word('valve'), new Word('valves'));
        yield new Substitution(new Word('volcano'), new Word('volcanoes'));
        yield new Substitution(new Word('abuse'), new Word('abuses'));
        yield new Substitution(new Word('avalanche'), new Word('avalanches'));
        yield new Substitution(new Word('cache'), new Word('caches'));
        yield new Substitution(new Word('criterion'), new Word('criteria'));
        yield new Substitution(new Word('curve'), new Word('curves'));
        yield new Substitution(new Word('emphasis'), new Word('emphases'));
        yield new Substitution(new Word('foe'), new Word('foes'));
        yield new Substitution(new Word('grave'), new Word('graves'));
        yield new Substitution(new Word('hoax'), new Word('hoaxes'));
        yield new Substitution(new Word('medium'), new Word('media'));
        yield new Substitution(new Word('neurosis'), new Word('neuroses'));
        yield new Substitution(new Word('save'), new Word('saves'));
        yield new Substitution(new Word('wave'), new Word('waves'));
        yield new Substitution(new Word('oasis'), new Word('oases'));
        yield new Substitution(new Word('valve'), new Word('valves'));
        yield new Substitution(new Word('zombie'), new Word('zombies'));
    }
}
PKb�$ZO�ll8inflector/lib/Doctrine/Inflector/Rules/English/Rules.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\English;

use Doctrine\Inflector\Rules\Patterns;
use Doctrine\Inflector\Rules\Ruleset;
use Doctrine\Inflector\Rules\Substitutions;
use Doctrine\Inflector\Rules\Transformations;

final class Rules
{
    public static function getSingularRuleset() : Ruleset
    {
        return new Ruleset(
            new Transformations(...Inflectible::getSingular()),
            new Patterns(...Uninflected::getSingular()),
            (new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
        );
    }

    public static function getPluralRuleset() : Ruleset
    {
        return new Ruleset(
            new Transformations(...Inflectible::getPlural()),
            new Patterns(...Uninflected::getPlural()),
            new Substitutions(...Inflectible::getIrregular())
        );
    }
}
PKb�$ZJEj���Cinflector/lib/Doctrine/Inflector/Rules/English/InflectorFactory.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\English;

use Doctrine\Inflector\GenericLanguageInflectorFactory;
use Doctrine\Inflector\Rules\Ruleset;

final class InflectorFactory extends GenericLanguageInflectorFactory
{
    protected function getSingularRuleset() : Ruleset
    {
        return Rules::getSingularRuleset();
    }

    protected function getPluralRuleset() : Ruleset
    {
        return Rules::getPluralRuleset();
    }
}
PKb�$ZV�;���7inflector/lib/Doctrine/Inflector/Rules/Substitution.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules;

final class Substitution
{
    /** @var Word */
    private $from;

    /** @var Word */
    private $to;

    public function __construct(Word $from, Word $to)
    {
        $this->from = $from;
        $this->to   = $to;
    }

    public function getFrom() : Word
    {
        return $this->from;
    }

    public function getTo() : Word
    {
        return $this->to;
    }
}
PKb�$Z�)O�2inflector/lib/Doctrine/Inflector/Rules/Pattern.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules;

use function preg_match;

final class Pattern
{
    /** @var string */
    private $pattern;

    /** @var string */
    private $regex;

    public function __construct(string $pattern)
    {
        $this->pattern = $pattern;

        if (isset($this->pattern[0]) && $this->pattern[0] === '/') {
            $this->regex = $this->pattern;
        } else {
            $this->regex = '/' . $this->pattern . '/i';
        }
    }

    public function getPattern() : string
    {
        return $this->pattern;
    }

    public function getRegex() : string
    {
        return $this->regex;
    }

    public function matches(string $word) : bool
    {
        return preg_match($this->getRegex(), $word) === 1;
    }
}
PKb�$ZHϽ�88=inflector/lib/Doctrine/Inflector/Rules/French/Uninflected.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\French;

use Doctrine\Inflector\Rules\Pattern;

final class Uninflected
{
    /**
     * @return Pattern[]
     */
    public static function getSingular() : iterable
    {
        yield from self::getDefault();
    }

    /**
     * @return Pattern[]
     */
    public static function getPlural() : iterable
    {
        yield from self::getDefault();
    }

    /**
     * @return Pattern[]
     */
    private static function getDefault() : iterable
    {
        yield new Pattern('');
    }
}
PKb�$Zy�[=inflector/lib/Doctrine/Inflector/Rules/French/Inflectible.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\French;

use Doctrine\Inflector\Rules\Pattern;
use Doctrine\Inflector\Rules\Substitution;
use Doctrine\Inflector\Rules\Transformation;
use Doctrine\Inflector\Rules\Word;

class Inflectible
{
    /**
     * @return Transformation[]
     */
    public static function getSingular() : iterable
    {
        yield new Transformation(new Pattern('/(b|cor|ém|gemm|soupir|trav|vant|vitr)aux$/'), '\1ail');
        yield new Transformation(new Pattern('/ails$/'), 'ail');
        yield new Transformation(new Pattern('/(journ|chev)aux$/'), '\1al');
        yield new Transformation(new Pattern('/(bijou|caillou|chou|genou|hibou|joujou|pou|au|eu|eau)x$/'), '\1');
        yield new Transformation(new Pattern('/s$/'), '');
    }

    /**
     * @return Transformation[]
     */
    public static function getPlural() : iterable
    {
        yield new Transformation(new Pattern('/(s|x|z)$/'), '\1');
        yield new Transformation(new Pattern('/(b|cor|ém|gemm|soupir|trav|vant|vitr)ail$/'), '\1aux');
        yield new Transformation(new Pattern('/ail$/'), 'ails');
        yield new Transformation(new Pattern('/al$/'), 'aux');
        yield new Transformation(new Pattern('/(bleu|émeu|landau|lieu|pneu|sarrau)$/'), '\1s');
        yield new Transformation(new Pattern('/(bijou|caillou|chou|genou|hibou|joujou|pou|au|eu|eau)$/'), '\1x');
        yield new Transformation(new Pattern('/$/'), 's');
    }

    /**
     * @return Substitution[]
     */
    public static function getIrregular() : iterable
    {
        yield new Substitution(new Word('monsieur'), new Word('messieurs'));
        yield new Substitution(new Word('madame'), new Word('mesdames'));
        yield new Substitution(new Word('mademoiselle'), new Word('mesdemoiselles'));
    }
}
PKb�$Z¶� kk7inflector/lib/Doctrine/Inflector/Rules/French/Rules.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\French;

use Doctrine\Inflector\Rules\Patterns;
use Doctrine\Inflector\Rules\Ruleset;
use Doctrine\Inflector\Rules\Substitutions;
use Doctrine\Inflector\Rules\Transformations;

final class Rules
{
    public static function getSingularRuleset() : Ruleset
    {
        return new Ruleset(
            new Transformations(...Inflectible::getSingular()),
            new Patterns(...Uninflected::getSingular()),
            (new Substitutions(...Inflectible::getIrregular()))->getFlippedSubstitutions()
        );
    }

    public static function getPluralRuleset() : Ruleset
    {
        return new Ruleset(
            new Transformations(...Inflectible::getPlural()),
            new Patterns(...Uninflected::getPlural()),
            new Substitutions(...Inflectible::getIrregular())
        );
    }
}
PKb�$ZL�C���Binflector/lib/Doctrine/Inflector/Rules/French/InflectorFactory.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules\French;

use Doctrine\Inflector\GenericLanguageInflectorFactory;
use Doctrine\Inflector\Rules\Ruleset;

final class InflectorFactory extends GenericLanguageInflectorFactory
{
    protected function getSingularRuleset() : Ruleset
    {
        return Rules::getSingularRuleset();
    }

    protected function getPluralRuleset() : Ruleset
    {
        return Rules::getPluralRuleset();
    }
}
PKb�$Z�r���3inflector/lib/Doctrine/Inflector/Rules/Patterns.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector\Rules;

use function array_map;
use function implode;
use function preg_match;

class Patterns
{
    /** @var Pattern[] */
    private $patterns;

    /** @var string */
    private $regex;

    public function __construct(Pattern ...$patterns)
    {
        $this->patterns = $patterns;

        $patterns = array_map(static function (Pattern $pattern) : string {
            return $pattern->getPattern();
        }, $this->patterns);

        $this->regex = '/^(?:' . implode('|', $patterns) . ')$/i';
    }

    public function matches(string $word) : bool
    {
        return preg_match($this->regex, $word, $regs) === 1;
    }
}
PKb�$Z����5inflector/lib/Doctrine/Inflector/InflectorFactory.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector;

use Doctrine\Inflector\Rules\English;
use Doctrine\Inflector\Rules\French;
use Doctrine\Inflector\Rules\NorwegianBokmal;
use Doctrine\Inflector\Rules\Portuguese;
use Doctrine\Inflector\Rules\Spanish;
use Doctrine\Inflector\Rules\Turkish;
use InvalidArgumentException;
use function sprintf;

final class InflectorFactory
{
    public static function create() : LanguageInflectorFactory
    {
        return self::createForLanguage(Language::ENGLISH);
    }

    public static function createForLanguage(string $language) : LanguageInflectorFactory
    {
        switch ($language) {
            case Language::ENGLISH:
                return new English\InflectorFactory();
            case Language::FRENCH:
                return new French\InflectorFactory();
            case Language::NORWEGIAN_BOKMAL:
                return new NorwegianBokmal\InflectorFactory();
            case Language::PORTUGUESE:
                return new Portuguese\InflectorFactory();
            case Language::SPANISH:
                return new Spanish\InflectorFactory();
            case Language::TURKISH:
                return new Turkish\InflectorFactory();
            default:
                throw new InvalidArgumentException(sprintf(
                    'Language "%s" is not supported.',
                    $language
                ));
        }
    }
}
PKb�$Z1ɍO8inflector/lib/Doctrine/Inflector/CachedWordInflector.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector;

class CachedWordInflector implements WordInflector
{
    /** @var WordInflector */
    private $wordInflector;

    /** @var string[] */
    private $cache = [];

    public function __construct(WordInflector $wordInflector)
    {
        $this->wordInflector = $wordInflector;
    }

    public function inflect(string $word) : string
    {
        return $this->cache[$word] ?? $this->cache[$word] = $this->wordInflector->inflect($word);
    }
}
PKb�$Z��Kڮ�-inflector/lib/Doctrine/Inflector/Language.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector;

final class Language
{
    public const ENGLISH          = 'english';
    public const FRENCH           = 'french';
    public const NORWEGIAN_BOKMAL = 'norwegian-bokmal';
    public const PORTUGUESE       = 'portuguese';
    public const SPANISH          = 'spanish';
    public const TURKISH          = 'turkish';

    private function __construct()
    {
    }
}
PKb�$Z���.��Dinflector/lib/Doctrine/Inflector/GenericLanguageInflectorFactory.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector;

use Doctrine\Inflector\Rules\Ruleset;
use function array_unshift;

abstract class GenericLanguageInflectorFactory implements LanguageInflectorFactory
{
    /** @var Ruleset[] */
    private $singularRulesets = [];

    /** @var Ruleset[] */
    private $pluralRulesets = [];

    final public function __construct()
    {
        $this->singularRulesets[] = $this->getSingularRuleset();
        $this->pluralRulesets[]   = $this->getPluralRuleset();
    }

    final public function build() : Inflector
    {
        return new Inflector(
            new CachedWordInflector(new RulesetInflector(
                ...$this->singularRulesets
            )),
            new CachedWordInflector(new RulesetInflector(
                ...$this->pluralRulesets
            ))
        );
    }

    final public function withSingularRules(?Ruleset $singularRules, bool $reset = false) : LanguageInflectorFactory
    {
        if ($reset) {
            $this->singularRulesets = [];
        }

        if ($singularRules instanceof Ruleset) {
            array_unshift($this->singularRulesets, $singularRules);
        }

        return $this;
    }

    final public function withPluralRules(?Ruleset $pluralRules, bool $reset = false) : LanguageInflectorFactory
    {
        if ($reset) {
            $this->pluralRulesets = [];
        }

        if ($pluralRules instanceof Ruleset) {
            array_unshift($this->pluralRulesets, $pluralRules);
        }

        return $this;
    }

    abstract protected function getSingularRuleset() : Ruleset;

    abstract protected function getPluralRuleset() : Ruleset;
}
PKb�$Zr&�ϐ�2inflector/lib/Doctrine/Inflector/WordInflector.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector;

interface WordInflector
{
    public function inflect(string $word) : string;
}
PKb�$Z~�5((=inflector/lib/Doctrine/Inflector/LanguageInflectorFactory.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Inflector;

use Doctrine\Inflector\Rules\Ruleset;

interface LanguageInflectorFactory
{
    /**
     * Applies custom rules for singularisation
     *
     * @param bool $reset If true, will unset default inflections for all new rules
     *
     * @return $this
     */
    public function withSingularRules(?Ruleset $singularRules, bool $reset = false) : self;

    /**
     * Applies custom rules for pluralisation
     *
     * @param bool $reset If true, will unset default inflections for all new rules
     *
     * @return $this
     */
    public function withPluralRules(?Ruleset $pluralRules, bool $reset = false) : self;

    /**
     * Builds the inflector instance with all applicable rules
     */
    public function build() : Inflector;
}
PKb�$Z�чq&&5inflector/lib/Doctrine/Common/Inflector/Inflector.phpnu�[���<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Inflector;

use Doctrine\Inflector\Inflector as InflectorObject;
use Doctrine\Inflector\InflectorFactory;
use Doctrine\Inflector\LanguageInflectorFactory;
use Doctrine\Inflector\Rules\Pattern;
use Doctrine\Inflector\Rules\Patterns;
use Doctrine\Inflector\Rules\Ruleset;
use Doctrine\Inflector\Rules\Substitution;
use Doctrine\Inflector\Rules\Substitutions;
use Doctrine\Inflector\Rules\Transformation;
use Doctrine\Inflector\Rules\Transformations;
use Doctrine\Inflector\Rules\Word;
use InvalidArgumentException;
use function array_keys;
use function array_map;
use function array_unshift;
use function array_values;
use function sprintf;
use function trigger_error;
use const E_USER_DEPRECATED;

/**
 * @deprecated
 */
class Inflector
{
    /**
     * @var LanguageInflectorFactory|null
     */
    private static $factory;

    /** @var InflectorObject|null */
    private static $instance;

    private static function getInstance() : InflectorObject
    {
        if (self::$factory === null) {
            self::$factory = self::createFactory();
        }

        if (self::$instance === null) {
            self::$instance = self::$factory->build();
        }

        return self::$instance;
    }

    private static function createFactory() : LanguageInflectorFactory
    {
        return InflectorFactory::create();
    }

    /**
     * Converts a word into the format for a Doctrine table name. Converts 'ModelName' to 'model_name'.
     *
     * @deprecated
     */
    public static function tableize(string $word) : string
    {
        @trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please update to the new Inflector API.', __METHOD__), E_USER_DEPRECATED);

        return self::getInstance()->tableize($word);
    }

    /**
     * Converts a word into the format for a Doctrine class name. Converts 'table_name' to 'TableName'.
     */
    public static function classify(string $word) : string
    {
        @trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please update to the new Inflector API.', __METHOD__), E_USER_DEPRECATED);

        return self::getInstance()->classify($word);
    }

    /**
     * Camelizes a word. This uses the classify() method and turns the first character to lowercase.
     *
     * @deprecated
     */
    public static function camelize(string $word) : string
    {
        @trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please update to the new Inflector API.', __METHOD__), E_USER_DEPRECATED);

        return self::getInstance()->camelize($word);
    }

    /**
     * Uppercases words with configurable delimiters between words.
     *
     * Takes a string and capitalizes all of the words, like PHP's built-in
     * ucwords function. This extends that behavior, however, by allowing the
     * word delimiters to be configured, rather than only separating on
     * whitespace.
     *
     * Here is an example:
     * <code>
     * <?php
     * $string = 'top-o-the-morning to all_of_you!';
     * echo \Doctrine\Common\Inflector\Inflector::ucwords($string);
     * // Top-O-The-Morning To All_of_you!
     *
     * echo \Doctrine\Common\Inflector\Inflector::ucwords($string, '-_ ');
     * // Top-O-The-Morning To All_Of_You!
     * ?>
     * </code>
     *
     * @param string $string The string to operate on.
     * @param string $delimiters A list of word separators.
     *
     * @return string The string with all delimiter-separated words capitalized.
     *
     * @deprecated
     */
    public static function ucwords(string $string, string $delimiters = " \n\t\r\0\x0B-") : string
    {
        @trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please use the "ucwords" function instead.', __METHOD__), E_USER_DEPRECATED);

        return ucwords($string, $delimiters);
    }

    /**
     * Clears Inflectors inflected value caches, and resets the inflection
     * rules to the initial values.
     *
     * @deprecated
     */
    public static function reset() : void
    {
        @trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please update to the new Inflector API.', __METHOD__), E_USER_DEPRECATED);

        self::$factory = null;
        self::$instance = null;
    }

    /**
     * Adds custom inflection $rules, of either 'plural' or 'singular' $type.
     *
     * ### Usage:
     *
     * {{{
     * Inflector::rules('plural', array('/^(inflect)or$/i' => '\1ables'));
     * Inflector::rules('plural', array(
     *     'rules' => array('/^(inflect)ors$/i' => '\1ables'),
     *     'uninflected' => array('dontinflectme'),
     *     'irregular' => array('red' => 'redlings')
     * ));
     * }}}
     *
     * @param string  $type         The type of inflection, either 'plural' or 'singular'
     * @param array|iterable $rules An array of rules to be added.
     * @param boolean $reset        If true, will unset default inflections for all
     *                              new rules that are being defined in $rules.
     *
     * @return void
     *
     * @deprecated
     */
    public static function rules(string $type, iterable $rules, bool $reset = false) : void
    {
        @trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please update to the new Inflector API.', __METHOD__), E_USER_DEPRECATED);

        if (self::$factory === null) {
            self::$factory = self::createFactory();
        }

        self::$instance = null;

        switch ($type) {
            case 'singular':
                self::$factory->withSingularRules(self::buildRuleset($rules), $reset);
                break;
            case 'plural':
                self::$factory->withPluralRules(self::buildRuleset($rules), $reset);
                break;
            default:
                throw new InvalidArgumentException(sprintf('Cannot define custom inflection rules for type "%s".', $type));
        }
    }

    private static function buildRuleset(iterable $rules) : Ruleset
    {
        $regular = [];
        $irregular = [];
        $uninflected = [];

        foreach ($rules as $rule => $pattern) {
            if ( ! is_array($pattern)) {
                $regular[$rule] = $pattern;

                continue;
            }

            switch ($rule) {
                case 'uninflected':
                    $uninflected = $pattern;
                    break;
                case 'irregular':
                    $irregular = $pattern;
                    break;
                case 'rules':
                    $regular = $pattern;
                    break;
            }
        }

        return new Ruleset(
            new Transformations(...array_map(
                static function (string $pattern, string $replacement) : Transformation {
                    return new Transformation(new Pattern($pattern), $replacement);
                },
                array_keys($regular),
                array_values($regular)
            )),
            new Patterns(...array_map(
                static function (string $pattern) : Pattern {
                    return new Pattern($pattern);
                },
                $uninflected
            )),
            new Substitutions(...array_map(
                static function (string $word, string $to) : Substitution {
                    return new Substitution(new Word($word), new Word($to));
                },
                array_keys($irregular),
                array_values($irregular)
            ))
        );
    }

    /**
     * Returns a word in plural form.
     *
     * @param string $word The word in singular form.
     *
     * @return string The word in plural form.
     *
     * @deprecated
     */
    public static function pluralize(string $word) : string
    {
        @trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please update to the new Inflector API.', __METHOD__), E_USER_DEPRECATED);

        return self::getInstance()->pluralize($word);
    }

    /**
     * Returns a word in singular form.
     *
     * @param string $word The word in plural form.
     *
     * @return string The word in singular form.
     *
     * @deprecated
     */
    public static function singularize(string $word) : string
    {
        @trigger_error(sprintf('The "%s" method is deprecated and will be dropped in doctrine/inflector 2.0. Please update to the new Inflector API.', __METHOD__), E_USER_DEPRECATED);

        return self::getInstance()->singularize($word);
    }
}
PKb�$Z�9�))inflector/LICENSEnu�[���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.
PKb�$ZJ�-��annotations/phpstan.neonnu�[���parameters:
    autoload_files:
        - %currentWorkingDirectory%/tests/Doctrine/Tests/Common/Annotations/DocParserTest.php
    excludes_analyse:
        - %currentWorkingDirectory%/tests/*/Fixtures/*
    polluteScopeWithLoopInitialAssignments: true
    ignoreErrors:
        - '#Class Doctrine_Tests_Common_Annotations_Fixtures_ClassNoNamespaceNoComment not found#'
        - '#Instantiated class Doctrine_Tests_Common_Annotations_Fixtures_ClassNoNamespaceNoComment not found#'
        - '#Property Doctrine\\Tests\\Common\\Annotations\\DummyClassNonAnnotationProblem::\$foo has unknown class#'
        - '#Class Doctrine\\Tests\\Common\\Annotations\\True not found#'
        - '#Class Doctrine\\Tests\\Common\\Annotations\\False not found#'
        - '#Class Doctrine\\Tests\\Common\\Annotations\\Null not found#'
        - '#Call to an undefined method ReflectionClass::getUseStatements\(\)#'
PKb�$Z���Tannotations/README.mdnu�[���# Doctrine Annotations

[![Build Status](https://travis-ci.org/doctrine/annotations.svg?branch=master)](https://travis-ci.org/doctrine/annotations)
[![Dependency Status](https://www.versioneye.com/package/php--doctrine--annotations/badge.png)](https://www.versioneye.com/package/php--doctrine--annotations)
[![Reference Status](https://www.versioneye.com/php/doctrine:annotations/reference_badge.svg)](https://www.versioneye.com/php/doctrine:annotations/references)
[![Total Downloads](https://poser.pugx.org/doctrine/annotations/downloads.png)](https://packagist.org/packages/doctrine/annotations)
[![Latest Stable Version](https://poser.pugx.org/doctrine/annotations/v/stable.png)](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/latest/index.html).

## Changelog

See [CHANGELOG.md](CHANGELOG.md).
PKb�$Zt�Yss"annotations/.doctrine-project.jsonnu�[���{
    "active": true,
    "name": "Annotations",
    "slug": "annotations",
    "docsSlug": "doctrine-annotations",
    "versions": [
        {
            "name": "1.9",
            "branchName": "1.9",
            "slug": "1.9",
            "aliases": [
                "latest"
            ],
            "upcoming": true
        },
        {
            "name": "1.8",
            "branchName": "1.8",
            "slug": "1.8",
            "current": true,
            "aliases": [
                "current",
                "stable"
            ],
            "maintained": true
        },
        {
            "name": "1.7",
            "branchName": "1.7",
            "slug": "1.7",
            "maintained": false
        },
        {
            "name": "1.6",
            "branchName": "1.6",
            "slug": "1.6",
            "maintained": false
        }
    ]
}
PKb�$Z`ۖ���Cannotations/lib/Doctrine/Common/Annotations/AnnotationException.phpnu�[���<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations;

/**
 * Description of AnnotationException
 *
 * @since  2.0
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
 * @author Jonathan Wage <jonwage@gmail.com>
 * @author Roman Borschel <roman@code-factory.org>
 */
class AnnotationException extends \Exception
{
    /**
     * Creates a new AnnotationException describing a Syntax error.
     *
     * @param string $message Exception message
     *
     * @return AnnotationException
     */
    public static function syntaxError($message)
    {
        return new self('[Syntax Error] ' . $message);
    }

    /**
     * Creates a new AnnotationException describing a Semantical error.
     *
     * @param string $message Exception message
     *
     * @return AnnotationException
     */
    public static function semanticalError($message)
    {
        return new self('[Semantical Error] ' . $message);
    }

    /**
     * Creates a new AnnotationException describing an error which occurred during
     * the creation of the annotation.
     *
     * @since 2.2
     *
     * @param string $message
     *
     * @return AnnotationException
     */
    public static function creationError($message)
    {
        return new self('[Creation Error] ' . $message);
    }

    /**
     * Creates a new AnnotationException describing a type error.
     *
     * @since 1.1
     *
     * @param string $message
     *
     * @return AnnotationException
     */
    public static function typeError($message)
    {
        return new self('[Type Error] ' . $message);
    }

    /**
     * Creates a new AnnotationException describing a constant semantical error.
     *
     * @since 2.3
     *
     * @param string $identifier
     * @param string $context
     *
     * @return AnnotationException
     */
    public static function semanticalErrorConstants($identifier, $context = null)
    {
        return self::semanticalError(sprintf(
            "Couldn't find constant %s%s.",
            $identifier,
            $context ? ', ' . $context : ''
        ));
    }

    /**
     * Creates a new AnnotationException describing an type error of an attribute.
     *
     * @since 2.2
     *
     * @param string $attributeName
     * @param string $annotationName
     * @param string $context
     * @param string $expected
     * @param mixed  $actual
     *
     * @return AnnotationException
     */
    public static function attributeTypeError($attributeName, $annotationName, $context, $expected, $actual)
    {
        return self::typeError(sprintf(
            'Attribute "%s" of @%s declared on %s expects %s, but got %s.',
            $attributeName,
            $annotationName,
            $context,
            $expected,
            is_object($actual) ? 'an instance of ' . get_class($actual) : gettype($actual)
        ));
    }

    /**
     * Creates a new AnnotationException describing an required error of an attribute.
     *
     * @since 2.2
     *
     * @param string $attributeName
     * @param string $annotationName
     * @param string $context
     * @param string $expected
     *
     * @return AnnotationException
     */
    public static function requiredError($attributeName, $annotationName, $context, $expected)
    {
        return self::typeError(sprintf(
            'Attribute "%s" of @%s declared on %s expects %s. This value should not be null.',
            $attributeName,
            $annotationName,
            $context,
            $expected
        ));
    }

    /**
     * Creates a new AnnotationException describing a invalid enummerator.
     *
     * @since 2.4
     *
     * @param string $attributeName
     * @param string $annotationName
     * @param string $context
     * @param array  $available
     * @param mixed  $given
     *
     * @return AnnotationException
     */
    public static function enumeratorError($attributeName, $annotationName, $context, $available, $given)
    {
        return new self(sprintf(
            '[Enum Error] Attribute "%s" of @%s declared on %s accept 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."
        );
    }
}
PKb�$Z�3+��<annotations/lib/Doctrine/Common/Annotations/CachedReader.phpnu�[���<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations;

use Doctrine\Common\Cache\Cache;
use ReflectionClass;

/**
 * A cache aware annotation reader.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 */
final class CachedReader implements Reader
{
    /**
     * @var Reader
     */
    private $delegate;

    /**
     * @var Cache
     */
    private $cache;

    /**
     * @var boolean
     */
    private $debug;

    /**
     * @var array
     */
    private $loadedAnnotations = [];

    /**
     * @var int[]
     */
    private $loadedFilemtimes = [];

    /**
     * @param bool $debug
     */
    public function __construct(Reader $reader, Cache $cache, $debug = false)
    {
        $this->delegate = $reader;
        $this->cache = $cache;
        $this->debug = (boolean) $debug;
    }

    /**
     * {@inheritDoc}
     */
    public function getClassAnnotations(ReflectionClass $class)
    {
        $cacheKey = $class->getName();

        if (isset($this->loadedAnnotations[$cacheKey])) {
            return $this->loadedAnnotations[$cacheKey];
        }

        if (false === ($annots = $this->fetchFromCache($cacheKey, $class))) {
            $annots = $this->delegate->getClassAnnotations($class);
            $this->saveToCache($cacheKey, $annots);
        }

        return $this->loadedAnnotations[$cacheKey] = $annots;
    }

    /**
     * {@inheritDoc}
     */
    public function getClassAnnotation(ReflectionClass $class, $annotationName)
    {
        foreach ($this->getClassAnnotations($class) as $annot) {
            if ($annot instanceof $annotationName) {
                return $annot;
            }
        }

        return null;
    }

    /**
     * {@inheritDoc}
     */
    public function getPropertyAnnotations(\ReflectionProperty $property)
    {
        $class = $property->getDeclaringClass();
        $cacheKey = $class->getName().'$'.$property->getName();

        if (isset($this->loadedAnnotations[$cacheKey])) {
            return $this->loadedAnnotations[$cacheKey];
        }

        if (false === ($annots = $this->fetchFromCache($cacheKey, $class))) {
            $annots = $this->delegate->getPropertyAnnotations($property);
            $this->saveToCache($cacheKey, $annots);
        }

        return $this->loadedAnnotations[$cacheKey] = $annots;
    }

    /**
     * {@inheritDoc}
     */
    public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName)
    {
        foreach ($this->getPropertyAnnotations($property) as $annot) {
            if ($annot instanceof $annotationName) {
                return $annot;
            }
        }

        return null;
    }

    /**
     * {@inheritDoc}
     */
    public function getMethodAnnotations(\ReflectionMethod $method)
    {
        $class = $method->getDeclaringClass();
        $cacheKey = $class->getName().'#'.$method->getName();

        if (isset($this->loadedAnnotations[$cacheKey])) {
            return $this->loadedAnnotations[$cacheKey];
        }

        if (false === ($annots = $this->fetchFromCache($cacheKey, $class))) {
            $annots = $this->delegate->getMethodAnnotations($method);
            $this->saveToCache($cacheKey, $annots);
        }

        return $this->loadedAnnotations[$cacheKey] = $annots;
    }

    /**
     * {@inheritDoc}
     */
    public function getMethodAnnotation(\ReflectionMethod $method, $annotationName)
    {
        foreach ($this->getMethodAnnotations($method) as $annot) {
            if ($annot instanceof $annotationName) {
                return $annot;
            }
        }

        return null;
    }

    /**
     * Clears loaded annotations.
     *
     * @return void
     */
    public function clearLoadedAnnotations()
    {
        $this->loadedAnnotations = [];
        $this->loadedFilemtimes = [];
    }

    /**
     * Fetches a value from the cache.
     *
     * @param string $cacheKey The cache key.
     *
     * @return mixed The cached value or false when the value is not in cache.
     */
    private function fetchFromCache($cacheKey, ReflectionClass $class)
    {
        if (($data = $this->cache->fetch($cacheKey)) !== false) {
            if (!$this->debug || $this->isCacheFresh($cacheKey, $class)) {
                return $data;
            }
        }

        return false;
    }

    /**
     * Saves a value to the cache.
     *
     * @param string $cacheKey The cache key.
     * @param mixed  $value    The value.
     *
     * @return void
     */
    private function saveToCache($cacheKey, $value)
    {
        $this->cache->save($cacheKey, $value);
        if ($this->debug) {
            $this->cache->save('[C]'.$cacheKey, time());
        }
    }

    /**
     * Checks if the cache is fresh.
     *
     * @param string $cacheKey
     *
     * @return boolean
     */
    private function isCacheFresh($cacheKey, ReflectionClass $class)
    {
        $lastModification = $this->getLastModification($class);
        if ($lastModification === 0) {
            return true;
        }

        return $this->cache->fetch('[C]'.$cacheKey) >= $lastModification;
    }

    /**
     * Returns the time the class was last modified, testing traits and parents
     *
     * @return int
     */
    private function getLastModification(ReflectionClass $class)
    {
        $filename = $class->getFileName();

        if (isset($this->loadedFilemtimes[$filename])) {
            return $this->loadedFilemtimes[$filename];
        }

        $parent   = $class->getParentClass();

        $lastModification =  max(array_merge(
            [$filename ? filemtime($filename) : 0],
            array_map([$this, 'getTraitLastModificationTime'], $class->getTraits()),
            array_map([$this, 'getLastModification'], $class->getInterfaces()),
            $parent ? [$this->getLastModification($parent)] : []
        ));

        assert($lastModification !== false);

        return $this->loadedFilemtimes[$filename] = $lastModification;
    }

    /**
     * @return int
     */
    private function getTraitLastModificationTime(ReflectionClass $reflectionTrait)
    {
        $fileName = $reflectionTrait->getFileName();

        if (isset($this->loadedFilemtimes[$fileName])) {
            return $this->loadedFilemtimes[$fileName];
        }

        $lastModificationTime = max(array_merge(
            [$fileName ? filemtime($fileName) : 0],
            array_map([$this, 'getTraitLastModificationTime'], $reflectionTrait->getTraits())
        ));

        assert($lastModificationTime !== false);

        return $this->loadedFilemtimes[$fileName] = $lastModificationTime;
    }
}
PKb�$Zn�T�IIFannotations/lib/Doctrine/Common/Annotations/SimpleAnnotationReader.phpnu�[���<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations;

/**
 * Simple Annotation Reader.
 *
 * This annotation reader is intended to be used in projects where you have
 * full-control over all annotations that are available.
 *
 * @since  2.2
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Fabio B. Silva <fabio.bat.silva@gmail.com>
 */
class SimpleAnnotationReader implements Reader
{
    /**
     * @var DocParser
     */
    private $parser;

    /**
     * Constructor.
     *
     * Initializes a new SimpleAnnotationReader.
     */
    public function __construct()
    {
        $this->parser = new DocParser();
        $this->parser->setIgnoreNotImportedAnnotations(true);
    }

    /**
     * Adds a namespace in which we will look for annotations.
     *
     * @param string $namespace
     *
     * @return void
     */
    public function addNamespace($namespace)
    {
        $this->parser->addNamespace($namespace);
    }

    /**
     * {@inheritDoc}
     */
    public function getClassAnnotations(\ReflectionClass $class)
    {
        return $this->parser->parse($class->getDocComment(), 'class '.$class->getName());
    }

    /**
     * {@inheritDoc}
     */
    public function getMethodAnnotations(\ReflectionMethod $method)
    {
        return $this->parser->parse($method->getDocComment(), 'method '.$method->getDeclaringClass()->name.'::'.$method->getName().'()');
    }

    /**
     * {@inheritDoc}
     */
    public function getPropertyAnnotations(\ReflectionProperty $property)
    {
        return $this->parser->parse($property->getDocComment(), 'property '.$property->getDeclaringClass()->name.'::$'.$property->getName());
    }

    /**
     * {@inheritDoc}
     */
    public function getClassAnnotation(\ReflectionClass $class, $annotationName)
    {
        foreach ($this->getClassAnnotations($class) as $annot) {
            if ($annot instanceof $annotationName) {
                return $annot;
            }
        }

        return null;
    }

    /**
     * {@inheritDoc}
     */
    public function getMethodAnnotation(\ReflectionMethod $method, $annotationName)
    {
        foreach ($this->getMethodAnnotations($method) as $annot) {
            if ($annot instanceof $annotationName) {
                return $annot;
            }
        }

        return null;
    }

    /**
     * {@inheritDoc}
     */
    public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName)
    {
        foreach ($this->getPropertyAnnotations($property) as $annot) {
            if ($annot instanceof $annotationName) {
                return $annot;
            }
        }

        return null;
    }
}
PKb�$ZO����9annotations/lib/Doctrine/Common/Annotations/DocParser.phpnu�[���<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations;

use Doctrine\Common\Annotations\Annotation\Attribute;
use Doctrine\Common\Annotations\Annotation\Enum;
use Doctrine\Common\Annotations\Annotation\Target;
use Doctrine\Common\Annotations\Annotation\Attributes;
use ReflectionClass;
use ReflectionException;
use ReflectionProperty;
use RuntimeException;
use stdClass;


/**
 * A parser for docblock annotations.
 *
 * It is strongly discouraged to change the default annotation parsing process.
 *
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
 * @author Jonathan Wage <jonwage@gmail.com>
 * @author Roman Borschel <roman@code-factory.org>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Fabio B. Silva <fabio.bat.silva@gmail.com>
 */
final class DocParser
{
    /**
     * An array of all valid tokens for a class name.
     *
     * @var array
     */
    private static $classIdentifiers = [
        DocLexer::T_IDENTIFIER,
        DocLexer::T_TRUE,
        DocLexer::T_FALSE,
        DocLexer::T_NULL
    ];

    /**
     * The lexer.
     *
     * @var DocLexer
     */
    private $lexer;

    /**
     * Current target context.
     *
     * @var integer
     */
    private $target;

    /**
     * Doc parser used to collect annotation target.
     *
     * @var DocParser
     */
    private static $metadataParser;

    /**
     * Flag to control if the current annotation is nested or not.
     *
     * @var boolean
     */
    private $isNestedAnnotation = false;

    /**
     * Hashmap containing all use-statements that are to be used when parsing
     * the given doc block.
     *
     * @var array
     */
    private $imports = [];

    /**
     * This hashmap is used internally to cache results of class_exists()
     * look-ups.
     *
     * @var array
     */
    private $classExists = [];

    /**
     * Whether annotations that have not been imported should be ignored.
     *
     * @var boolean
     */
    private $ignoreNotImportedAnnotations = false;

    /**
     * An array of default namespaces if operating in simple mode.
     *
     * @var string[]
     */
    private $namespaces = [];

    /**
     * A list with annotations that are not causing exceptions when not resolved to an annotation class.
     *
     * The names must be the raw names as used in the class, not the fully qualified
     * class names.
     *
     * @var bool[] indexed by annotation name
     */
    private $ignoredAnnotationNames = [];

    /**
     * A list with annotations in namespaced format
     * that are not causing exceptions when not resolved to an annotation class.
     *
     * @var bool[] indexed by namespace name
     */
    private $ignoredAnnotationNamespaces = [];

    /**
     * @var string
     */
    private $context = '';

    /**
     * Hash-map for caching annotation metadata.
     *
     * @var array
     */
    private static $annotationMetadata = [
        'Doctrine\Common\Annotations\Annotation\Target' => [
            'is_annotation'    => true,
            'has_constructor'  => true,
            'properties'       => [],
            'targets_literal'  => 'ANNOTATION_CLASS',
            'targets'          => Target::TARGET_CLASS,
            'default_property' => 'value',
            'attribute_types'  => [
                'value'  => [
                    'required'  => false,
                    'type'      =>'array',
                    'array_type'=>'string',
                    'value'     =>'array<string>'
                ]
             ],
        ],
        'Doctrine\Common\Annotations\Annotation\Attribute' => [
            'is_annotation'    => true,
            'has_constructor'  => false,
            'targets_literal'  => 'ANNOTATION_ANNOTATION',
            'targets'          => Target::TARGET_ANNOTATION,
            'default_property' => 'name',
            'properties'       => [
                'name'      => 'name',
                'type'      => 'type',
                'required'  => 'required'
            ],
            'attribute_types'  => [
                'value'  => [
                    'required'  => true,
                    'type'      =>'string',
                    'value'     =>'string'
                ],
                'type'  => [
                    'required'  =>true,
                    'type'      =>'string',
                    'value'     =>'string'
                ],
                'required'  => [
                    'required'  =>false,
                    'type'      =>'boolean',
                    'value'     =>'boolean'
                ]
             ],
        ],
        'Doctrine\Common\Annotations\Annotation\Attributes' => [
            'is_annotation'    => true,
            'has_constructor'  => false,
            'targets_literal'  => 'ANNOTATION_CLASS',
            'targets'          => Target::TARGET_CLASS,
            'default_property' => 'value',
            'properties'       => [
                'value' => 'value'
            ],
            'attribute_types'  => [
                'value' => [
                    'type'      =>'array',
                    'required'  =>true,
                    'array_type'=>'Doctrine\Common\Annotations\Annotation\Attribute',
                    'value'     =>'array<Doctrine\Common\Annotations\Annotation\Attribute>'
                ]
             ],
        ],
        'Doctrine\Common\Annotations\Annotation\Enum' => [
            'is_annotation'    => true,
            'has_constructor'  => true,
            'targets_literal'  => 'ANNOTATION_PROPERTY',
            'targets'          => Target::TARGET_PROPERTY,
            'default_property' => 'value',
            'properties'       => [
                'value' => 'value'
            ],
            'attribute_types'  => [
                'value' => [
                    'type'      => 'array',
                    'required'  => true,
                ],
                'literal' => [
                    'type'      => 'array',
                    'required'  => false,
                ],
             ],
        ],
    ];

    /**
     * Hash-map for handle types declaration.
     *
     * @var array
     */
    private static $typeMap = [
        'float'     => 'double',
        'bool'      => 'boolean',
        // allow uppercase Boolean in honor of George Boole
        'Boolean'   => 'boolean',
        'int'       => 'integer',
    ];

    /**
     * Constructs a new DocParser.
     */
    public function __construct()
    {
        $this->lexer = new DocLexer;
    }

    /**
     * Sets the annotation names that are ignored during the parsing process.
     *
     * The names are supposed to be the raw names as used in the class, not the
     * fully qualified class names.
     *
     * @param bool[] $names indexed by annotation name
     *
     * @return void
     */
    public function setIgnoredAnnotationNames(array $names)
    {
        $this->ignoredAnnotationNames = $names;
    }

    /**
     * Sets the annotation namespaces that are ignored during the parsing process.
     *
     * @param bool[] $ignoredAnnotationNamespaces indexed by annotation namespace name
     *
     * @return void
     */
    public function setIgnoredAnnotationNamespaces($ignoredAnnotationNamespaces)
    {
        $this->ignoredAnnotationNamespaces = $ignoredAnnotationNamespaces;
    }

    /**
     * Sets ignore on not-imported annotations.
     *
     * @param boolean $bool
     *
     * @return void
     */
    public function setIgnoreNotImportedAnnotations($bool)
    {
        $this->ignoreNotImportedAnnotations = (boolean) $bool;
    }

    /**
     * Sets the default namespaces.
     *
     * @param string $namespace
     *
     * @return void
     * @throws RuntimeException
     */
    public function addNamespace($namespace)
    {
        if ($this->imports) {
            throw new RuntimeException('You must either use addNamespace(), or setImports(), but not both.');
        }

        $this->namespaces[] = $namespace;
    }

    /**
     * Sets the imports.
     *
     * @param array $imports
     *
     * @return void
     * @throws RuntimeException
     */
    public function setImports(array $imports)
    {
        if ($this->namespaces) {
            throw new RuntimeException('You must either use addNamespace(), or setImports(), but not both.');
        }

        $this->imports = $imports;
    }

    /**
     * Sets current target context as bitmask.
     *
     * @param integer $target
     *
     * @return void
     */
    public function setTarget($target)
    {
        $this->target = $target;
    }

    /**
     * Parses the given docblock string for annotations.
     *
     * @param string $input   The docblock string to parse.
     * @param string $context The parsing context.
     *
     * @return array Array of annotations. If no annotations are found, an empty array is returned.
     * @throws AnnotationException
     * @throws ReflectionException
     */
    public function parse($input, $context = '')
    {
        $pos = $this->findInitialTokenPosition($input);
        if ($pos === null) {
            return [];
        }

        $this->context = $context;

        $this->lexer->setInput(trim(substr($input, $pos), '* /'));
        $this->lexer->moveNext();

        return $this->Annotations();
    }

    /**
     * Finds the first valid annotation
     *
     * @param string $input The docblock string to parse
     */
    private function findInitialTokenPosition($input): ?int
    {
        $pos = 0;

        // search for first valid annotation
        while (($pos = strpos($input, '@', $pos)) !== false) {
            $preceding = substr($input, $pos - 1, 1);

            // if the @ is preceded by a space, a tab or * it is valid
            if ($pos === 0 || $preceding === ' ' || $preceding === '*' || $preceding === "\t") {
                return $pos;
            }

            $pos++;
        }

        return null;
    }

    /**
     * Attempts to match the given token with the current lookahead token.
     * If they match, updates the lookahead token; otherwise raises a syntax error.
     *
     * @param int $token Type of token.
     *
     * @return bool True if tokens match; false otherwise.
     * @throws AnnotationException
     */
    private function match(int $token): bool
    {
        if ( ! $this->lexer->isNextToken($token) ) {
            throw $this->syntaxError($this->lexer->getLiteral($token));
        }

        return $this->lexer->moveNext();
    }

    /**
     * Attempts to match the current lookahead token with any of the given tokens.
     *
     * If any of them matches, this method updates the lookahead token; otherwise
     * a syntax error is raised.
     *
     * @throws AnnotationException
     */
    private function matchAny(array $tokens): bool
    {
        if ( ! $this->lexer->isNextTokenAny($tokens)) {
            throw $this->syntaxError(implode(' or ', array_map([$this->lexer, 'getLiteral'], $tokens)));
        }

        return $this->lexer->moveNext();
    }

    /**
     * Generates a new syntax error.
     *
     * @param string     $expected Expected string.
     * @param array|null $token    Optional token.
     */
    private function syntaxError(string $expected, ?array $token = null): AnnotationException
    {
        if ($token === null) {
            $token = $this->lexer->lookahead;
        }

        $message  = sprintf('Expected %s, got ', $expected);
        $message .= ($this->lexer->lookahead === null)
            ? 'end of string'
            : sprintf("'%s' at position %s", $token['value'], $token['position']);

        if (strlen($this->context)) {
            $message .= ' in ' . $this->context;
        }

        $message .= '.';

        return AnnotationException::syntaxError($message);
    }

    /**
     * Attempts to check if a class exists or not. This never goes through the PHP autoloading mechanism
     * but uses the {@link AnnotationRegistry} to load classes.
     */
    private function classExists(string $fqcn): bool
    {
        if (isset($this->classExists[$fqcn])) {
            return $this->classExists[$fqcn];
        }

        // first check if the class already exists, maybe loaded through another AnnotationReader
        if (class_exists($fqcn, false)) {
            return $this->classExists[$fqcn] = true;
        }

        // final check, does this class exist?
        return $this->classExists[$fqcn] = AnnotationRegistry::loadAnnotationClass($fqcn);
    }

    /**
     * Collects parsing metadata for a given annotation class
     *
     * @param string $name The annotation name
     *
     * @throws AnnotationException
     * @throws ReflectionException
     */
    private function collectAnnotationMetadata(string $name): void
    {
        if (self::$metadataParser === null) {
            self::$metadataParser = new self();

            self::$metadataParser->setIgnoreNotImportedAnnotations(true);
            self::$metadataParser->setIgnoredAnnotationNames($this->ignoredAnnotationNames);
            self::$metadataParser->setImports([
                'enum'          => 'Doctrine\Common\Annotations\Annotation\Enum',
                'target'        => 'Doctrine\Common\Annotations\Annotation\Target',
                'attribute'     => 'Doctrine\Common\Annotations\Annotation\Attribute',
                'attributes'    => 'Doctrine\Common\Annotations\Annotation\Attributes'
            ]);

            // Make sure that annotations from metadata are loaded
            class_exists(Enum::class);
            class_exists(Target::class);
            class_exists(Attribute::class);
            class_exists(Attributes::class);
        }

        $class      = new ReflectionClass($name);
        $docComment = $class->getDocComment();

        // Sets default values for annotation metadata
        $metadata = [
            'default_property' => null,
            'has_constructor'  => (null !== $constructor = $class->getConstructor()) && $constructor->getNumberOfParameters() > 0,
            'properties'       => [],
            'property_types'   => [],
            'attribute_types'  => [],
            'targets_literal'  => null,
            'targets'          => Target::TARGET_ALL,
            'is_annotation'    => false !== strpos($docComment, '@Annotation'),
        ];

        // verify that the class is really meant to be an annotation
        if ($metadata['is_annotation']) {
            self::$metadataParser->setTarget(Target::TARGET_CLASS);

            foreach (self::$metadataParser->parse($docComment, 'class @' . $name) as $annotation) {
                if ($annotation instanceof Target) {
                    $metadata['targets']         = $annotation->targets;
                    $metadata['targets_literal'] = $annotation->literal;

                    continue;
                }

                if ($annotation instanceof Attributes) {
                    foreach ($annotation->value as $attribute) {
                        $this->collectAttributeTypeMetadata($metadata, $attribute);
                    }
                }
            }

            // if not has a constructor will inject values into public properties
            if (false === $metadata['has_constructor']) {
                // collect all public properties
                foreach ($class->getProperties(ReflectionProperty::IS_PUBLIC) as $property) {
                    $metadata['properties'][$property->name] = $property->name;

                    if (false === ($propertyComment = $property->getDocComment())) {
                        continue;
                    }

                    $attribute = new Attribute();

                    $attribute->required = (false !== strpos($propertyComment, '@Required'));
                    $attribute->name     = $property->name;
                    $attribute->type     = (false !== strpos($propertyComment, '@var') && preg_match('/@var\s+([^\s]+)/',$propertyComment, $matches))
                        ? $matches[1]
                        : 'mixed';

                    $this->collectAttributeTypeMetadata($metadata, $attribute);

                    // checks if the property has @Enum
                    if (false !== strpos($propertyComment, '@Enum')) {
                        $context = 'property ' . $class->name . "::\$" . $property->name;

                        self::$metadataParser->setTarget(Target::TARGET_PROPERTY);

                        foreach (self::$metadataParser->parse($propertyComment, $context) as $annotation) {
                            if ( ! $annotation instanceof Enum) {
                                continue;
                            }

                            $metadata['enum'][$property->name]['value']   = $annotation->value;
                            $metadata['enum'][$property->name]['literal'] = ( ! empty($annotation->literal))
                                ? $annotation->literal
                                : $annotation->value;
                        }
                    }
                }

                // choose the first property as default property
                $metadata['default_property'] = reset($metadata['properties']);
            }
        }

        self::$annotationMetadata[$name] = $metadata;
    }

    /**
     * Collects parsing metadata for a given attribute.
     */
    private function collectAttributeTypeMetadata(array &$metadata, Attribute $attribute): void
    {
        // handle internal type declaration
        $type = self::$typeMap[$attribute->type] ?? $attribute->type;

        // handle the case if the property type is mixed
        if ('mixed' === $type) {
            return;
        }

        // Evaluate type
        switch (true) {
            // Checks if the property has array<type>
            case (false !== $pos = strpos($type, '<')):
                $arrayType  = substr($type, $pos + 1, -1);
                $type       = 'array';

                if (isset(self::$typeMap[$arrayType])) {
                    $arrayType = self::$typeMap[$arrayType];
                }

                $metadata['attribute_types'][$attribute->name]['array_type'] = $arrayType;
                break;

            // Checks if the property has type[]
            case (false !== $pos = strrpos($type, '[')):
                $arrayType  = substr($type, 0, $pos);
                $type       = 'array';

                if (isset(self::$typeMap[$arrayType])) {
                    $arrayType = self::$typeMap[$arrayType];
                }

                $metadata['attribute_types'][$attribute->name]['array_type'] = $arrayType;
                break;
        }

        $metadata['attribute_types'][$attribute->name]['type']     = $type;
        $metadata['attribute_types'][$attribute->name]['value']    = $attribute->type;
        $metadata['attribute_types'][$attribute->name]['required'] = $attribute->required;
    }

    /**
     * Annotations ::= Annotation {[ "*" ]* [Annotation]}*
     *
     * @throws AnnotationException
     * @throws ReflectionException
     */
    private function Annotations(): array
    {
        $annotations = [];

        while (null !== $this->lexer->lookahead) {
            if (DocLexer::T_AT !== $this->lexer->lookahead['type']) {
                $this->lexer->moveNext();
                continue;
            }

            // make sure the @ is preceded by non-catchable pattern
            if (null !== $this->lexer->token && $this->lexer->lookahead['position'] === $this->lexer->token['position'] + strlen($this->lexer->token['value'])) {
                $this->lexer->moveNext();
                continue;
            }

            // make sure the @ is followed by either a namespace separator, or
            // an identifier token
            if ((null === $peek = $this->lexer->glimpse())
                || (DocLexer::T_NAMESPACE_SEPARATOR !== $peek['type'] && !in_array($peek['type'], self::$classIdentifiers, true))
                || $peek['position'] !== $this->lexer->lookahead['position'] + 1) {
                $this->lexer->moveNext();
                continue;
            }

            $this->isNestedAnnotation = false;
            if (false !== $annot = $this->Annotation()) {
                $annotations[] = $annot;
            }
        }

        return $annotations;
    }

    /**
     * Annotation     ::= "@" AnnotationName MethodCall
     * AnnotationName ::= QualifiedName | SimpleName
     * QualifiedName  ::= NameSpacePart "\" {NameSpacePart "\"}* SimpleName
     * NameSpacePart  ::= identifier | null | false | true
     * SimpleName     ::= identifier | null | false | true
     *
     * @return mixed False if it is not a valid annotation.
     *
     * @throws AnnotationException
     * @throws ReflectionException
     */
    private function Annotation()
    {
        $this->match(DocLexer::T_AT);

        // check if we have an annotation
        $name = $this->Identifier();

        if ($this->lexer->isNextToken(DocLexer::T_MINUS)
            && $this->lexer->nextTokenIsAdjacent()
        ) {
            // Annotations with dashes, such as "@foo-" or "@foo-bar", are to be discarded
            return false;
        }

        // only process names which are not fully qualified, yet
        // fully qualified names must start with a \
        $originalName = $name;

        if ('\\' !== $name[0]) {
            $pos = strpos($name, '\\');
            $alias = (false === $pos)? $name : substr($name, 0, $pos);
            $found = false;
            $loweredAlias = strtolower($alias);

            if ($this->namespaces) {
                foreach ($this->namespaces as $namespace) {
                    if ($this->classExists($namespace.'\\'.$name)) {
                        $name = $namespace.'\\'.$name;
                        $found = true;
                        break;
                    }
                }
            } elseif (isset($this->imports[$loweredAlias])) {
                $namespace = ltrim($this->imports[$loweredAlias], '\\');
                $name = (false !== $pos)
                    ? $namespace . substr($name, $pos)
                    : $namespace;
                $found = $this->classExists($name);
            } elseif ( ! isset($this->ignoredAnnotationNames[$name])
                && isset($this->imports['__NAMESPACE__'])
                && $this->classExists($this->imports['__NAMESPACE__'] . '\\' . $name)
            ) {
                $name  = $this->imports['__NAMESPACE__'].'\\'.$name;
                $found = true;
            } elseif (! isset($this->ignoredAnnotationNames[$name]) && $this->classExists($name)) {
                $found = true;
            }

            if ( ! $found) {
                if ($this->isIgnoredAnnotation($name)) {
                    return false;
                }

                throw AnnotationException::semanticalError(sprintf('The annotation "@%s" in %s was never imported. Did you maybe forget to add a "use" statement for this annotation?', $name, $this->context));
            }
        }

        $name = ltrim($name,'\\');

        if ( ! $this->classExists($name)) {
            throw AnnotationException::semanticalError(sprintf('The annotation "@%s" in %s does not exist, or could not be auto-loaded.', $name, $this->context));
        }

        // at this point, $name contains the fully qualified class name of the
        // annotation, and it is also guaranteed that this class exists, and
        // that it is loaded


        // collects the metadata annotation only if there is not yet
        if ( ! isset(self::$annotationMetadata[$name])) {
            $this->collectAnnotationMetadata($name);
        }

        // verify that the class is really meant to be an annotation and not just any ordinary class
        if (self::$annotationMetadata[$name]['is_annotation'] === false) {
            if ($this->isIgnoredAnnotation($originalName) || $this->isIgnoredAnnotation($name)) {
                return false;
            }

            throw AnnotationException::semanticalError(sprintf('The class "%s" is not annotated with @Annotation. Are you sure this class can be used as annotation? If so, then you need to add @Annotation to the _class_ doc comment of "%s". If it is indeed no annotation, then you need to add @IgnoreAnnotation("%s") to the _class_ doc comment of %s.', $name, $name, $originalName, $this->context));
        }

        //if target is nested annotation
        $target = $this->isNestedAnnotation ? Target::TARGET_ANNOTATION : $this->target;

        // Next will be nested
        $this->isNestedAnnotation = true;

        //if annotation does not support current target
        if (0 === (self::$annotationMetadata[$name]['targets'] & $target) && $target) {
            throw AnnotationException::semanticalError(
                sprintf('Annotation @%s is not allowed to be declared on %s. You may only use this annotation on these code elements: %s.',
                     $originalName, $this->context, self::$annotationMetadata[$name]['targets_literal'])
            );
        }

        $values = $this->MethodCall();

        if (isset(self::$annotationMetadata[$name]['enum'])) {
            // checks all declared attributes
            foreach (self::$annotationMetadata[$name]['enum'] as $property => $enum) {
                // checks if the attribute is a valid enumerator
                if (isset($values[$property]) && ! in_array($values[$property], $enum['value'])) {
                    throw AnnotationException::enumeratorError($property, $name, $this->context, $enum['literal'], $values[$property]);
                }
            }
        }

        // checks all declared attributes
        foreach (self::$annotationMetadata[$name]['attribute_types'] as $property => $type) {
            if ($property === self::$annotationMetadata[$name]['default_property']
                && !isset($values[$property]) && isset($values['value'])) {
                $property = 'value';
            }

            // handle a not given attribute or null value
            if (!isset($values[$property])) {
                if ($type['required']) {
                    throw AnnotationException::requiredError($property, $originalName, $this->context, 'a(n) '.$type['value']);
                }

                continue;
            }

            if ($type['type'] === 'array') {
                // handle the case of a single value
                if ( ! is_array($values[$property])) {
                    $values[$property] = [$values[$property]];
                }

                // checks if the attribute has array type declaration, such as "array<string>"
                if (isset($type['array_type'])) {
                    foreach ($values[$property] as $item) {
                        if (gettype($item) !== $type['array_type'] && !$item instanceof $type['array_type']) {
                            throw AnnotationException::attributeTypeError($property, $originalName, $this->context, 'either a(n) '.$type['array_type'].', or an array of '.$type['array_type'].'s', $item);
                        }
                    }
                }
            } elseif (gettype($values[$property]) !== $type['type'] && !$values[$property] instanceof $type['type']) {
                throw AnnotationException::attributeTypeError($property, $originalName, $this->context, 'a(n) '.$type['value'], $values[$property]);
            }
        }

        // check if the annotation expects values via the constructor,
        // or directly injected into public properties
        if (self::$annotationMetadata[$name]['has_constructor'] === true) {
            return new $name($values);
        }

        $instance = new $name();

        foreach ($values as $property => $value) {
            if (!isset(self::$annotationMetadata[$name]['properties'][$property])) {
                if ('value' !== $property) {
                    throw AnnotationException::creationError(sprintf('The annotation @%s declared on %s does not have a property named "%s". Available properties: %s', $originalName, $this->context, $property, implode(', ', self::$annotationMetadata[$name]['properties'])));
                }

                // handle the case if the property has no annotations
                if ( ! $property = self::$annotationMetadata[$name]['default_property']) {
                    throw AnnotationException::creationError(sprintf('The annotation @%s declared on %s does not accept any values, but got %s.', $originalName, $this->context, json_encode($values)));
                }
            }

            $instance->{$property} = $value;
        }

        return $instance;
    }

    /**
     * MethodCall ::= ["(" [Values] ")"]
     *
     * @throws AnnotationException
     * @throws ReflectionException
     */
    private function MethodCall(): array
    {
        $values = [];

        if ( ! $this->lexer->isNextToken(DocLexer::T_OPEN_PARENTHESIS)) {
            return $values;
        }

        $this->match(DocLexer::T_OPEN_PARENTHESIS);

        if ( ! $this->lexer->isNextToken(DocLexer::T_CLOSE_PARENTHESIS)) {
            $values = $this->Values();
        }

        $this->match(DocLexer::T_CLOSE_PARENTHESIS);

        return $values;
    }

    /**
     * Values ::= Array | Value {"," Value}* [","]
     *
     * @throws AnnotationException
     * @throws ReflectionException
     */
    private function Values(): array
    {
        $values = [$this->Value()];

        while ($this->lexer->isNextToken(DocLexer::T_COMMA)) {
            $this->match(DocLexer::T_COMMA);

            if ($this->lexer->isNextToken(DocLexer::T_CLOSE_PARENTHESIS)) {
                break;
            }

            $token = $this->lexer->lookahead;
            $value = $this->Value();

            if ( ! is_object($value) && ! is_array($value)) {
                throw $this->syntaxError('Value', $token);
            }

            $values[] = $value;
        }

        foreach ($values as $k => $value) {
            if (is_object($value) && $value instanceof stdClass) {
                $values[$value->name] = $value->value;
            } else if ( ! isset($values['value'])){
                $values['value'] = $value;
            } else {
                if ( ! is_array($values['value'])) {
                    $values['value'] = [$values['value']];
                }

                $values['value'][] = $value;
            }

            unset($values[$k]);
        }

        return $values;
    }

    /**
     * Constant ::= integer | string | float | boolean
     *
     * @return mixed
     *
     * @throws AnnotationException
     */
    private function Constant()
    {
        $identifier = $this->Identifier();

        if ( ! defined($identifier) && false !== strpos($identifier, '::') && '\\' !== $identifier[0]) {
            list($className, $const) = explode('::', $identifier);

            $pos = strpos($className, '\\');
            $alias = (false === $pos) ? $className : substr($className, 0, $pos);
            $found = false;
            $loweredAlias = strtolower($alias);

            switch (true) {
                case !empty ($this->namespaces):
                    foreach ($this->namespaces as $ns) {
                        if (class_exists($ns.'\\'.$className) || interface_exists($ns.'\\'.$className)) {
                             $className = $ns.'\\'.$className;
                             $found = true;
                             break;
                        }
                    }
                    break;

                case isset($this->imports[$loweredAlias]):
                    $found     = true;
                    $className = (false !== $pos)
                        ? $this->imports[$loweredAlias] . substr($className, $pos)
                        : $this->imports[$loweredAlias];
                    break;

                default:
                    if(isset($this->imports['__NAMESPACE__'])) {
                        $ns = $this->imports['__NAMESPACE__'];

                        if (class_exists($ns.'\\'.$className) || interface_exists($ns.'\\'.$className)) {
                            $className = $ns.'\\'.$className;
                            $found = true;
                        }
                    }
                    break;
            }

            if ($found) {
                 $identifier = $className . '::' . $const;
            }
        }

        /**
         * Checks if identifier ends with ::class and remove the leading backslash if it exists.
         */
        if ($this->identifierEndsWithClassConstant($identifier) && ! $this->identifierStartsWithBackslash($identifier)) {
            return substr($identifier, 0, $this->getClassConstantPositionInIdentifier($identifier));
        }
        if ($this->identifierEndsWithClassConstant($identifier) && $this->identifierStartsWithBackslash($identifier)) {
            return substr($identifier, 1, $this->getClassConstantPositionInIdentifier($identifier) - 1);
        }

        if (!defined($identifier)) {
            throw AnnotationException::semanticalErrorConstants($identifier, $this->context);
        }

        return constant($identifier);
    }

    private function identifierStartsWithBackslash(string $identifier) : bool
    {
        return '\\' === $identifier[0];
    }

    private function identifierEndsWithClassConstant(string $identifier) : bool
    {
        return $this->getClassConstantPositionInIdentifier($identifier) === strlen($identifier) - strlen('::class');
    }

    /**
     * @return int|false
     */
    private function getClassConstantPositionInIdentifier(string $identifier)
    {
        return stripos($identifier, '::class');
    }

    /**
     * Identifier ::= string
     *
     * @throws AnnotationException
     */
    private function Identifier(): string
    {
        // check if we have an annotation
        if ( ! $this->lexer->isNextTokenAny(self::$classIdentifiers)) {
            throw $this->syntaxError('namespace separator or identifier');
        }

        $this->lexer->moveNext();

        $className = $this->lexer->token['value'];

        while (
            null !== $this->lexer->lookahead &&
            $this->lexer->lookahead['position'] === ($this->lexer->token['position'] + strlen($this->lexer->token['value'])) &&
            $this->lexer->isNextToken(DocLexer::T_NAMESPACE_SEPARATOR)
        ) {
            $this->match(DocLexer::T_NAMESPACE_SEPARATOR);
            $this->matchAny(self::$classIdentifiers);

            $className .= '\\' . $this->lexer->token['value'];
        }

        return $className;
    }

    /**
     * Value ::= PlainValue | FieldAssignment
     *
     * @return mixed
     * @throws AnnotationException
     * @throws ReflectionException
     */
    private function Value()
    {
        $peek = $this->lexer->glimpse();

        if (DocLexer::T_EQUALS === $peek['type']) {
            return $this->FieldAssignment();
        }

        return $this->PlainValue();
    }

    /**
     * PlainValue ::= integer | string | float | boolean | Array | Annotation
     *
     * @return mixed
     * @throws AnnotationException
     * @throws ReflectionException
     */
    private function PlainValue()
    {
        if ($this->lexer->isNextToken(DocLexer::T_OPEN_CURLY_BRACES)) {
            return $this->Arrayx();
        }

        if ($this->lexer->isNextToken(DocLexer::T_AT)) {
            return $this->Annotation();
        }

        if ($this->lexer->isNextToken(DocLexer::T_IDENTIFIER)) {
            return $this->Constant();
        }

        switch ($this->lexer->lookahead['type']) {
            case DocLexer::T_STRING:
                $this->match(DocLexer::T_STRING);
                return $this->lexer->token['value'];

            case DocLexer::T_INTEGER:
                $this->match(DocLexer::T_INTEGER);
                return (int)$this->lexer->token['value'];

            case DocLexer::T_FLOAT:
                $this->match(DocLexer::T_FLOAT);
                return (float)$this->lexer->token['value'];

            case DocLexer::T_TRUE:
                $this->match(DocLexer::T_TRUE);
                return true;

            case DocLexer::T_FALSE:
                $this->match(DocLexer::T_FALSE);
                return false;

            case DocLexer::T_NULL:
                $this->match(DocLexer::T_NULL);
                return null;

            default:
                throw $this->syntaxError('PlainValue');
        }
    }

    /**
     * FieldAssignment ::= FieldName "=" PlainValue
     * FieldName ::= identifier
     * @throws AnnotationException
     * @throws ReflectionException
     */
    private function FieldAssignment(): stdClass
    {
        $this->match(DocLexer::T_IDENTIFIER);
        $fieldName = $this->lexer->token['value'];

        $this->match(DocLexer::T_EQUALS);

        $item = new stdClass();
        $item->name  = $fieldName;
        $item->value = $this->PlainValue();

        return $item;
    }

    /**
     * Array ::= "{" ArrayEntry {"," ArrayEntry}* [","] "}"
     * @throws AnnotationException
     * @throws ReflectionException
     */
    private function Arrayx(): array
    {
        $array = $values = [];

        $this->match(DocLexer::T_OPEN_CURLY_BRACES);

        // If the array is empty, stop parsing and return.
        if ($this->lexer->isNextToken(DocLexer::T_CLOSE_CURLY_BRACES)) {
            $this->match(DocLexer::T_CLOSE_CURLY_BRACES);

            return $array;
        }

        $values[] = $this->ArrayEntry();

        while ($this->lexer->isNextToken(DocLexer::T_COMMA)) {
            $this->match(DocLexer::T_COMMA);

            // optional trailing comma
            if ($this->lexer->isNextToken(DocLexer::T_CLOSE_CURLY_BRACES)) {
                break;
            }

            $values[] = $this->ArrayEntry();
        }

        $this->match(DocLexer::T_CLOSE_CURLY_BRACES);

        foreach ($values as $value) {
            list ($key, $val) = $value;

            if ($key !== null) {
                $array[$key] = $val;
            } else {
                $array[] = $val;
            }
        }

        return $array;
    }

    /**
     * ArrayEntry ::= Value | KeyValuePair
     * KeyValuePair ::= Key ("=" | ":") PlainValue | Constant
     * Key ::= string | integer | Constant
     *
     * @throws AnnotationException
     * @throws ReflectionException
     */
    private function ArrayEntry(): array
    {
        $peek = $this->lexer->glimpse();

        if (DocLexer::T_EQUALS === $peek['type']
                || DocLexer::T_COLON === $peek['type']) {

            if ($this->lexer->isNextToken(DocLexer::T_IDENTIFIER)) {
                $key = $this->Constant();
            } else {
                $this->matchAny([DocLexer::T_INTEGER, DocLexer::T_STRING]);
                $key = $this->lexer->token['value'];
            }

            $this->matchAny([DocLexer::T_EQUALS, DocLexer::T_COLON]);

            return [$key, $this->PlainValue()];
        }

        return [null, $this->Value()];
    }

    /**
     * Checks whether the given $name matches any ignored annotation name or namespace
     */
    private function isIgnoredAnnotation(string $name): bool
    {
        if ($this->ignoreNotImportedAnnotations || isset($this->ignoredAnnotationNames[$name])) {
            return true;
        }

        foreach (array_keys($this->ignoredAnnotationNamespaces) as $ignoredAnnotationNamespace) {
            $ignoredAnnotationNamespace = rtrim($ignoredAnnotationNamespace, '\\') . '\\';

            if (0 === stripos(rtrim($name, '\\') . '\\', $ignoredAnnotationNamespace)) {
                return true;
            }
        }

        return false;
    }
}
PKb�$Z/����8annotations/lib/Doctrine/Common/Annotations/DocLexer.phpnu�[���<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations;

use Doctrine\Common\Lexer\AbstractLexer;

/**
 * Simple lexer for docblock annotations.
 *
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
 * @author Jonathan Wage <jonwage@gmail.com>
 * @author Roman Borschel <roman@code-factory.org>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
final class DocLexer extends AbstractLexer
{
    const T_NONE                = 1;
    const T_INTEGER             = 2;
    const T_STRING              = 3;
    const T_FLOAT               = 4;

    // All tokens that are also identifiers should be >= 100
    const T_IDENTIFIER          = 100;
    const T_AT                  = 101;
    const T_CLOSE_CURLY_BRACES  = 102;
    const T_CLOSE_PARENTHESIS   = 103;
    const T_COMMA               = 104;
    const T_EQUALS              = 105;
    const T_FALSE               = 106;
    const T_NAMESPACE_SEPARATOR = 107;
    const T_OPEN_CURLY_BRACES   = 108;
    const T_OPEN_PARENTHESIS    = 109;
    const T_TRUE                = 110;
    const T_NULL                = 111;
    const T_COLON               = 112;
    const T_MINUS               = 113;

    /**
     * @var array
     */
    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
     */
    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;
    }
}
PKb�$Z0���=annotations/lib/Doctrine/Common/Annotations/IndexedReader.phpnu�[���<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations;

/**
 * Allows the reader to be used in-place of Doctrine's reader.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class IndexedReader implements Reader
{
    /**
     * @var Reader
     */
    private $delegate;

    /**
     * Constructor.
     *
     * @param Reader $reader
     */
    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, $annotation)
    {
        return $this->delegate->getClassAnnotation($class, $annotation);
    }

    /**
     * {@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, $annotation)
    {
        return $this->delegate->getMethodAnnotation($method, $annotation);
    }

    /**
     * {@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, $annotation)
    {
        return $this->delegate->getPropertyAnnotation($property, $annotation);
    }

    /**
     * Proxies all methods to the delegate.
     *
     * @param string $method
     * @param array  $args
     *
     * @return mixed
     */
    public function __call($method, $args)
    {
        return call_user_func_array([$this->delegate, $method], $args);
    }
}
PKb�$Z�ф´"�"?annotations/lib/Doctrine/Common/Annotations/FileCacheReader.phpnu�[���<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations;

/**
 * File cache reader for annotations.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 *
 * @deprecated the FileCacheReader is deprecated and will be removed
 *             in version 2.0.0 of doctrine/annotations. Please use the
 *             {@see \Doctrine\Common\Annotations\CachedReader} instead.
 */
class FileCacheReader implements Reader
{
    /**
     * @var Reader
     */
    private $reader;

    /**
     * @var string
     */
    private $dir;

    /**
     * @var bool
     */
    private $debug;

    /**
     * @var array
     */
    private $loadedAnnotations = [];

    /**
     * @var array
     */
    private $classNameHashes = [];

    /**
     * @var int
     */
    private $umask;

    /**
     * Constructor.
     *
     * @param Reader  $reader
     * @param string  $cacheDir
     * @param boolean $debug
     *
     * @throws \InvalidArgumentException
     */
    public function __construct(Reader $reader, $cacheDir, $debug = false, $umask = 0002)
    {
        if ( ! is_int($umask)) {
            throw new \InvalidArgumentException(sprintf(
                'The parameter umask must be an integer, was: %s',
                gettype($umask)
            ));
        }

        $this->reader = $reader;
        $this->umask = $umask;

        if (!is_dir($cacheDir) && !@mkdir($cacheDir, 0777 & (~$this->umask), true)) {
            throw new \InvalidArgumentException(sprintf('The directory "%s" does not exist and could not be created.', $cacheDir));
        }

        $this->dir   = rtrim($cacheDir, '\\/');
        $this->debug = $debug;
    }

    /**
     * {@inheritDoc}
     */
    public function getClassAnnotations(\ReflectionClass $class)
    {
        if ( ! isset($this->classNameHashes[$class->name])) {
            $this->classNameHashes[$class->name] = sha1($class->name);
        }
        $key = $this->classNameHashes[$class->name];

        if (isset($this->loadedAnnotations[$key])) {
            return $this->loadedAnnotations[$key];
        }

        $path = $this->dir.'/'.strtr($key, '\\', '-').'.cache.php';
        if (!is_file($path)) {
            $annot = $this->reader->getClassAnnotations($class);
            $this->saveCacheFile($path, $annot);
            return $this->loadedAnnotations[$key] = $annot;
        }

        if ($this->debug
            && (false !== $filename = $class->getFileName())
            && filemtime($path) < filemtime($filename)) {
            @unlink($path);

            $annot = $this->reader->getClassAnnotations($class);
            $this->saveCacheFile($path, $annot);
            return $this->loadedAnnotations[$key] = $annot;
        }

        return $this->loadedAnnotations[$key] = include $path;
    }

    /**
     * {@inheritDoc}
     */
    public function getPropertyAnnotations(\ReflectionProperty $property)
    {
        $class = $property->getDeclaringClass();
        if ( ! isset($this->classNameHashes[$class->name])) {
            $this->classNameHashes[$class->name] = sha1($class->name);
        }
        $key = $this->classNameHashes[$class->name].'$'.$property->getName();

        if (isset($this->loadedAnnotations[$key])) {
            return $this->loadedAnnotations[$key];
        }

        $path = $this->dir.'/'.strtr($key, '\\', '-').'.cache.php';
        if (!is_file($path)) {
            $annot = $this->reader->getPropertyAnnotations($property);
            $this->saveCacheFile($path, $annot);
            return $this->loadedAnnotations[$key] = $annot;
        }

        if ($this->debug
            && (false !== $filename = $class->getFilename())
            && filemtime($path) < filemtime($filename)) {
            @unlink($path);

            $annot = $this->reader->getPropertyAnnotations($property);
            $this->saveCacheFile($path, $annot);
            return $this->loadedAnnotations[$key] = $annot;
        }

        return $this->loadedAnnotations[$key] = include $path;
    }

    /**
     * {@inheritDoc}
     */
    public function getMethodAnnotations(\ReflectionMethod $method)
    {
        $class = $method->getDeclaringClass();
        if ( ! isset($this->classNameHashes[$class->name])) {
            $this->classNameHashes[$class->name] = sha1($class->name);
        }
        $key = $this->classNameHashes[$class->name].'#'.$method->getName();

        if (isset($this->loadedAnnotations[$key])) {
            return $this->loadedAnnotations[$key];
        }

        $path = $this->dir.'/'.strtr($key, '\\', '-').'.cache.php';
        if (!is_file($path)) {
            $annot = $this->reader->getMethodAnnotations($method);
            $this->saveCacheFile($path, $annot);
            return $this->loadedAnnotations[$key] = $annot;
        }

        if ($this->debug
            && (false !== $filename = $class->getFilename())
            && filemtime($path) < filemtime($filename)) {
            @unlink($path);

            $annot = $this->reader->getMethodAnnotations($method);
            $this->saveCacheFile($path, $annot);
            return $this->loadedAnnotations[$key] = $annot;
        }

        return $this->loadedAnnotations[$key] = include $path;
    }

    /**
     * Saves the cache file.
     *
     * @param string $path
     * @param mixed  $data
     *
     * @return void
     */
    private function saveCacheFile($path, $data)
    {
        if (!is_writable($this->dir)) {
            throw new \InvalidArgumentException(sprintf('The directory "%s" is not writable. Both, the webserver and the console user need access. You can manage access rights for multiple users with "chmod +a". If your system does not support this, check out the acl package.', $this->dir));
        }

        $tempfile = tempnam($this->dir, uniqid('', true));

        if (false === $tempfile) {
            throw new \RuntimeException(sprintf('Unable to create tempfile in directory: %s', $this->dir));
        }

        @chmod($tempfile, 0666 & (~$this->umask));

        $written = file_put_contents($tempfile, '<?php return unserialize('.var_export(serialize($data), true).');');

        if (false === $written) {
            throw new \RuntimeException(sprintf('Unable to write cached file to: %s', $tempfile));
        }

        @chmod($tempfile, 0666 & (~$this->umask));

        if (false === rename($tempfile, $path)) {
            @unlink($tempfile);
            throw new \RuntimeException(sprintf('Unable to rename %s to %s', $tempfile, $path));
        }
    }

    /**
     * {@inheritDoc}
     */
    public function getClassAnnotation(\ReflectionClass $class, $annotationName)
    {
        $annotations = $this->getClassAnnotations($class);

        foreach ($annotations as $annotation) {
            if ($annotation instanceof $annotationName) {
                return $annotation;
            }
        }

        return null;
    }

    /**
     * {@inheritDoc}
     */
    public function getMethodAnnotation(\ReflectionMethod $method, $annotationName)
    {
        $annotations = $this->getMethodAnnotations($method);

        foreach ($annotations as $annotation) {
            if ($annotation instanceof $annotationName) {
                return $annotation;
            }
        }

        return null;
    }

    /**
     * {@inheritDoc}
     */
    public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName)
    {
        $annotations = $this->getPropertyAnnotations($property);

        foreach ($annotations as $annotation) {
            if ($annotation instanceof $annotationName) {
                return $annotation;
            }
        }

        return null;
    }

    /**
     * Clears loaded annotations.
     *
     * @return void
     */
    public function clearLoadedAnnotations()
    {
        $this->loadedAnnotations = [];
    }
}
PKb�$Z"��ӗ�;annotations/lib/Doctrine/Common/Annotations/TokenParser.phpnu�[���<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations;

/**
 * Parses a file for namespaces/use/class declarations.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Christian Kaps <christian.kaps@mohiva.com>
 */
class TokenParser
{
    /**
     * The token list.
     *
     * @var array
     */
    private $tokens;

    /**
     * The number of tokens.
     *
     * @var int
     */
    private $numTokens;

    /**
     * The current array pointer.
     *
     * @var int
     */
    private $pointer = 0;

    /**
     * @param string $contents
     */
    public function __construct($contents)
    {
        $this->tokens = token_get_all($contents);

        // The PHP parser sets internal compiler globals for certain things. Annoyingly, the last docblock comment it
        // saw gets stored in doc_comment. When it comes to compile the next thing to be include()d this stored
        // doc_comment becomes owned by the first thing the compiler sees in the file that it considers might have a
        // docblock. If the first thing in the file is a class without a doc block this would cause calls to
        // getDocBlock() on said class to return our long lost doc_comment. Argh.
        // To workaround, cause the parser to parse an empty docblock. Sure getDocBlock() will return this, but at least
        // it's harmless to us.
        token_get_all("<?php\n/**\n *\n */");

        $this->numTokens = count($this->tokens);
    }

    /**
     * Gets the next non whitespace and non comment token.
     *
     * @param boolean $docCommentIsComment If TRUE then a doc comment is considered a comment and skipped.
     *                                     If FALSE then only whitespace and normal comments are skipped.
     *
     * @return array|null The token if exists, null otherwise.
     */
    public function next($docCommentIsComment = TRUE)
    {
        for ($i = $this->pointer; $i < $this->numTokens; $i++) {
            $this->pointer++;
            if ($this->tokens[$i][0] === T_WHITESPACE ||
                $this->tokens[$i][0] === T_COMMENT ||
                ($docCommentIsComment && $this->tokens[$i][0] === T_DOC_COMMENT)) {

                continue;
            }

            return $this->tokens[$i];
        }

        return null;
    }

    /**
     * Parses a single use statement.
     *
     * @return array 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];
            } else if ($explicitAlias && $token[0] === T_STRING) {
                $alias = $token[1];
            } else if (\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];
            } else if ($token[0] === T_NS_SEPARATOR) {
                $class .= '\\';
                $alias = '';
            } else if ($token[0] === T_AS) {
                $explicitAlias = true;
                $alias = '';
            } else if ($token === ',') {
                $statements[strtolower($alias)] = $groupRoot . $class;
                $class = '';
                $alias = '';
                $explicitAlias = false;
            } else if ($token === ';') {
                $statements[strtolower($alias)] = $groupRoot . $class;
                break;
            } else if ($token === '{' ) {
                $groupRoot = $class;
                $class = '';
            } else if ($token === '}' ) {
                continue;
            } else {
                break;
            }
        }

        return $statements;
    }

    /**
     * Gets all use statements.
     *
     * @param string $namespaceName The namespace name of the reflected class.
     *
     * @return array A list with all found use statements.
     */
    public function parseUseStatements($namespaceName)
    {
        $statements = [];
        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();
    }
}
PKb�$Z!�
���9annotations/lib/Doctrine/Common/Annotations/PhpParser.phpnu�[���<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations;

use SplFileObject;

/**
 * Parses a file for namespaces/use/class declarations.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Christian Kaps <christian.kaps@mohiva.com>
 */
final class PhpParser
{
    /**
     * Parses a class.
     *
     * @param \ReflectionClass $class A <code>ReflectionClass</code> object.
     *
     * @return array A list with use statements in the form (Alias => FQN).
     */
    public function parseClass(\ReflectionClass $class)
    {
        if (method_exists($class, 'getUseStatements')) {
            return $class->getUseStatements();
        }

        if (false === $filename = $class->getFileName()) {
            return [];
        }

        $content = $this->getFileContent($filename, $class->getStartLine());

        if (null === $content) {
            return [];
        }

        $namespace = preg_quote($class->getNamespaceName());
        $content = preg_replace('/^.*?(\bnamespace\s+' . $namespace . '\s*[;{].*)$/s', '\\1', $content);
        $tokenizer = new TokenParser('<?php ' . $content);

        $statements = $tokenizer->parseUseStatements($class->getNamespaceName());

        return $statements;
    }

    /**
     * Gets the content of the file right up to the given line number.
     *
     * @param string  $filename   The name of the file to load.
     * @param integer $lineNumber The number of lines to read from file.
     *
     * @return string|null The content of the file or null if the file does not exist.
     */
    private function getFileContent($filename, $lineNumber)
    {
        if ( ! is_file($filename)) {
            return null;
        }

        $content = '';
        $lineCnt = 0;
        $file = new SplFileObject($filename);
        while (!$file->eof()) {
            if ($lineCnt++ == $lineNumber) {
                break;
            }

            $content .= $file->fgets();
        }

        return $content;
    }
}
PKb�$ZX\��	�	:annotations/lib/Doctrine/Common/Annotations/Annotation.phpnu�[���<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations;

/**
 * Annotations class.
 *
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
 * @author Jonathan Wage <jonwage@gmail.com>
 * @author Roman Borschel <roman@code-factory.org>
 */
class Annotation
{
    /**
     * Value property. Common among all derived classes.
     *
     * @var string
     */
    public $value;

    /**
     * Constructor.
     *
     * @param array $data Key-value for properties to be defined in this class.
     */
    public final function __construct(array $data)
    {
        foreach ($data as $key => $value) {
            $this->$key = $value;
        }
    }

    /**
     * Error handler for unknown property accessor in Annotation class.
     *
     * @param string $name Unknown property name.
     *
     * @throws \BadMethodCallException
     */
    public function __get($name)
    {
        throw new \BadMethodCallException(
            sprintf("Unknown property '%s' on annotation '%s'.", $name, get_class($this))
        );
    }

    /**
     * Error handler for unknown property mutator in Annotation class.
     *
     * @param string $name  Unknown property name.
     * @param mixed  $value Property value.
     *
     * @throws \BadMethodCallException
     */
    public function __set($name, $value)
    {
        throw new \BadMethodCallException(
            sprintf("Unknown property '%s' on annotation '%s'.", $name, get_class($this))
        );
    }
}
PKb�$Z�x��Bannotations/lib/Doctrine/Common/Annotations/AnnotationRegistry.phpnu�[���<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations;

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[]
     */
    static private $autoloadNamespaces = [];

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

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

    /**
     * Whenever registerFile() was used. Disables use of standard autoloader.
     *
     * @var bool
     */
    static private $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.
     *
     * @param string            $namespace
     * @param string|array|null $dirs
     *
     * @deprecated This method is deprecated and will be removed in doctrine/annotations 2.0. Annotations will be autoloaded in 2.0.
     */
    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.
     *
     * @param string[][]|string[]|null[] $namespaces indexed by namespace name
     *
     * @deprecated This method is deprecated and will be removed in doctrine/annotations 2.0. Annotations will be autoloaded in 2.0.
     */
    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) ) {
            self::registerLoader($callable);
        }
    }

    /**
     * Autoloads an annotation class silently.
     */
    public static function loadAnnotationClass(string $class) : bool
    {
        if (\class_exists($class, false)) {
            return true;
        }

        if (\array_key_exists($class, self::$failedToAutoload)) {
            return false;
        }

        foreach (self::$autoloadNamespaces AS $namespace => $dirs) {
            if (\strpos($class, $namespace) === 0) {
                $file = \str_replace('\\', \DIRECTORY_SEPARATOR, $class) . '.php';

                if ($dirs === null) {
                    if ($path = stream_resolve_include_path($file)) {
                        require $path;
                        return true;
                    }
                } else {
                    foreach((array) $dirs AS $dir) {
                        if (is_file($dir . \DIRECTORY_SEPARATOR . $file)) {
                            require $dir . \DIRECTORY_SEPARATOR . $file;
                            return true;
                        }
                    }
                }
            }
        }

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

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

        self::$failedToAutoload[$class] = null;

        return false;
    }
}
PKb�$Z�����
�
6annotations/lib/Doctrine/Common/Annotations/Reader.phpnu�[���<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations;

/**
 * Interface for annotation readers.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
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 An array of Annotations.
     */
    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 string           $annotationName The name of the annotation.
     *
     * @return object|null The Annotation or NULL, if the requested annotation does not exist.
     */
    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 An array of Annotations.
     */
    function getMethodAnnotations(\ReflectionMethod $method);

    /**
     * Gets a method annotation.
     *
     * @param \ReflectionMethod $method         The ReflectionMethod to read the annotations from.
     * @param string            $annotationName The name of the annotation.
     *
     * @return object|null The Annotation or NULL, if the requested annotation does not exist.
     */
    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 An array of Annotations.
     */
    function getPropertyAnnotations(\ReflectionProperty $property);

    /**
     * Gets a property annotation.
     *
     * @param \ReflectionProperty $property       The ReflectionProperty to read the annotations from.
     * @param string              $annotationName The name of the annotation.
     *
     * @return object|null The Annotation or NULL, if the requested annotation does not exist.
     */
    function getPropertyAnnotation(\ReflectionProperty $property, $annotationName);
}
PKb�$Z�-���2�2@annotations/lib/Doctrine/Common/Annotations/AnnotationReader.phpnu�[���<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations;

use Doctrine\Common\Annotations\Annotation\IgnoreAnnotation;
use Doctrine\Common\Annotations\Annotation\Target;
use ReflectionClass;
use ReflectionMethod;
use ReflectionProperty;

/**
 * A reader for docblock annotations.
 *
 * @author  Benjamin Eberlei <kontakt@beberlei.de>
 * @author  Guilherme Blanco <guilhermeblanco@hotmail.com>
 * @author  Jonathan Wage <jonwage@gmail.com>
 * @author  Roman Borschel <roman@code-factory.org>
 * @author  Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class AnnotationReader implements Reader
{
    /**
     * Global map for imports.
     *
     * @var array
     */
    private static $globalImports = [
        'ignoreannotation' => 'Doctrine\Common\Annotations\Annotation\IgnoreAnnotation',
    ];

    /**
     * A list with annotations that are not causing exceptions when not resolved to an annotation class.
     *
     * The names are case sensitive.
     *
     * @var array
     */
    private static $globalIgnoredNames = [
        // Annotation tags
        'Annotation' => true, 'Attribute' => true, 'Attributes' => true,
        /* Can we enable this? 'Enum' => true, */
        'Required' => true,
        'Target' => true,
        // Widely used tags (but not existent in phpdoc)
        'fix' => true , 'fixme' => true,
        'override' => true,
        // PHPDocumentor 1 tags
        'abstract'=> true, 'access'=> true,
        'code' => true,
        'deprec'=> true,
        'endcode' => true, 'exception'=> true,
        'final'=> true,
        'ingroup' => true, 'inheritdoc'=> true, 'inheritDoc'=> true,
        'magic' => true,
        'name'=> true,
        'toc' => true, 'tutorial'=> true,
        'private' => true,
        'static'=> true, 'staticvar'=> true, 'staticVar'=> true,
        'throw' => true,
        // PHPDocumentor 2 tags.
        '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,
        // PHPUnit tags
        'codeCoverageIgnore' => true, 'codeCoverageIgnoreStart' => true, 'codeCoverageIgnoreEnd' => true,
        // PHPCheckStyle
        'SuppressWarnings' => true,
        // PHPStorm
        'noinspection' => true,
        // PEAR
        'package_version' => true,
        // PlantUML
        'startuml' => true, 'enduml' => true,
        // Symfony 3.3 Cache Adapter
        'experimental' => true,
        // Slevomat Coding Standard
        'phpcsSuppress' => true,
        // PHP CodeSniffer
        'codingStandardsIgnoreStart' => true,
        'codingStandardsIgnoreEnd' => true,
        // PHPStan
        'template' => true, 'implements' => true, 'extends' => true, 'use' => true,
    ];

    /**
     * A list with annotations that are not causing exceptions when not resolved to an annotation class.
     *
     * The names are case sensitive.
     *
     * @var array
     */
    private static $globalIgnoredNamespaces = [];

    /**
     * Add a new annotation to the globally ignored annotation names with regard to exception handling.
     *
     * @param string $name
     */
    static public function addGlobalIgnoredName($name)
    {
        self::$globalIgnoredNames[$name] = true;
    }

    /**
     * Add a new annotation to the globally ignored annotation namespaces with regard to exception handling.
     *
     * @param string $namespace
     */
    static public function addGlobalIgnoredNamespace($namespace)
    {
        self::$globalIgnoredNamespaces[$namespace] = true;
    }

    /**
     * Annotations parser.
     *
     * @var \Doctrine\Common\Annotations\DocParser
     */
    private $parser;

    /**
     * Annotations parser used to collect parsing metadata.
     *
     * @var \Doctrine\Common\Annotations\DocParser
     */
    private $preParser;

    /**
     * PHP parser used to collect imports.
     *
     * @var \Doctrine\Common\Annotations\PhpParser
     */
    private $phpParser;

    /**
     * In-memory cache mechanism to store imported annotations per class.
     *
     * @var array
     */
    private $imports = [];

    /**
     * In-memory cache mechanism to store ignored annotations per class.
     *
     * @var array
     */
    private $ignoredAnnotationNames = [];

    /**
     * Constructor.
     *
     * Initializes a new AnnotationReader.
     *
     * @param DocParser $parser
     *
     * @throws AnnotationException
     */
    public function __construct(DocParser $parser = null)
    {
        if (extension_loaded('Zend Optimizer+') && (ini_get('zend_optimizerplus.save_comments') === "0" || ini_get('opcache.save_comments') === "0")) {
            throw AnnotationException::optimizerPlusSaveComments();
        }

        if (extension_loaded('Zend OPcache') && ini_get('opcache.save_comments') == 0) {
            throw AnnotationException::optimizerPlusSaveComments();
        }

        // Make sure that the IgnoreAnnotation annotation is loaded
        class_exists(IgnoreAnnotation::class);

        $this->parser = $parser ?: new DocParser();

        $this->preParser = new DocParser;

        $this->preParser->setImports(self::$globalImports);
        $this->preParser->setIgnoreNotImportedAnnotations(true);
        $this->preParser->setIgnoredAnnotationNames(self::$globalIgnoredNames);

        $this->phpParser = new PhpParser;
    }

    /**
     * {@inheritDoc}
     */
    public function getClassAnnotations(ReflectionClass $class)
    {
        $this->parser->setTarget(Target::TARGET_CLASS);
        $this->parser->setImports($this->getClassImports($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;
    }

    /**
     * Returns the ignored annotations for the given class.
     *
     * @param \ReflectionClass $class
     *
     * @return array
     */
    private function getIgnoredAnnotationNames(ReflectionClass $class)
    {
        $name = $class->getName();
        if (isset($this->ignoredAnnotationNames[$name])) {
            return $this->ignoredAnnotationNames[$name];
        }

        $this->collectParsingMetadata($class);

        return $this->ignoredAnnotationNames[$name];
    }

    /**
     * Retrieves imports.
     *
     * @param \ReflectionClass $class
     *
     * @return array
     */
    private function getClassImports(ReflectionClass $class)
    {
        $name = $class->getName();
        if (isset($this->imports[$name])) {
            return $this->imports[$name];
        }

        $this->collectParsingMetadata($class);

        return $this->imports[$name];
    }

    /**
     * Retrieves imports for methods.
     *
     * @param \ReflectionMethod $method
     *
     * @return array
     */
    private function getMethodImports(ReflectionMethod $method)
    {
        $class = $method->getDeclaringClass();
        $classImports = $this->getClassImports($class);

        $traitImports = [];

        foreach ($class->getTraits() as $trait) {
            if ($trait->hasMethod($method->getName())
                && $trait->getFileName() === $method->getFileName()
            ) {
                $traitImports = array_merge($traitImports, $this->phpParser->parseClass($trait));
            }
        }

        return array_merge($classImports, $traitImports);
    }

    /**
     * Retrieves imports for properties.
     *
     * @param \ReflectionProperty $property
     *
     * @return array
     */
    private function getPropertyImports(ReflectionProperty $property)
    {
        $class = $property->getDeclaringClass();
        $classImports = $this->getClassImports($class);

        $traitImports = [];

        foreach ($class->getTraits() as $trait) {
            if ($trait->hasProperty($property->getName())) {
                $traitImports = array_merge($traitImports, $this->phpParser->parseClass($trait));
            }
        }

        return array_merge($classImports, $traitImports);
    }

    /**
     * Collects parsing metadata for a given class.
     *
     * @param \ReflectionClass $class
     */
    private function collectParsingMetadata(ReflectionClass $class)
    {
        $ignoredAnnotationNames = self::$globalIgnoredNames;
        $annotations            = $this->preParser->parse($class->getDocComment(), 'class ' . $class->name);

        foreach ($annotations as $annotation) {
            if ($annotation instanceof IgnoreAnnotation) {
                foreach ($annotation->names AS $annot) {
                    $ignoredAnnotationNames[$annot] = true;
                }
            }
        }

        $name = $class->getName();

        $this->imports[$name] = array_merge(
            self::$globalImports,
            $this->phpParser->parseClass($class),
            ['__NAMESPACE__' => $class->getNamespaceName()]
        );

        $this->ignoredAnnotationNames[$name] = $ignoredAnnotationNames;
    }
}
PKb�$Z����Dannotations/lib/Doctrine/Common/Annotations/Annotation/Attribute.phpnu�[���<?php

/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations\Annotation;

/**
 * Annotation that can be used to signal to the parser
 * to check the attribute type during the parsing process.
 *
 * @author Fabio B. Silva <fabio.bat.silva@gmail.com>
 *
 * @Annotation
 */
final class Attribute
{
    /**
     * @var string
     */
    public $name;

    /**
     * @var string
     */
    public $type;

    /**
     * @var boolean
     */
    public $required = false;
}
PKb�$Z��"
"
?annotations/lib/Doctrine/Common/Annotations/Annotation/Enum.phpnu�[���<?php

/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations\Annotation;

/**
 * Annotation that can be used to signal to the parser
 * to check the available values during the parsing process.
 *
 * @since  2.4
 * @author Fabio B. Silva <fabio.bat.silva@gmail.com>
 *
 * @Annotation
 * @Attributes({
 *    @Attribute("value",   required = true,  type = "array"),
 *    @Attribute("literal", required = false, type = "array")
 * })
 */
final class Enum
{
    /**
     * @var array
     */
    public $value;

    /**
     * Literal target declaration.
     *
     * @var array
     */
    public $literal;

    /**
     * Annotation constructor.
     *
     * @param array $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'];
    }
}
PKb�$Z�ִLCCEannotations/lib/Doctrine/Common/Annotations/Annotation/Attributes.phpnu�[���<?php

/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

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.
 *
 * @author Fabio B. Silva <fabio.bat.silva@gmail.com>
 *
 * @Annotation
 */
final class Attributes
{
    /**
     * @var array<Attribute>
     */
    public $value;
}
PKb�$Z$�ߊEEKannotations/lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.phpnu�[���<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations\Annotation;

/**
 * Annotation that can be used to signal to the parser to ignore specific
 * annotations during the parsing process.
 *
 * @Annotation
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
final class IgnoreAnnotation
{
    /**
     * @var array
     */
    public $names;

    /**
     * Constructor.
     *
     * @param array $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'];
    }
}
PKb�$Z�M��Cannotations/lib/Doctrine/Common/Annotations/Annotation/Required.phpnu�[���<?php

/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

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.
 *
 * @author Fabio B. Silva <fabio.bat.silva@gmail.com>
 *
 * @Annotation
 */
final class Required
{
}
PKb�$ZlN����Aannotations/lib/Doctrine/Common/Annotations/Annotation/Target.phpnu�[���<?php

/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Annotations\Annotation;

/**
 * Annotation that can be used to signal to the parser
 * to check the annotation target during the parsing process.
 *
 * @author Fabio B. Silva <fabio.bat.silva@gmail.com>
 *
 * @Annotation
 */
final class Target
{
    const TARGET_CLASS              = 1;
    const TARGET_METHOD             = 2;
    const TARGET_PROPERTY           = 4;
    const TARGET_ANNOTATION         = 8;
    const TARGET_ALL                = 15;

    /**
     * @var array
     */
    private static $map = [
        'ALL'        => self::TARGET_ALL,
        'CLASS'      => self::TARGET_CLASS,
        'METHOD'     => self::TARGET_METHOD,
        'PROPERTY'   => self::TARGET_PROPERTY,
        'ANNOTATION' => self::TARGET_ANNOTATION,
    ];

    /**
     * @var array
     */
    public $value;

    /**
     * Targets as bitmask.
     *
     * @var integer
     */
    public $targets;

    /**
     * Literal target declaration.
     *
     * @var string
     */
    public $literal;

    /**
     * Annotation constructor.
     *
     * @param array $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);
    }
}
PKb�$Z"K�W�#�#annotations/CHANGELOG.mdnu�[���## Changelog

### 1.6.1

This release fixes an issue in which annotations such as `@foo-bar`
and `@foo-` were incorrectly recognised as valid, and both erroneously
parsed as `@foo`.

Any annotation with `@name-*` format will now silently be ignored,
allowing vendor-specific annotations to be prefixed with the tool
name.

Total issues resolved: **3**

- [165: Update the composer branch alias](https://github.com/doctrine/annotations/pull/165) thanks to @mikeSimonson
- [209: Change Annotation::value typehint to mixed](https://github.com/doctrine/annotations/pull/209) thanks to @malarzm
- [257: Skip parsing annotations containing dashes, such as `@Foo-bar`, or `@Foo-`](https://github.com/doctrine/annotations/pull/257) thanks to @Ocramius

### 1.6.0

This release brings a new endpoint that make sure that you can't shoot yourself in the foot by calling ```registerLoader``` multiple times and a few tests improvements.

Total issues resolved: **7**

- [145: Memory leak in AnnotationRegistry::registerLoader() when called multiple times](https://github.com/doctrine/annotations/issues/145) thanks to @TriAnMan
- [146: Import error on @experimental Annotation](https://github.com/doctrine/annotations/issues/146) thanks to @aturki
- [147: Ignoring @experimental annotation used by Symfony 3.3 CacheAdapter](https://github.com/doctrine/annotations/pull/147) thanks to @aturki
- [151: Remove duplicate code in `DCOM58Test`](https://github.com/doctrine/annotations/pull/151) thanks to @tuanphpvn
- [161: Prevent loading class&#95;exists multiple times](https://github.com/doctrine/annotations/pull/161) thanks to @jrjohnson
- [162: Add registerUniqueLoader to AnnotationRegistry](https://github.com/doctrine/annotations/pull/162) thanks to @jrjohnson
- [163: Use assertDirectoryExists and assertDirectoryNotExists](https://github.com/doctrine/annotations/pull/163) thanks to @carusogabriel

Thanks to everyone involved in this release.

### 1.5.0

This release increments the minimum supported PHP version to 7.1.0.

Also, HHVM official support has been dropped.

Some noticeable performance improvements to annotation autoloading
have been applied, making failed annotation autoloading less heavy
on the filesystem access.

- [133: Add @throws annotation in AnnotationReader#__construct()](https://github.com/doctrine/annotations/issues/133) thanks to @SenseException
- [134: Require PHP 7.1, drop HHVM support](https://github.com/doctrine/annotations/issues/134) thanks to @lcobucci
- [135: Prevent the same loader from being registered twice](https://github.com/doctrine/annotations/issues/135)  thanks to @jrjohnson
- [137: #135 optimise multiple class load attempts in AnnotationRegistry](https://github.com/doctrine/annotations/issues/137)  thanks to @Ocramius


### 1.4.0

This release fix an issue were some annotations could be not loaded if the namespace in the use statement started with a backslash.
It also update the tests and drop the support for php 5.X

- [115: Missing annotations with the latest composer version](https://github.com/doctrine/annotations/issues/115) thanks to @pascalporedda
- [120: Missing annotations with the latest composer version](https://github.com/doctrine/annotations/pull/120) thanks to @gnat42
- [121: Adding a more detailed explanation of the test](https://github.com/doctrine/annotations/pull/121) thanks to @mikeSimonson
- [101: Test annotation parameters containing space](https://github.com/doctrine/annotations/pull/101) thanks to @mikeSimonson
- [111: Cleanup: move to correct phpunit assertions](https://github.com/doctrine/annotations/pull/111) thanks to @Ocramius
- [112: Removes support for PHP 5.x](https://github.com/doctrine/annotations/pull/112) thanks to @railto
- [113: bumped phpunit version to 5.7](https://github.com/doctrine/annotations/pull/113) thanks to @gabbydgab
- [114: Enhancement: Use SVG Travis build badge](https://github.com/doctrine/annotations/pull/114) thanks to @localheinz
- [118: Integrating PHPStan](https://github.com/doctrine/annotations/pull/118) thanks to @ondrejmirtes

### 1.3.1 - 2016-12-30

This release fixes an issue with ignored annotations that were already
autoloaded, causing the `SimpleAnnotationReader` to pick them up
anyway. [#110](https://github.com/doctrine/annotations/pull/110)

Additionally, an issue was fixed in the `CachedReader`, which was
not correctly checking the freshness of cached annotations when
traits were defined on a class. [#105](https://github.com/doctrine/annotations/pull/105)

Total issues resolved: **2**

- [105: Return single max timestamp](https://github.com/doctrine/annotations/pull/105)
- [110: setIgnoreNotImportedAnnotations(true) didn&rsquo;t work for existing classes](https://github.com/doctrine/annotations/pull/110)

### 1.3.0

This release introduces a PHP version bump. `doctrine/annotations` now requires PHP
5.6 or later to be installed.

A series of additional improvements have been introduced:

 * support for PHP 7 "grouped use statements"
 * support for ignoring entire namespace names
   via `Doctrine\Common\Annotations\AnnotationReader::addGlobalIgnoredNamespace()` and
   `Doctrine\Common\Annotations\DocParser::setIgnoredAnnotationNamespaces()`. This will
   allow you to ignore annotations from namespaces that you cannot autoload
 * testing all parent classes and interfaces when checking if the annotation cache
   in the `CachedReader` is fresh
 * simplifying the cache keys used by the `CachedReader`: keys are no longer artificially
   namespaced, since `Doctrine\Common\Cache` already supports that
 * corrected parsing of multibyte strings when `mbstring.func_overload` is enabled
 * corrected parsing of annotations when `"\t"` is put before the first annotation
   in a docblock
 * allow skipping non-imported annotations when a custom `DocParser` is passed to
   the `AnnotationReader` constructor

Total issues resolved: **15**

- [45: DocParser can now ignore whole namespaces](https://github.com/doctrine/annotations/pull/45)
- [57: Switch to the docker-based infrastructure on Travis](https://github.com/doctrine/annotations/pull/57)
- [59: opcache.load&#95;comments has been removed from PHP 7](https://github.com/doctrine/annotations/pull/59)
- [62: &#91;CachedReader&#92; Test traits and parent class to see if cache is fresh](https://github.com/doctrine/annotations/pull/62)
- [65: Remove cache salt making key unnecessarily long](https://github.com/doctrine/annotations/pull/65)
- [66: Fix of incorrect parsing multibyte strings](https://github.com/doctrine/annotations/pull/66)
- [68: Annotations that are indented by tab are not processed.](https://github.com/doctrine/annotations/issues/68)
- [69: Support for Group Use Statements](https://github.com/doctrine/annotations/pull/69)
- [70: Allow tab character before first annotation in DocBlock](https://github.com/doctrine/annotations/pull/70)
- [74: Ignore not registered annotations fix](https://github.com/doctrine/annotations/pull/74)
- [92: Added tests for AnnotationRegistry class.](https://github.com/doctrine/annotations/pull/92)
- [96: Fix/#62 check trait and parent class ttl in annotations](https://github.com/doctrine/annotations/pull/96)
- [97: Feature - #45 - allow ignoring entire namespaces](https://github.com/doctrine/annotations/pull/97)
- [98: Enhancement/#65 remove cache salt from cached reader](https://github.com/doctrine/annotations/pull/98)
- [99: Fix - #70 - allow tab character before first annotation in docblock](https://github.com/doctrine/annotations/pull/99)

### 1.2.4

Total issues resolved: **1**

- [51: FileCacheReader::saveCacheFile::unlink fix](https://github.com/doctrine/annotations/pull/51)

### 1.2.3

Total issues resolved: [**2**](https://github.com/doctrine/annotations/milestones/v1.2.3)

- [49: #46 - applying correct `chmod()` to generated cache file](https://github.com/doctrine/annotations/pull/49)
- [50: Hotfix: match escaped quotes (revert #44)](https://github.com/doctrine/annotations/pull/50)

### 1.2.2

Total issues resolved: **4**

- [43: Exclude files from distribution with .gitattributes](https://github.com/doctrine/annotations/pull/43)
- [44: Update DocLexer.php](https://github.com/doctrine/annotations/pull/44)
- [46: A plain &quot;file&#95;put&#95;contents&quot; can cause havoc](https://github.com/doctrine/annotations/pull/46)
- [48: Deprecating the `FileCacheReader` in 1.2.2: will be removed in 2.0.0](https://github.com/doctrine/annotations/pull/48)

### 1.2.1

Total issues resolved: **4**

- [38: fixes doctrine/common#326](https://github.com/doctrine/annotations/pull/38)
- [39: Remove superfluous NS](https://github.com/doctrine/annotations/pull/39)
- [41: Warn if load_comments is not enabled.](https://github.com/doctrine/annotations/pull/41)
- [42: Clean up unused uses](https://github.com/doctrine/annotations/pull/42)

### 1.2.0

 * HHVM support
 * Allowing dangling comma in annotations
 * Excluded annotations are no longer autoloaded
 * Importing namespaces also in traits
 * Added support for `::class` 5.5-style constant, works also in 5.3 and 5.4

### 1.1.0

 * Add Exception when ZendOptimizer+ or Opcache is configured to drop comments
PKb�$Z``�))annotations/LICENSEnu�[���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.
PKb�$Z ���annotations/phpbench.json.distnu�[���{
    "bootstrap": "tests/Doctrine/Performance/Common/bootstrap.php",
    "path": "tests/Doctrine/Performance/Common/Annotations"
}
PKb�$Z��``lexer/README.mdnu�[���# Doctrine Lexer

Build Status: [![Build Status](https://travis-ci.org/doctrine/lexer.svg?branch=master)](https://travis-ci.org/doctrine/lexer)

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
PKb�$ZU��ylexer/.doctrine-project.jsonnu�[���{
    "active": true,
    "name": "Lexer",
    "slug": "lexer",
    "docsSlug": "doctrine-lexer",
    "versions": [
        {
            "name": "1.0",
            "branchName": "1.0",
            "slug": "1.0",
            "current": true,
            "maintained": true,
            "aliases": [
                "current",
                "stable"
            ]
        },
        {
            "name": "master",
            "branchName": "master",
            "slug": "latest",
            "upcoming": true
        }
    ]
}
PKb�$ZՋ���1lexer/lib/Doctrine/Common/Lexer/AbstractLexer.phpnu�[���<?php

declare(strict_types=1);

namespace Doctrine\Common\Lexer;

use ReflectionClass;
use const PREG_SPLIT_DELIM_CAPTURE;
use const PREG_SPLIT_NO_EMPTY;
use const PREG_SPLIT_OFFSET_CAPTURE;
use function implode;
use function in_array;
use function preg_split;
use function sprintf;
use function substr;

/**
 * Base class for writing simple lexers, i.e. for creating small DSLs.
 */
abstract class AbstractLexer
{
    /**
     * Lexer original input string.
     *
     * @var string
     */
    private $input;

    /**
     * Array of scanned tokens.
     *
     * Each token is an associative array containing three items:
     *  - 'value'    : the string value of the token in the input string
     *  - 'type'     : the type of the token (identifier, numeric, string, input
     *                 parameter, none)
     *  - 'position' : the position of the token in the input string
     *
     * @var array
     */
    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 array|null
     */
    public $lookahead;

    /**
     * The last matched/seen token.
     *
     * @var array|null
     */
    public $token;

    /**
     * Composed regex for input parsing.
     *
     * @var string
     */
    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 int|string $token
     *
     * @return bool
     */
    public function isNextToken($token)
    {
        return $this->lookahead !== null && $this->lookahead['type'] === $token;
    }

    /**
     * Checks whether any of the given tokens matches the current lookahead.
     *
     * @param array $tokens
     *
     * @return bool
     */
    public function isNextTokenAny(array $tokens)
    {
        return $this->lookahead !== null && in_array($this->lookahead['type'], $tokens, true);
    }

    /**
     * Moves to the next token in the input string.
     *
     * @return bool
     */
    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 string $type The token type to skip until.
     *
     * @return void
     */
    public function skipUntil($type)
    {
        while ($this->lookahead !== null && $this->lookahead['type'] !== $type) {
            $this->moveNext();
        }
    }

    /**
     * Checks if given value is identical to the given token.
     *
     * @param mixed      $value
     * @param int|string $token
     *
     * @return bool
     */
    public function isA($value, $token)
    {
        return $this->getType($value) === $token;
    }

    /**
     * Moves the lookahead token forward.
     *
     * @return array|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 array|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
            $type = $this->getType($match[0]);

            $this->tokens[] = [
                'value' => $match[0],
                'type'  => $type,
                'position' => $match[1],
            ];
        }
    }

    /**
     * Gets the literal for a given token.
     *
     * @param int|string $token
     *
     * @return int|string
     */
    public function getLiteral($token)
    {
        $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 array
     */
    abstract protected function getCatchablePatterns();

    /**
     * Lexical non-catchable patterns.
     *
     * @return array
     */
    abstract protected function getNonCatchablePatterns();

    /**
     * Retrieve token type. Also processes the token value if necessary.
     *
     * @param string $value
     *
     * @return int|string|null
     */
    abstract protected function getType(&$value);
}
PKb�$Z`XQ�))
lexer/LICENSEnu�[���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.
PKb�$Z�ﻦinstantiator/CONTRIBUTING.mdnu�[���PKb�$ZS�ǚ""Tinstantiator/.travis.install.shnu�[���PKb�$Z��Q==�instantiator/phpmd.xml.distnu�[���PKb�$Z��.U��@Minstantiator/src/Doctrine/Instantiator/InstantiatorInterface.phpnu�[���PKb�$Z�z.�WWM�
instantiator/src/Doctrine/Instantiator/Exception/UnexpectedValueException.phpnu�[���PKb�$Z�f���G�instantiator/src/Doctrine/Instantiator/Exception/ExceptionInterface.phpnu�[���PKb�$Z$�8���M�instantiator/src/Doctrine/Instantiator/Exception/InvalidArgumentException.phpnu�[���PKb�$Z��447instantiator/src/Doctrine/Instantiator/Instantiator.phpnu�[���PKb�$Za��w==�9instantiator/README.mdnu�[���PKb�$Zxxd#8@instantiator/.doctrine-project.jsonnu�[���PKb�$Z
͂�$$�Dinstantiator/LICENSEnu�[���PKb�$Z�
!ffIinflector/README.mdnu�[���PKb�$Z�mY�� �Kinflector/.doctrine-project.jsonnu�[���PKb�$Z��bu8282.�Minflector/lib/Doctrine/Inflector/Inflector.phpnu�[���PKb�$Z�f�w��6��inflector/lib/Doctrine/Inflector/NoopWordInflector.phpnu�[���PKb�$Z4��5��inflector/lib/Doctrine/Inflector/RulesetInflector.phpnu�[���PKb�$Z�U��>�inflector/lib/Doctrine/Inflector/Rules/Turkish/Uninflected.phpnu�[���PKb�$Z��U>܊inflector/lib/Doctrine/Inflector/Rules/Turkish/Inflectible.phpnu�[���PKb�$ZӇ4xll8_�inflector/lib/Doctrine/Inflector/Rules/Turkish/Rules.phpnu�[���PKb�$ZԬ7��C3�inflector/lib/Doctrine/Inflector/Rules/Turkish/InflectorFactory.phpnu�[���PKb�$Z��}0��:u�inflector/lib/Doctrine/Inflector/Rules/Transformations.phpnu�[���PKb�$Z�}�9h�inflector/lib/Doctrine/Inflector/Rules/Transformation.phpnu�[���PKb�$Z
�� ��F�inflector/lib/Doctrine/Inflector/Rules/NorwegianBokmal/Uninflected.phpnu�[���PKb�$Zs�0b��F�inflector/lib/Doctrine/Inflector/Rules/NorwegianBokmal/Inflectible.phpnu�[���PKb�$Z�';�tt@6�inflector/lib/Doctrine/Inflector/Rules/NorwegianBokmal/Rules.phpnu�[���PKb�$Z�C���K�inflector/lib/Doctrine/Inflector/Rules/NorwegianBokmal/InflectorFactory.phpnu�[���PKb�$Z��٣2l�inflector/lib/Doctrine/Inflector/Rules/Ruleset.phpnu�[���PKb�$ZG�iv''/ڬinflector/lib/Doctrine/Inflector/Rules/Word.phpnu�[���PKb�$Z��L<��A`�inflector/lib/Doctrine/Inflector/Rules/Portuguese/Uninflected.phpnu�[���PKb�$Z���77A��inflector/lib/Doctrine/Inflector/Rules/Portuguese/Inflectible.phpnu�[���PKb�$Z1w�oo;P�inflector/lib/Doctrine/Inflector/Rules/Portuguese/Rules.phpnu�[���PKb�$Z�t!���F*�inflector/lib/Doctrine/Inflector/Rules/Portuguese/InflectorFactory.phpnu�[���PKb�$ZaZ�}��>r�inflector/lib/Doctrine/Inflector/Rules/Spanish/Uninflected.phpnu�[���PKb�$Z6DK�``>n�inflector/lib/Doctrine/Inflector/Rules/Spanish/Inflectible.phpnu�[���PKb�$Z-��ll8<�inflector/lib/Doctrine/Inflector/Rules/Spanish/Rules.phpnu�[���PKb�$Z�L���C�inflector/lib/Doctrine/Inflector/Rules/Spanish/InflectorFactory.phpnu�[���PKb�$Z���+]]8R�inflector/lib/Doctrine/Inflector/Rules/Substitutions.phpnu�[���PKb�$Z��"ƻ�>�inflector/lib/Doctrine/Inflector/Rules/English/Uninflected.phpnu�[���PKb�$Z���+�+>@�inflector/lib/Doctrine/Inflector/Rules/English/Inflectible.phpnu�[���PKb�$ZO�ll8�+inflector/lib/Doctrine/Inflector/Rules/English/Rules.phpnu�[���PKb�$ZJEj���C~/inflector/lib/Doctrine/Inflector/Rules/English/InflectorFactory.phpnu�[���PKb�$ZV�;���7�1inflector/lib/Doctrine/Inflector/Rules/Substitution.phpnu�[���PKb�$Z�)O�2�3inflector/lib/Doctrine/Inflector/Rules/Pattern.phpnu�[���PKb�$ZHϽ�88=e7inflector/lib/Doctrine/Inflector/Rules/French/Uninflected.phpnu�[���PKb�$Zy�[=
:inflector/lib/Doctrine/Inflector/Rules/French/Inflectible.phpnu�[���PKb�$Z¶� kk7�Ainflector/lib/Doctrine/Inflector/Rules/French/Rules.phpnu�[���PKb�$ZL�C���BfEinflector/lib/Doctrine/Inflector/Rules/French/InflectorFactory.phpnu�[���PKb�$Z�r���3�Ginflector/lib/Doctrine/Inflector/Rules/Patterns.phpnu�[���PKb�$Z����5�Jinflector/lib/Doctrine/Inflector/InflectorFactory.phpnu�[���PKb�$Z1ɍO8�Pinflector/lib/Doctrine/Inflector/CachedWordInflector.phpnu�[���PKb�$Z��Kڮ�-Sinflector/lib/Doctrine/Inflector/Language.phpnu�[���PKb�$Z���.��D$Uinflector/lib/Doctrine/Inflector/GenericLanguageInflectorFactory.phpnu�[���PKb�$Zr&�ϐ�2'\inflector/lib/Doctrine/Inflector/WordInflector.phpnu�[���PKb�$Z~�5((=]inflector/lib/Doctrine/Inflector/LanguageInflectorFactory.phpnu�[���PKb�$Z�чq&&5�`inflector/lib/Doctrine/Common/Inflector/Inflector.phpnu�[���PKb�$Z�9�)).�inflector/LICENSEnu�[���PKb�$ZJ�-����annotations/phpstan.neonnu�[���PKb�$Z���Tb�annotations/README.mdnu�[���PKb�$Zt�Yss"��annotations/.doctrine-project.jsonnu�[���PKb�$Z`ۖ���Cw�annotations/lib/Doctrine/Common/Annotations/AnnotationException.phpnu�[���PKb�$Z�3+��<��annotations/lib/Doctrine/Common/Annotations/CachedReader.phpnu�[���PKb�$Zn�T�IIF�annotations/lib/Doctrine/Common/Annotations/SimpleAnnotationReader.phpnu�[���PKb�$ZO����9��annotations/lib/Doctrine/Common/Annotations/DocParser.phpnu�[���PKb�$Z/����8J|annotations/lib/Doctrine/Common/Annotations/DocLexer.phpnu�[���PKb�$Z0���=8�annotations/lib/Doctrine/Common/Annotations/IndexedReader.phpnu�[���PKb�$Z�ф´"�"?r�annotations/lib/Doctrine/Common/Annotations/FileCacheReader.phpnu�[���PKb�$Z"��ӗ�;��annotations/lib/Doctrine/Common/Annotations/TokenParser.phpnu�[���PKb�$Z!�
���9��annotations/lib/Doctrine/Common/Annotations/PhpParser.phpnu�[���PKb�$ZX\��	�	:��annotations/lib/Doctrine/Common/Annotations/Annotation.phpnu�[���PKb�$Z�x��B��annotations/lib/Doctrine/Common/Annotations/AnnotationRegistry.phpnu�[���PKb�$Z�����
�
6�annotations/lib/Doctrine/Common/Annotations/Reader.phpnu�[���PKb�$Z�-���2�2@annotations/lib/Doctrine/Common/Annotations/AnnotationReader.phpnu�[���PKb�$Z����DqJannotations/lib/Doctrine/Common/Annotations/Annotation/Attribute.phpnu�[���PKb�$Z��"
"
?�Pannotations/lib/Doctrine/Common/Annotations/Annotation/Enum.phpnu�[���PKb�$Z�ִLCCE[annotations/lib/Doctrine/Common/Annotations/Annotation/Attributes.phpnu�[���PKb�$Z$�ߊEEK�`annotations/lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.phpnu�[���PKb�$Z�M��C�hannotations/lib/Doctrine/Common/Annotations/Annotation/Required.phpnu�[���PKb�$ZlN����A�mannotations/lib/Doctrine/Common/Annotations/Annotation/Target.phpnu�[���PKb�$Z"K�W�#�#={annotations/CHANGELOG.mdnu�[���PKb�$Z``�))K�annotations/LICENSEnu�[���PKb�$ZВ �����annotations/phpbench.json.distnu�[���PKb�$Z��``��lexer/README.mdnu�[���PKb�$ZU��y(�lexer/.doctrine-project.jsonnu�[���PKb�$ZՋ���1��lexer/lib/Doctrine/Common/Lexer/AbstractLexer.phpnu�[���PKb�$Z`XQ�))
��lexer/LICENSEnu�[���PKUU�&C�