[
  {
    "path": ".doctrine-project.json",
    "content": "{\n    \"active\": false,\n    \"name\": \"Cache\",\n    \"slug\": \"cache\",\n    \"docsSlug\": \"doctrine-cache\",\n    \"versions\": [\n        {\n            \"name\": \"2.2\",\n            \"branchName\": \"2.2.x\",\n            \"slug\": \"2.2\",\n            \"current\": true\n        },\n        {\n            \"name\": \"2.1\",\n            \"branchName\": \"2.1.x\",\n            \"slug\": \"2.1\",\n            \"maintained\": false\n        },\n        {\n            \"name\": \"2.0\",\n            \"branchName\": \"2.0.x\",\n            \"slug\": \"2.0\",\n            \"maintained\": false\n        },\n        {\n            \"name\": \"1.13\",\n            \"branchName\": \"1.13.x\",\n            \"slug\": \"1.13\",\n            \"maintained\": true\n        },\n        {\n            \"name\": \"1.12\",\n            \"branchName\": \"1.12.x\",\n            \"slug\": \"1.12\",\n            \"maintained\": false\n        },\n        {\n            \"name\": \"1.11\",\n            \"branchName\": \"1.11.x\",\n            \"slug\": \"1.11\",\n            \"maintained\": false\n        },\n        {\n            \"name\": \"1.10\",\n            \"branchName\": \"1.10.x\",\n            \"slug\": \"1.10\",\n            \"maintained\": false\n        },\n        {\n            \"name\": \"1.9\",\n            \"branchName\": \"1.9.x\",\n            \"slug\": \"1.9\",\n            \"maintained\": false\n        },\n        {\n            \"name\": \"1.8\",\n            \"branchName\": \"1.8.x\",\n            \"slug\": \"1.8\",\n            \"maintained\": false\n        }\n    ]\n}\n"
  },
  {
    "path": ".gitattributes",
    "content": "/docs export-ignore\n/.github export-ignore\n/tests export-ignore\n.doctrine-project.json export-ignore\n.gitattributes export-ignore\n.gitignore export-ignore\n.scrutinizer.yml export-ignore\nbuild.properties export-ignore\nbuild.xml export-ignore\nphpcs.xml.dist export-ignore\nphpunit.xml.dist export-ignore\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "patreon: phpdoctrine\ntidelift: packagist/doctrine%2Fcache\ncustom: https://www.doctrine-project.org/sponsorship.html\n"
  },
  {
    "path": ".github/workflows/coding-standards.yml",
    "content": "name: \"Coding Standards\"\n\non:\n  pull_request:\n    branches:\n      - \"*.x\"\n  push:\n    branches:\n      - \"*.x\"\n\njobs:\n  coding-standards:\n    uses: \"doctrine/.github/.github/workflows/coding-standards.yml@5.0.1\"\n"
  },
  {
    "path": ".github/workflows/continuous-integration.yml",
    "content": "\nname: \"Continuous Integration\"\n\non:\n  pull_request:\n    branches:\n      - \"*.x\"\n  push:\n    branches:\n      - \"*.x\"\n\nenv:\n  fail-fast: true\n\njobs:\n  phpunit:\n    name: \"PHPUnit\"\n    runs-on: \"ubuntu-22.04\"\n\n    strategy:\n      fail-fast: false\n      matrix:\n        php-version:\n          - \"7.1\"\n          - \"7.2\"\n          - \"7.3\"\n          - \"7.4\"\n          - \"8.0\"\n          - \"8.1\"\n          - \"8.2\"\n          - \"8.3\"\n\n    steps:\n      - name: \"Checkout\"\n        uses: \"actions/checkout@v4\"\n        with:\n          fetch-depth: 2\n\n      - name: \"Install PHP with XDebug\"\n        uses: \"shivammathur/setup-php@v2\"\n        if: \"${{ matrix.php-version == '7.1' }}\"\n        with:\n          php-version: \"${{ matrix.php-version }}\"\n          coverage: \"xdebug\"\n          ini-values: \"zend.assertions=1\"\n\n      - name: \"Install PHP with PCOV\"\n        uses: \"shivammathur/setup-php@v2\"\n        if: \"${{ matrix.php-version != '7.1' }}\"\n        with:\n          php-version: \"${{ matrix.php-version }}\"\n          coverage: \"pcov\"\n          ini-values: \"zend.assertions=1\"\n\n      - name: \"Install dependencies with Composer\"\n        uses: \"ramsey/composer-install@v3\"\n        with:\n          dependency-versions: \"${{ matrix.dependencies }}\"\n          composer-options: \"--prefer-dist --no-suggest\"\n\n      - name: \"Run PHPUnit\"\n        run: \"vendor/bin/phpunit --coverage-clover=coverage.xml\"\n\n      - name: \"Upload coverage file\"\n        uses: \"actions/upload-artifact@v4\"\n        with:\n          name: \"phpunit-${{ matrix.php-version }}.coverage\"\n          path: \"coverage.xml\"\n\n  upload_coverage:\n    name: \"Upload coverage to Codecov\"\n    runs-on: \"ubuntu-22.04\"\n    needs:\n      - \"phpunit\"\n\n    steps:\n      - name: \"Checkout\"\n        uses: \"actions/checkout@v4\"\n        with:\n          fetch-depth: 2\n\n      - name: \"Download coverage files\"\n        uses: \"actions/download-artifact@v4\"\n        with:\n          path: \"reports\"\n\n      - name: \"Upload to Codecov\"\n        uses: \"codecov/codecov-action@v4\"\n        with:\n          directory: reports\n"
  },
  {
    "path": ".github/workflows/release-on-milestone-closed.yml",
    "content": "name: \"Automatic Releases\"\n\non:\n  milestone:\n    types:\n      - \"closed\"\n\njobs:\n  release:\n    uses: \"doctrine/.github/.github/workflows/release-on-milestone-closed.yml@5.0.1\"\n    secrets:\n      GIT_AUTHOR_EMAIL: ${{ secrets.GIT_AUTHOR_EMAIL }}\n      GIT_AUTHOR_NAME: ${{ secrets.GIT_AUTHOR_NAME }}\n      ORGANIZATION_ADMIN_TOKEN: ${{ secrets.ORGANIZATION_ADMIN_TOKEN }}\n      SIGNING_SECRET_KEY: ${{ secrets.SIGNING_SECRET_KEY }}\n"
  },
  {
    "path": ".gitignore",
    "content": "vendor/\n/composer.lock\nbuild/\nphpunit.xml\n/.phpunit.result.cache\nclover.xml\n.phpcs-cache\nphpcs.xml\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright (c) 2006-2015 Doctrine Project\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Doctrine Cache\n\n[![Build Status](https://github.com/doctrine/cache/workflows/Continuous%20Integration/badge.svg)](https://github.com/doctrine/cache/actions)\n[![Code Coverage](https://codecov.io/gh/doctrine/cache/branch/1.10.x/graph/badge.svg)](https://codecov.io/gh/doctrine/cache/branch/1.10.x)\n\n[![Latest Stable Version](https://img.shields.io/packagist/v/doctrine/cache.svg?style=flat-square)](https://packagist.org/packages/doctrine/cache)\n[![Total Downloads](https://img.shields.io/packagist/dt/doctrine/cache.svg?style=flat-square)](https://packagist.org/packages/doctrine/cache)\n\nCache component extracted from the Doctrine Common project. [Documentation](https://www.doctrine-project.org/projects/doctrine-cache/en/current/index.html)\n\nThis library is deprecated and will no longer receive bug fixes from the\nDoctrine Project. Please use a different cache library, preferably PSR-6 or\nPSR-16 instead.\n"
  },
  {
    "path": "UPGRADE-1.11.md",
    "content": "# Upgrade to 1.11\n\ndoctrine/cache will no longer be maintained and all cache implementations have\nbeen marked as deprecated. These implementations will be removed in 2.0, which\nwill only contain interfaces to provide a lightweight package for backward\ncompatibility.\n\nThere are two new classes to use in the `Doctrine\\Common\\Cache\\Psr6` namespace:\n* The `CacheAdapter` class allows using any Doctrine Cache as PSR-6 cache. This\n  is useful to provide a forward compatibility layer in libraries that accept\n  Doctrine cache implementations and switch to PSR-6.\n* The `DoctrineProvider` class allows using any PSR-6 cache as Doctrine cache.\n  This implementation is designed for libraries that leak the cache and want to\n  switch to allowing PSR-6 implementations. This class is design to be used\n  during the transition phase of sunsetting doctrine/cache support.\n\nA full example to setup a filesystem based PSR-6 cache with symfony/cache\nusing the `DoctrineProvider` to convert back to Doctrine's `Cache` interface:\n\n```php\nuse Doctrine\\Common\\Cache\\Psr6\\DoctrineProvider;\nuse Symfony\\Component\\Cache\\Adapter\\FilesystemAdapter;\n\n$cachePool = new FilesystemAdapter();\n$cache = DoctrineProvider::wrap($cachePool);\n// $cache instanceof \\Doctrine\\Common\\Cache\\Cache\n```\n"
  },
  {
    "path": "UPGRADE-1.4.md",
    "content": "# Upgrade to 1.4\n\n## Minor BC Break: `Doctrine\\Common\\Cache\\FileCache#$extension` is now `private`.\n\nIf you need to override the value of `Doctrine\\Common\\Cache\\FileCache#$extension`, then use the\nsecond parameter of `Doctrine\\Common\\Cache\\FileCache#__construct()` instead of overriding\nthe property in your own implementation.\n\n## Minor BC Break: file based caches paths changed\n\n`Doctrine\\Common\\Cache\\FileCache`, `Doctrine\\Common\\Cache\\PhpFileCache` and\n`Doctrine\\Common\\Cache\\FilesystemCache` are using a different cache paths structure.\n\nIf you rely on warmed up caches for deployments, consider that caches generated\nwith `doctrine/cache` `<1.4` are not compatible with the new directory structure,\nand will be ignored.\n"
  },
  {
    "path": "build.properties",
    "content": "# Version class and file\nproject.version_class = Doctrine\\\\Common\\\\Cache\\\\Version\nproject.version_file = lib/Doctrine/Common/Cache/Version.php\n"
  },
  {
    "path": "build.xml",
    "content": "<?xml version=\"1.0\"?>\n<project name=\"DoctrineCommonCache\" default=\"build\" basedir=\".\">\n    <property file=\"build.properties\" />\n\n    <target name=\"php\">\n        <exec executable=\"which\" outputproperty=\"php_executable\">\n            <arg value=\"php\" />\n        </exec>\n    </target>\n\n    <target name=\"prepare\">\n        <mkdir dir=\"build\" />\n    </target>\n\n    <target name=\"build\" depends=\"check-git-checkout-clean,prepare,php,composer\">\n        <exec executable=\"${php_executable}\">\n            <arg value=\"build/composer.phar\" />\n            <arg value=\"archive\" />\n            <arg value=\"--dir=build\" />\n        </exec>\n    </target>\n\n    <target name=\"composer\" depends=\"php,composer-check,composer-download\">\n        <exec executable=\"${php_executable}\">\n            <arg value=\"build/composer.phar\" />\n            <arg value=\"install\" />\n        </exec>\n    </target>\n\n    <target name=\"composer-check\" depends=\"prepare\">\n        <available file=\"build/composer.phar\" property=\"composer.present\"/>\n    </target>\n\n    <target name=\"composer-download\" unless=\"composer.present\">\n        <exec executable=\"wget\">\n            <arg value=\"-Obuild/composer.phar\" />\n            <arg value=\"http://getcomposer.org/composer.phar\" />\n        </exec>\n    </target>\n\n    <target name=\"make-release\" depends=\"check-git-checkout-clean,prepare,php\">\n        <replace file=\"${project.version_file}\" token=\"-DEV\" value=\"\" failOnNoReplacements=\"true\" />\n        <exec executable=\"git\" failonerror=\"true\" outputproperty=\"current_git_branch\">\n            <arg value=\"rev-parse\" />\n            <arg value=\"--abbrev-ref\" />\n            <arg value=\"HEAD\" />\n        </exec>\n        <exec executable=\"${php_executable}\" outputproperty=\"doctrine.current_version\" failonerror=\"true\">\n            <arg value=\"-r\" />\n            <arg value=\"require_once '${project.version_file}';echo ${project.version_class}::VERSION;\" />\n        </exec>\n        <exec executable=\"${php_executable}\" outputproperty=\"doctrine.next_version\" failonerror=\"true\">\n            <arg value=\"-r\" />\n            <arg value=\"$parts = explode('.', str_ireplace(array('-DEV', '-ALPHA', '-BETA'), '', '${doctrine.current_version}'));\n                if (count($parts) != 3) {\n                    throw new \\InvalidArgumentException('Version is assumed in format x.y.z, ${doctrine.current_version} given');\n                }\n                $parts[2]++;\n                echo implode('.', $parts);\n            \" />\n        </exec>\n\n        <git-commit file=\"${project.version_file}\" message=\"Release ${doctrine.current_version}\" />\n        <git-tag version=\"${doctrine.current_version}\" />\n        <replace file=\"${project.version_file}\" token=\"${doctrine.current_version}\" value=\"${doctrine.next_version}-DEV\" />\n        <git-commit file=\"${project.version_file}\" message=\"Bump version to ${doctrine.next_version}\" />\n    </target>\n\n    <target name=\"check-git-checkout-clean\">\n        <exec executable=\"git\" failonerror=\"true\">\n            <arg value=\"diff-index\" />\n            <arg value=\"--quiet\" />\n            <arg value=\"HEAD\" />\n        </exec>\n    </target>\n\n    <macrodef name=\"git-commit\">\n        <attribute name=\"file\" default=\"NOT SET\"/>\n        <attribute name=\"message\" default=\"NOT SET\"/>\n\n        <sequential>\n            <exec executable=\"git\">\n                <arg value=\"add\" />\n                <arg value=\"@{file}\" />\n            </exec>\n            <exec executable=\"git\">\n                <arg value=\"commit\" />\n                <arg value=\"-m\" />\n                <arg value=\"@{message}\" />\n            </exec>\n        </sequential>\n    </macrodef>\n\n    <macrodef name=\"git-tag\">\n        <attribute name=\"version\" default=\"NOT SET\" />\n\n        <sequential>\n            <exec executable=\"git\">\n                <arg value=\"tag\" />\n                <arg value=\"-m\" />\n                <arg value=\"v@{version}\" />\n                <arg value=\"v@{version}\" />\n            </exec>\n        </sequential>\n    </macrodef>\n</project>\n"
  },
  {
    "path": "composer.json",
    "content": "{\n    \"name\": \"doctrine/cache\",\n    \"abandoned\": true,\n    \"type\": \"library\",\n    \"description\": \"PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.\",\n    \"keywords\": [\n        \"php\",\n        \"cache\",\n        \"caching\",\n        \"abstraction\",\n        \"redis\",\n        \"memcached\",\n        \"couchdb\",\n        \"xcache\",\n        \"apcu\"\n    ],\n    \"homepage\": \"https://www.doctrine-project.org/projects/cache.html\",\n    \"license\": \"MIT\",\n    \"authors\": [\n        {\"name\": \"Guilherme Blanco\", \"email\": \"guilhermeblanco@gmail.com\"},\n        {\"name\": \"Roman Borschel\", \"email\": \"roman@code-factory.org\"},\n        {\"name\": \"Benjamin Eberlei\", \"email\": \"kontakt@beberlei.de\"},\n        {\"name\": \"Jonathan Wage\", \"email\": \"jonwage@gmail.com\"},\n        {\"name\": \"Johannes Schmitt\", \"email\": \"schmittjoh@gmail.com\"}\n    ],\n    \"require\": {\n        \"php\": \"~7.1 || ^8.0\"\n    },\n    \"require-dev\": {\n        \"phpunit/phpunit\": \"^7.5 || ^8.5 || ^9.5\",\n        \"doctrine/coding-standard\": \"^9\",\n        \"psr/cache\": \"^1.0 || ^2.0 || ^3.0\",\n        \"cache/integration-tests\": \"dev-master\",\n        \"symfony/cache\": \"^4.4 || ^5.4 || ^6\",\n        \"symfony/var-exporter\": \"^4.4 || ^5.4 || ^6\"\n    },\n    \"conflict\": {\n        \"doctrine/common\": \">2.2,<2.4\"\n    },\n    \"autoload\": {\n        \"psr-4\": { \"Doctrine\\\\Common\\\\Cache\\\\\": \"lib/Doctrine/Common/Cache\" }\n    },\n    \"autoload-dev\": {\n        \"psr-4\": { \"Doctrine\\\\Tests\\\\\": \"tests/Doctrine/Tests\" }\n    },\n    \"config\": {\n        \"allow-plugins\": {\n            \"dealerdirect/phpcodesniffer-composer-installer\": true\n        }\n    }\n}\n"
  },
  {
    "path": "docs/en/index.rst",
    "content": "Deprecation Notice\n==================\n\nPlease note that doctrine/cache is deprecated and no longer maintained. The last\nversion to include cache drivers is 1.11. The 2.x major release series only\nprovides the interfaces for libraries that need to maintain backward\ncompatibility. For all cache uses, we suggest relying on PSR-6 or PSR-16 instead\nand using a cache library that supports those interfaces.\n\nIntroduction\n============\n\nDoctrine Cache is a library that provides an interface for caching data.\nHere is what the ``Cache`` interface looks like.\n\n.. code-block:: php\n    namespace Doctrine\\Common\\Cache;\n\n    interface Cache\n    {\n        public function fetch($id);\n        public function contains($id);\n        public function save($id, $data, $lifeTime = 0);\n        public function delete($id);\n        public function getStats();\n    }\n\nUse with PSR-6\n==============\n\nIf you are using the ``Cache`` interface in your application, then you need to\nupgrade your application to use a PSR-6 cache library and wrap the PSR-6\n``CacheItemPoolInterface`` into the\n``Doctrine\\Common\\Cache\\Psr6\\DoctrineProvider`` wrapper:\n\n.. code-block:: php\n\n    use Doctrine\\Common\\Cache\\Psr6\\DoctrineProvider;\n\n    $cache = DoctrineProvider::wrap($psr6CachePool);\n\nAn implementation of the PSR-6 cache is provided by `\"symfony/cache\" library\n<https://symfony.com/doc/current/components/cache.html>`_ for example, you can install it\nvia Composer with:\n\n::\n\n    composer require symfony/cache\n\nA full example to setup a filesystem based cache with symfony/cache then looks\nlike this:\n\n.. code-block:: php\n\n    use Doctrine\\Common\\Cache\\Psr6\\DoctrineProvider;\n    use Symfony\\Component\\Cache\\Adapter\\FilesystemAdapter;\n\n    $cachePool = new FilesystemAdapter();\n    $cache = DoctrineProvider::wrap($cachePool);\n    // $cache instanceof \\Doctrine\\Common\\Cache\\Cache\n"
  },
  {
    "path": "lib/Doctrine/Common/Cache/Cache.php",
    "content": "<?php\n\nnamespace Doctrine\\Common\\Cache;\n\n/**\n * Interface for cache drivers.\n *\n * @link   www.doctrine-project.org\n */\ninterface Cache\n{\n    public const STATS_HITS             = 'hits';\n    public const STATS_MISSES           = 'misses';\n    public const STATS_UPTIME           = 'uptime';\n    public const STATS_MEMORY_USAGE     = 'memory_usage';\n    public const STATS_MEMORY_AVAILABLE = 'memory_available';\n    /**\n     * Only for backward compatibility (may be removed in next major release)\n     *\n     * @deprecated\n     */\n    public const STATS_MEMORY_AVAILIABLE = 'memory_available';\n\n    /**\n     * Fetches an entry from the cache.\n     *\n     * @param string $id The id of the cache entry to fetch.\n     *\n     * @return mixed The cached data or FALSE, if no cache entry exists for the given id.\n     */\n    public function fetch($id);\n\n    /**\n     * Tests if an entry exists in the cache.\n     *\n     * @param string $id The cache id of the entry to check for.\n     *\n     * @return bool TRUE if a cache entry exists for the given cache id, FALSE otherwise.\n     */\n    public function contains($id);\n\n    /**\n     * Puts data into the cache.\n     *\n     * If a cache entry with the given id already exists, its data will be replaced.\n     *\n     * @param string $id       The cache id.\n     * @param mixed  $data     The cache entry/data.\n     * @param int    $lifeTime The lifetime in number of seconds for this cache entry.\n     *                         If zero (the default), the entry never expires (although it may be deleted from the cache\n     *                         to make place for other entries).\n     *\n     * @return bool TRUE if the entry was successfully stored in the cache, FALSE otherwise.\n     */\n    public function save($id, $data, $lifeTime = 0);\n\n    /**\n     * Deletes a cache entry.\n     *\n     * @param string $id The cache id.\n     *\n     * @return bool TRUE if the cache entry was successfully deleted, FALSE otherwise.\n     *              Deleting a non-existing entry is considered successful.\n     */\n    public function delete($id);\n\n    /**\n     * Retrieves cached information from the data store.\n     *\n     * The server's statistics array has the following values:\n     *\n     * - <b>hits</b>\n     * Number of keys that have been requested and found present.\n     *\n     * - <b>misses</b>\n     * Number of items that have been requested and not found.\n     *\n     * - <b>uptime</b>\n     * Time that the server is running.\n     *\n     * - <b>memory_usage</b>\n     * Memory used by this server to store items.\n     *\n     * - <b>memory_available</b>\n     * Memory allowed to use for storage.\n     *\n     * @return mixed[]|null An associative array with server's statistics if available, NULL otherwise.\n     */\n    public function getStats();\n}\n"
  },
  {
    "path": "lib/Doctrine/Common/Cache/CacheProvider.php",
    "content": "<?php\n\nnamespace Doctrine\\Common\\Cache;\n\nuse function array_combine;\nuse function array_key_exists;\nuse function array_map;\nuse function sprintf;\n\n/**\n * Base class for cache provider implementations.\n */\nabstract class CacheProvider implements Cache, FlushableCache, ClearableCache, MultiOperationCache\n{\n    public const DOCTRINE_NAMESPACE_CACHEKEY = 'DoctrineNamespaceCacheKey[%s]';\n\n    /**\n     * The namespace to prefix all cache ids with.\n     *\n     * @var string\n     */\n    private $namespace = '';\n\n    /**\n     * The namespace version.\n     *\n     * @var int|null\n     */\n    private $namespaceVersion;\n\n    /**\n     * Sets the namespace to prefix all cache ids with.\n     *\n     * @param string $namespace\n     *\n     * @return void\n     */\n    public function setNamespace($namespace)\n    {\n        $this->namespace        = (string) $namespace;\n        $this->namespaceVersion = null;\n    }\n\n    /**\n     * Retrieves the namespace that prefixes all cache ids.\n     *\n     * @return string\n     */\n    public function getNamespace()\n    {\n        return $this->namespace;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function fetch($id)\n    {\n        return $this->doFetch($this->getNamespacedId($id));\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function fetchMultiple(array $keys)\n    {\n        if (empty($keys)) {\n            return [];\n        }\n\n        // note: the array_combine() is in place to keep an association between our $keys and the $namespacedKeys\n        $namespacedKeys = array_combine($keys, array_map([$this, 'getNamespacedId'], $keys));\n        $items          = $this->doFetchMultiple($namespacedKeys);\n        $foundItems     = [];\n\n        // no internal array function supports this sort of mapping: needs to be iterative\n        // this filters and combines keys in one pass\n        foreach ($namespacedKeys as $requestedKey => $namespacedKey) {\n            if (! isset($items[$namespacedKey]) && ! array_key_exists($namespacedKey, $items)) {\n                continue;\n            }\n\n            $foundItems[$requestedKey] = $items[$namespacedKey];\n        }\n\n        return $foundItems;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function saveMultiple(array $keysAndValues, $lifetime = 0)\n    {\n        $namespacedKeysAndValues = [];\n        foreach ($keysAndValues as $key => $value) {\n            $namespacedKeysAndValues[$this->getNamespacedId($key)] = $value;\n        }\n\n        return $this->doSaveMultiple($namespacedKeysAndValues, $lifetime);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function contains($id)\n    {\n        return $this->doContains($this->getNamespacedId($id));\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function save($id, $data, $lifeTime = 0)\n    {\n        return $this->doSave($this->getNamespacedId($id), $data, $lifeTime);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function deleteMultiple(array $keys)\n    {\n        return $this->doDeleteMultiple(array_map([$this, 'getNamespacedId'], $keys));\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function delete($id)\n    {\n        return $this->doDelete($this->getNamespacedId($id));\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function getStats()\n    {\n        return $this->doGetStats();\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public function flushAll()\n    {\n        return $this->doFlush();\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public function deleteAll()\n    {\n        $namespaceCacheKey = $this->getNamespaceCacheKey();\n        $namespaceVersion  = $this->getNamespaceVersion() + 1;\n\n        if ($this->doSave($namespaceCacheKey, $namespaceVersion)) {\n            $this->namespaceVersion = $namespaceVersion;\n\n            return true;\n        }\n\n        return false;\n    }\n\n    /**\n     * Prefixes the passed id with the configured namespace value.\n     *\n     * @param string $id The id to namespace.\n     *\n     * @return string The namespaced id.\n     */\n    private function getNamespacedId(string $id): string\n    {\n        $namespaceVersion = $this->getNamespaceVersion();\n\n        return sprintf('%s[%s][%s]', $this->namespace, $id, $namespaceVersion);\n    }\n\n    /**\n     * Returns the namespace cache key.\n     */\n    private function getNamespaceCacheKey(): string\n    {\n        return sprintf(self::DOCTRINE_NAMESPACE_CACHEKEY, $this->namespace);\n    }\n\n    /**\n     * Returns the namespace version.\n     */\n    private function getNamespaceVersion(): int\n    {\n        if ($this->namespaceVersion !== null) {\n            return $this->namespaceVersion;\n        }\n\n        $namespaceCacheKey      = $this->getNamespaceCacheKey();\n        $this->namespaceVersion = (int) $this->doFetch($namespaceCacheKey) ?: 1;\n\n        return $this->namespaceVersion;\n    }\n\n    /**\n     * Default implementation of doFetchMultiple. Each driver that supports multi-get should owerwrite it.\n     *\n     * @param string[] $keys Array of keys to retrieve from cache\n     *\n     * @return mixed[] Array of values retrieved for the given keys.\n     */\n    protected function doFetchMultiple(array $keys)\n    {\n        $returnValues = [];\n\n        foreach ($keys as $key) {\n            $item = $this->doFetch($key);\n            if ($item === false && ! $this->doContains($key)) {\n                continue;\n            }\n\n            $returnValues[$key] = $item;\n        }\n\n        return $returnValues;\n    }\n\n    /**\n     * Fetches an entry from the cache.\n     *\n     * @param string $id The id of the cache entry to fetch.\n     *\n     * @return mixed|false The cached data or FALSE, if no cache entry exists for the given id.\n     */\n    abstract protected function doFetch($id);\n\n    /**\n     * Tests if an entry exists in the cache.\n     *\n     * @param string $id The cache id of the entry to check for.\n     *\n     * @return bool TRUE if a cache entry exists for the given cache id, FALSE otherwise.\n     */\n    abstract protected function doContains($id);\n\n    /**\n     * Default implementation of doSaveMultiple. Each driver that supports multi-put should override it.\n     *\n     * @param mixed[] $keysAndValues Array of keys and values to save in cache\n     * @param int     $lifetime      The lifetime. If != 0, sets a specific lifetime for these\n     *                               cache entries (0 => infinite lifeTime).\n     *\n     * @return bool TRUE if the operation was successful, FALSE if it wasn't.\n     */\n    protected function doSaveMultiple(array $keysAndValues, $lifetime = 0)\n    {\n        $success = true;\n\n        foreach ($keysAndValues as $key => $value) {\n            if ($this->doSave($key, $value, $lifetime)) {\n                continue;\n            }\n\n            $success = false;\n        }\n\n        return $success;\n    }\n\n    /**\n     * Puts data into the cache.\n     *\n     * @param string $id       The cache id.\n     * @param string $data     The cache entry/data.\n     * @param int    $lifeTime The lifetime. If != 0, sets a specific lifetime for this\n     *                           cache entry (0 => infinite lifeTime).\n     *\n     * @return bool TRUE if the entry was successfully stored in the cache, FALSE otherwise.\n     */\n    abstract protected function doSave($id, $data, $lifeTime = 0);\n\n    /**\n     * Default implementation of doDeleteMultiple. Each driver that supports multi-delete should override it.\n     *\n     * @param string[] $keys Array of keys to delete from cache\n     *\n     * @return bool TRUE if the operation was successful, FALSE if it wasn't\n     */\n    protected function doDeleteMultiple(array $keys)\n    {\n        $success = true;\n\n        foreach ($keys as $key) {\n            if ($this->doDelete($key)) {\n                continue;\n            }\n\n            $success = false;\n        }\n\n        return $success;\n    }\n\n    /**\n     * Deletes a cache entry.\n     *\n     * @param string $id The cache id.\n     *\n     * @return bool TRUE if the cache entry was successfully deleted, FALSE otherwise.\n     */\n    abstract protected function doDelete($id);\n\n    /**\n     * Flushes all cache entries.\n     *\n     * @return bool TRUE if the cache entries were successfully flushed, FALSE otherwise.\n     */\n    abstract protected function doFlush();\n\n    /**\n     * Retrieves cached information from the data store.\n     *\n     * @return mixed[]|null An associative array with server's statistics if available, NULL otherwise.\n     */\n    abstract protected function doGetStats();\n}\n"
  },
  {
    "path": "lib/Doctrine/Common/Cache/ClearableCache.php",
    "content": "<?php\n\nnamespace Doctrine\\Common\\Cache;\n\n/**\n * Interface for cache that can be flushed.\n *\n * Intended to be used for partial clearing of a cache namespace. For a more\n * global \"flushing\", see {@see FlushableCache}.\n *\n * @link   www.doctrine-project.org\n */\ninterface ClearableCache\n{\n    /**\n     * Deletes all cache entries in the current cache namespace.\n     *\n     * @return bool TRUE if the cache entries were successfully deleted, FALSE otherwise.\n     */\n    public function deleteAll();\n}\n"
  },
  {
    "path": "lib/Doctrine/Common/Cache/FlushableCache.php",
    "content": "<?php\n\nnamespace Doctrine\\Common\\Cache;\n\n/**\n * Interface for cache that can be flushed.\n *\n * @link   www.doctrine-project.org\n */\ninterface FlushableCache\n{\n    /**\n     * Flushes all cache entries, globally.\n     *\n     * @return bool TRUE if the cache entries were successfully flushed, FALSE otherwise.\n     */\n    public function flushAll();\n}\n"
  },
  {
    "path": "lib/Doctrine/Common/Cache/MultiDeleteCache.php",
    "content": "<?php\n\nnamespace Doctrine\\Common\\Cache;\n\n/**\n * Interface for cache drivers that allows to put many items at once.\n *\n * @deprecated\n *\n * @link   www.doctrine-project.org\n */\ninterface MultiDeleteCache\n{\n    /**\n     * Deletes several cache entries.\n     *\n     * @param string[] $keys Array of keys to delete from cache\n     *\n     * @return bool TRUE if the operation was successful, FALSE if it wasn't.\n     */\n    public function deleteMultiple(array $keys);\n}\n"
  },
  {
    "path": "lib/Doctrine/Common/Cache/MultiGetCache.php",
    "content": "<?php\n\nnamespace Doctrine\\Common\\Cache;\n\n/**\n * Interface for cache drivers that allows to get many items at once.\n *\n * @deprecated\n *\n * @link   www.doctrine-project.org\n */\ninterface MultiGetCache\n{\n    /**\n     * Returns an associative array of values for keys is found in cache.\n     *\n     * @param string[] $keys Array of keys to retrieve from cache\n     *\n     * @return mixed[] Array of retrieved values, indexed by the specified keys.\n     *                 Values that couldn't be retrieved are not contained in this array.\n     */\n    public function fetchMultiple(array $keys);\n}\n"
  },
  {
    "path": "lib/Doctrine/Common/Cache/MultiOperationCache.php",
    "content": "<?php\n\nnamespace Doctrine\\Common\\Cache;\n\n/**\n * Interface for cache drivers that supports multiple items manipulation.\n *\n * @link   www.doctrine-project.org\n */\ninterface MultiOperationCache extends MultiGetCache, MultiDeleteCache, MultiPutCache\n{\n}\n"
  },
  {
    "path": "lib/Doctrine/Common/Cache/MultiPutCache.php",
    "content": "<?php\n\nnamespace Doctrine\\Common\\Cache;\n\n/**\n * Interface for cache drivers that allows to put many items at once.\n *\n * @deprecated\n *\n * @link   www.doctrine-project.org\n */\ninterface MultiPutCache\n{\n    /**\n     * Returns a boolean value indicating if the operation succeeded.\n     *\n     * @param mixed[] $keysAndValues Array of keys and values to save in cache\n     * @param int     $lifetime      The lifetime. If != 0, sets a specific lifetime for these\n     *                               cache entries (0 => infinite lifeTime).\n     *\n     * @return bool TRUE if the operation was successful, FALSE if it wasn't.\n     */\n    public function saveMultiple(array $keysAndValues, $lifetime = 0);\n}\n"
  },
  {
    "path": "lib/Doctrine/Common/Cache/Psr6/CacheAdapter.php",
    "content": "<?php\n\nnamespace Doctrine\\Common\\Cache\\Psr6;\n\nuse Doctrine\\Common\\Cache\\Cache;\nuse Doctrine\\Common\\Cache\\ClearableCache;\nuse Doctrine\\Common\\Cache\\MultiDeleteCache;\nuse Doctrine\\Common\\Cache\\MultiGetCache;\nuse Doctrine\\Common\\Cache\\MultiPutCache;\nuse Psr\\Cache\\CacheItemInterface;\nuse Psr\\Cache\\CacheItemPoolInterface;\nuse Symfony\\Component\\Cache\\DoctrineProvider as SymfonyDoctrineProvider;\n\nuse function array_key_exists;\nuse function assert;\nuse function count;\nuse function current;\nuse function get_class;\nuse function gettype;\nuse function is_object;\nuse function is_string;\nuse function microtime;\nuse function sprintf;\nuse function strpbrk;\n\nuse const PHP_VERSION_ID;\n\nfinal class CacheAdapter implements CacheItemPoolInterface\n{\n    private const RESERVED_CHARACTERS = '{}()/\\@:';\n\n    /** @var Cache */\n    private $cache;\n\n    /** @var array<CacheItem|TypedCacheItem> */\n    private $deferredItems = [];\n\n    public static function wrap(Cache $cache): CacheItemPoolInterface\n    {\n        if ($cache instanceof DoctrineProvider && ! $cache->getNamespace()) {\n            return $cache->getPool();\n        }\n\n        if ($cache instanceof SymfonyDoctrineProvider && ! $cache->getNamespace()) {\n            $getPool = function () {\n                // phpcs:ignore Squiz.Scope.StaticThisUsage.Found\n                return $this->pool;\n            };\n\n            return $getPool->bindTo($cache, SymfonyDoctrineProvider::class)();\n        }\n\n        return new self($cache);\n    }\n\n    private function __construct(Cache $cache)\n    {\n        $this->cache = $cache;\n    }\n\n    /** @internal */\n    public function getCache(): Cache\n    {\n        return $this->cache;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public function getItem($key): CacheItemInterface\n    {\n        assert(self::validKey($key));\n\n        if (isset($this->deferredItems[$key])) {\n            $this->commit();\n        }\n\n        $value = $this->cache->fetch($key);\n\n        if (PHP_VERSION_ID >= 80000) {\n            if ($value !== false) {\n                return new TypedCacheItem($key, $value, true);\n            }\n\n            return new TypedCacheItem($key, null, false);\n        }\n\n        if ($value !== false) {\n            return new CacheItem($key, $value, true);\n        }\n\n        return new CacheItem($key, null, false);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public function getItems(array $keys = []): array\n    {\n        if ($this->deferredItems) {\n            $this->commit();\n        }\n\n        assert(self::validKeys($keys));\n\n        $values = $this->doFetchMultiple($keys);\n        $items  = [];\n\n        if (PHP_VERSION_ID >= 80000) {\n            foreach ($keys as $key) {\n                if (array_key_exists($key, $values)) {\n                    $items[$key] = new TypedCacheItem($key, $values[$key], true);\n                } else {\n                    $items[$key] = new TypedCacheItem($key, null, false);\n                }\n            }\n\n            return $items;\n        }\n\n        foreach ($keys as $key) {\n            if (array_key_exists($key, $values)) {\n                $items[$key] = new CacheItem($key, $values[$key], true);\n            } else {\n                $items[$key] = new CacheItem($key, null, false);\n            }\n        }\n\n        return $items;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public function hasItem($key): bool\n    {\n        assert(self::validKey($key));\n\n        if (isset($this->deferredItems[$key])) {\n            $this->commit();\n        }\n\n        return $this->cache->contains($key);\n    }\n\n    public function clear(): bool\n    {\n        $this->deferredItems = [];\n\n        if (! $this->cache instanceof ClearableCache) {\n            return false;\n        }\n\n        return $this->cache->deleteAll();\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public function deleteItem($key): bool\n    {\n        assert(self::validKey($key));\n        unset($this->deferredItems[$key]);\n\n        return $this->cache->delete($key);\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public function deleteItems(array $keys): bool\n    {\n        foreach ($keys as $key) {\n            assert(self::validKey($key));\n            unset($this->deferredItems[$key]);\n        }\n\n        return $this->doDeleteMultiple($keys);\n    }\n\n    public function save(CacheItemInterface $item): bool\n    {\n        return $this->saveDeferred($item) && $this->commit();\n    }\n\n    public function saveDeferred(CacheItemInterface $item): bool\n    {\n        if (! $item instanceof CacheItem && ! $item instanceof TypedCacheItem) {\n            return false;\n        }\n\n        $this->deferredItems[$item->getKey()] = $item;\n\n        return true;\n    }\n\n    public function commit(): bool\n    {\n        if (! $this->deferredItems) {\n            return true;\n        }\n\n        $now         = microtime(true);\n        $itemsCount  = 0;\n        $byLifetime  = [];\n        $expiredKeys = [];\n\n        foreach ($this->deferredItems as $key => $item) {\n            $lifetime = ($item->getExpiry() ?? $now) - $now;\n\n            if ($lifetime < 0) {\n                $expiredKeys[] = $key;\n\n                continue;\n            }\n\n            ++$itemsCount;\n            $byLifetime[(int) $lifetime][$key] = $item->get();\n        }\n\n        $this->deferredItems = [];\n\n        switch (count($expiredKeys)) {\n            case 0:\n                break;\n            case 1:\n                $this->cache->delete(current($expiredKeys));\n                break;\n            default:\n                $this->doDeleteMultiple($expiredKeys);\n                break;\n        }\n\n        if ($itemsCount === 1) {\n            return $this->cache->save($key, $item->get(), (int) $lifetime);\n        }\n\n        $success = true;\n        foreach ($byLifetime as $lifetime => $values) {\n            $success = $this->doSaveMultiple($values, $lifetime) && $success;\n        }\n\n        return $success;\n    }\n\n    public function __destruct()\n    {\n        $this->commit();\n    }\n\n    /**\n     * @param mixed $key\n     */\n    private static function validKey($key): bool\n    {\n        if (! is_string($key)) {\n            throw new InvalidArgument(sprintf('Cache key must be string, \"%s\" given.', is_object($key) ? get_class($key) : gettype($key)));\n        }\n\n        if ($key === '') {\n            throw new InvalidArgument('Cache key length must be greater than zero.');\n        }\n\n        if (strpbrk($key, self::RESERVED_CHARACTERS) !== false) {\n            throw new InvalidArgument(sprintf('Cache key \"%s\" contains reserved characters \"%s\".', $key, self::RESERVED_CHARACTERS));\n        }\n\n        return true;\n    }\n\n    /**\n     * @param mixed[] $keys\n     */\n    private static function validKeys(array $keys): bool\n    {\n        foreach ($keys as $key) {\n            self::validKey($key);\n        }\n\n        return true;\n    }\n\n    /**\n     * @param mixed[] $keys\n     */\n    private function doDeleteMultiple(array $keys): bool\n    {\n        if ($this->cache instanceof MultiDeleteCache) {\n            return $this->cache->deleteMultiple($keys);\n        }\n\n        $success = true;\n        foreach ($keys as $key) {\n            $success = $this->cache->delete($key) && $success;\n        }\n\n        return $success;\n    }\n\n    /**\n     * @param mixed[] $keys\n     *\n     * @return mixed[]\n     */\n    private function doFetchMultiple(array $keys): array\n    {\n        if ($this->cache instanceof MultiGetCache) {\n            return $this->cache->fetchMultiple($keys);\n        }\n\n        $values = [];\n        foreach ($keys as $key) {\n            $value = $this->cache->fetch($key);\n            if (! $value) {\n                continue;\n            }\n\n            $values[$key] = $value;\n        }\n\n        return $values;\n    }\n\n    /**\n     * @param mixed[] $keysAndValues\n     */\n    private function doSaveMultiple(array $keysAndValues, int $lifetime = 0): bool\n    {\n        if ($this->cache instanceof MultiPutCache) {\n            return $this->cache->saveMultiple($keysAndValues, $lifetime);\n        }\n\n        $success = true;\n        foreach ($keysAndValues as $key => $value) {\n            $success = $this->cache->save($key, $value, $lifetime) && $success;\n        }\n\n        return $success;\n    }\n}\n"
  },
  {
    "path": "lib/Doctrine/Common/Cache/Psr6/CacheItem.php",
    "content": "<?php\n\nnamespace Doctrine\\Common\\Cache\\Psr6;\n\nuse DateInterval;\nuse DateTime;\nuse DateTimeInterface;\nuse Psr\\Cache\\CacheItemInterface;\nuse TypeError;\n\nuse function get_class;\nuse function gettype;\nuse function is_int;\nuse function is_object;\nuse function microtime;\nuse function sprintf;\n\nfinal class CacheItem implements CacheItemInterface\n{\n    /** @var string */\n    private $key;\n    /** @var mixed */\n    private $value;\n    /** @var bool */\n    private $isHit;\n    /** @var float|null */\n    private $expiry;\n\n    /**\n     * @internal\n     *\n     * @param mixed $data\n     */\n    public function __construct(string $key, $data, bool $isHit)\n    {\n        $this->key   = $key;\n        $this->value = $data;\n        $this->isHit = $isHit;\n    }\n\n    public function getKey(): string\n    {\n        return $this->key;\n    }\n\n    /**\n     * {@inheritDoc}\n     *\n     * @return mixed\n     */\n    public function get()\n    {\n        return $this->value;\n    }\n\n    public function isHit(): bool\n    {\n        return $this->isHit;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public function set($value): self\n    {\n        $this->value = $value;\n\n        return $this;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public function expiresAt($expiration): self\n    {\n        if ($expiration === null) {\n            $this->expiry = null;\n        } elseif ($expiration instanceof DateTimeInterface) {\n            $this->expiry = (float) $expiration->format('U.u');\n        } else {\n            throw new TypeError(sprintf(\n                'Expected $expiration to be an instance of DateTimeInterface or null, got %s',\n                is_object($expiration) ? get_class($expiration) : gettype($expiration)\n            ));\n        }\n\n        return $this;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public function expiresAfter($time): self\n    {\n        if ($time === null) {\n            $this->expiry = null;\n        } elseif ($time instanceof DateInterval) {\n            $this->expiry = microtime(true) + DateTime::createFromFormat('U', 0)->add($time)->format('U.u');\n        } elseif (is_int($time)) {\n            $this->expiry = $time + microtime(true);\n        } else {\n            throw new TypeError(sprintf(\n                'Expected $time to be either an integer, an instance of DateInterval or null, got %s',\n                is_object($time) ? get_class($time) : gettype($time)\n            ));\n        }\n\n        return $this;\n    }\n\n    /**\n     * @internal\n     */\n    public function getExpiry(): ?float\n    {\n        return $this->expiry;\n    }\n}\n"
  },
  {
    "path": "lib/Doctrine/Common/Cache/Psr6/DoctrineProvider.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Doctrine\\Common\\Cache\\Psr6;\n\nuse Doctrine\\Common\\Cache\\Cache;\nuse Doctrine\\Common\\Cache\\CacheProvider;\nuse Psr\\Cache\\CacheItemPoolInterface;\nuse Symfony\\Component\\Cache\\Adapter\\DoctrineAdapter as SymfonyDoctrineAdapter;\nuse Symfony\\Contracts\\Service\\ResetInterface;\n\nuse function rawurlencode;\n\n/**\n * This class was copied from the Symfony Framework, see the original copyright\n * notice above. The code is distributed subject to the license terms in\n * https://github.com/symfony/symfony/blob/ff0cf61278982539c49e467db9ab13cbd342f76d/LICENSE\n */\nfinal class DoctrineProvider extends CacheProvider\n{\n    /** @var CacheItemPoolInterface */\n    private $pool;\n\n    public static function wrap(CacheItemPoolInterface $pool): Cache\n    {\n        if ($pool instanceof CacheAdapter) {\n            return $pool->getCache();\n        }\n\n        if ($pool instanceof SymfonyDoctrineAdapter) {\n            $getCache = function () {\n                // phpcs:ignore Squiz.Scope.StaticThisUsage.Found\n                return $this->provider;\n            };\n\n            return $getCache->bindTo($pool, SymfonyDoctrineAdapter::class)();\n        }\n\n        return new self($pool);\n    }\n\n    private function __construct(CacheItemPoolInterface $pool)\n    {\n        $this->pool = $pool;\n    }\n\n    /** @internal */\n    public function getPool(): CacheItemPoolInterface\n    {\n        return $this->pool;\n    }\n\n    public function reset(): void\n    {\n        if ($this->pool instanceof ResetInterface) {\n            $this->pool->reset();\n        }\n\n        $this->setNamespace($this->getNamespace());\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function doFetch($id)\n    {\n        $item = $this->pool->getItem(rawurlencode($id));\n\n        return $item->isHit() ? $item->get() : false;\n    }\n\n    /**\n     * {@inheritdoc}\n     *\n     * @return bool\n     */\n    protected function doContains($id)\n    {\n        return $this->pool->hasItem(rawurlencode($id));\n    }\n\n    /**\n     * {@inheritdoc}\n     *\n     * @return bool\n     */\n    protected function doSave($id, $data, $lifeTime = 0)\n    {\n        $item = $this->pool->getItem(rawurlencode($id));\n\n        if (0 < $lifeTime) {\n            $item->expiresAfter($lifeTime);\n        }\n\n        return $this->pool->save($item->set($data));\n    }\n\n    /**\n     * {@inheritdoc}\n     *\n     * @return bool\n     */\n    protected function doDelete($id)\n    {\n        return $this->pool->deleteItem(rawurlencode($id));\n    }\n\n    /**\n     * {@inheritdoc}\n     *\n     * @return bool\n     */\n    protected function doFlush()\n    {\n        return $this->pool->clear();\n    }\n\n    /**\n     * {@inheritdoc}\n     *\n     * @return array|null\n     */\n    protected function doGetStats()\n    {\n        return null;\n    }\n}\n"
  },
  {
    "path": "lib/Doctrine/Common/Cache/Psr6/InvalidArgument.php",
    "content": "<?php\n\nnamespace Doctrine\\Common\\Cache\\Psr6;\n\nuse InvalidArgumentException;\nuse Psr\\Cache\\InvalidArgumentException as PsrInvalidArgumentException;\n\n/**\n * @internal\n */\nfinal class InvalidArgument extends InvalidArgumentException implements PsrInvalidArgumentException\n{\n}\n"
  },
  {
    "path": "lib/Doctrine/Common/Cache/Psr6/TypedCacheItem.php",
    "content": "<?php\n\nnamespace Doctrine\\Common\\Cache\\Psr6;\n\nuse DateInterval;\nuse DateTime;\nuse DateTimeInterface;\nuse Psr\\Cache\\CacheItemInterface;\nuse TypeError;\n\nuse function get_debug_type;\nuse function is_int;\nuse function microtime;\nuse function sprintf;\n\nfinal class TypedCacheItem implements CacheItemInterface\n{\n    private ?float $expiry = null;\n\n    /**\n     * @internal\n     */\n    public function __construct(\n        private string $key,\n        private mixed $value,\n        private bool $isHit,\n    ) {\n    }\n\n    public function getKey(): string\n    {\n        return $this->key;\n    }\n\n    public function get(): mixed\n    {\n        return $this->value;\n    }\n\n    public function isHit(): bool\n    {\n        return $this->isHit;\n    }\n\n    public function set(mixed $value): static\n    {\n        $this->value = $value;\n\n        return $this;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public function expiresAt($expiration): static\n    {\n        if ($expiration === null) {\n            $this->expiry = null;\n        } elseif ($expiration instanceof DateTimeInterface) {\n            $this->expiry = (float) $expiration->format('U.u');\n        } else {\n            throw new TypeError(sprintf(\n                'Expected $expiration to be an instance of DateTimeInterface or null, got %s',\n                get_debug_type($expiration)\n            ));\n        }\n\n        return $this;\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public function expiresAfter($time): static\n    {\n        if ($time === null) {\n            $this->expiry = null;\n        } elseif ($time instanceof DateInterval) {\n            $this->expiry = microtime(true) + DateTime::createFromFormat('U', 0)->add($time)->format('U.u');\n        } elseif (is_int($time)) {\n            $this->expiry = $time + microtime(true);\n        } else {\n            throw new TypeError(sprintf(\n                'Expected $time to be either an integer, an instance of DateInterval or null, got %s',\n                get_debug_type($time)\n            ));\n        }\n\n        return $this;\n    }\n\n    /**\n     * @internal\n     */\n    public function getExpiry(): ?float\n    {\n        return $this->expiry;\n    }\n}\n"
  },
  {
    "path": "phpcs.xml.dist",
    "content": "<?xml version=\"1.0\"?>\n<ruleset name=\"Coding Standards for doctrine\">\n    <description>Coding Standards for doctrine.</description>\n\n    <arg name=\"basepath\" value=\".\"/>\n    <arg name=\"extensions\" value=\"php\"/>\n    <arg name=\"parallel\" value=\"80\"/>\n    <arg name=\"cache\" value=\".phpcs-cache\"/>\n    <arg name=\"colors\" />\n\n    <config name=\"php_version\" value=\"70100\"/>\n\n    <!-- Ignore warnings and show progress of the run -->\n    <arg value=\"np\"/>\n\n    <file>lib</file>\n    <file>tests</file>\n\n    <rule ref=\"Doctrine\">\n        <exclude name=\"SlevomatCodingStandard.TypeHints.DeclareStrictTypes\"/>\n        <exclude name=\"SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint\"/>\n        <exclude name=\"SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingNativeTypeHint\"/>\n        <exclude name=\"SlevomatCodingStandard.Operators.DisallowEqualOperators\"/>\n        <exclude name=\"SlevomatCodingStandard.Classes.DisallowLateStaticBindingForConstants\" />\n    </rule>\n\n    <rule ref=\"PSR1.Classes.ClassDeclaration.MultipleClasses\">\n        <exclude-pattern>tests/Doctrine/Tests/Common/Cache/PhpFileCacheTest.php</exclude-pattern>\n    </rule>\n\n    <!-- Multiple classes confuse this rule -->\n    <rule ref=\"Squiz.Classes.ClassFileName\">\n        <exclude-pattern>tests/Doctrine/Tests/Common/Cache/PhpFileCacheTest.php</exclude-pattern>\n    </rule>\n</ruleset>\n"
  },
  {
    "path": "phpunit.xml.dist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n     xsi:noNamespaceSchemaLocation=\"vendor/phpunit/phpunit/phpunit.xsd\"\n     backupGlobals=\"false\"\n     colors=\"true\"\n     verbose=\"true\"\n     beStrictAboutOutputDuringTests=\"true\"\n     beStrictAboutTestsThatDoNotTestAnything=\"true\"\n     beStrictAboutChangesToGlobalState=\"true\"\n>\n    <php>\n        <ini name=\"error_reporting\" value=\"-1\" />\n    </php>\n\n    <testsuites>\n        <testsuite name=\"Doctrine Cache Test Suite\">\n            <directory>./tests/Doctrine/</directory>\n        </testsuite>\n    </testsuites>\n\n    <filter>\n        <whitelist>\n            <directory>./lib/Doctrine/</directory>\n            <exclude>\n                <file>lib/Doctrine/Common/Cache/ApcCache.php</file>\n                <file>lib/Doctrine/Common/Cache/CouchbaseCache.php</file>\n                <file>lib/Doctrine/Common/Cache/XcacheCache.php</file>\n            </exclude>\n        </whitelist>\n    </filter>\n</phpunit>\n"
  },
  {
    "path": "tests/Doctrine/Tests/Common/Cache/ArrayCache.php",
    "content": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Cache;\n\nuse Doctrine\\Common\\Cache\\Cache;\nuse Doctrine\\Common\\Cache\\CacheProvider;\n\nuse function time;\n\n/**\n * Array cache driver used for testing\n *\n * @internal\n */\nclass ArrayCache extends CacheProvider\n{\n    /** @psalm-var array<string, array{mixed, int|bool}>> $data each element being a tuple of [$data, $expiration], where the expiration is int|bool */\n    private $data = [];\n\n    /** @var int */\n    private $hitsCount = 0;\n\n    /** @var int */\n    private $missesCount = 0;\n\n    /** @var int */\n    private $upTime;\n\n    /**\n     * {@inheritdoc}\n     */\n    public function __construct()\n    {\n        $this->upTime = time();\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function doFetch($id)\n    {\n        if (! $this->doContains($id)) {\n            $this->missesCount += 1;\n\n            return false;\n        }\n\n        $this->hitsCount += 1;\n\n        return $this->data[$id][0];\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function doContains($id)\n    {\n        if (! isset($this->data[$id])) {\n            return false;\n        }\n\n        $expiration = $this->data[$id][1];\n\n        if ($expiration && $expiration < time()) {\n            $this->doDelete($id);\n\n            return false;\n        }\n\n        return true;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function doSave($id, $data, $lifeTime = 0)\n    {\n        $this->data[$id] = [$data, $lifeTime ? time() + $lifeTime : false];\n\n        return true;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function doDelete($id)\n    {\n        unset($this->data[$id]);\n\n        return true;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function doFlush()\n    {\n        $this->data = [];\n\n        return true;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function doGetStats()\n    {\n        return [\n            Cache::STATS_HITS             => $this->hitsCount,\n            Cache::STATS_MISSES           => $this->missesCount,\n            Cache::STATS_UPTIME           => $this->upTime,\n            Cache::STATS_MEMORY_USAGE     => null,\n            Cache::STATS_MEMORY_AVAILABLE => null,\n        ];\n    }\n}\n"
  },
  {
    "path": "tests/Doctrine/Tests/Common/Cache/ArrayCacheTest.php",
    "content": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Cache;\n\nuse Doctrine\\Common\\Cache\\Cache;\nuse Doctrine\\Common\\Cache\\CacheProvider;\n\nclass ArrayCacheTest extends CacheTest\n{\n    protected function getCacheDriver(): CacheProvider\n    {\n        return new ArrayCache();\n    }\n\n    public function testGetStats(): void\n    {\n        $cache = $this->getCacheDriver();\n        $cache->fetch('test1');\n        $cache->fetch('test2');\n        $cache->fetch('test3');\n\n        $cache->save('test1', 123);\n        $cache->save('test2', 123);\n\n        $cache->fetch('test1');\n        $cache->fetch('test2');\n        $cache->fetch('test3');\n\n        $stats = $cache->getStats();\n        self::assertEquals(2, $stats[Cache::STATS_HITS]);\n        self::assertEquals(5, $stats[Cache::STATS_MISSES]); // +1 for internal call to DoctrineNamespaceCacheKey\n        self::assertNotNull($stats[Cache::STATS_UPTIME]);\n        self::assertNull($stats[Cache::STATS_MEMORY_USAGE]);\n        self::assertNull($stats[Cache::STATS_MEMORY_AVAILABLE]);\n\n        $cache->delete('test1');\n        $cache->delete('test2');\n\n        $cache->fetch('test1');\n        $cache->fetch('test2');\n        $cache->fetch('test3');\n\n        $stats = $cache->getStats();\n        self::assertEquals(2, $stats[Cache::STATS_HITS]);\n        self::assertEquals(8, $stats[Cache::STATS_MISSES]); // +1 for internal call to DoctrineNamespaceCacheKey\n    }\n\n    protected function isSharedStorage(): bool\n    {\n        return false;\n    }\n}\n"
  },
  {
    "path": "tests/Doctrine/Tests/Common/Cache/CacheProviderTest.php",
    "content": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Cache;\n\nuse Doctrine\\Common\\Cache\\CacheProvider;\nuse Doctrine\\Tests\\DoctrineTestCase;\nuse PHPUnit_Framework_MockObject_MockObject;\n\nuse function assert;\n\nclass CacheProviderTest extends DoctrineTestCase\n{\n    public function testFetchMultiWillFilterNonRequestedKeys(): void\n    {\n        $cache = $this->getMockForAbstractClass(\n            CacheProvider::class,\n            [],\n            '',\n            true,\n            true,\n            true,\n            ['doFetchMultiple']\n        );\n        assert($cache instanceof CacheProvider || $cache instanceof PHPUnit_Framework_MockObject_MockObject);\n\n        $cache\n            ->expects($this->once())\n            ->method('doFetchMultiple')\n            ->will($this->returnValue([\n                '[foo][1]' => 'bar',\n                '[bar][1]' => 'baz',\n                '[baz][1]' => 'tab',\n            ]));\n\n        self::assertEquals(\n            ['foo' => 'bar', 'bar' => 'baz'],\n            $cache->fetchMultiple(['foo', 'bar'])\n        );\n    }\n\n    public function testFailedDeleteAllDoesNotChangeNamespaceVersion(): void\n    {\n        $cache = $this->getMockForAbstractClass(\n            CacheProvider::class,\n            [],\n            '',\n            true,\n            true,\n            true,\n            ['doFetch', 'doSave', 'doContains']\n        );\n        assert($cache instanceof CacheProvider || $cache instanceof PHPUnit_Framework_MockObject_MockObject);\n\n        $cache\n            ->expects($this->once())\n            ->method('doFetch')\n            ->with('DoctrineNamespaceCacheKey[]')\n            ->will($this->returnValue(false));\n\n        // doSave is only called once from deleteAll as we do not need to persist the default version in getNamespaceVersion()\n        $cache\n            ->expects($this->once())\n            ->method('doSave')\n            ->with('DoctrineNamespaceCacheKey[]')\n            ->will($this->returnValue(false));\n\n        // After a failed deleteAll() the local namespace version is not increased (still 1). Otherwise all data written afterwards\n        // would be lost outside the current instance.\n        $cache\n            ->expects($this->once())\n            ->method('doContains')\n            ->with('[key][1]')\n            ->will($this->returnValue(true));\n\n        self::assertFalse($cache->deleteAll(), 'deleteAll() returns false when saving the namespace version fails');\n        $cache->contains('key');\n    }\n\n    public function testSaveMultipleNoFail(): void\n    {\n        $cache = $this->getMockForAbstractClass(\n            CacheProvider::class,\n            [],\n            '',\n            true,\n            true,\n            true,\n            ['doSave']\n        );\n        assert($cache instanceof CacheProvider || $cache instanceof PHPUnit_Framework_MockObject_MockObject);\n\n        $cache\n            ->expects($this->at(1))\n            ->method('doSave')\n            ->with('[kerr][1]', 'verr', 0)\n            ->will($this->returnValue(false));\n\n        $cache\n            ->expects($this->at(2))\n            ->method('doSave')\n            ->with('[kok][1]', 'vok', 0)\n            ->will($this->returnValue(true));\n\n        $cache->saveMultiple([\n            'kerr'  => 'verr',\n            'kok'   => 'vok',\n        ]);\n    }\n\n    public function testDeleteMultipleNoFail(): void\n    {\n        $cache = $this\n            ->getMockBuilder(CacheProvider::class)\n            ->setMethods(['doDelete'])\n            ->getMockForAbstractClass();\n        assert($cache instanceof CacheProvider || $cache instanceof PHPUnit_Framework_MockObject_MockObject);\n\n        $cache\n            ->expects($this->at(1))\n            ->method('doDelete')\n            ->with('[kerr][1]')\n            ->will($this->returnValue(false));\n\n        $cache\n            ->expects($this->at(2))\n            ->method('doDelete')\n            ->with('[kok][1]')\n            ->will($this->returnValue(true));\n\n        $cache->deleteMultiple(['kerr', 'kok']);\n    }\n\n    public function testInvalidNamespaceVersionCacheEntry(): void\n    {\n        $cache = $this->getMockForAbstractClass(CacheProvider::class);\n        assert($cache instanceof CacheProvider || $cache instanceof PHPUnit_Framework_MockObject_MockObject);\n\n        $cache->expects($this->once())\n              ->method('doFetch')\n              ->with('DoctrineNamespaceCacheKey[]')\n              ->willReturn('corruptedStringKey');\n\n        $cache->expects($this->once())\n              ->method('doSave')\n              ->with('DoctrineNamespaceCacheKey[]', 2, 0)\n              ->willReturn(true);\n\n        self::assertTrue($cache->deleteAll());\n    }\n}\n"
  },
  {
    "path": "tests/Doctrine/Tests/Common/Cache/CacheTest.php",
    "content": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Cache;\n\nuse ArrayObject;\nuse Doctrine\\Common\\Cache\\Cache;\nuse Doctrine\\Common\\Cache\\CacheProvider;\nuse Doctrine\\Tests\\DoctrineTestCase;\nuse stdClass;\n\nuse function array_keys;\nuse function array_map;\nuse function array_slice;\nuse function is_object;\nuse function restore_error_handler;\nuse function set_error_handler;\nuse function sleep;\nuse function sprintf;\nuse function str_repeat;\n\nabstract class CacheTest extends DoctrineTestCase\n{\n    /**\n     * @param mixed $value\n     *\n     * @dataProvider provideDataToCache\n     */\n    public function testSetContainsFetchDelete($value): void\n    {\n        $cache = $this->getCacheDriver();\n\n        // Test saving a value, checking if it exists, and fetching it back\n        self::assertTrue($cache->save('key', $value));\n        self::assertTrue($cache->contains('key'));\n        if (is_object($value)) {\n            self::assertEquals($value, $cache->fetch('key'), 'Objects retrieved from the cache must be equal but not necessarily the same reference');\n        } else {\n            self::assertSame($value, $cache->fetch('key'), 'Scalar and array data retrieved from the cache must be the same as the original, e.g. same type');\n        }\n\n        // Test deleting a value\n        self::assertTrue($cache->delete('key'));\n        self::assertFalse($cache->contains('key'));\n        self::assertFalse($cache->fetch('key'));\n    }\n\n    /**\n     * @param mixed $value\n     *\n     * @dataProvider provideDataToCache\n     */\n    public function testUpdateExistingEntry($value): void\n    {\n        $cache = $this->getCacheDriver();\n\n        self::assertTrue($cache->save('key', 'old-value'));\n        self::assertTrue($cache->contains('key'));\n\n        self::assertTrue($cache->save('key', $value));\n        self::assertTrue($cache->contains('key'));\n        if (is_object($value)) {\n            self::assertEquals($value, $cache->fetch('key'), 'Objects retrieved from the cache must be equal but not necessarily the same reference');\n        } else {\n            self::assertSame($value, $cache->fetch('key'), 'Scalar and array data retrieved from the cache must be the same as the original, e.g. same type');\n        }\n    }\n\n    public function testCacheKeyIsCaseSensitive(): void\n    {\n        $cache = $this->getCacheDriver();\n\n        self::assertTrue($cache->save('key', 'value'));\n        self::assertTrue($cache->contains('key'));\n        self::assertSame('value', $cache->fetch('key'));\n\n        self::assertFalse($cache->contains('KEY'));\n        self::assertFalse($cache->fetch('KEY'));\n\n        $cache->delete('KEY');\n        self::assertTrue($cache->contains('key'), 'Deleting cache item with different case must not affect other cache item');\n    }\n\n    public function testFetchMultiple(): void\n    {\n        $cache  = $this->getCacheDriver();\n        $values = $this->provideDataToCache();\n        $saved  = [];\n\n        foreach ($values as $key => $value) {\n            $cache->save($key, $value[0]);\n\n            $saved[$key] = $value[0];\n        }\n\n        $keys = array_keys($saved);\n\n        self::assertEquals(\n            $saved,\n            $cache->fetchMultiple($keys),\n            'Testing fetchMultiple with different data types'\n        );\n        self::assertEquals(\n            array_slice($saved, 0, 1),\n            $cache->fetchMultiple(array_slice($keys, 0, 1)),\n            'Testing fetchMultiple with a single key'\n        );\n\n        $keysWithNonExisting   = [];\n        $keysWithNonExisting[] = 'non_existing1';\n        $keysWithNonExisting[] = $keys[0];\n        $keysWithNonExisting[] = 'non_existing2';\n        $keysWithNonExisting[] = $keys[1];\n        $keysWithNonExisting[] = 'non_existing3';\n\n        self::assertEquals(\n            array_slice($saved, 0, 2),\n            $cache->fetchMultiple($keysWithNonExisting),\n            'Testing fetchMultiple with a subset of keys and mixed with non-existing ones'\n        );\n    }\n\n    public function testFetchMultipleWithNoKeys(): void\n    {\n        $cache = $this->getCacheDriver();\n\n        self::assertSame([], $cache->fetchMultiple([]));\n    }\n\n    public function testSaveMultiple(): void\n    {\n        $cache = $this->getCacheDriver();\n        $cache->deleteAll();\n\n        $data = array_map(static function ($value) {\n            return $value[0];\n        }, $this->provideDataToCache());\n\n        self::assertTrue($cache->saveMultiple($data));\n\n        $keys = array_keys($data);\n\n        self::assertEquals($data, $cache->fetchMultiple($keys));\n    }\n\n    /**\n     * @return array<string, array{mixed}>\n     */\n    public function provideDataToCache(): array\n    {\n        $obj       = new stdClass();\n        $obj->foo  = 'bar';\n        $obj2      = new stdClass();\n        $obj2->bar = 'foo';\n        $obj2->obj = $obj;\n        $obj->obj2 = $obj2;\n\n        return [\n            'array' => [['one', 2, 3.01]],\n            'string' => ['value'],\n            'string_invalid_utf8' => [\"\\xc3\\x28\"],\n            'string_null_byte' => ['with' . \"\\0\" . 'null char'],\n            'integer' => [1],\n            'float' => [1.5],\n            'object' => [new ArrayObject(['one', 2, 3.01])],\n            'object_recursive' => [$obj],\n            'true' => [true],\n            // the following are considered FALSE in boolean context, but caches should still recognize their existence\n            'null' => [null],\n            'false' => [false],\n            'array_empty' => [[]],\n            'string_zero' => ['0'],\n            'integer_zero' => [0],\n            'float_zero' => [0.0],\n            'string_empty' => [''],\n        ];\n    }\n\n    public function testDeleteIsSuccessfulWhenKeyDoesNotExist(): void\n    {\n        $cache = $this->getCacheDriver();\n\n        $cache->delete('key');\n        self::assertFalse($cache->contains('key'));\n        self::assertTrue($cache->delete('key'));\n    }\n\n    public function testDeleteAll(): void\n    {\n        $cache = $this->getCacheDriver();\n\n        self::assertTrue($cache->save('key1', 1));\n        self::assertTrue($cache->save('key2', 2));\n        self::assertTrue($cache->deleteAll());\n        self::assertFalse($cache->contains('key1'), sprintf(\n            'key1 should have disappeared but did not. The namespace is \"%s\"',\n            $cache->getNamespace()\n        ));\n        self::assertFalse($cache->contains('key2'));\n    }\n\n    public function testDeleteMulti(): void\n    {\n        $cache = $this->getCacheDriver();\n\n        self::assertTrue($cache->save('key1', 1));\n        self::assertTrue($cache->save('key2', 1));\n        self::assertTrue($cache->deleteMultiple(['key1', 'key2', 'key3']));\n        self::assertFalse($cache->contains('key1'));\n        self::assertFalse($cache->contains('key2'));\n        self::assertFalse($cache->contains('key3'));\n    }\n\n    /**\n     * @dataProvider provideCacheIds\n     */\n    public function testCanHandleSpecialCacheIds(string $id): void\n    {\n        $cache = $this->getCacheDriver();\n\n        self::assertTrue($cache->save($id, 'value'));\n        self::assertTrue($cache->contains($id));\n        self::assertEquals('value', $cache->fetch($id));\n\n        self::assertTrue($cache->delete($id));\n        self::assertFalse($cache->contains($id));\n        self::assertFalse($cache->fetch($id));\n    }\n\n    public function testNoCacheIdCollisions(): void\n    {\n        $cache = $this->getCacheDriver();\n\n        $ids = $this->provideCacheIds();\n\n        // fill cache with each id having a different value\n        foreach ($ids as $index => $id) {\n            $cache->save($id[0], $index);\n        }\n\n        // then check value of each cache id\n        foreach ($ids as $index => $id) {\n            $value = $cache->fetch($id[0]);\n            self::assertNotFalse($value, sprintf('Failed to retrieve data for cache id \"%s\".', $id[0]));\n            if ($index === $value) {\n                continue;\n            }\n\n            $this->fail(sprintf('Cache id \"%s\" collides with id \"%s\".', $id[0], $ids[$value][0]));\n        }\n    }\n\n    /**\n     * Returns cache ids with special characters that should still work.\n     *\n     * For example, the characters :\\/<>\"*?| are not valid in Windows filenames. So they must be encoded properly.\n     * Each cache id should be considered different from the others.\n     *\n     * @psalm-return list<array{string}>\n     */\n    public function provideCacheIds(): array\n    {\n        return [\n            [':'],\n            ['\\\\'],\n            ['/'],\n            ['<'],\n            ['>'],\n            ['\"'],\n            ['*'],\n            ['?'],\n            ['|'],\n            ['['],\n            [']'],\n            ['ä'],\n            ['a'],\n            ['é'],\n            ['e'],\n            ['.'], // directory traversal\n            ['..'], // directory traversal\n            ['-'],\n            ['_'],\n            ['$'],\n            ['%'],\n            [' '],\n            [\"\\0\"],\n            [''],\n            [str_repeat('a', 300)], // long key\n            [str_repeat('a', 113)],\n        ];\n    }\n\n    public function testLifetime(): void\n    {\n        $cache = $this->getCacheDriver();\n        $cache->save('expire', 'value', 1);\n        self::assertTrue($cache->contains('expire'), 'Data should not be expired yet');\n        // @TODO should more TTL-based tests pop up, so then we should mock the `time` API instead\n        sleep(2);\n        self::assertFalse($cache->contains('expire'), 'Data should be expired');\n    }\n\n    public function testNoExpire(): void\n    {\n        $cache = $this->getCacheDriver();\n        $cache->save('noexpire', 'value', 0);\n        // @TODO should more TTL-based tests pop up, so then we should mock the `time` API instead\n        sleep(1);\n        self::assertTrue($cache->contains('noexpire'), 'Data with lifetime of zero should not expire');\n    }\n\n    public function testLongLifetime(): void\n    {\n        $cache = $this->getCacheDriver();\n        $cache->save('longlifetime', 'value', 30 * 24 * 3600 + 1);\n        self::assertTrue($cache->contains('longlifetime'), 'Data with lifetime > 30 days should be accepted');\n    }\n\n    public function testDeleteAllAndNamespaceVersioningBetweenCaches(): void\n    {\n        if (! $this->isSharedStorage()) {\n            $this->markTestSkipped('The cache storage needs to be shared.');\n        }\n\n        $cache1 = $this->getCacheDriver();\n        $cache2 = $this->getCacheDriver();\n\n        self::assertTrue($cache1->save('key1', 1));\n        self::assertTrue($cache2->save('key2', 2));\n\n        /* Both providers are initialized with the same namespace version, so\n         * they can see entries set by each other.\n         */\n        self::assertTrue($cache1->contains('key1'));\n        self::assertTrue($cache1->contains('key2'));\n        self::assertTrue($cache2->contains('key1'));\n        self::assertTrue($cache2->contains('key2'));\n\n        /* Deleting all entries through one provider will only increment the\n         * namespace version on that object (and in the cache itself, which new\n         * instances will use to initialize). The second provider will retain\n         * its original version and still see stale data.\n         */\n        self::assertTrue($cache1->deleteAll());\n        self::assertFalse($cache1->contains('key1'));\n        self::assertFalse($cache1->contains('key2'));\n        self::assertTrue($cache2->contains('key1'));\n        self::assertTrue($cache2->contains('key2'));\n\n        /* A new cache provider should not see the deleted entries, since its\n         * namespace version will be initialized.\n         */\n        $cache3 = $this->getCacheDriver();\n        self::assertFalse($cache3->contains('key1'));\n        self::assertFalse($cache3->contains('key2'));\n    }\n\n    public function testFlushAll(): void\n    {\n        $cache = $this->getCacheDriver();\n\n        self::assertTrue($cache->save('key1', 1));\n        self::assertTrue($cache->save('key2', 2));\n        self::assertTrue($cache->flushAll());\n        self::assertFalse($cache->contains('key1'));\n        self::assertFalse($cache->contains('key2'));\n    }\n\n    public function testFlushAllAndNamespaceVersioningBetweenCaches(): void\n    {\n        if (! $this->isSharedStorage()) {\n            $this->markTestSkipped('The cache storage needs to be shared.');\n        }\n\n        $cache1 = $this->getCacheDriver();\n        $cache2 = $this->getCacheDriver();\n\n        /* Deleting all elements from the first provider should increment its\n         * namespace version before saving the first entry.\n         */\n        $cache1->deleteAll();\n        self::assertTrue($cache1->save('key1', 1));\n\n        /* The second provider will be initialized with the same namespace\n         * version upon its first save operation.\n         */\n        self::assertTrue($cache2->save('key2', 2));\n\n        /* Both providers have the same namespace version and can see entries\n         * set by each other.\n         */\n        self::assertTrue($cache1->contains('key1'));\n        self::assertTrue($cache1->contains('key2'));\n        self::assertTrue($cache2->contains('key1'));\n        self::assertTrue($cache2->contains('key2'));\n\n        /* Flushing all entries through one cache will remove all entries from\n         * the cache but leave their namespace version as-is.\n         */\n        self::assertTrue($cache1->flushAll());\n        self::assertFalse($cache1->contains('key1'));\n        self::assertFalse($cache1->contains('key2'));\n        self::assertFalse($cache2->contains('key1'));\n        self::assertFalse($cache2->contains('key2'));\n\n        /* Inserting a new entry will use the same, incremented namespace\n         * version, and it will be visible to both providers.\n         */\n        self::assertTrue($cache1->save('key1', 1));\n        self::assertTrue($cache1->contains('key1'));\n        self::assertTrue($cache2->contains('key1'));\n\n        /* A new cache provider will be initialized with the original namespace\n         * version and not share any visibility with the first two providers.\n         */\n        $cache3 = $this->getCacheDriver();\n        self::assertFalse($cache3->contains('key1'));\n        self::assertFalse($cache3->contains('key2'));\n        self::assertTrue($cache3->save('key3', 3));\n        self::assertTrue($cache3->contains('key3'));\n    }\n\n    public function testNamespace(): void\n    {\n        $cache = $this->getCacheDriver();\n\n        $cache->setNamespace('ns1_');\n\n        self::assertTrue($cache->save('key1', 1));\n        self::assertTrue($cache->contains('key1'));\n\n        $cache->setNamespace('ns2_');\n\n        self::assertFalse($cache->contains('key1'));\n    }\n\n    public function testDeleteAllNamespace(): void\n    {\n        $cache = $this->getCacheDriver();\n\n        $cache->setNamespace('ns1');\n        self::assertFalse($cache->contains('key1'));\n        $cache->save('key1', 'test');\n        self::assertTrue($cache->contains('key1'));\n\n        $cache->setNamespace('ns2');\n        self::assertFalse($cache->contains('key1'));\n        $cache->save('key1', 'test');\n        self::assertTrue($cache->contains('key1'));\n\n        $cache->setNamespace('ns1');\n        self::assertTrue($cache->contains('key1'));\n        $cache->deleteAll();\n        self::assertFalse($cache->contains('key1'));\n\n        $cache->setNamespace('ns2');\n        self::assertTrue($cache->contains('key1'));\n        $cache->deleteAll();\n        self::assertFalse($cache->contains('key1'));\n    }\n\n    /**\n     * @group DCOM-43\n     */\n    public function testGetStats(): void\n    {\n        $cache = $this->getCacheDriver();\n        $stats = $cache->getStats();\n\n        self::assertArrayHasKey(Cache::STATS_HITS, $stats);\n        self::assertArrayHasKey(Cache::STATS_MISSES, $stats);\n        self::assertArrayHasKey(Cache::STATS_UPTIME, $stats);\n        self::assertArrayHasKey(Cache::STATS_MEMORY_USAGE, $stats);\n        self::assertArrayHasKey(Cache::STATS_MEMORY_AVAILABLE, $stats);\n    }\n\n    public function testSaveReturnsTrueWithAndWithoutTTlSet(): void\n    {\n        $cache = $this->getCacheDriver();\n        $cache->deleteAll();\n        self::assertTrue($cache->save('without_ttl', 'without_ttl'));\n        self::assertTrue($cache->save('with_ttl', 'with_ttl', 3600));\n    }\n\n    public function testValueThatIsFalseBooleanIsProperlyRetrieved()\n    {\n        $cache = $this->getCacheDriver();\n        $cache->deleteAll();\n\n        self::assertTrue($cache->save('key1', false));\n        self::assertTrue($cache->contains('key1'));\n        self::assertFalse($cache->fetch('key1'));\n    }\n\n    /**\n     * @group 147\n     * @group 152\n     */\n    public function testFetchingANonExistingKeyShouldNeverCauseANoticeOrWarning(): void\n    {\n        $cache = $this->getCacheDriver();\n\n        $errorHandler = function () {\n            restore_error_handler();\n\n            $this->fail('include failure captured');\n        };\n\n        set_error_handler($errorHandler);\n\n        $cache->fetch('key');\n\n        self::assertSame(\n            $errorHandler,\n            set_error_handler(static function () {\n            }),\n            'The error handler is the one set by this test, and wasn\\'t replaced'\n        );\n\n        restore_error_handler();\n        restore_error_handler();\n    }\n\n    /**\n     * Return whether multiple cache providers share the same storage.\n     *\n     * This is used for skipping certain tests for shared storage behavior.\n     */\n    protected function isSharedStorage(): bool\n    {\n        return true;\n    }\n\n    abstract protected function getCacheDriver(): CacheProvider;\n}\n"
  },
  {
    "path": "tests/Doctrine/Tests/Common/Cache/Psr6/CacheAdapterTest.php",
    "content": "<?php\n\nnamespace Doctrine\\Tests\\Common\\Cache\\Psr6;\n\nuse Cache\\IntegrationTests\\CachePoolTest;\nuse Doctrine\\Common\\Cache\\Cache;\nuse Doctrine\\Common\\Cache\\Psr6\\CacheAdapter;\nuse Doctrine\\Common\\Cache\\Psr6\\DoctrineProvider;\nuse Doctrine\\Tests\\Common\\Cache\\ArrayCache;\nuse Psr\\Cache\\CacheItemInterface;\nuse Psr\\Cache\\CacheItemPoolInterface;\nuse Symfony\\Component\\Cache\\Adapter\\ArrayAdapter;\nuse Symfony\\Component\\Cache\\DoctrineProvider as SymfonyDoctrineProvider;\n\nuse function array_key_exists;\nuse function assert;\n\nfinal class CacheAdapterTest extends CachePoolTest\n{\n    /** @var ArrayCache */\n    private $arrayCache;\n\n    public function createCachePool(): CacheItemPoolInterface\n    {\n        if (! $this->arrayCache) {\n            $this->arrayCache = new ArrayCache();\n        }\n\n        return CacheAdapter::wrap($this->arrayCache);\n    }\n\n    public function testWithWrappedCache()\n    {\n        $rootCache = new ArrayAdapter();\n        $wrapped   = DoctrineProvider::wrap($rootCache);\n\n        self::assertSame($rootCache, CacheAdapter::wrap($wrapped));\n    }\n\n    /**\n     * @requires function Symfony\\Component\\Cache\\DoctrineProvider::__construct\n     */\n    public function testWithWrappedSymfonyCache()\n    {\n        $rootCache = new ArrayAdapter();\n        $wrapped   = new SymfonyDoctrineProvider($rootCache);\n\n        self::assertSame($rootCache, CacheAdapter::wrap($wrapped));\n    }\n\n    public function testWithWrappedMinimalCache()\n    {\n        $rootCache = new class implements Cache {\n            /** @var mixed[] */\n            public $values = [];\n\n            /** @inheritdoc **/\n            public function fetch($id)\n            {\n                return $values[$id] ?? false;\n            }\n\n            /** @inheritdoc **/\n            public function contains($id)\n            {\n                return array_key_exists($id, $this->values);\n            }\n\n            /** @inheritdoc **/\n            public function save($id, $data, $lifeTime = 0)\n            {\n                $this->values[$id] = $data;\n\n                return true;\n            }\n\n            /** @inheritdoc **/\n            public function delete($id)\n            {\n                unset($this->values[$id]);\n\n                return true;\n            }\n\n            /** @inheritdoc **/\n            public function getStats()\n            {\n                return null;\n            }\n        };\n\n        $adapter = CacheAdapter::wrap($rootCache);\n        self::assertInstanceOf(CacheAdapter::class, $adapter);\n        assert($adapter instanceof CacheAdapter);\n\n        /** @var CacheItemInterface[] $items */\n        $items = $adapter->getItems(['1', '2', '3']);\n        self::assertCount(3, $items);\n        foreach ($items as $key => $item) {\n            $item->set($key);\n            $adapter->saveDeferred($item);\n        }\n\n        self::assertTrue($adapter->commit());\n        self::assertCount(3, $rootCache->values);\n\n        self::assertFalse($adapter->clear());\n        self::assertCount(3, $rootCache->values);\n\n        self::assertTrue($adapter->deleteItems(['1', '2']));\n        self::assertCount(1, $rootCache->values);\n    }\n\n    public function testItemsAreFlushedToTheUnderlyingCacheOnce(): void\n    {\n        $wrapped = $this->createMock(Cache::class);\n\n        $adapter   = CacheAdapter::wrap($wrapped);\n        $cacheItem = $adapter->getItem('answer-to-life-universe-everything');\n        $cacheItem->set(42);\n        $adapter->saveDeferred($cacheItem);\n\n        $wrapped->expects(self::once())\n            ->method('save')\n            ->willReturn(true);\n\n        $adapter->commit();\n        $adapter->commit();\n    }\n\n    public function testNamespacingFeatureIsPreservedWithDoctrineProvider(): void\n    {\n        $wrapped = new ArrayAdapter();\n\n        $cacheApp1 = DoctrineProvider::wrap($wrapped);\n        $cacheApp1->setNamespace('app 1');\n\n        $cacheApp2 = DoctrineProvider::wrap($wrapped);\n        $cacheApp2->setNamespace('app 2');\n\n        $psrCacheApp1 = CacheAdapter::wrap($cacheApp1);\n        $psrCacheApp2 = CacheAdapter::wrap($cacheApp2);\n\n        $item = $psrCacheApp1->getItem('some key')->set('some value');\n        $psrCacheApp1->save($item);\n        self::assertFalse($psrCacheApp2->getItem('some key')->isHit());\n    }\n\n    /**\n     * @requires function Symfony\\Component\\Cache\\DoctrineProvider::__construct\n     */\n    public function testNamespacingFeatureIsPreservedWithSymfonyDoctrineProvider(): void\n    {\n        $wrapped = new ArrayAdapter();\n\n        $cacheApp1 = new SymfonyDoctrineProvider($wrapped);\n        $cacheApp1->setNamespace('app 1');\n\n        $cacheApp2 = new SymfonyDoctrineProvider($wrapped);\n        $cacheApp2->setNamespace('app 2');\n\n        $psrCacheApp1 = CacheAdapter::wrap($cacheApp1);\n        $psrCacheApp2 = CacheAdapter::wrap($cacheApp2);\n\n        $item = $psrCacheApp1->getItem('some key')->set('some value');\n        $psrCacheApp1->save($item);\n        self::assertFalse($psrCacheApp2->getItem('some key')->isHit());\n    }\n}\n"
  },
  {
    "path": "tests/Doctrine/Tests/Common/Cache/Psr6/DoctrineProviderTest.php",
    "content": "<?php\n\n/*\n * This file is part of the Symfony package.\n *\n * (c) Fabien Potencier <fabien@symfony.com>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Doctrine\\Tests\\Common\\Cache\\Psr6;\n\nuse Doctrine\\Common\\Cache\\CacheProvider;\nuse Doctrine\\Common\\Cache\\Psr6\\CacheAdapter;\nuse Doctrine\\Common\\Cache\\Psr6\\DoctrineProvider;\nuse Doctrine\\Tests\\Common\\Cache\\ArrayCache;\nuse Doctrine\\Tests\\Common\\Cache\\CacheTest;\nuse Symfony\\Component\\Cache\\Adapter\\ArrayAdapter;\nuse Symfony\\Component\\Cache\\Adapter\\DoctrineAdapter as SymfonyDoctrineAdapter;\nuse Symfony\\Component\\Cache\\Adapter\\FilesystemAdapter;\n\nuse function class_exists;\nuse function sprintf;\nuse function sys_get_temp_dir;\n\nclass DoctrineProviderTest extends CacheTest\n{\n    protected function getCacheDriver(): CacheProvider\n    {\n        $pool = new ArrayAdapter();\n\n        return DoctrineProvider::wrap($pool);\n    }\n\n    public function testProvider()\n    {\n        $cache = $this->getCacheDriver();\n\n        $this->assertInstanceOf(CacheProvider::class, $cache);\n\n        $key = '{}()/\\@:';\n\n        $this->assertTrue($cache->delete($key));\n        $this->assertFalse($cache->contains($key));\n\n        $this->assertTrue($cache->save($key, 'bar'));\n        $this->assertTrue($cache->contains($key));\n        $this->assertSame('bar', $cache->fetch($key));\n\n        $this->assertTrue($cache->delete($key));\n        $this->assertFalse($cache->fetch($key));\n        $this->assertTrue($cache->save($key, 'bar'));\n\n        $cache->flushAll();\n        $this->assertFalse($cache->fetch($key));\n        $this->assertFalse($cache->contains($key));\n    }\n\n    public function testWithWrappedCache()\n    {\n        $rootCache = new ArrayCache();\n        $wrapped   = CacheAdapter::wrap($rootCache);\n\n        self::assertSame($rootCache, DoctrineProvider::wrap($wrapped));\n    }\n\n    public function testWithWrappedSymfonyCache()\n    {\n        if (! class_exists(SymfonyDoctrineAdapter::class)) {\n            self::markTestSkipped('This test requires Symfony 5 or lower.');\n        }\n\n        $rootCache = new ArrayCache();\n        $wrapped   = new SymfonyDoctrineAdapter($rootCache);\n\n        self::assertSame($rootCache, DoctrineProvider::wrap($wrapped));\n    }\n\n    public function testGetStats(): void\n    {\n        $this->markTestSkipped(sprintf('\"%s\" does not expose statistics', DoctrineProvider::class));\n    }\n\n    public function testResetArrayAdapter()\n    {\n        $cache = $this->getCacheDriver();\n\n        $cache->save('test', 'test');\n\n        $cache->reset();\n\n        $this->assertSame(false, $cache->fetch('test'));\n    }\n\n    public function testResetFilesystemAdapter()\n    {\n        $pool   = new FilesystemAdapter('', 0, sys_get_temp_dir() . '/doctrine-cache-test');\n        $pool2  = new FilesystemAdapter('', 0, sys_get_temp_dir() . '/doctrine-cache-test');\n        $cache  = DoctrineProvider::wrap($pool);\n        $cache2 = DoctrineProvider::wrap($pool2);\n\n        $cache->save('test', 'test');\n        $cache->reset();\n\n        // we make sure with the next assertion the cache behave like expected and the test is not accidentally changed\n        // to use ArrayAdapter as this test scenario requires a persisted cache adapter\n        $this->assertSame('test', $cache->fetch('test'));\n\n        // the second cache instance will now remove all exist files via namespaceVersion still the first cache\n        // will receive the data until then the reset is called. the assertion after deleteAll is not required\n        // but better show why the reset is even needed when cache service is used in long-running processes.\n        $cache2->deleteAll();\n        $this->assertSame('test', $cache->fetch('test'));\n        $cache->reset();\n\n        // the previous called reset will reset the namespaceVersion and so the cache is correctly false now\n        $this->assertSame(false, $cache->fetch('test'));\n    }\n\n    protected function isSharedStorage(): bool\n    {\n        return false;\n    }\n}\n"
  },
  {
    "path": "tests/Doctrine/Tests/DoctrineTestCase.php",
    "content": "<?php\n\nnamespace Doctrine\\Tests;\n\nuse PHPUnit\\Framework\\TestCase;\n\n/**\n * Base testcase class for all Doctrine testcases.\n */\nabstract class DoctrineTestCase extends TestCase\n{\n}\n"
  },
  {
    "path": "tests/travis/php.ini",
    "content": "extension=\"apcu.so\"\nextension=\"mongodb.so\"\nextension=\"memcached.so\"\nextension=\"redis.so\"\nextension=\"couchbase.so\"\n\napc.enabled=1\napc.enable_cli=1\n"
  }
]