[
  {
    "path": ".doctrine-project.json",
    "content": "{\n    \"active\": true,\n    \"name\": \"Instantiator\",\n    \"slug\": \"instantiator\",\n    \"docsSlug\": \"doctrine-instantiator\",\n    \"versions\": [\n        {\n            \"name\": \"2.2\",\n            \"branchName\": \"2.2.x\",\n            \"slug\": \"2.2\",\n            \"upcoming\": true\n        },\n        {\n            \"name\": \"2.1\",\n            \"branchName\": \"2.1.x\",\n            \"slug\": \"2.1\",\n            \"current\": true\n        },\n        {\n            \"name\": \"2.0\",\n            \"slug\": \"2.0\",\n            \"maintained\": false\n        },\n        {\n            \"name\": \"1.5\",\n            \"slug\": \"1.5\",\n            \"maintained\": false\n        },\n        {\n            \"name\": \"1.4\",\n            \"slug\": \"1.4\",\n            \"maintained\": false\n        },\n        {\n            \"name\": \"1.3\",\n            \"slug\": \"1.3\",\n            \"maintained\": false\n        }\n    ]\n}\n"
  },
  {
    "path": ".gitattributes",
    "content": "/.github               export-ignore\n/tests                 export-ignore\n/docs                  export-ignore\n.doctrine-project.json export-ignore\n.gitattributes         export-ignore\n.gitignore             export-ignore\nphpbench.json          export-ignore\nphpcs.xml.dist         export-ignore\nphpmd.xml.dist         export-ignore\nphpstan.neon.dist      export-ignore\nphpunit.xml.dist       export-ignore\ncomposer.lock          export-ignore\n/CONTRIBUTING.md       export-ignore\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "patreon: phpdoctrine\ntidelift: packagist/doctrine%2Finstantiator\ncustom: https://www.doctrine-project.org/sponsorship.html\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      interval: \"weekly\"\n    labels:\n      - \"CI\"\n"
  },
  {
    "path": ".github/workflows/coding-standards.yml",
    "content": "\nname: \"Coding Standards\"\n\non:\n  pull_request:\n    branches:\n      - \"*.x\"\n  push:\n    branches:\n      - \"*.x\"\n\njobs:\n  coding-standards:\n    name: \"Coding Standards\"\n    uses: \"doctrine/.github/.github/workflows/coding-standards.yml@14.0.0\"\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\njobs:\n  phpunit:\n    name: \"PHPUnit\"\n    uses: \"doctrine/.github/.github/workflows/continuous-integration.yml@14.0.0\"\n    with:\n      php-versions: '[\"8.4\", \"8.5\"]'\n    secrets:\n      CODECOV_TOKEN: \"${{ secrets.CODECOV_TOKEN }}\"\n"
  },
  {
    "path": ".github/workflows/phpbench.yml",
    "content": "\nname: \"Performance benchmark\"\n\non:\n  pull_request:\n    branches:\n      - \"*.x\"\n  push:\n    branches:\n      - \"*.x\"\n\nenv:\n  fail-fast: true\n\njobs:\n  phpbench:\n    name: \"PHPBench\"\n    runs-on: \"ubuntu-22.04\"\n\n    strategy:\n      matrix:\n        php-version:\n          - \"8.4\"\n          - \"8.5\"\n\n    steps:\n      - name: \"Checkout\"\n        uses: \"actions/checkout@v6\"\n        with:\n          fetch-depth: 2\n\n      - name: \"Install PHP\"\n        uses: \"shivammathur/setup-php@v2\"\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@v4\"\n\n      - name: \"Run PHPBench\"\n        run: \"php ./vendor/bin/phpbench run --iterations=3 --warmup=1 --report=aggregate\"\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    name: \"Git tag, release & create merge-up PR\"\n    uses: \"doctrine/.github/.github/workflows/release-on-milestone-closed.yml@13.1.0\"\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": ".github/workflows/static-analysis.yml",
    "content": "\nname: \"Static Analysis\"\n\non:\n  pull_request:\n    branches:\n      - \"*.x\"\n  push:\n    branches:\n      - \"*.x\"\n\njobs:\n  static-analysis:\n    name: \"Static Analysis\"\n    uses: \"doctrine/.github/.github/workflows/phpstan.yml@14.0.0\"\n"
  },
  {
    "path": ".github/workflows/website-schema.yml",
    "content": "\nname: \"Website config validation\"\n\non:\n  pull_request:\n    branches:\n      - \"*.x\"\n    paths:\n      - \".doctrine-project.json\"\n      - \".github/workflows/website-schema.yml\"\n  push:\n    branches:\n      - \"*.x\"\n    paths:\n      - \".doctrine-project.json\"\n      - \".github/workflows/website-schema.yml\"\n\njobs:\n  json-validate:\n    name: \"Validate JSON schema\"\n    uses: \"doctrine/.github/.github/workflows/website-schema.yml@14.0.0\"\n"
  },
  {
    "path": ".gitignore",
    "content": "phpunit.xml\n/.phpunit.cache\nbuild\nvendor\n/composer.lock\ncoverage.clover\n/phpcs.xml\n/.phpcs-cache\n/phpstan.neon\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing\n\n * Follow the [Doctrine Coding Standard](https://github.com/doctrine/coding-standard)\n * The project will follow strict [object calisthenics](http://www.slideshare.net/guilhermeblanco/object-calisthenics-applied-to-php)\n * Any contribution must provide tests for additional introduced conditions\n * Any un-confirmed issue needs a failing test case before being accepted\n * Pull requests must be sent from a new hotfix/feature branch, not from `master`.\n\n## Installation\n\nTo install the project and run the tests, you need to clone it first:\n\n```sh\n$ git clone git://github.com/doctrine/instantiator.git\n```\n\nYou will then need to run a composer installation:\n\n```sh\n$ cd Instantiator\n$ curl -s https://getcomposer.org/installer | php\n$ php composer.phar update\n```\n\n## Testing\n\nThe PHPUnit version to be used is the one installed as a dev- dependency via composer:\n\n```sh\n$ ./vendor/bin/phpunit\n```\n\nAccepted coverage for new contributions is 80%. Any contribution not satisfying this requirement \nwon't be merged.\n\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright (c) 2014 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 Instantiator\n\nThis library provides a way of avoiding usage of constructors when instantiating PHP classes.\n\n[![Build Status](https://travis-ci.org/doctrine/instantiator.svg?branch=master)](https://travis-ci.org/doctrine/instantiator)\n[![Code Coverage](https://codecov.io/gh/doctrine/instantiator/branch/master/graph/badge.svg)](https://codecov.io/gh/doctrine/instantiator/branch/master)\n[![Dependency Status](https://www.versioneye.com/package/php--doctrine--instantiator/badge.svg)](https://www.versioneye.com/package/php--doctrine--instantiator)\n\n[![Latest Stable Version](https://poser.pugx.org/doctrine/instantiator/v/stable.png)](https://packagist.org/packages/doctrine/instantiator)\n[![Latest Unstable Version](https://poser.pugx.org/doctrine/instantiator/v/unstable.png)](https://packagist.org/packages/doctrine/instantiator)\n\n## Installation\n\nThe suggested installation method is via [composer](https://getcomposer.org/):\n\n```sh\ncomposer require doctrine/instantiator\n```\n\n## Usage\n\nThe instantiator is able to create new instances of any class without using the constructor or any API of the class\nitself:\n\n```php\n$instantiator = new \\Doctrine\\Instantiator\\Instantiator();\n\n$instance = $instantiator->instantiate(\\My\\ClassName\\Here::class);\n```\n\n## Contributing\n\nPlease read the [CONTRIBUTING.md](CONTRIBUTING.md) contents if you wish to help out!\n\n## Credits\n\nThis library was migrated from [ocramius/instantiator](https://github.com/Ocramius/Instantiator), which\nhas been donated to the doctrine organization, and which is now deprecated in favour of this package.\n"
  },
  {
    "path": "composer.json",
    "content": "{\n    \"name\":              \"doctrine/instantiator\",\n    \"description\":       \"A small, lightweight utility to instantiate objects in PHP without invoking their constructors\",\n    \"type\":              \"library\",\n    \"license\":           \"MIT\",\n    \"homepage\":          \"https://www.doctrine-project.org/projects/instantiator.html\",\n    \"keywords\":          [\n        \"instantiate\",\n        \"constructor\"\n    ],\n    \"authors\": [\n        {\n            \"name\":     \"Marco Pivetta\",\n            \"email\":    \"ocramius@gmail.com\",\n            \"homepage\": \"https://ocramius.github.io/\"\n        }\n    ],\n    \"require\": {\n        \"php\": \"^8.4\"\n    },\n    \"require-dev\": {\n        \"ext-phar\":                  \"*\",\n        \"ext-pdo\":                   \"*\",\n        \"doctrine/coding-standard\":  \"^14\",\n        \"phpbench/phpbench\":         \"^1.2\",\n        \"phpstan/phpstan\":           \"^2.1\",\n        \"phpstan/phpstan-phpunit\":   \"^2.0\",\n        \"phpunit/phpunit\":           \"^10.5.58\"\n    },\n    \"autoload\": {\n        \"psr-4\": {\n            \"Doctrine\\\\Instantiator\\\\\": \"src/\"\n        }\n    },\n    \"autoload-dev\": {\n        \"psr-4\": {\n            \"DoctrineTest\\\\InstantiatorPerformance\\\\\": \"tests/InstantiatorPerformance\",\n            \"DoctrineTest\\\\InstantiatorTest\\\\\": \"tests/InstantiatorTest\",\n            \"DoctrineTest\\\\InstantiatorTestAsset\\\\\": \"tests/InstantiatorTestAsset\"\n        }\n    },\n    \"config\": {\n        \"allow-plugins\": {\n            \"dealerdirect/phpcodesniffer-composer-installer\": true\n        }\n    }\n}\n"
  },
  {
    "path": "docs/en/index.rst",
    "content": "Introduction\n============\n\nThis library provides a way of avoiding usage of constructors when instantiating PHP classes.\n\nInstallation\n============\n\nThe suggested installation method is via `composer`_:\n\n.. code-block:: console\n\n   $ composer require doctrine/instantiator\n\nUsage\n=====\n\nThe instantiator is able to create new instances of any class without\nusing the constructor or any API of the class itself:\n\n.. code-block:: php\n\n    <?php\n\n    use Doctrine\\Instantiator\\Instantiator;\n    use App\\Entities\\User;\n\n    $instantiator = new Instantiator();\n\n    $user = $instantiator->instantiate(User::class);\n\nContributing\n============\n\n-  Follow the `Doctrine Coding Standard`_\n-  The project will follow strict `object calisthenics`_\n-  Any contribution must provide tests for additional introduced\n   conditions\n-  Any un-confirmed issue needs a failing test case before being\n   accepted\n-  Pull requests must be sent from a new hotfix/feature branch, not from\n   ``master``.\n\nTesting\n=======\n\nThe PHPUnit version to be used is the one installed as a dev- dependency\nvia composer:\n\n.. code-block:: console\n\n   $ ./vendor/bin/phpunit\n\nAccepted coverage for new contributions is 80%. Any contribution not\nsatisfying this requirement won’t be merged.\n\nCredits\n=======\n\nThis library was migrated from `ocramius/instantiator`_, which has been\ndonated to the doctrine organization, and which is now deprecated in\nfavour of this package.\n\n.. _composer: https://getcomposer.org/\n.. _CONTRIBUTING.md: CONTRIBUTING.md\n.. _ocramius/instantiator: https://github.com/Ocramius/Instantiator\n.. _Doctrine Coding Standard: https://github.com/doctrine/coding-standard\n.. _object calisthenics: http://www.slideshare.net/guilhermeblanco/object-calisthenics-applied-to-php\n"
  },
  {
    "path": "docs/en/sidebar.rst",
    "content": ".. toctree::\n    :depth: 3\n\n    index\n"
  },
  {
    "path": "phpbench.json",
    "content": "{\n    \"runner.bootstrap\": \"vendor/autoload.php\",\n    \"runner.path\": \"tests/InstantiatorPerformance\"\n}\n"
  },
  {
    "path": "phpcs.xml.dist",
    "content": "<?xml version=\"1.0\"?>\n<ruleset\n        xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n        xsi:noNamespaceSchemaLocation=\"vendor/squizlabs/php_codesniffer/phpcs.xsd\"\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    <!-- Ignore warnings, show progress of the run and show sniff names -->\n    <arg value=\"nps\"/>\n\n    <config name=\"php_version\" value=\"80400\"/>\n\n    <file>src</file>\n    <file>tests</file>\n\n    <rule ref=\"Doctrine\">\n        <exclude name=\"SlevomatCodingStandard.Exceptions.ReferenceThrowableOnly.ReferencedGeneralException\"/>\n    </rule>\n\n    <rule ref=\"SlevomatCodingStandard.Classes.SuperfluousAbstractClassNaming\">\n        <exclude-pattern>tests/InstantiatorTestAsset/AbstractClassAsset.php</exclude-pattern>\n    </rule>\n\n    <rule ref=\"SlevomatCodingStandard.Classes.SuperfluousExceptionNaming\">\n        <exclude-pattern>src/Exception/UnexpectedValueException.php</exclude-pattern>\n        <exclude-pattern>src/Exception/InvalidArgumentException.php</exclude-pattern>\n    </rule>\n\n    <rule ref=\"SlevomatCodingStandard.Classes.SuperfluousInterfaceNaming\">\n        <exclude-pattern>src/Exception/ExceptionInterface.php</exclude-pattern>\n        <exclude-pattern>src/InstantiatorInterface.php</exclude-pattern>\n    </rule>\n</ruleset>\n"
  },
  {
    "path": "phpmd.xml.dist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<ruleset\n    name=\"Instantiator rules\"\n    xmlns=\"http://pmd.sf.net/ruleset/1.0.0\"\n    xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n    xsi:schemaLocation=\"http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd\"\n    xsi:noNamespaceSchemaLocation=\"http://pmd.sf.net/ruleset_xml_schema.xsd\"\n>\n    <rule ref=\"rulesets/cleancode.xml\">\n        <!-- static access is used for caching purposes -->\n        <exclude name=\"StaticAccess\"/>\n    </rule>\n    <rule ref=\"rulesets/codesize.xml\"/>\n    <rule ref=\"rulesets/controversial.xml\"/>\n    <rule ref=\"rulesets/design.xml\"/>\n    <rule ref=\"rulesets/naming.xml\"/>\n    <rule ref=\"rulesets/unusedcode.xml\"/>\n    <rule\n        name=\"NPathComplexity\"\n        message=\"The {0} {1}() has an NPath complexity of {2}. The configured NPath complexity threshold is {3}.\"\n        class=\"PHP_PMD_Rule_Design_NpathComplexity\"\n    >\n        <properties>\n            <property name=\"minimum\" description=\"The npath reporting threshold\" value=\"10\"/>\n        </properties>\n    </rule>\n</ruleset>\n"
  },
  {
    "path": "phpstan.neon.dist",
    "content": "includes:\n    - vendor/phpstan/phpstan-phpunit/extension.neon\n    - vendor/phpstan/phpstan-phpunit/rules.neon\n\nparameters:\n    level: max\n    phpVersion: 80400\n    paths:\n        - src\n        - tests\n\n    ignoreErrors:\n        # PHPStan is unable to infer the return type of unserialize() in this case.\n        -\n            message: '#Method Doctrine\\\\Instantiator\\\\Instantiator\\:\\:buildFactory\\(\\) should return callable\\(\\): T but returns Closure\\(\\): mixed\\.#'\n            path: 'src/Instantiator.php'\n\n        # dynamic properties confuse static analysis\n        -\n            message: '#Access to an undefined property object::\\$foo\\.#'\n            path: 'tests/InstantiatorTest/InstantiatorTest.php'\n\n\t# The property is static, we cannot use templating here\n        -\n            message: '#instantiate\\(\\) should return#'\n            path: 'src/Instantiator.php'\n\n\t# this trait is not meant to be use'd\n        -\n            message: '#is used zero times#'\n            path: 'tests/InstantiatorTestAsset/SimpleTraitAsset.php'\n"
  },
  {
    "path": "phpunit.xml.dist",
    "content": "<?xml version=\"1.0\"?>\n<phpunit xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n    xsi:noNamespaceSchemaLocation=\"vendor/phpunit/phpunit/phpunit.xsd\"\n    bootstrap=\"./vendor/autoload.php\"\n    colors=\"true\"\n    stopOnFailure=\"false\"\n    processIsolation=\"false\"\n    backupGlobals=\"false\"\n    cacheDirectory=\".phpunit.cache\">\n    <coverage includeUncoveredFiles=\"true\"/>\n    <php>\n        <ini name=\"error_reporting\" value=\"-1\"/>\n    </php>\n\n    <testsuite name=\"Doctrine\\Instantiator tests\">\n        <directory>./tests/InstantiatorTest</directory>\n    </testsuite>\n    <source>\n        <include>\n            <directory suffix=\".php\">./src</directory>\n        </include>\n    </source>\n</phpunit>\n"
  },
  {
    "path": "src/Exception/ExceptionInterface.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Doctrine\\Instantiator\\Exception;\n\nuse Throwable;\n\n/**\n * Base exception marker interface for the instantiator component\n */\ninterface ExceptionInterface extends Throwable\n{\n}\n"
  },
  {
    "path": "src/Exception/InvalidArgumentException.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Doctrine\\Instantiator\\Exception;\n\nuse InvalidArgumentException as BaseInvalidArgumentException;\nuse ReflectionClass;\n\nuse function interface_exists;\nuse function sprintf;\nuse function trait_exists;\n\n/**\n * Exception for invalid arguments provided to the instantiator\n */\nclass InvalidArgumentException extends BaseInvalidArgumentException implements ExceptionInterface\n{\n    public static function fromNonExistingClass(string $className): self\n    {\n        if (interface_exists($className)) {\n            return new self(sprintf('The provided type \"%s\" is an interface, and cannot be instantiated', $className));\n        }\n\n        if (trait_exists($className)) {\n            return new self(sprintf('The provided type \"%s\" is a trait, and cannot be instantiated', $className));\n        }\n\n        return new self(sprintf('The provided class \"%s\" does not exist', $className));\n    }\n\n    /**\n     * @phpstan-param ReflectionClass<T> $reflectionClass\n     *\n     * @template T of object\n     */\n    public static function fromAbstractClass(ReflectionClass $reflectionClass): self\n    {\n        return new self(sprintf(\n            'The provided class \"%s\" is abstract, and cannot be instantiated',\n            $reflectionClass->getName(),\n        ));\n    }\n\n    public static function fromEnum(string $className): self\n    {\n        return new self(sprintf(\n            'The provided class \"%s\" is an enum, and cannot be instantiated',\n            $className,\n        ));\n    }\n}\n"
  },
  {
    "path": "src/Exception/UnexpectedValueException.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Doctrine\\Instantiator\\Exception;\n\nuse Exception;\nuse ReflectionClass;\nuse UnexpectedValueException as BaseUnexpectedValueException;\n\nuse function sprintf;\n\n/**\n * Exception for given parameters causing invalid/unexpected state on instantiation\n */\nclass UnexpectedValueException extends BaseUnexpectedValueException implements ExceptionInterface\n{\n    /**\n     * @phpstan-param ReflectionClass<T> $reflectionClass\n     *\n     * @template T of object\n     */\n    public static function fromSerializationTriggeredException(\n        ReflectionClass $reflectionClass,\n        Exception $exception,\n    ): self {\n        return new self(\n            sprintf(\n                'An exception was raised while trying to instantiate an instance of \"%s\" via un-serialization',\n                $reflectionClass->getName(),\n            ),\n            0,\n            $exception,\n        );\n    }\n\n    /**\n     * @phpstan-param ReflectionClass<T> $reflectionClass\n     *\n     * @template T of object\n     */\n    public static function fromUncleanUnSerialization(\n        ReflectionClass $reflectionClass,\n        string $errorString,\n        int $errorCode,\n        string $errorFile,\n        int $errorLine,\n    ): self {\n        return new self(\n            sprintf(\n                'Could not produce an instance of \"%s\" via un-serialization, since an error was triggered '\n                . 'in file \"%s\" at line \"%d\"',\n                $reflectionClass->getName(),\n                $errorFile,\n                $errorLine,\n            ),\n            0,\n            new Exception($errorString, $errorCode),\n        );\n    }\n}\n"
  },
  {
    "path": "src/Instantiator.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Doctrine\\Instantiator;\n\nuse ArrayIterator;\nuse Doctrine\\Instantiator\\Exception\\ExceptionInterface;\nuse Doctrine\\Instantiator\\Exception\\InvalidArgumentException;\nuse Doctrine\\Instantiator\\Exception\\UnexpectedValueException;\nuse Exception;\nuse ReflectionClass;\nuse ReflectionException;\nuse Serializable;\n\nuse function class_exists;\nuse function enum_exists;\nuse function is_subclass_of;\nuse function restore_error_handler;\nuse function set_error_handler;\nuse function sprintf;\nuse function strlen;\nuse function unserialize;\n\nfinal class Instantiator implements InstantiatorInterface\n{\n    /**\n     * Markers used internally by PHP to define whether {@see \\unserialize} should invoke\n     * the method {@see \\Serializable::unserialize()} when dealing with classes implementing\n     * the {@see \\Serializable} interface.\n     */\n    private const string SERIALIZATION_FORMAT_USE_UNSERIALIZER   = 'C';\n    private const string SERIALIZATION_FORMAT_AVOID_UNSERIALIZER = 'O';\n\n    /**\n     * Used to instantiate specific classes, indexed by class name.\n     *\n     * @var array<class-string, callable(): object>\n     */\n    private static array $cachedInstantiators = [];\n\n    /**\n     * Array of objects that can directly be cloned, indexed by class name.\n     *\n     * @var object[]\n     */\n    private static array $cachedCloneables = [];\n\n    /**\n     * @phpstan-param class-string<T> $className\n     *\n     * @phpstan-return T\n     *\n     * @throws ExceptionInterface\n     *\n     * @template T of object\n     */\n    public function instantiate(string $className): object\n    {\n        if (isset(self::$cachedCloneables[$className])) {\n            /** @phpstan-var T */\n            $cachedCloneable = self::$cachedCloneables[$className];\n\n            return clone $cachedCloneable;\n        }\n\n        if (isset(self::$cachedInstantiators[$className])) {\n            $factory = self::$cachedInstantiators[$className];\n\n            return $factory();\n        }\n\n        return $this->buildAndCacheFromFactory($className);\n    }\n\n    /**\n     * Builds the requested object and caches it in static properties for performance\n     *\n     * @phpstan-param class-string<T> $className\n     *\n     * @phpstan-return T\n     *\n     * @template T of object\n     */\n    private function buildAndCacheFromFactory(string $className): object\n    {\n        $factory  = self::$cachedInstantiators[$className] = $this->buildFactory($className);\n        $instance = $factory();\n\n        if ($this->isSafeToClone(new ReflectionClass($instance))) {\n            self::$cachedCloneables[$className] = clone $instance;\n        }\n\n        return $instance;\n    }\n\n    /**\n     * Builds a callable capable of instantiating the given $className without\n     * invoking its constructor.\n     *\n     * @phpstan-param class-string<T> $className\n     *\n     * @phpstan-return callable(): T\n     *\n     * @throws InvalidArgumentException\n     * @throws UnexpectedValueException\n     * @throws ReflectionException\n     *\n     * @template T of object\n     */\n    private function buildFactory(string $className): callable\n    {\n        $reflectionClass = $this->getReflectionClass($className);\n\n        if ($this->isInstantiableViaReflection($reflectionClass)) {\n            return [$reflectionClass, 'newInstanceWithoutConstructor'];\n        }\n\n        $serializedString = sprintf(\n            '%s:%d:\"%s\":0:{}',\n            is_subclass_of($className, Serializable::class) ? self::SERIALIZATION_FORMAT_USE_UNSERIALIZER : self::SERIALIZATION_FORMAT_AVOID_UNSERIALIZER,\n            strlen($className),\n            $className,\n        );\n\n        $this->checkIfUnSerializationIsSupported($reflectionClass, $serializedString);\n\n        return static fn () => unserialize($serializedString);\n    }\n\n    /**\n     * @phpstan-param class-string<T> $className\n     *\n     * @phpstan-return ReflectionClass<T>\n     *\n     * @throws InvalidArgumentException\n     * @throws ReflectionException\n     *\n     * @template T of object\n     */\n    private function getReflectionClass(string $className): ReflectionClass\n    {\n        if (! class_exists($className)) {\n            throw InvalidArgumentException::fromNonExistingClass($className);\n        }\n\n        if (enum_exists($className, false)) {\n            throw InvalidArgumentException::fromEnum($className);\n        }\n\n        $reflection = new ReflectionClass($className);\n\n        if ($reflection->isAbstract()) {\n            throw InvalidArgumentException::fromAbstractClass($reflection);\n        }\n\n        return $reflection;\n    }\n\n    /**\n     * @phpstan-param ReflectionClass<T> $reflectionClass\n     *\n     * @throws UnexpectedValueException\n     *\n     * @template T of object\n     */\n    private function checkIfUnSerializationIsSupported(ReflectionClass $reflectionClass, string $serializedString): void\n    {\n        set_error_handler(static function (int $code, string $message, string $file, int $line) use ($reflectionClass, &$error): bool {\n            $error = UnexpectedValueException::fromUncleanUnSerialization(\n                $reflectionClass,\n                $message,\n                $code,\n                $file,\n                $line,\n            );\n\n            return true;\n        });\n\n        try {\n            $this->attemptInstantiationViaUnSerialization($reflectionClass, $serializedString);\n        } finally {\n            restore_error_handler();\n        }\n\n        if ($error) {\n            throw $error;\n        }\n    }\n\n    /**\n     * @phpstan-param ReflectionClass<T> $reflectionClass\n     *\n     * @throws UnexpectedValueException\n     *\n     * @template T of object\n     */\n    private function attemptInstantiationViaUnSerialization(ReflectionClass $reflectionClass, string $serializedString): void\n    {\n        try {\n            unserialize($serializedString);\n        } catch (Exception $exception) {\n            throw UnexpectedValueException::fromSerializationTriggeredException($reflectionClass, $exception);\n        }\n    }\n\n    /**\n     * @phpstan-param ReflectionClass<T> $reflectionClass\n     *\n     * @template T of object\n     */\n    private function isInstantiableViaReflection(ReflectionClass $reflectionClass): bool\n    {\n        return ! ($this->hasInternalAncestors($reflectionClass) && $reflectionClass->isFinal());\n    }\n\n    /**\n     * Verifies whether the given class is to be considered internal\n     *\n     * @phpstan-param ReflectionClass<T> $reflectionClass\n     *\n     * @template T of object\n     */\n    private function hasInternalAncestors(ReflectionClass $reflectionClass): bool\n    {\n        do {\n            if ($reflectionClass->isInternal()) {\n                return true;\n            }\n\n            $reflectionClass = $reflectionClass->getParentClass();\n        } while ($reflectionClass);\n\n        return false;\n    }\n\n    /**\n     * Checks if a class is cloneable\n     *\n     * Classes implementing `__clone` cannot be safely cloned, as that may cause side-effects.\n     *\n     * @phpstan-param ReflectionClass<T> $reflectionClass\n     *\n     * @template T of object\n     */\n    private function isSafeToClone(ReflectionClass $reflectionClass): bool\n    {\n        return $reflectionClass->isCloneable()\n            && ! $reflectionClass->hasMethod('__clone')\n            && ! $reflectionClass->isSubclassOf(ArrayIterator::class);\n    }\n}\n"
  },
  {
    "path": "src/InstantiatorInterface.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Doctrine\\Instantiator;\n\nuse Doctrine\\Instantiator\\Exception\\ExceptionInterface;\n\n/**\n * Instantiator provides utility methods to build objects without invoking their constructors\n */\ninterface InstantiatorInterface\n{\n    /**\n     * @phpstan-param class-string<T> $className\n     *\n     * @phpstan-return T\n     *\n     * @throws ExceptionInterface\n     *\n     * @template T of object\n     */\n    public function instantiate(string $className): object;\n}\n"
  },
  {
    "path": "tests/InstantiatorPerformance/InstantiatorPerformanceBench.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorPerformance;\n\nuse ArrayObject;\nuse Doctrine\\Instantiator\\Instantiator;\nuse DoctrineTest\\InstantiatorTestAsset\\SerializableArrayObjectAsset;\nuse DoctrineTest\\InstantiatorTestAsset\\SimpleSerializableAsset;\nuse DoctrineTest\\InstantiatorTestAsset\\UnCloneableAsset;\nuse PhpBench\\Benchmark\\Metadata\\Annotations\\BeforeMethods;\nuse PhpBench\\Benchmark\\Metadata\\Annotations\\Revs;\n\n/**\n * Performance tests for {@see \\Doctrine\\Instantiator\\Instantiator}\n *\n * @BeforeMethods({\"init\"})\n */\nclass InstantiatorPerformanceBench\n{\n    private Instantiator $instantiator;\n\n    public function init(): void\n    {\n        $this->instantiator = new Instantiator();\n\n        $this->instantiator->instantiate(self::class);\n        $this->instantiator->instantiate(ArrayObject::class);\n        $this->instantiator->instantiate(SimpleSerializableAsset::class);\n        $this->instantiator->instantiate(SerializableArrayObjectAsset::class);\n        $this->instantiator->instantiate(UnCloneableAsset::class);\n    }\n\n    /** @Revs(20000) */\n    public function benchInstantiateSelf(): void\n    {\n        $this->instantiator->instantiate(self::class);\n    }\n\n    /** @Revs(20000) */\n    public function benchInstantiateInternalClass(): void\n    {\n        $this->instantiator->instantiate(ArrayObject::class);\n    }\n\n    /** @Revs(20000) */\n    public function benchInstantiateSimpleSerializableAssetClass(): void\n    {\n        $this->instantiator->instantiate(SimpleSerializableAsset::class);\n    }\n\n    /** @Revs(20000) */\n    public function benchInstantiateSerializableArrayObjectAsset(): void\n    {\n        $this->instantiator->instantiate(SerializableArrayObjectAsset::class);\n    }\n\n    /** @Revs(20000) */\n    public function benchInstantiateUnCloneableAsset(): void\n    {\n        $this->instantiator->instantiate(UnCloneableAsset::class);\n    }\n}\n"
  },
  {
    "path": "tests/InstantiatorTest/Exception/InvalidArgumentExceptionTest.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTest\\Exception;\n\nuse Doctrine\\Instantiator\\Exception\\InvalidArgumentException;\nuse Doctrine\\Instantiator\\InstantiatorInterface;\nuse DoctrineTest\\InstantiatorTestAsset\\AbstractClassAsset;\nuse DoctrineTest\\InstantiatorTestAsset\\SimpleTraitAsset;\nuse PHPUnit\\Framework\\TestCase;\nuse ReflectionClass;\n\nuse function sprintf;\nuse function str_replace;\nuse function uniqid;\n\n/**\n * Tests for {@see \\Doctrine\\Instantiator\\Exception\\InvalidArgumentException}\n *\n * @covers \\Doctrine\\Instantiator\\Exception\\InvalidArgumentException\n */\nclass InvalidArgumentExceptionTest extends TestCase\n{\n    public function testFromNonExistingTypeWithNonExistingClass(): void\n    {\n        $className = self::class . str_replace('.', '', uniqid('', true));\n        $exception = InvalidArgumentException::fromNonExistingClass($className);\n\n        self::assertSame('The provided class \"' . $className . '\" does not exist', $exception->getMessage());\n    }\n\n    public function testFromNonExistingTypeWithTrait(): void\n    {\n        $exception = InvalidArgumentException::fromNonExistingClass(SimpleTraitAsset::class);\n\n        self::assertSame(\n            sprintf('The provided type \"%s\" is a trait, and cannot be instantiated', SimpleTraitAsset::class),\n            $exception->getMessage(),\n        );\n    }\n\n    public function testFromNonExistingTypeWithInterface(): void\n    {\n        $exception = InvalidArgumentException::fromNonExistingClass(InstantiatorInterface::class);\n\n        self::assertSame(\n            sprintf(\n                'The provided type \"%s\" is an interface, and cannot be instantiated',\n                InstantiatorInterface::class,\n            ),\n            $exception->getMessage(),\n        );\n    }\n\n    public function testFromAbstractClass(): void\n    {\n        $reflection = new ReflectionClass(AbstractClassAsset::class);\n        $exception  = InvalidArgumentException::fromAbstractClass($reflection);\n\n        self::assertSame(\n            sprintf(\n                'The provided class \"%s\" is abstract, and cannot be instantiated',\n                AbstractClassAsset::class,\n            ),\n            $exception->getMessage(),\n        );\n    }\n}\n"
  },
  {
    "path": "tests/InstantiatorTest/Exception/UnexpectedValueExceptionTest.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTest\\Exception;\n\nuse Doctrine\\Instantiator\\Exception\\UnexpectedValueException;\nuse DoctrineTest\\InstantiatorTestAsset\\AbstractClassAsset;\nuse Exception;\nuse PHPUnit\\Framework\\TestCase;\nuse ReflectionClass;\n\nuse function sprintf;\n\n/**\n * Tests for {@see \\Doctrine\\Instantiator\\Exception\\UnexpectedValueException}\n *\n * @covers \\Doctrine\\Instantiator\\Exception\\UnexpectedValueException\n */\nclass UnexpectedValueExceptionTest extends TestCase\n{\n    public function testFromSerializationTriggeredException(): void\n    {\n        $reflectionClass = new ReflectionClass($this);\n        $previous        = new Exception();\n        $exception       = UnexpectedValueException::fromSerializationTriggeredException($reflectionClass, $previous);\n\n        self::assertSame($previous, $exception->getPrevious());\n        self::assertSame(\n            'An exception was raised while trying to instantiate an instance of \"'\n            . self::class . '\" via un-serialization',\n            $exception->getMessage(),\n        );\n    }\n\n    public function testFromUncleanUnSerialization(): void\n    {\n        $reflection = new ReflectionClass(AbstractClassAsset::class);\n        $exception  = UnexpectedValueException::fromUncleanUnSerialization($reflection, 'foo', 123, 'bar', 456);\n\n        self::assertSame(\n            sprintf(\n                'Could not produce an instance of \"%s\" '\n                . 'via un-serialization, since an error was triggered in file \"bar\" at line \"456\"',\n                AbstractClassAsset::class,\n            ),\n            $exception->getMessage(),\n        );\n\n        $previous = $exception->getPrevious();\n\n        self::assertInstanceOf(Exception::class, $previous);\n        self::assertSame('foo', $previous->getMessage());\n        self::assertSame(123, $previous->getCode());\n    }\n}\n"
  },
  {
    "path": "tests/InstantiatorTest/InstantiatorTest.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTest;\n\nuse ArrayObject;\nuse Doctrine\\Instantiator\\Exception\\InvalidArgumentException;\nuse Doctrine\\Instantiator\\Exception\\UnexpectedValueException;\nuse Doctrine\\Instantiator\\Instantiator;\nuse Doctrine\\Instantiator\\InstantiatorInterface;\nuse DoctrineTest\\InstantiatorTestAsset\\AbstractClassAsset;\nuse DoctrineTest\\InstantiatorTestAsset\\ArrayObjectAsset;\nuse DoctrineTest\\InstantiatorTestAsset\\ExceptionAsset;\nuse DoctrineTest\\InstantiatorTestAsset\\FinalExceptionAsset;\nuse DoctrineTest\\InstantiatorTestAsset\\PharExceptionAsset;\nuse DoctrineTest\\InstantiatorTestAsset\\SerializableArrayObjectAsset;\nuse DoctrineTest\\InstantiatorTestAsset\\SerializableFinalInternalChildAsset;\nuse DoctrineTest\\InstantiatorTestAsset\\SimpleEnumAsset;\nuse DoctrineTest\\InstantiatorTestAsset\\SimpleSerializableAsset;\nuse DoctrineTest\\InstantiatorTestAsset\\SimpleTraitAsset;\nuse DoctrineTest\\InstantiatorTestAsset\\UnCloneableAsset;\nuse DoctrineTest\\InstantiatorTestAsset\\UnserializeExceptionArrayObjectAsset;\nuse DoctrineTest\\InstantiatorTestAsset\\WakeUpNoticesAsset;\nuse DoctrineTest\\InstantiatorTestAsset\\XMLReaderAsset;\nuse Exception;\nuse Generator;\nuse PDORow;\nuse PharException;\nuse PHPUnit\\Framework\\TestCase;\nuse stdClass;\n\nuse function str_replace;\nuse function uniqid;\n\n/**\n * Tests for {@see \\Doctrine\\Instantiator\\Instantiator}\n *\n * @covers \\Doctrine\\Instantiator\\Instantiator\n */\nclass InstantiatorTest extends TestCase\n{\n    private Instantiator $instantiator;\n\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->instantiator = new Instantiator();\n    }\n\n    /**\n     * @phpstan-param class-string $className\n     *\n     * @dataProvider getInstantiableClasses\n     */\n    public function testCanInstantiate(string $className): void\n    {\n        self::assertInstanceOf($className, $this->instantiator->instantiate($className));\n    }\n\n    /**\n     * @phpstan-param class-string $className\n     *\n     * @dataProvider getInstantiableClasses\n     */\n    public function testInstantiatesSeparateInstances(string $className): void\n    {\n        $instance1 = $this->instantiator->instantiate($className);\n        $instance2 = $this->instantiator->instantiate($className);\n\n        self::assertEquals($instance1, $instance2);\n        self::assertNotSame($instance1, $instance2);\n    }\n\n    public function testExceptionOnUnSerializationException(): void\n    {\n        $this->expectException(UnexpectedValueException::class);\n\n        $this->instantiator->instantiate(PDORow::class);\n    }\n\n    /**\n     * @phpstan-param class-string $invalidClassName\n     *\n     * @dataProvider getInvalidClassNames\n     */\n    public function testInstantiationFromNonExistingClass(string $invalidClassName): void\n    {\n        $this->expectException(InvalidArgumentException::class);\n\n        $this->instantiator->instantiate($invalidClassName);\n    }\n\n    public function testInstancesAreNotCloned(): void\n    {\n        $namespace = __NAMESPACE__;\n        $className = 'TemporaryClass' . str_replace('.', '', uniqid('', true));\n\n        eval(<<< PHP\nnamespace $namespace;\n#[\\AllowDynamicProperties]\nclass $className {}\nPHP\n        );\n\n        /** @phpstan-var class-string */\n        $classNameWithNamespace = $namespace . '\\\\' . $className;\n\n        $instance = $this->instantiator->instantiate($classNameWithNamespace);\n\n        $instance->foo = 'bar';\n\n        $instance2 = $this->instantiator->instantiate($classNameWithNamespace);\n\n        self::assertObjectNotHasProperty('foo', $instance2);\n    }\n\n    /**\n     * Provides a list of instantiable classes (existing)\n     *\n     * @return string[][]\n     * @phpstan-return list<array{class-string}>\n     */\n    public static function getInstantiableClasses(): array\n    {\n        return [\n            [stdClass::class],\n            [self::class],\n            [Instantiator::class],\n            [Exception::class],\n            [PharException::class],\n            [SimpleSerializableAsset::class],\n            [ExceptionAsset::class],\n            [FinalExceptionAsset::class],\n            [PharExceptionAsset::class],\n            [UnCloneableAsset::class],\n            [XMLReaderAsset::class],\n            [PharException::class],\n            [ArrayObject::class],\n            [ArrayObjectAsset::class],\n            [SerializableArrayObjectAsset::class],\n            [WakeUpNoticesAsset::class],\n            [UnserializeExceptionArrayObjectAsset::class],\n            [SerializableFinalInternalChildAsset::class],\n        ];\n    }\n\n    /**\n     * Provides a list of instantiable classes (existing)\n     *\n     * @return Generator<string, array{string}>\n     */\n    public static function getInvalidClassNames(): Generator\n    {\n        yield 'invalid string' => [self::class . str_replace('.', '', uniqid('', true))];\n        yield 'interface' => [InstantiatorInterface::class];\n        yield 'abstract class' => [AbstractClassAsset::class];\n        yield 'trait' => [SimpleTraitAsset::class];\n        yield 'enum' => [SimpleEnumAsset::class];\n    }\n}\n"
  },
  {
    "path": "tests/InstantiatorTestAsset/AbstractClassAsset.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTestAsset;\n\n/**\n * A simple asset for an abstract class\n */\nabstract class AbstractClassAsset\n{\n}\n"
  },
  {
    "path": "tests/InstantiatorTestAsset/ArrayObjectAsset.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTestAsset;\n\nuse ArrayObject;\nuse BadMethodCallException;\n\n/**\n * Test asset that extends an internal PHP class\n *\n * @template TValue\n * @template-extends ArrayObject<int, TValue>\n */\nclass ArrayObjectAsset extends ArrayObject\n{\n    /**\n     * Constructor - should not be called\n     *\n     * @throws BadMethodCallException\n     */\n    public function __construct()\n    {\n        throw new BadMethodCallException('Not supposed to be called!');\n    }\n}\n"
  },
  {
    "path": "tests/InstantiatorTestAsset/ExceptionAsset.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTestAsset;\n\nuse BadMethodCallException;\nuse Exception;\n\n/**\n * Test asset that extends an internal PHP base exception\n */\nclass ExceptionAsset extends Exception\n{\n    /**\n     * Constructor - should not be called\n     *\n     * @throws BadMethodCallException\n     */\n    public function __construct()\n    {\n        throw new BadMethodCallException('Not supposed to be called!');\n    }\n}\n"
  },
  {
    "path": "tests/InstantiatorTestAsset/FinalExceptionAsset.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTestAsset;\n\nuse BadMethodCallException;\nuse Exception;\n\n/**\n * Test asset that extends an internal PHP base exception\n */\nfinal class FinalExceptionAsset extends Exception\n{\n    /**\n     * Constructor - should not be called\n     *\n     * @throws BadMethodCallException\n     */\n    public function __construct()\n    {\n        throw new BadMethodCallException('Not supposed to be called!');\n    }\n}\n"
  },
  {
    "path": "tests/InstantiatorTestAsset/PharAsset.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTestAsset;\n\nuse BadMethodCallException;\nuse Phar;\n\n/**\n * Test asset that extends an internal PHP class\n */\nclass PharAsset extends Phar\n{\n    /**\n     * Constructor - should not be called\n     *\n     * @throws BadMethodCallException\n     */\n    public function __construct()\n    {\n        throw new BadMethodCallException('Not supposed to be called!');\n    }\n}\n"
  },
  {
    "path": "tests/InstantiatorTestAsset/PharExceptionAsset.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTestAsset;\n\nuse BadMethodCallException;\nuse PharException;\n\n/**\n * Test asset that extends an internal PHP class\n * This class should be serializable without problems\n * and without getting the \"Erroneous data format for unserializing\"\n * error\n */\nclass PharExceptionAsset extends PharException\n{\n    /**\n     * Constructor - should not be called\n     *\n     * @throws BadMethodCallException\n     */\n    public function __construct()\n    {\n        throw new BadMethodCallException('Not supposed to be called!');\n    }\n}\n"
  },
  {
    "path": "tests/InstantiatorTestAsset/SerializableArrayObjectAsset.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTestAsset;\n\nuse ArrayObject;\nuse BadMethodCallException;\nuse Serializable;\n\n/**\n * Serializable test asset that also extends an internal class\n *\n * @template TValue\n * @template-extends ArrayObject<int, TValue>\n */\nclass SerializableArrayObjectAsset extends ArrayObject implements Serializable\n{\n    /**\n     * Constructor - should not be called\n     *\n     * @throws BadMethodCallException\n     */\n    public function __construct()\n    {\n        throw new BadMethodCallException('Not supposed to be called!');\n    }\n\n    /**\n     * {@inheritDoc}\n     *\n     * Should not be called\n     *\n     * @throws BadMethodCallException\n     */\n    public function unserialize($serialized): void\n    {\n        throw new BadMethodCallException('Not supposed to be called!');\n    }\n\n    /** @param mixed[] $data */\n    public function __unserialize(array $data): void\n    {\n        throw new BadMethodCallException('Not supposed to be called!');\n    }\n}\n"
  },
  {
    "path": "tests/InstantiatorTestAsset/SerializableFinalInternalChildAsset.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTestAsset;\n\nuse ArrayIterator;\n\n/**\n * @template TValue\n * @template-extends ArrayIterator<int, TValue>\n */\nfinal class SerializableFinalInternalChildAsset extends ArrayIterator\n{\n}\n"
  },
  {
    "path": "tests/InstantiatorTestAsset/SimpleEnumAsset.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTestAsset;\n\nenum SimpleEnumAsset\n{\n    case Foo;\n    case Bar;\n}\n"
  },
  {
    "path": "tests/InstantiatorTestAsset/SimpleSerializableAsset.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTestAsset;\n\nuse BadMethodCallException;\nuse Serializable;\n\n/**\n * Base serializable test asset\n */\nclass SimpleSerializableAsset implements Serializable\n{\n    /**\n     * Constructor - should not be called\n     *\n     * @throws BadMethodCallException\n     */\n    public function __construct()\n    {\n        throw new BadMethodCallException('Not supposed to be called!');\n    }\n\n    public function serialize(): string\n    {\n        return '';\n    }\n\n    /**\n     * {@inheritDoc}\n     *\n     * Should not be called\n     *\n     * @throws BadMethodCallException\n     */\n    public function unserialize(string $serialized): void\n    {\n        throw new BadMethodCallException('Not supposed to be called!');\n    }\n\n    /** @return mixed[] */\n    public function __serialize(): array\n    {\n        return [];\n    }\n\n    /** @param mixed[] $data */\n    public function __unserialize(array $data): void\n    {\n        throw new BadMethodCallException('Not supposed to be called!');\n    }\n}\n"
  },
  {
    "path": "tests/InstantiatorTestAsset/SimpleTraitAsset.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTestAsset;\n\n/**\n * A simple trait with no attached logic\n */\ntrait SimpleTraitAsset\n{\n}\n"
  },
  {
    "path": "tests/InstantiatorTestAsset/UnCloneableAsset.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTestAsset;\n\nuse BadMethodCallException;\n\n/**\n * Base un-cloneable asset\n */\nclass UnCloneableAsset\n{\n    /**\n     * Constructor - should not be called\n     *\n     * @throws BadMethodCallException\n     */\n    public function __construct()\n    {\n        throw new BadMethodCallException('Not supposed to be called!');\n    }\n\n    /**\n     * Magic `__clone` - should not be invoked\n     *\n     * @throws BadMethodCallException\n     */\n    public function __clone()\n    {\n        throw new BadMethodCallException('Not supposed to be called!');\n    }\n}\n"
  },
  {
    "path": "tests/InstantiatorTestAsset/UnserializeExceptionArrayObjectAsset.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTestAsset;\n\nuse ArrayObject;\nuse BadMethodCallException;\n\n/**\n * A simple asset for an abstract class\n *\n * @template TValue\n * @template-extends ArrayObject<int, TValue>\n */\nclass UnserializeExceptionArrayObjectAsset extends ArrayObject\n{\n    /**\n     * {@inheritDoc}\n     */\n    public function __wakeup()\n    {\n        throw new BadMethodCallException();\n    }\n}\n"
  },
  {
    "path": "tests/InstantiatorTestAsset/WakeUpNoticesAsset.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTestAsset;\n\nuse ArrayObject;\n\nuse function trigger_error;\n\n/**\n * A simple asset for an abstract class\n *\n * @template TValue\n * @template-extends ArrayObject<int, TValue>\n */\nclass WakeUpNoticesAsset extends ArrayObject\n{\n    /**\n     * Wakeup method called after un-serialization\n     */\n    public function __wakeup(): void\n    {\n        trigger_error('Something went bananas while un-serializing this instance');\n    }\n}\n"
  },
  {
    "path": "tests/InstantiatorTestAsset/XMLReaderAsset.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTestAsset;\n\nuse BadMethodCallException;\nuse XMLReader;\n\n/**\n * Test asset that extends an internal PHP class\n */\nclass XMLReaderAsset extends XMLReader\n{\n    /**\n     * Constructor - should not be called\n     *\n     * @throws BadMethodCallException\n     */\n    public function __construct()\n    {\n        throw new BadMethodCallException('Not supposed to be called!');\n    }\n}\n"
  }
]