Repository: doctrine/instantiator
Branch: 2.1.x
Commit: eede1167376e
Files: 46
Total size: 44.1 KB
Directory structure:
gitextract_gga815b3/
├── .doctrine-project.json
├── .gitattributes
├── .github/
│ ├── FUNDING.yml
│ ├── dependabot.yml
│ └── workflows/
│ ├── coding-standards.yml
│ ├── continuous-integration.yml
│ ├── phpbench.yml
│ ├── release-on-milestone-closed.yml
│ ├── static-analysis.yml
│ └── website-schema.yml
├── .gitignore
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── composer.json
├── docs/
│ └── en/
│ ├── index.rst
│ └── sidebar.rst
├── phpbench.json
├── phpcs.xml.dist
├── phpmd.xml.dist
├── phpstan.neon.dist
├── phpunit.xml.dist
├── src/
│ ├── Exception/
│ │ ├── ExceptionInterface.php
│ │ ├── InvalidArgumentException.php
│ │ └── UnexpectedValueException.php
│ ├── Instantiator.php
│ └── InstantiatorInterface.php
└── tests/
├── InstantiatorPerformance/
│ └── InstantiatorPerformanceBench.php
├── InstantiatorTest/
│ ├── Exception/
│ │ ├── InvalidArgumentExceptionTest.php
│ │ └── UnexpectedValueExceptionTest.php
│ └── InstantiatorTest.php
└── InstantiatorTestAsset/
├── AbstractClassAsset.php
├── ArrayObjectAsset.php
├── ExceptionAsset.php
├── FinalExceptionAsset.php
├── PharAsset.php
├── PharExceptionAsset.php
├── SerializableArrayObjectAsset.php
├── SerializableFinalInternalChildAsset.php
├── SimpleEnumAsset.php
├── SimpleSerializableAsset.php
├── SimpleTraitAsset.php
├── UnCloneableAsset.php
├── UnserializeExceptionArrayObjectAsset.php
├── WakeUpNoticesAsset.php
└── XMLReaderAsset.php
================================================
FILE CONTENTS
================================================
================================================
FILE: .doctrine-project.json
================================================
{
"active": true,
"name": "Instantiator",
"slug": "instantiator",
"docsSlug": "doctrine-instantiator",
"versions": [
{
"name": "2.2",
"branchName": "2.2.x",
"slug": "2.2",
"upcoming": true
},
{
"name": "2.1",
"branchName": "2.1.x",
"slug": "2.1",
"current": true
},
{
"name": "2.0",
"slug": "2.0",
"maintained": false
},
{
"name": "1.5",
"slug": "1.5",
"maintained": false
},
{
"name": "1.4",
"slug": "1.4",
"maintained": false
},
{
"name": "1.3",
"slug": "1.3",
"maintained": false
}
]
}
================================================
FILE: .gitattributes
================================================
/.github export-ignore
/tests export-ignore
/docs export-ignore
.doctrine-project.json export-ignore
.gitattributes export-ignore
.gitignore export-ignore
phpbench.json export-ignore
phpcs.xml.dist export-ignore
phpmd.xml.dist export-ignore
phpstan.neon.dist export-ignore
phpunit.xml.dist export-ignore
composer.lock export-ignore
/CONTRIBUTING.md export-ignore
================================================
FILE: .github/FUNDING.yml
================================================
patreon: phpdoctrine
tidelift: packagist/doctrine%2Finstantiator
custom: https://www.doctrine-project.org/sponsorship.html
================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
labels:
- "CI"
================================================
FILE: .github/workflows/coding-standards.yml
================================================
name: "Coding Standards"
on:
pull_request:
branches:
- "*.x"
push:
branches:
- "*.x"
jobs:
coding-standards:
name: "Coding Standards"
uses: "doctrine/.github/.github/workflows/coding-standards.yml@14.0.0"
================================================
FILE: .github/workflows/continuous-integration.yml
================================================
name: "Continuous Integration"
on:
pull_request:
branches:
- "*.x"
push:
branches:
- "*.x"
jobs:
phpunit:
name: "PHPUnit"
uses: "doctrine/.github/.github/workflows/continuous-integration.yml@14.0.0"
with:
php-versions: '["8.4", "8.5"]'
secrets:
CODECOV_TOKEN: "${{ secrets.CODECOV_TOKEN }}"
================================================
FILE: .github/workflows/phpbench.yml
================================================
name: "Performance benchmark"
on:
pull_request:
branches:
- "*.x"
push:
branches:
- "*.x"
env:
fail-fast: true
jobs:
phpbench:
name: "PHPBench"
runs-on: "ubuntu-22.04"
strategy:
matrix:
php-version:
- "8.4"
- "8.5"
steps:
- name: "Checkout"
uses: "actions/checkout@v6"
with:
fetch-depth: 2
- name: "Install PHP"
uses: "shivammathur/setup-php@v2"
with:
php-version: "${{ matrix.php-version }}"
coverage: "pcov"
ini-values: "zend.assertions=1"
- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v4"
- name: "Run PHPBench"
run: "php ./vendor/bin/phpbench run --iterations=3 --warmup=1 --report=aggregate"
================================================
FILE: .github/workflows/release-on-milestone-closed.yml
================================================
name: "Automatic Releases"
on:
milestone:
types:
- "closed"
jobs:
release:
name: "Git tag, release & create merge-up PR"
uses: "doctrine/.github/.github/workflows/release-on-milestone-closed.yml@13.1.0"
secrets:
GIT_AUTHOR_EMAIL: ${{ secrets.GIT_AUTHOR_EMAIL }}
GIT_AUTHOR_NAME: ${{ secrets.GIT_AUTHOR_NAME }}
ORGANIZATION_ADMIN_TOKEN: ${{ secrets.ORGANIZATION_ADMIN_TOKEN }}
SIGNING_SECRET_KEY: ${{ secrets.SIGNING_SECRET_KEY }}
================================================
FILE: .github/workflows/static-analysis.yml
================================================
name: "Static Analysis"
on:
pull_request:
branches:
- "*.x"
push:
branches:
- "*.x"
jobs:
static-analysis:
name: "Static Analysis"
uses: "doctrine/.github/.github/workflows/phpstan.yml@14.0.0"
================================================
FILE: .github/workflows/website-schema.yml
================================================
name: "Website config validation"
on:
pull_request:
branches:
- "*.x"
paths:
- ".doctrine-project.json"
- ".github/workflows/website-schema.yml"
push:
branches:
- "*.x"
paths:
- ".doctrine-project.json"
- ".github/workflows/website-schema.yml"
jobs:
json-validate:
name: "Validate JSON schema"
uses: "doctrine/.github/.github/workflows/website-schema.yml@14.0.0"
================================================
FILE: .gitignore
================================================
phpunit.xml
/.phpunit.cache
build
vendor
/composer.lock
coverage.clover
/phpcs.xml
/.phpcs-cache
/phpstan.neon
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing
* Follow the [Doctrine Coding Standard](https://github.com/doctrine/coding-standard)
* The project will follow strict [object calisthenics](http://www.slideshare.net/guilhermeblanco/object-calisthenics-applied-to-php)
* Any contribution must provide tests for additional introduced conditions
* Any un-confirmed issue needs a failing test case before being accepted
* Pull requests must be sent from a new hotfix/feature branch, not from `master`.
## Installation
To install the project and run the tests, you need to clone it first:
```sh
$ git clone git://github.com/doctrine/instantiator.git
```
You will then need to run a composer installation:
```sh
$ cd Instantiator
$ curl -s https://getcomposer.org/installer | php
$ php composer.phar update
```
## Testing
The PHPUnit version to be used is the one installed as a dev- dependency via composer:
```sh
$ ./vendor/bin/phpunit
```
Accepted coverage for new contributions is 80%. Any contribution not satisfying this requirement
won't be merged.
================================================
FILE: LICENSE
================================================
Copyright (c) 2014 Doctrine Project
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# Doctrine Instantiator
This library provides a way of avoiding usage of constructors when instantiating PHP classes.
[](https://travis-ci.org/doctrine/instantiator)
[](https://codecov.io/gh/doctrine/instantiator/branch/master)
[](https://www.versioneye.com/package/php--doctrine--instantiator)
[](https://packagist.org/packages/doctrine/instantiator)
[](https://packagist.org/packages/doctrine/instantiator)
## Installation
The suggested installation method is via [composer](https://getcomposer.org/):
```sh
composer require doctrine/instantiator
```
## Usage
The instantiator is able to create new instances of any class without using the constructor or any API of the class
itself:
```php
$instantiator = new \Doctrine\Instantiator\Instantiator();
$instance = $instantiator->instantiate(\My\ClassName\Here::class);
```
## Contributing
Please read the [CONTRIBUTING.md](CONTRIBUTING.md) contents if you wish to help out!
## Credits
This library was migrated from [ocramius/instantiator](https://github.com/Ocramius/Instantiator), which
has been donated to the doctrine organization, and which is now deprecated in favour of this package.
================================================
FILE: composer.json
================================================
{
"name": "doctrine/instantiator",
"description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
"type": "library",
"license": "MIT",
"homepage": "https://www.doctrine-project.org/projects/instantiator.html",
"keywords": [
"instantiate",
"constructor"
],
"authors": [
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com",
"homepage": "https://ocramius.github.io/"
}
],
"require": {
"php": "^8.4"
},
"require-dev": {
"ext-phar": "*",
"ext-pdo": "*",
"doctrine/coding-standard": "^14",
"phpbench/phpbench": "^1.2",
"phpstan/phpstan": "^2.1",
"phpstan/phpstan-phpunit": "^2.0",
"phpunit/phpunit": "^10.5.58"
},
"autoload": {
"psr-4": {
"Doctrine\\Instantiator\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"DoctrineTest\\InstantiatorPerformance\\": "tests/InstantiatorPerformance",
"DoctrineTest\\InstantiatorTest\\": "tests/InstantiatorTest",
"DoctrineTest\\InstantiatorTestAsset\\": "tests/InstantiatorTestAsset"
}
},
"config": {
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
}
}
================================================
FILE: docs/en/index.rst
================================================
Introduction
============
This library provides a way of avoiding usage of constructors when instantiating PHP classes.
Installation
============
The suggested installation method is via `composer`_:
.. code-block:: console
$ composer require doctrine/instantiator
Usage
=====
The instantiator is able to create new instances of any class without
using the constructor or any API of the class itself:
.. code-block:: php
<?php
use Doctrine\Instantiator\Instantiator;
use App\Entities\User;
$instantiator = new Instantiator();
$user = $instantiator->instantiate(User::class);
Contributing
============
- Follow the `Doctrine Coding Standard`_
- The project will follow strict `object calisthenics`_
- Any contribution must provide tests for additional introduced
conditions
- Any un-confirmed issue needs a failing test case before being
accepted
- Pull requests must be sent from a new hotfix/feature branch, not from
``master``.
Testing
=======
The PHPUnit version to be used is the one installed as a dev- dependency
via composer:
.. code-block:: console
$ ./vendor/bin/phpunit
Accepted coverage for new contributions is 80%. Any contribution not
satisfying this requirement won’t be merged.
Credits
=======
This library was migrated from `ocramius/instantiator`_, which has been
donated to the doctrine organization, and which is now deprecated in
favour of this package.
.. _composer: https://getcomposer.org/
.. _CONTRIBUTING.md: CONTRIBUTING.md
.. _ocramius/instantiator: https://github.com/Ocramius/Instantiator
.. _Doctrine Coding Standard: https://github.com/doctrine/coding-standard
.. _object calisthenics: http://www.slideshare.net/guilhermeblanco/object-calisthenics-applied-to-php
================================================
FILE: docs/en/sidebar.rst
================================================
.. toctree::
:depth: 3
index
================================================
FILE: phpbench.json
================================================
{
"runner.bootstrap": "vendor/autoload.php",
"runner.path": "tests/InstantiatorPerformance"
}
================================================
FILE: phpcs.xml.dist
================================================
<?xml version="1.0"?>
<ruleset
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/squizlabs/php_codesniffer/phpcs.xsd"
>
<arg name="basepath" value="."/>
<arg name="extensions" value="php"/>
<arg name="parallel" value="80"/>
<arg name="cache" value=".phpcs-cache"/>
<arg name="colors"/>
<!-- Ignore warnings, show progress of the run and show sniff names -->
<arg value="nps"/>
<config name="php_version" value="80400"/>
<file>src</file>
<file>tests</file>
<rule ref="Doctrine">
<exclude name="SlevomatCodingStandard.Exceptions.ReferenceThrowableOnly.ReferencedGeneralException"/>
</rule>
<rule ref="SlevomatCodingStandard.Classes.SuperfluousAbstractClassNaming">
<exclude-pattern>tests/InstantiatorTestAsset/AbstractClassAsset.php</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.Classes.SuperfluousExceptionNaming">
<exclude-pattern>src/Exception/UnexpectedValueException.php</exclude-pattern>
<exclude-pattern>src/Exception/InvalidArgumentException.php</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.Classes.SuperfluousInterfaceNaming">
<exclude-pattern>src/Exception/ExceptionInterface.php</exclude-pattern>
<exclude-pattern>src/InstantiatorInterface.php</exclude-pattern>
</rule>
</ruleset>
================================================
FILE: phpmd.xml.dist
================================================
<?xml version="1.0" encoding="UTF-8" ?>
<ruleset
name="Instantiator rules"
xmlns="http://pmd.sf.net/ruleset/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd"
>
<rule ref="rulesets/cleancode.xml">
<!-- static access is used for caching purposes -->
<exclude name="StaticAccess"/>
</rule>
<rule ref="rulesets/codesize.xml"/>
<rule ref="rulesets/controversial.xml"/>
<rule ref="rulesets/design.xml"/>
<rule ref="rulesets/naming.xml"/>
<rule ref="rulesets/unusedcode.xml"/>
<rule
name="NPathComplexity"
message="The {0} {1}() has an NPath complexity of {2}. The configured NPath complexity threshold is {3}."
class="PHP_PMD_Rule_Design_NpathComplexity"
>
<properties>
<property name="minimum" description="The npath reporting threshold" value="10"/>
</properties>
</rule>
</ruleset>
================================================
FILE: phpstan.neon.dist
================================================
includes:
- vendor/phpstan/phpstan-phpunit/extension.neon
- vendor/phpstan/phpstan-phpunit/rules.neon
parameters:
level: max
phpVersion: 80400
paths:
- src
- tests
ignoreErrors:
# PHPStan is unable to infer the return type of unserialize() in this case.
-
message: '#Method Doctrine\\Instantiator\\Instantiator\:\:buildFactory\(\) should return callable\(\): T but returns Closure\(\): mixed\.#'
path: 'src/Instantiator.php'
# dynamic properties confuse static analysis
-
message: '#Access to an undefined property object::\$foo\.#'
path: 'tests/InstantiatorTest/InstantiatorTest.php'
# The property is static, we cannot use templating here
-
message: '#instantiate\(\) should return#'
path: 'src/Instantiator.php'
# this trait is not meant to be use'd
-
message: '#is used zero times#'
path: 'tests/InstantiatorTestAsset/SimpleTraitAsset.php'
================================================
FILE: phpunit.xml.dist
================================================
<?xml version="1.0"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="./vendor/autoload.php"
colors="true"
stopOnFailure="false"
processIsolation="false"
backupGlobals="false"
cacheDirectory=".phpunit.cache">
<coverage includeUncoveredFiles="true"/>
<php>
<ini name="error_reporting" value="-1"/>
</php>
<testsuite name="Doctrine\Instantiator tests">
<directory>./tests/InstantiatorTest</directory>
</testsuite>
<source>
<include>
<directory suffix=".php">./src</directory>
</include>
</source>
</phpunit>
================================================
FILE: src/Exception/ExceptionInterface.php
================================================
<?php
declare(strict_types=1);
namespace Doctrine\Instantiator\Exception;
use Throwable;
/**
* Base exception marker interface for the instantiator component
*/
interface ExceptionInterface extends Throwable
{
}
================================================
FILE: src/Exception/InvalidArgumentException.php
================================================
<?php
declare(strict_types=1);
namespace Doctrine\Instantiator\Exception;
use InvalidArgumentException as BaseInvalidArgumentException;
use ReflectionClass;
use function interface_exists;
use function sprintf;
use function trait_exists;
/**
* Exception for invalid arguments provided to the instantiator
*/
class InvalidArgumentException extends BaseInvalidArgumentException implements ExceptionInterface
{
public static function fromNonExistingClass(string $className): self
{
if (interface_exists($className)) {
return new self(sprintf('The provided type "%s" is an interface, and cannot be instantiated', $className));
}
if (trait_exists($className)) {
return new self(sprintf('The provided type "%s" is a trait, and cannot be instantiated', $className));
}
return new self(sprintf('The provided class "%s" does not exist', $className));
}
/**
* @phpstan-param ReflectionClass<T> $reflectionClass
*
* @template T of object
*/
public static function fromAbstractClass(ReflectionClass $reflectionClass): self
{
return new self(sprintf(
'The provided class "%s" is abstract, and cannot be instantiated',
$reflectionClass->getName(),
));
}
public static function fromEnum(string $className): self
{
return new self(sprintf(
'The provided class "%s" is an enum, and cannot be instantiated',
$className,
));
}
}
================================================
FILE: src/Exception/UnexpectedValueException.php
================================================
<?php
declare(strict_types=1);
namespace Doctrine\Instantiator\Exception;
use Exception;
use ReflectionClass;
use UnexpectedValueException as BaseUnexpectedValueException;
use function sprintf;
/**
* Exception for given parameters causing invalid/unexpected state on instantiation
*/
class UnexpectedValueException extends BaseUnexpectedValueException implements ExceptionInterface
{
/**
* @phpstan-param ReflectionClass<T> $reflectionClass
*
* @template T of object
*/
public static function fromSerializationTriggeredException(
ReflectionClass $reflectionClass,
Exception $exception,
): self {
return new self(
sprintf(
'An exception was raised while trying to instantiate an instance of "%s" via un-serialization',
$reflectionClass->getName(),
),
0,
$exception,
);
}
/**
* @phpstan-param ReflectionClass<T> $reflectionClass
*
* @template T of object
*/
public static function fromUncleanUnSerialization(
ReflectionClass $reflectionClass,
string $errorString,
int $errorCode,
string $errorFile,
int $errorLine,
): self {
return new self(
sprintf(
'Could not produce an instance of "%s" via un-serialization, since an error was triggered '
. 'in file "%s" at line "%d"',
$reflectionClass->getName(),
$errorFile,
$errorLine,
),
0,
new Exception($errorString, $errorCode),
);
}
}
================================================
FILE: src/Instantiator.php
================================================
<?php
declare(strict_types=1);
namespace Doctrine\Instantiator;
use ArrayIterator;
use Doctrine\Instantiator\Exception\ExceptionInterface;
use Doctrine\Instantiator\Exception\InvalidArgumentException;
use Doctrine\Instantiator\Exception\UnexpectedValueException;
use Exception;
use ReflectionClass;
use ReflectionException;
use Serializable;
use function class_exists;
use function enum_exists;
use function is_subclass_of;
use function restore_error_handler;
use function set_error_handler;
use function sprintf;
use function strlen;
use function unserialize;
final class Instantiator implements InstantiatorInterface
{
/**
* Markers used internally by PHP to define whether {@see \unserialize} should invoke
* the method {@see \Serializable::unserialize()} when dealing with classes implementing
* the {@see \Serializable} interface.
*/
private const string SERIALIZATION_FORMAT_USE_UNSERIALIZER = 'C';
private const string SERIALIZATION_FORMAT_AVOID_UNSERIALIZER = 'O';
/**
* Used to instantiate specific classes, indexed by class name.
*
* @var array<class-string, callable(): object>
*/
private static array $cachedInstantiators = [];
/**
* Array of objects that can directly be cloned, indexed by class name.
*
* @var object[]
*/
private static array $cachedCloneables = [];
/**
* @phpstan-param class-string<T> $className
*
* @phpstan-return T
*
* @throws ExceptionInterface
*
* @template T of object
*/
public function instantiate(string $className): object
{
if (isset(self::$cachedCloneables[$className])) {
/** @phpstan-var T */
$cachedCloneable = self::$cachedCloneables[$className];
return clone $cachedCloneable;
}
if (isset(self::$cachedInstantiators[$className])) {
$factory = self::$cachedInstantiators[$className];
return $factory();
}
return $this->buildAndCacheFromFactory($className);
}
/**
* Builds the requested object and caches it in static properties for performance
*
* @phpstan-param class-string<T> $className
*
* @phpstan-return T
*
* @template T of object
*/
private function buildAndCacheFromFactory(string $className): object
{
$factory = self::$cachedInstantiators[$className] = $this->buildFactory($className);
$instance = $factory();
if ($this->isSafeToClone(new ReflectionClass($instance))) {
self::$cachedCloneables[$className] = clone $instance;
}
return $instance;
}
/**
* Builds a callable capable of instantiating the given $className without
* invoking its constructor.
*
* @phpstan-param class-string<T> $className
*
* @phpstan-return callable(): T
*
* @throws InvalidArgumentException
* @throws UnexpectedValueException
* @throws ReflectionException
*
* @template T of object
*/
private function buildFactory(string $className): callable
{
$reflectionClass = $this->getReflectionClass($className);
if ($this->isInstantiableViaReflection($reflectionClass)) {
return [$reflectionClass, 'newInstanceWithoutConstructor'];
}
$serializedString = sprintf(
'%s:%d:"%s":0:{}',
is_subclass_of($className, Serializable::class) ? self::SERIALIZATION_FORMAT_USE_UNSERIALIZER : self::SERIALIZATION_FORMAT_AVOID_UNSERIALIZER,
strlen($className),
$className,
);
$this->checkIfUnSerializationIsSupported($reflectionClass, $serializedString);
return static fn () => unserialize($serializedString);
}
/**
* @phpstan-param class-string<T> $className
*
* @phpstan-return ReflectionClass<T>
*
* @throws InvalidArgumentException
* @throws ReflectionException
*
* @template T of object
*/
private function getReflectionClass(string $className): ReflectionClass
{
if (! class_exists($className)) {
throw InvalidArgumentException::fromNonExistingClass($className);
}
if (enum_exists($className, false)) {
throw InvalidArgumentException::fromEnum($className);
}
$reflection = new ReflectionClass($className);
if ($reflection->isAbstract()) {
throw InvalidArgumentException::fromAbstractClass($reflection);
}
return $reflection;
}
/**
* @phpstan-param ReflectionClass<T> $reflectionClass
*
* @throws UnexpectedValueException
*
* @template T of object
*/
private function checkIfUnSerializationIsSupported(ReflectionClass $reflectionClass, string $serializedString): void
{
set_error_handler(static function (int $code, string $message, string $file, int $line) use ($reflectionClass, &$error): bool {
$error = UnexpectedValueException::fromUncleanUnSerialization(
$reflectionClass,
$message,
$code,
$file,
$line,
);
return true;
});
try {
$this->attemptInstantiationViaUnSerialization($reflectionClass, $serializedString);
} finally {
restore_error_handler();
}
if ($error) {
throw $error;
}
}
/**
* @phpstan-param ReflectionClass<T> $reflectionClass
*
* @throws UnexpectedValueException
*
* @template T of object
*/
private function attemptInstantiationViaUnSerialization(ReflectionClass $reflectionClass, string $serializedString): void
{
try {
unserialize($serializedString);
} catch (Exception $exception) {
throw UnexpectedValueException::fromSerializationTriggeredException($reflectionClass, $exception);
}
}
/**
* @phpstan-param ReflectionClass<T> $reflectionClass
*
* @template T of object
*/
private function isInstantiableViaReflection(ReflectionClass $reflectionClass): bool
{
return ! ($this->hasInternalAncestors($reflectionClass) && $reflectionClass->isFinal());
}
/**
* Verifies whether the given class is to be considered internal
*
* @phpstan-param ReflectionClass<T> $reflectionClass
*
* @template T of object
*/
private function hasInternalAncestors(ReflectionClass $reflectionClass): bool
{
do {
if ($reflectionClass->isInternal()) {
return true;
}
$reflectionClass = $reflectionClass->getParentClass();
} while ($reflectionClass);
return false;
}
/**
* Checks if a class is cloneable
*
* Classes implementing `__clone` cannot be safely cloned, as that may cause side-effects.
*
* @phpstan-param ReflectionClass<T> $reflectionClass
*
* @template T of object
*/
private function isSafeToClone(ReflectionClass $reflectionClass): bool
{
return $reflectionClass->isCloneable()
&& ! $reflectionClass->hasMethod('__clone')
&& ! $reflectionClass->isSubclassOf(ArrayIterator::class);
}
}
================================================
FILE: src/InstantiatorInterface.php
================================================
<?php
declare(strict_types=1);
namespace Doctrine\Instantiator;
use Doctrine\Instantiator\Exception\ExceptionInterface;
/**
* Instantiator provides utility methods to build objects without invoking their constructors
*/
interface InstantiatorInterface
{
/**
* @phpstan-param class-string<T> $className
*
* @phpstan-return T
*
* @throws ExceptionInterface
*
* @template T of object
*/
public function instantiate(string $className): object;
}
================================================
FILE: tests/InstantiatorPerformance/InstantiatorPerformanceBench.php
================================================
<?php
declare(strict_types=1);
namespace DoctrineTest\InstantiatorPerformance;
use ArrayObject;
use Doctrine\Instantiator\Instantiator;
use DoctrineTest\InstantiatorTestAsset\SerializableArrayObjectAsset;
use DoctrineTest\InstantiatorTestAsset\SimpleSerializableAsset;
use DoctrineTest\InstantiatorTestAsset\UnCloneableAsset;
use PhpBench\Benchmark\Metadata\Annotations\BeforeMethods;
use PhpBench\Benchmark\Metadata\Annotations\Revs;
/**
* Performance tests for {@see \Doctrine\Instantiator\Instantiator}
*
* @BeforeMethods({"init"})
*/
class InstantiatorPerformanceBench
{
private Instantiator $instantiator;
public function init(): void
{
$this->instantiator = new Instantiator();
$this->instantiator->instantiate(self::class);
$this->instantiator->instantiate(ArrayObject::class);
$this->instantiator->instantiate(SimpleSerializableAsset::class);
$this->instantiator->instantiate(SerializableArrayObjectAsset::class);
$this->instantiator->instantiate(UnCloneableAsset::class);
}
/** @Revs(20000) */
public function benchInstantiateSelf(): void
{
$this->instantiator->instantiate(self::class);
}
/** @Revs(20000) */
public function benchInstantiateInternalClass(): void
{
$this->instantiator->instantiate(ArrayObject::class);
}
/** @Revs(20000) */
public function benchInstantiateSimpleSerializableAssetClass(): void
{
$this->instantiator->instantiate(SimpleSerializableAsset::class);
}
/** @Revs(20000) */
public function benchInstantiateSerializableArrayObjectAsset(): void
{
$this->instantiator->instantiate(SerializableArrayObjectAsset::class);
}
/** @Revs(20000) */
public function benchInstantiateUnCloneableAsset(): void
{
$this->instantiator->instantiate(UnCloneableAsset::class);
}
}
================================================
FILE: tests/InstantiatorTest/Exception/InvalidArgumentExceptionTest.php
================================================
<?php
declare(strict_types=1);
namespace DoctrineTest\InstantiatorTest\Exception;
use Doctrine\Instantiator\Exception\InvalidArgumentException;
use Doctrine\Instantiator\InstantiatorInterface;
use DoctrineTest\InstantiatorTestAsset\AbstractClassAsset;
use DoctrineTest\InstantiatorTestAsset\SimpleTraitAsset;
use PHPUnit\Framework\TestCase;
use ReflectionClass;
use function sprintf;
use function str_replace;
use function uniqid;
/**
* Tests for {@see \Doctrine\Instantiator\Exception\InvalidArgumentException}
*
* @covers \Doctrine\Instantiator\Exception\InvalidArgumentException
*/
class InvalidArgumentExceptionTest extends TestCase
{
public function testFromNonExistingTypeWithNonExistingClass(): void
{
$className = self::class . str_replace('.', '', uniqid('', true));
$exception = InvalidArgumentException::fromNonExistingClass($className);
self::assertSame('The provided class "' . $className . '" does not exist', $exception->getMessage());
}
public function testFromNonExistingTypeWithTrait(): void
{
$exception = InvalidArgumentException::fromNonExistingClass(SimpleTraitAsset::class);
self::assertSame(
sprintf('The provided type "%s" is a trait, and cannot be instantiated', SimpleTraitAsset::class),
$exception->getMessage(),
);
}
public function testFromNonExistingTypeWithInterface(): void
{
$exception = InvalidArgumentException::fromNonExistingClass(InstantiatorInterface::class);
self::assertSame(
sprintf(
'The provided type "%s" is an interface, and cannot be instantiated',
InstantiatorInterface::class,
),
$exception->getMessage(),
);
}
public function testFromAbstractClass(): void
{
$reflection = new ReflectionClass(AbstractClassAsset::class);
$exception = InvalidArgumentException::fromAbstractClass($reflection);
self::assertSame(
sprintf(
'The provided class "%s" is abstract, and cannot be instantiated',
AbstractClassAsset::class,
),
$exception->getMessage(),
);
}
}
================================================
FILE: tests/InstantiatorTest/Exception/UnexpectedValueExceptionTest.php
================================================
<?php
declare(strict_types=1);
namespace DoctrineTest\InstantiatorTest\Exception;
use Doctrine\Instantiator\Exception\UnexpectedValueException;
use DoctrineTest\InstantiatorTestAsset\AbstractClassAsset;
use Exception;
use PHPUnit\Framework\TestCase;
use ReflectionClass;
use function sprintf;
/**
* Tests for {@see \Doctrine\Instantiator\Exception\UnexpectedValueException}
*
* @covers \Doctrine\Instantiator\Exception\UnexpectedValueException
*/
class UnexpectedValueExceptionTest extends TestCase
{
public function testFromSerializationTriggeredException(): void
{
$reflectionClass = new ReflectionClass($this);
$previous = new Exception();
$exception = UnexpectedValueException::fromSerializationTriggeredException($reflectionClass, $previous);
self::assertSame($previous, $exception->getPrevious());
self::assertSame(
'An exception was raised while trying to instantiate an instance of "'
. self::class . '" via un-serialization',
$exception->getMessage(),
);
}
public function testFromUncleanUnSerialization(): void
{
$reflection = new ReflectionClass(AbstractClassAsset::class);
$exception = UnexpectedValueException::fromUncleanUnSerialization($reflection, 'foo', 123, 'bar', 456);
self::assertSame(
sprintf(
'Could not produce an instance of "%s" '
. 'via un-serialization, since an error was triggered in file "bar" at line "456"',
AbstractClassAsset::class,
),
$exception->getMessage(),
);
$previous = $exception->getPrevious();
self::assertInstanceOf(Exception::class, $previous);
self::assertSame('foo', $previous->getMessage());
self::assertSame(123, $previous->getCode());
}
}
================================================
FILE: tests/InstantiatorTest/InstantiatorTest.php
================================================
<?php
declare(strict_types=1);
namespace DoctrineTest\InstantiatorTest;
use ArrayObject;
use Doctrine\Instantiator\Exception\InvalidArgumentException;
use Doctrine\Instantiator\Exception\UnexpectedValueException;
use Doctrine\Instantiator\Instantiator;
use Doctrine\Instantiator\InstantiatorInterface;
use DoctrineTest\InstantiatorTestAsset\AbstractClassAsset;
use DoctrineTest\InstantiatorTestAsset\ArrayObjectAsset;
use DoctrineTest\InstantiatorTestAsset\ExceptionAsset;
use DoctrineTest\InstantiatorTestAsset\FinalExceptionAsset;
use DoctrineTest\InstantiatorTestAsset\PharExceptionAsset;
use DoctrineTest\InstantiatorTestAsset\SerializableArrayObjectAsset;
use DoctrineTest\InstantiatorTestAsset\SerializableFinalInternalChildAsset;
use DoctrineTest\InstantiatorTestAsset\SimpleEnumAsset;
use DoctrineTest\InstantiatorTestAsset\SimpleSerializableAsset;
use DoctrineTest\InstantiatorTestAsset\SimpleTraitAsset;
use DoctrineTest\InstantiatorTestAsset\UnCloneableAsset;
use DoctrineTest\InstantiatorTestAsset\UnserializeExceptionArrayObjectAsset;
use DoctrineTest\InstantiatorTestAsset\WakeUpNoticesAsset;
use DoctrineTest\InstantiatorTestAsset\XMLReaderAsset;
use Exception;
use Generator;
use PDORow;
use PharException;
use PHPUnit\Framework\TestCase;
use stdClass;
use function str_replace;
use function uniqid;
/**
* Tests for {@see \Doctrine\Instantiator\Instantiator}
*
* @covers \Doctrine\Instantiator\Instantiator
*/
class InstantiatorTest extends TestCase
{
private Instantiator $instantiator;
protected function setUp(): void
{
parent::setUp();
$this->instantiator = new Instantiator();
}
/**
* @phpstan-param class-string $className
*
* @dataProvider getInstantiableClasses
*/
public function testCanInstantiate(string $className): void
{
self::assertInstanceOf($className, $this->instantiator->instantiate($className));
}
/**
* @phpstan-param class-string $className
*
* @dataProvider getInstantiableClasses
*/
public function testInstantiatesSeparateInstances(string $className): void
{
$instance1 = $this->instantiator->instantiate($className);
$instance2 = $this->instantiator->instantiate($className);
self::assertEquals($instance1, $instance2);
self::assertNotSame($instance1, $instance2);
}
public function testExceptionOnUnSerializationException(): void
{
$this->expectException(UnexpectedValueException::class);
$this->instantiator->instantiate(PDORow::class);
}
/**
* @phpstan-param class-string $invalidClassName
*
* @dataProvider getInvalidClassNames
*/
public function testInstantiationFromNonExistingClass(string $invalidClassName): void
{
$this->expectException(InvalidArgumentException::class);
$this->instantiator->instantiate($invalidClassName);
}
public function testInstancesAreNotCloned(): void
{
$namespace = __NAMESPACE__;
$className = 'TemporaryClass' . str_replace('.', '', uniqid('', true));
eval(<<< PHP
namespace $namespace;
#[\AllowDynamicProperties]
class $className {}
PHP
);
/** @phpstan-var class-string */
$classNameWithNamespace = $namespace . '\\' . $className;
$instance = $this->instantiator->instantiate($classNameWithNamespace);
$instance->foo = 'bar';
$instance2 = $this->instantiator->instantiate($classNameWithNamespace);
self::assertObjectNotHasProperty('foo', $instance2);
}
/**
* Provides a list of instantiable classes (existing)
*
* @return string[][]
* @phpstan-return list<array{class-string}>
*/
public static function getInstantiableClasses(): array
{
return [
[stdClass::class],
[self::class],
[Instantiator::class],
[Exception::class],
[PharException::class],
[SimpleSerializableAsset::class],
[ExceptionAsset::class],
[FinalExceptionAsset::class],
[PharExceptionAsset::class],
[UnCloneableAsset::class],
[XMLReaderAsset::class],
[PharException::class],
[ArrayObject::class],
[ArrayObjectAsset::class],
[SerializableArrayObjectAsset::class],
[WakeUpNoticesAsset::class],
[UnserializeExceptionArrayObjectAsset::class],
[SerializableFinalInternalChildAsset::class],
];
}
/**
* Provides a list of instantiable classes (existing)
*
* @return Generator<string, array{string}>
*/
public static function getInvalidClassNames(): Generator
{
yield 'invalid string' => [self::class . str_replace('.', '', uniqid('', true))];
yield 'interface' => [InstantiatorInterface::class];
yield 'abstract class' => [AbstractClassAsset::class];
yield 'trait' => [SimpleTraitAsset::class];
yield 'enum' => [SimpleEnumAsset::class];
}
}
================================================
FILE: tests/InstantiatorTestAsset/AbstractClassAsset.php
================================================
<?php
declare(strict_types=1);
namespace DoctrineTest\InstantiatorTestAsset;
/**
* A simple asset for an abstract class
*/
abstract class AbstractClassAsset
{
}
================================================
FILE: tests/InstantiatorTestAsset/ArrayObjectAsset.php
================================================
<?php
declare(strict_types=1);
namespace DoctrineTest\InstantiatorTestAsset;
use ArrayObject;
use BadMethodCallException;
/**
* Test asset that extends an internal PHP class
*
* @template TValue
* @template-extends ArrayObject<int, TValue>
*/
class ArrayObjectAsset extends ArrayObject
{
/**
* Constructor - should not be called
*
* @throws BadMethodCallException
*/
public function __construct()
{
throw new BadMethodCallException('Not supposed to be called!');
}
}
================================================
FILE: tests/InstantiatorTestAsset/ExceptionAsset.php
================================================
<?php
declare(strict_types=1);
namespace DoctrineTest\InstantiatorTestAsset;
use BadMethodCallException;
use Exception;
/**
* Test asset that extends an internal PHP base exception
*/
class ExceptionAsset extends Exception
{
/**
* Constructor - should not be called
*
* @throws BadMethodCallException
*/
public function __construct()
{
throw new BadMethodCallException('Not supposed to be called!');
}
}
================================================
FILE: tests/InstantiatorTestAsset/FinalExceptionAsset.php
================================================
<?php
declare(strict_types=1);
namespace DoctrineTest\InstantiatorTestAsset;
use BadMethodCallException;
use Exception;
/**
* Test asset that extends an internal PHP base exception
*/
final class FinalExceptionAsset extends Exception
{
/**
* Constructor - should not be called
*
* @throws BadMethodCallException
*/
public function __construct()
{
throw new BadMethodCallException('Not supposed to be called!');
}
}
================================================
FILE: tests/InstantiatorTestAsset/PharAsset.php
================================================
<?php
declare(strict_types=1);
namespace DoctrineTest\InstantiatorTestAsset;
use BadMethodCallException;
use Phar;
/**
* Test asset that extends an internal PHP class
*/
class PharAsset extends Phar
{
/**
* Constructor - should not be called
*
* @throws BadMethodCallException
*/
public function __construct()
{
throw new BadMethodCallException('Not supposed to be called!');
}
}
================================================
FILE: tests/InstantiatorTestAsset/PharExceptionAsset.php
================================================
<?php
declare(strict_types=1);
namespace DoctrineTest\InstantiatorTestAsset;
use BadMethodCallException;
use PharException;
/**
* Test asset that extends an internal PHP class
* This class should be serializable without problems
* and without getting the "Erroneous data format for unserializing"
* error
*/
class PharExceptionAsset extends PharException
{
/**
* Constructor - should not be called
*
* @throws BadMethodCallException
*/
public function __construct()
{
throw new BadMethodCallException('Not supposed to be called!');
}
}
================================================
FILE: tests/InstantiatorTestAsset/SerializableArrayObjectAsset.php
================================================
<?php
declare(strict_types=1);
namespace DoctrineTest\InstantiatorTestAsset;
use ArrayObject;
use BadMethodCallException;
use Serializable;
/**
* Serializable test asset that also extends an internal class
*
* @template TValue
* @template-extends ArrayObject<int, TValue>
*/
class SerializableArrayObjectAsset extends ArrayObject implements Serializable
{
/**
* Constructor - should not be called
*
* @throws BadMethodCallException
*/
public function __construct()
{
throw new BadMethodCallException('Not supposed to be called!');
}
/**
* {@inheritDoc}
*
* Should not be called
*
* @throws BadMethodCallException
*/
public function unserialize($serialized): void
{
throw new BadMethodCallException('Not supposed to be called!');
}
/** @param mixed[] $data */
public function __unserialize(array $data): void
{
throw new BadMethodCallException('Not supposed to be called!');
}
}
================================================
FILE: tests/InstantiatorTestAsset/SerializableFinalInternalChildAsset.php
================================================
<?php
declare(strict_types=1);
namespace DoctrineTest\InstantiatorTestAsset;
use ArrayIterator;
/**
* @template TValue
* @template-extends ArrayIterator<int, TValue>
*/
final class SerializableFinalInternalChildAsset extends ArrayIterator
{
}
================================================
FILE: tests/InstantiatorTestAsset/SimpleEnumAsset.php
================================================
<?php
declare(strict_types=1);
namespace DoctrineTest\InstantiatorTestAsset;
enum SimpleEnumAsset
{
case Foo;
case Bar;
}
================================================
FILE: tests/InstantiatorTestAsset/SimpleSerializableAsset.php
================================================
<?php
declare(strict_types=1);
namespace DoctrineTest\InstantiatorTestAsset;
use BadMethodCallException;
use Serializable;
/**
* Base serializable test asset
*/
class SimpleSerializableAsset implements Serializable
{
/**
* Constructor - should not be called
*
* @throws BadMethodCallException
*/
public function __construct()
{
throw new BadMethodCallException('Not supposed to be called!');
}
public function serialize(): string
{
return '';
}
/**
* {@inheritDoc}
*
* Should not be called
*
* @throws BadMethodCallException
*/
public function unserialize(string $serialized): void
{
throw new BadMethodCallException('Not supposed to be called!');
}
/** @return mixed[] */
public function __serialize(): array
{
return [];
}
/** @param mixed[] $data */
public function __unserialize(array $data): void
{
throw new BadMethodCallException('Not supposed to be called!');
}
}
================================================
FILE: tests/InstantiatorTestAsset/SimpleTraitAsset.php
================================================
<?php
declare(strict_types=1);
namespace DoctrineTest\InstantiatorTestAsset;
/**
* A simple trait with no attached logic
*/
trait SimpleTraitAsset
{
}
================================================
FILE: tests/InstantiatorTestAsset/UnCloneableAsset.php
================================================
<?php
declare(strict_types=1);
namespace DoctrineTest\InstantiatorTestAsset;
use BadMethodCallException;
/**
* Base un-cloneable asset
*/
class UnCloneableAsset
{
/**
* Constructor - should not be called
*
* @throws BadMethodCallException
*/
public function __construct()
{
throw new BadMethodCallException('Not supposed to be called!');
}
/**
* Magic `__clone` - should not be invoked
*
* @throws BadMethodCallException
*/
public function __clone()
{
throw new BadMethodCallException('Not supposed to be called!');
}
}
================================================
FILE: tests/InstantiatorTestAsset/UnserializeExceptionArrayObjectAsset.php
================================================
<?php
declare(strict_types=1);
namespace DoctrineTest\InstantiatorTestAsset;
use ArrayObject;
use BadMethodCallException;
/**
* A simple asset for an abstract class
*
* @template TValue
* @template-extends ArrayObject<int, TValue>
*/
class UnserializeExceptionArrayObjectAsset extends ArrayObject
{
/**
* {@inheritDoc}
*/
public function __wakeup()
{
throw new BadMethodCallException();
}
}
================================================
FILE: tests/InstantiatorTestAsset/WakeUpNoticesAsset.php
================================================
<?php
declare(strict_types=1);
namespace DoctrineTest\InstantiatorTestAsset;
use ArrayObject;
use function trigger_error;
/**
* A simple asset for an abstract class
*
* @template TValue
* @template-extends ArrayObject<int, TValue>
*/
class WakeUpNoticesAsset extends ArrayObject
{
/**
* Wakeup method called after un-serialization
*/
public function __wakeup(): void
{
trigger_error('Something went bananas while un-serializing this instance');
}
}
================================================
FILE: tests/InstantiatorTestAsset/XMLReaderAsset.php
================================================
<?php
declare(strict_types=1);
namespace DoctrineTest\InstantiatorTestAsset;
use BadMethodCallException;
use XMLReader;
/**
* Test asset that extends an internal PHP class
*/
class XMLReaderAsset extends XMLReader
{
/**
* Constructor - should not be called
*
* @throws BadMethodCallException
*/
public function __construct()
{
throw new BadMethodCallException('Not supposed to be called!');
}
}
gitextract_gga815b3/
├── .doctrine-project.json
├── .gitattributes
├── .github/
│ ├── FUNDING.yml
│ ├── dependabot.yml
│ └── workflows/
│ ├── coding-standards.yml
│ ├── continuous-integration.yml
│ ├── phpbench.yml
│ ├── release-on-milestone-closed.yml
│ ├── static-analysis.yml
│ └── website-schema.yml
├── .gitignore
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── composer.json
├── docs/
│ └── en/
│ ├── index.rst
│ └── sidebar.rst
├── phpbench.json
├── phpcs.xml.dist
├── phpmd.xml.dist
├── phpstan.neon.dist
├── phpunit.xml.dist
├── src/
│ ├── Exception/
│ │ ├── ExceptionInterface.php
│ │ ├── InvalidArgumentException.php
│ │ └── UnexpectedValueException.php
│ ├── Instantiator.php
│ └── InstantiatorInterface.php
└── tests/
├── InstantiatorPerformance/
│ └── InstantiatorPerformanceBench.php
├── InstantiatorTest/
│ ├── Exception/
│ │ ├── InvalidArgumentExceptionTest.php
│ │ └── UnexpectedValueExceptionTest.php
│ └── InstantiatorTest.php
└── InstantiatorTestAsset/
├── AbstractClassAsset.php
├── ArrayObjectAsset.php
├── ExceptionAsset.php
├── FinalExceptionAsset.php
├── PharAsset.php
├── PharExceptionAsset.php
├── SerializableArrayObjectAsset.php
├── SerializableFinalInternalChildAsset.php
├── SimpleEnumAsset.php
├── SimpleSerializableAsset.php
├── SimpleTraitAsset.php
├── UnCloneableAsset.php
├── UnserializeExceptionArrayObjectAsset.php
├── WakeUpNoticesAsset.php
└── XMLReaderAsset.php
SYMBOL INDEX (76 symbols across 23 files)
FILE: src/Exception/ExceptionInterface.php
type ExceptionInterface (line 12) | interface ExceptionInterface extends Throwable
FILE: src/Exception/InvalidArgumentException.php
class InvalidArgumentException (line 17) | class InvalidArgumentException extends BaseInvalidArgumentException impl...
method fromNonExistingClass (line 19) | public static function fromNonExistingClass(string $className): self
method fromAbstractClass (line 37) | public static function fromAbstractClass(ReflectionClass $reflectionCl...
method fromEnum (line 45) | public static function fromEnum(string $className): self
FILE: src/Exception/UnexpectedValueException.php
class UnexpectedValueException (line 16) | class UnexpectedValueException extends BaseUnexpectedValueException impl...
method fromSerializationTriggeredException (line 23) | public static function fromSerializationTriggeredException(
method fromUncleanUnSerialization (line 42) | public static function fromUncleanUnSerialization(
FILE: src/Instantiator.php
class Instantiator (line 25) | final class Instantiator implements InstantiatorInterface
method instantiate (line 58) | public function instantiate(string $className): object
method buildAndCacheFromFactory (line 85) | private function buildAndCacheFromFactory(string $className): object
method buildFactory (line 111) | private function buildFactory(string $className): callable
method getReflectionClass (line 141) | private function getReflectionClass(string $className): ReflectionClass
method checkIfUnSerializationIsSupported (line 167) | private function checkIfUnSerializationIsSupported(ReflectionClass $re...
method attemptInstantiationViaUnSerialization (line 199) | private function attemptInstantiationViaUnSerialization(ReflectionClas...
method isInstantiableViaReflection (line 213) | private function isInstantiableViaReflection(ReflectionClass $reflecti...
method hasInternalAncestors (line 225) | private function hasInternalAncestors(ReflectionClass $reflectionClass...
method isSafeToClone (line 247) | private function isSafeToClone(ReflectionClass $reflectionClass): bool
FILE: src/InstantiatorInterface.php
type InstantiatorInterface (line 12) | interface InstantiatorInterface
method instantiate (line 23) | public function instantiate(string $className): object;
FILE: tests/InstantiatorPerformance/InstantiatorPerformanceBench.php
class InstantiatorPerformanceBench (line 20) | class InstantiatorPerformanceBench
method init (line 24) | public function init(): void
method benchInstantiateSelf (line 36) | public function benchInstantiateSelf(): void
method benchInstantiateInternalClass (line 42) | public function benchInstantiateInternalClass(): void
method benchInstantiateSimpleSerializableAssetClass (line 48) | public function benchInstantiateSimpleSerializableAssetClass(): void
method benchInstantiateSerializableArrayObjectAsset (line 54) | public function benchInstantiateSerializableArrayObjectAsset(): void
method benchInstantiateUnCloneableAsset (line 60) | public function benchInstantiateUnCloneableAsset(): void
FILE: tests/InstantiatorTest/Exception/InvalidArgumentExceptionTest.php
class InvalidArgumentExceptionTest (line 23) | class InvalidArgumentExceptionTest extends TestCase
method testFromNonExistingTypeWithNonExistingClass (line 25) | public function testFromNonExistingTypeWithNonExistingClass(): void
method testFromNonExistingTypeWithTrait (line 33) | public function testFromNonExistingTypeWithTrait(): void
method testFromNonExistingTypeWithInterface (line 43) | public function testFromNonExistingTypeWithInterface(): void
method testFromAbstractClass (line 56) | public function testFromAbstractClass(): void
FILE: tests/InstantiatorTest/Exception/UnexpectedValueExceptionTest.php
class UnexpectedValueExceptionTest (line 20) | class UnexpectedValueExceptionTest extends TestCase
method testFromSerializationTriggeredException (line 22) | public function testFromSerializationTriggeredException(): void
method testFromUncleanUnSerialization (line 36) | public function testFromUncleanUnSerialization(): void
FILE: tests/InstantiatorTest/InstantiatorTest.php
class InstantiatorTest (line 41) | class InstantiatorTest extends TestCase
method setUp (line 45) | protected function setUp(): void
method testCanInstantiate (line 57) | public function testCanInstantiate(string $className): void
method testInstantiatesSeparateInstances (line 67) | public function testInstantiatesSeparateInstances(string $className): ...
method testExceptionOnUnSerializationException (line 76) | public function testExceptionOnUnSerializationException(): void
method testInstantiationFromNonExistingClass (line 88) | public function testInstantiationFromNonExistingClass(string $invalidC...
method testInstancesAreNotCloned (line 95) | public function testInstancesAreNotCloned(): void
method getInstantiableClasses (line 125) | public static function getInstantiableClasses(): array
method getInvalidClassNames (line 154) | public static function getInvalidClassNames(): Generator
FILE: tests/InstantiatorTestAsset/AbstractClassAsset.php
class AbstractClassAsset (line 10) | abstract class AbstractClassAsset
FILE: tests/InstantiatorTestAsset/ArrayObjectAsset.php
class ArrayObjectAsset (line 16) | class ArrayObjectAsset extends ArrayObject
method __construct (line 23) | public function __construct()
FILE: tests/InstantiatorTestAsset/ExceptionAsset.php
class ExceptionAsset (line 13) | class ExceptionAsset extends Exception
method __construct (line 20) | public function __construct()
FILE: tests/InstantiatorTestAsset/FinalExceptionAsset.php
class FinalExceptionAsset (line 13) | final class FinalExceptionAsset extends Exception
method __construct (line 20) | public function __construct()
FILE: tests/InstantiatorTestAsset/PharAsset.php
class PharAsset (line 13) | class PharAsset extends Phar
method __construct (line 20) | public function __construct()
FILE: tests/InstantiatorTestAsset/PharExceptionAsset.php
class PharExceptionAsset (line 16) | class PharExceptionAsset extends PharException
method __construct (line 23) | public function __construct()
FILE: tests/InstantiatorTestAsset/SerializableArrayObjectAsset.php
class SerializableArrayObjectAsset (line 17) | class SerializableArrayObjectAsset extends ArrayObject implements Serial...
method __construct (line 24) | public function __construct()
method unserialize (line 36) | public function unserialize($serialized): void
method __unserialize (line 42) | public function __unserialize(array $data): void
FILE: tests/InstantiatorTestAsset/SerializableFinalInternalChildAsset.php
class SerializableFinalInternalChildAsset (line 13) | final class SerializableFinalInternalChildAsset extends ArrayIterator
FILE: tests/InstantiatorTestAsset/SimpleSerializableAsset.php
class SimpleSerializableAsset (line 13) | class SimpleSerializableAsset implements Serializable
method __construct (line 20) | public function __construct()
method serialize (line 25) | public function serialize(): string
method unserialize (line 37) | public function unserialize(string $serialized): void
method __serialize (line 43) | public function __serialize(): array
method __unserialize (line 49) | public function __unserialize(array $data): void
FILE: tests/InstantiatorTestAsset/SimpleTraitAsset.php
type SimpleTraitAsset (line 10) | trait SimpleTraitAsset
FILE: tests/InstantiatorTestAsset/UnCloneableAsset.php
class UnCloneableAsset (line 12) | class UnCloneableAsset
method __construct (line 19) | public function __construct()
method __clone (line 29) | public function __clone()
FILE: tests/InstantiatorTestAsset/UnserializeExceptionArrayObjectAsset.php
class UnserializeExceptionArrayObjectAsset (line 16) | class UnserializeExceptionArrayObjectAsset extends ArrayObject
method __wakeup (line 21) | public function __wakeup()
FILE: tests/InstantiatorTestAsset/WakeUpNoticesAsset.php
class WakeUpNoticesAsset (line 17) | class WakeUpNoticesAsset extends ArrayObject
method __wakeup (line 22) | public function __wakeup(): void
FILE: tests/InstantiatorTestAsset/XMLReaderAsset.php
class XMLReaderAsset (line 13) | class XMLReaderAsset extends XMLReader
method __construct (line 20) | public function __construct()
Condensed preview — 46 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (50K chars).
[
{
"path": ".doctrine-project.json",
"chars": 849,
"preview": "{\n \"active\": true,\n \"name\": \"Instantiator\",\n \"slug\": \"instantiator\",\n \"docsSlug\": \"doctrine-instantiator\",\n "
},
{
"path": ".gitattributes",
"chars": 481,
"preview": "/.github export-ignore\n/tests export-ignore\n/docs export-ignore\n.doctrine"
},
{
"path": ".github/FUNDING.yml",
"chars": 123,
"preview": "patreon: phpdoctrine\ntidelift: packagist/doctrine%2Finstantiator\ncustom: https://www.doctrine-project.org/sponsorship.ht"
},
{
"path": ".github/dependabot.yml",
"chars": 143,
"preview": "version: 2\nupdates:\n - package-ecosystem: \"github-actions\"\n directory: \"/\"\n schedule:\n interval: \"weekly\"\n "
},
{
"path": ".github/workflows/coding-standards.yml",
"chars": 242,
"preview": "\nname: \"Coding Standards\"\n\non:\n pull_request:\n branches:\n - \"*.x\"\n push:\n branches:\n - \"*.x\"\n\njobs:\n "
},
{
"path": ".github/workflows/continuous-integration.yml",
"chars": 348,
"preview": "\nname: \"Continuous Integration\"\n\non:\n pull_request:\n branches:\n - \"*.x\"\n push:\n branches:\n - \"*.x\"\n\njo"
},
{
"path": ".github/workflows/phpbench.yml",
"chars": 826,
"preview": "\nname: \"Performance benchmark\"\n\non:\n pull_request:\n branches:\n - \"*.x\"\n push:\n branches:\n - \"*.x\"\n\nenv"
},
{
"path": ".github/workflows/release-on-milestone-closed.yml",
"chars": 482,
"preview": "name: \"Automatic Releases\"\n\non:\n milestone:\n types:\n - \"closed\"\n\njobs:\n release:\n name: \"Git tag, release &"
},
{
"path": ".github/workflows/static-analysis.yml",
"chars": 230,
"preview": "\nname: \"Static Analysis\"\n\non:\n pull_request:\n branches:\n - \"*.x\"\n push:\n branches:\n - \"*.x\"\n\njobs:\n s"
},
{
"path": ".github/workflows/website-schema.yml",
"chars": 432,
"preview": "\nname: \"Website config validation\"\n\non:\n pull_request:\n branches:\n - \"*.x\"\n paths:\n - \".doctrine-projec"
},
{
"path": ".gitignore",
"chars": 111,
"preview": "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",
"chars": 1032,
"preview": "# Contributing\n\n * Follow the [Doctrine Coding Standard](https://github.com/doctrine/coding-standard)\n * The project wil"
},
{
"path": "LICENSE",
"chars": 1060,
"preview": "Copyright (c) 2014 Doctrine Project\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthi"
},
{
"path": "README.md",
"chars": 1588,
"preview": "# Doctrine Instantiator\n\nThis library provides a way of avoiding usage of constructors when instantiating PHP classes.\n\n"
},
{
"path": "composer.json",
"chars": 1512,
"preview": "{\n \"name\": \"doctrine/instantiator\",\n \"description\": \"A small, lightweight utility to instantiat"
},
{
"path": "docs/en/index.rst",
"chars": 1757,
"preview": "Introduction\n============\n\nThis library provides a way of avoiding usage of constructors when instantiating PHP classes."
},
{
"path": "docs/en/sidebar.rst",
"chars": 38,
"preview": ".. toctree::\n :depth: 3\n\n index\n"
},
{
"path": "phpbench.json",
"chars": 102,
"preview": "{\n \"runner.bootstrap\": \"vendor/autoload.php\",\n \"runner.path\": \"tests/InstantiatorPerformance\"\n}\n"
},
{
"path": "phpcs.xml.dist",
"chars": 1404,
"preview": "<?xml version=\"1.0\"?>\n<ruleset\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xsi:noNamespaceSche"
},
{
"path": "phpmd.xml.dist",
"chars": 1085,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<ruleset\n name=\"Instantiator rules\"\n xmlns=\"http://pmd.sf.net/ruleset/1.0."
},
{
"path": "phpstan.neon.dist",
"chars": 1035,
"preview": "includes:\n - vendor/phpstan/phpstan-phpunit/extension.neon\n - vendor/phpstan/phpstan-phpunit/rules.neon\n\nparameter"
},
{
"path": "phpunit.xml.dist",
"chars": 700,
"preview": "<?xml version=\"1.0\"?>\n<phpunit xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n xsi:noNamespaceSchemaLocation=\""
},
{
"path": "src/Exception/ExceptionInterface.php",
"chars": 218,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Doctrine\\Instantiator\\Exception;\n\nuse Throwable;\n\n/**\n * Base exception marke"
},
{
"path": "src/Exception/InvalidArgumentException.php",
"chars": 1524,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Doctrine\\Instantiator\\Exception;\n\nuse InvalidArgumentException as BaseInvalid"
},
{
"path": "src/Exception/UnexpectedValueException.php",
"chars": 1655,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Doctrine\\Instantiator\\Exception;\n\nuse Exception;\nuse ReflectionClass;\nuse Une"
},
{
"path": "src/Instantiator.php",
"chars": 7367,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Doctrine\\Instantiator;\n\nuse ArrayIterator;\nuse Doctrine\\Instantiator\\Exceptio"
},
{
"path": "src/InstantiatorInterface.php",
"chars": 496,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Doctrine\\Instantiator;\n\nuse Doctrine\\Instantiator\\Exception\\ExceptionInterfac"
},
{
"path": "tests/InstantiatorPerformance/InstantiatorPerformanceBench.php",
"chars": 1895,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorPerformance;\n\nuse ArrayObject;\nuse Doctrine\\Instanti"
},
{
"path": "tests/InstantiatorTest/Exception/InvalidArgumentExceptionTest.php",
"chars": 2228,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTest\\Exception;\n\nuse Doctrine\\Instantiator\\Exception"
},
{
"path": "tests/InstantiatorTest/Exception/UnexpectedValueExceptionTest.php",
"chars": 1875,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTest\\Exception;\n\nuse Doctrine\\Instantiator\\Exception"
},
{
"path": "tests/InstantiatorTest/InstantiatorTest.php",
"chars": 5071,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTest;\n\nuse ArrayObject;\nuse Doctrine\\Instantiator\\Ex"
},
{
"path": "tests/InstantiatorTestAsset/AbstractClassAsset.php",
"chars": 166,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTestAsset;\n\n/**\n * A simple asset for an abstract cl"
},
{
"path": "tests/InstantiatorTestAsset/ArrayObjectAsset.php",
"chars": 520,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTestAsset;\n\nuse ArrayObject;\nuse BadMethodCallExcept"
},
{
"path": "tests/InstantiatorTestAsset/ExceptionAsset.php",
"chars": 454,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTestAsset;\n\nuse BadMethodCallException;\nuse Exceptio"
},
{
"path": "tests/InstantiatorTestAsset/FinalExceptionAsset.php",
"chars": 465,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTestAsset;\n\nuse BadMethodCallException;\nuse Exceptio"
},
{
"path": "tests/InstantiatorTestAsset/PharAsset.php",
"chars": 430,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTestAsset;\n\nuse BadMethodCallException;\nuse Phar;\n\n/"
},
{
"path": "tests/InstantiatorTestAsset/PharExceptionAsset.php",
"chars": 589,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTestAsset;\n\nuse BadMethodCallException;\nuse PharExce"
},
{
"path": "tests/InstantiatorTestAsset/SerializableArrayObjectAsset.php",
"chars": 1011,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTestAsset;\n\nuse ArrayObject;\nuse BadMethodCallExcept"
},
{
"path": "tests/InstantiatorTestAsset/SerializableFinalInternalChildAsset.php",
"chars": 250,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTestAsset;\n\nuse ArrayIterator;\n\n/**\n * @template TVa"
},
{
"path": "tests/InstantiatorTestAsset/SimpleEnumAsset.php",
"chars": 133,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTestAsset;\n\nenum SimpleEnumAsset\n{\n case Foo;\n "
},
{
"path": "tests/InstantiatorTestAsset/SimpleSerializableAsset.php",
"chars": 1048,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTestAsset;\n\nuse BadMethodCallException;\nuse Serializ"
},
{
"path": "tests/InstantiatorTestAsset/SimpleTraitAsset.php",
"chars": 156,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTestAsset;\n\n/**\n * A simple trait with no attached l"
},
{
"path": "tests/InstantiatorTestAsset/UnCloneableAsset.php",
"chars": 615,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTestAsset;\n\nuse BadMethodCallException;\n\n/**\n * Base"
},
{
"path": "tests/InstantiatorTestAsset/UnserializeExceptionArrayObjectAsset.php",
"chars": 434,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTestAsset;\n\nuse ArrayObject;\nuse BadMethodCallExcept"
},
{
"path": "tests/InstantiatorTestAsset/WakeUpNoticesAsset.php",
"chars": 493,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTestAsset;\n\nuse ArrayObject;\n\nuse function trigger_e"
},
{
"path": "tests/InstantiatorTestAsset/XMLReaderAsset.php",
"chars": 445,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace DoctrineTest\\InstantiatorTestAsset;\n\nuse BadMethodCallException;\nuse XMLReade"
}
]
About this extraction
This page contains the full source code of the doctrine/instantiator GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 46 files (44.1 KB), approximately 11.7k tokens, and a symbol index with 76 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.