summaryrefslogtreecommitdiff
path: root/vendor/doctrine/instantiator/src/Doctrine
diff options
context:
space:
mode:
authorpolo <ordipolo@gmx.fr>2024-08-13 23:45:21 +0200
committerpolo <ordipolo@gmx.fr>2024-08-13 23:45:21 +0200
commitbf6655a534a6775d30cafa67bd801276bda1d98d (patch)
treec6381e3f6c81c33eab72508f410b165ba05f7e9c /vendor/doctrine/instantiator/src/Doctrine
parent94d67a4b51f8e62e7d518cce26a526ae1ec48278 (diff)
downloadAppliGestionPHP-bf6655a534a6775d30cafa67bd801276bda1d98d.zip
VERSION 0.2 doctrine ORM et entités
Diffstat (limited to 'vendor/doctrine/instantiator/src/Doctrine')
-rw-r--r--vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/ExceptionInterface.php14
-rw-r--r--vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/InvalidArgumentException.php52
-rw-r--r--vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/UnexpectedValueException.php61
-rw-r--r--vendor/doctrine/instantiator/src/Doctrine/Instantiator/Instantiator.php255
-rw-r--r--vendor/doctrine/instantiator/src/Doctrine/Instantiator/InstantiatorInterface.php24
5 files changed, 406 insertions, 0 deletions
diff --git a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/ExceptionInterface.php b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/ExceptionInterface.php
new file mode 100644
index 0000000..1e59192
--- /dev/null
+++ b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/ExceptionInterface.php
@@ -0,0 +1,14 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Instantiator\Exception;
6
7use Throwable;
8
9/**
10 * Base exception marker interface for the instantiator component
11 */
12interface ExceptionInterface extends Throwable
13{
14}
diff --git a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/InvalidArgumentException.php b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/InvalidArgumentException.php
new file mode 100644
index 0000000..5b91a00
--- /dev/null
+++ b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/InvalidArgumentException.php
@@ -0,0 +1,52 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Instantiator\Exception;
6
7use InvalidArgumentException as BaseInvalidArgumentException;
8use ReflectionClass;
9
10use function interface_exists;
11use function sprintf;
12use function trait_exists;
13
14/**
15 * Exception for invalid arguments provided to the instantiator
16 */
17class InvalidArgumentException extends BaseInvalidArgumentException implements ExceptionInterface
18{
19 public static function fromNonExistingClass(string $className): self
20 {
21 if (interface_exists($className)) {
22 return new self(sprintf('The provided type "%s" is an interface, and cannot be instantiated', $className));
23 }
24
25 if (trait_exists($className)) {
26 return new self(sprintf('The provided type "%s" is a trait, and cannot be instantiated', $className));
27 }
28
29 return new self(sprintf('The provided class "%s" does not exist', $className));
30 }
31
32 /**
33 * @phpstan-param ReflectionClass<T> $reflectionClass
34 *
35 * @template T of object
36 */
37 public static function fromAbstractClass(ReflectionClass $reflectionClass): self
38 {
39 return new self(sprintf(
40 'The provided class "%s" is abstract, and cannot be instantiated',
41 $reflectionClass->getName(),
42 ));
43 }
44
45 public static function fromEnum(string $className): self
46 {
47 return new self(sprintf(
48 'The provided class "%s" is an enum, and cannot be instantiated',
49 $className,
50 ));
51 }
52}
diff --git a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/UnexpectedValueException.php b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/UnexpectedValueException.php
new file mode 100644
index 0000000..4f70ded
--- /dev/null
+++ b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Exception/UnexpectedValueException.php
@@ -0,0 +1,61 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Instantiator\Exception;
6
7use Exception;
8use ReflectionClass;
9use UnexpectedValueException as BaseUnexpectedValueException;
10
11use function sprintf;
12
13/**
14 * Exception for given parameters causing invalid/unexpected state on instantiation
15 */
16class UnexpectedValueException extends BaseUnexpectedValueException implements ExceptionInterface
17{
18 /**
19 * @phpstan-param ReflectionClass<T> $reflectionClass
20 *
21 * @template T of object
22 */
23 public static function fromSerializationTriggeredException(
24 ReflectionClass $reflectionClass,
25 Exception $exception,
26 ): self {
27 return new self(
28 sprintf(
29 'An exception was raised while trying to instantiate an instance of "%s" via un-serialization',
30 $reflectionClass->getName(),
31 ),
32 0,
33 $exception,
34 );
35 }
36
37 /**
38 * @phpstan-param ReflectionClass<T> $reflectionClass
39 *
40 * @template T of object
41 */
42 public static function fromUncleanUnSerialization(
43 ReflectionClass $reflectionClass,
44 string $errorString,
45 int $errorCode,
46 string $errorFile,
47 int $errorLine,
48 ): self {
49 return new self(
50 sprintf(
51 'Could not produce an instance of "%s" via un-serialization, since an error was triggered '
52 . 'in file "%s" at line "%d"',
53 $reflectionClass->getName(),
54 $errorFile,
55 $errorLine,
56 ),
57 0,
58 new Exception($errorString, $errorCode),
59 );
60 }
61}
diff --git a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Instantiator.php b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Instantiator.php
new file mode 100644
index 0000000..f803f89
--- /dev/null
+++ b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/Instantiator.php
@@ -0,0 +1,255 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Instantiator;
6
7use ArrayIterator;
8use Doctrine\Instantiator\Exception\ExceptionInterface;
9use Doctrine\Instantiator\Exception\InvalidArgumentException;
10use Doctrine\Instantiator\Exception\UnexpectedValueException;
11use Exception;
12use ReflectionClass;
13use ReflectionException;
14use Serializable;
15
16use function class_exists;
17use function enum_exists;
18use function is_subclass_of;
19use function restore_error_handler;
20use function set_error_handler;
21use function sprintf;
22use function strlen;
23use function unserialize;
24
25final class Instantiator implements InstantiatorInterface
26{
27 /**
28 * Markers used internally by PHP to define whether {@see \unserialize} should invoke
29 * the method {@see \Serializable::unserialize()} when dealing with classes implementing
30 * the {@see \Serializable} interface.
31 *
32 * @deprecated This constant will be private in 2.0
33 */
34 private const SERIALIZATION_FORMAT_USE_UNSERIALIZER = 'C';
35 private const SERIALIZATION_FORMAT_AVOID_UNSERIALIZER = 'O';
36
37 /**
38 * Used to instantiate specific classes, indexed by class name.
39 *
40 * @var callable[]
41 */
42 private static array $cachedInstantiators = [];
43
44 /**
45 * Array of objects that can directly be cloned, indexed by class name.
46 *
47 * @var object[]
48 */
49 private static array $cachedCloneables = [];
50
51 /**
52 * @phpstan-param class-string<T> $className
53 *
54 * @phpstan-return T
55 *
56 * @throws ExceptionInterface
57 *
58 * @template T of object
59 */
60 public function instantiate(string $className): object
61 {
62 if (isset(self::$cachedCloneables[$className])) {
63 /** @phpstan-var T */
64 $cachedCloneable = self::$cachedCloneables[$className];
65
66 return clone $cachedCloneable;
67 }
68
69 if (isset(self::$cachedInstantiators[$className])) {
70 $factory = self::$cachedInstantiators[$className];
71
72 return $factory();
73 }
74
75 return $this->buildAndCacheFromFactory($className);
76 }
77
78 /**
79 * Builds the requested object and caches it in static properties for performance
80 *
81 * @phpstan-param class-string<T> $className
82 *
83 * @phpstan-return T
84 *
85 * @template T of object
86 */
87 private function buildAndCacheFromFactory(string $className): object
88 {
89 $factory = self::$cachedInstantiators[$className] = $this->buildFactory($className);
90 $instance = $factory();
91
92 if ($this->isSafeToClone(new ReflectionClass($instance))) {
93 self::$cachedCloneables[$className] = clone $instance;
94 }
95
96 return $instance;
97 }
98
99 /**
100 * Builds a callable capable of instantiating the given $className without
101 * invoking its constructor.
102 *
103 * @phpstan-param class-string<T> $className
104 *
105 * @phpstan-return callable(): T
106 *
107 * @throws InvalidArgumentException
108 * @throws UnexpectedValueException
109 * @throws ReflectionException
110 *
111 * @template T of object
112 */
113 private function buildFactory(string $className): callable
114 {
115 $reflectionClass = $this->getReflectionClass($className);
116
117 if ($this->isInstantiableViaReflection($reflectionClass)) {
118 return [$reflectionClass, 'newInstanceWithoutConstructor'];
119 }
120
121 $serializedString = sprintf(
122 '%s:%d:"%s":0:{}',
123 is_subclass_of($className, Serializable::class) ? self::SERIALIZATION_FORMAT_USE_UNSERIALIZER : self::SERIALIZATION_FORMAT_AVOID_UNSERIALIZER,
124 strlen($className),
125 $className,
126 );
127
128 $this->checkIfUnSerializationIsSupported($reflectionClass, $serializedString);
129
130 return static fn () => unserialize($serializedString);
131 }
132
133 /**
134 * @phpstan-param class-string<T> $className
135 *
136 * @phpstan-return ReflectionClass<T>
137 *
138 * @throws InvalidArgumentException
139 * @throws ReflectionException
140 *
141 * @template T of object
142 */
143 private function getReflectionClass(string $className): ReflectionClass
144 {
145 if (! class_exists($className)) {
146 throw InvalidArgumentException::fromNonExistingClass($className);
147 }
148
149 if (enum_exists($className, false)) {
150 throw InvalidArgumentException::fromEnum($className);
151 }
152
153 $reflection = new ReflectionClass($className);
154
155 if ($reflection->isAbstract()) {
156 throw InvalidArgumentException::fromAbstractClass($reflection);
157 }
158
159 return $reflection;
160 }
161
162 /**
163 * @phpstan-param ReflectionClass<T> $reflectionClass
164 *
165 * @throws UnexpectedValueException
166 *
167 * @template T of object
168 */
169 private function checkIfUnSerializationIsSupported(ReflectionClass $reflectionClass, string $serializedString): void
170 {
171 set_error_handler(static function (int $code, string $message, string $file, int $line) use ($reflectionClass, &$error): bool {
172 $error = UnexpectedValueException::fromUncleanUnSerialization(
173 $reflectionClass,
174 $message,
175 $code,
176 $file,
177 $line,
178 );
179
180 return true;
181 });
182
183 try {
184 $this->attemptInstantiationViaUnSerialization($reflectionClass, $serializedString);
185 } finally {
186 restore_error_handler();
187 }
188
189 if ($error) {
190 throw $error;
191 }
192 }
193
194 /**
195 * @phpstan-param ReflectionClass<T> $reflectionClass
196 *
197 * @throws UnexpectedValueException
198 *
199 * @template T of object
200 */
201 private function attemptInstantiationViaUnSerialization(ReflectionClass $reflectionClass, string $serializedString): void
202 {
203 try {
204 unserialize($serializedString);
205 } catch (Exception $exception) {
206 throw UnexpectedValueException::fromSerializationTriggeredException($reflectionClass, $exception);
207 }
208 }
209
210 /**
211 * @phpstan-param ReflectionClass<T> $reflectionClass
212 *
213 * @template T of object
214 */
215 private function isInstantiableViaReflection(ReflectionClass $reflectionClass): bool
216 {
217 return ! ($this->hasInternalAncestors($reflectionClass) && $reflectionClass->isFinal());
218 }
219
220 /**
221 * Verifies whether the given class is to be considered internal
222 *
223 * @phpstan-param ReflectionClass<T> $reflectionClass
224 *
225 * @template T of object
226 */
227 private function hasInternalAncestors(ReflectionClass $reflectionClass): bool
228 {
229 do {
230 if ($reflectionClass->isInternal()) {
231 return true;
232 }
233
234 $reflectionClass = $reflectionClass->getParentClass();
235 } while ($reflectionClass);
236
237 return false;
238 }
239
240 /**
241 * Checks if a class is cloneable
242 *
243 * Classes implementing `__clone` cannot be safely cloned, as that may cause side-effects.
244 *
245 * @phpstan-param ReflectionClass<T> $reflectionClass
246 *
247 * @template T of object
248 */
249 private function isSafeToClone(ReflectionClass $reflectionClass): bool
250 {
251 return $reflectionClass->isCloneable()
252 && ! $reflectionClass->hasMethod('__clone')
253 && ! $reflectionClass->isSubclassOf(ArrayIterator::class);
254 }
255}
diff --git a/vendor/doctrine/instantiator/src/Doctrine/Instantiator/InstantiatorInterface.php b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/InstantiatorInterface.php
new file mode 100644
index 0000000..c6ebe35
--- /dev/null
+++ b/vendor/doctrine/instantiator/src/Doctrine/Instantiator/InstantiatorInterface.php
@@ -0,0 +1,24 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Instantiator;
6
7use Doctrine\Instantiator\Exception\ExceptionInterface;
8
9/**
10 * Instantiator provides utility methods to build objects without invoking their constructors
11 */
12interface InstantiatorInterface
13{
14 /**
15 * @phpstan-param class-string<T> $className
16 *
17 * @phpstan-return T
18 *
19 * @throws ExceptionInterface
20 *
21 * @template T of object
22 */
23 public function instantiate(string $className): object;
24}