summaryrefslogtreecommitdiff
path: root/vendor/symfony/var-exporter
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/symfony/var-exporter
parent94d67a4b51f8e62e7d518cce26a526ae1ec48278 (diff)
downloadAppliGestionPHP-bf6655a534a6775d30cafa67bd801276bda1d98d.zip
VERSION 0.2 doctrine ORM et entités
Diffstat (limited to 'vendor/symfony/var-exporter')
-rw-r--r--vendor/symfony/var-exporter/CHANGELOG.md25
-rw-r--r--vendor/symfony/var-exporter/Exception/ClassNotFoundException.php20
-rw-r--r--vendor/symfony/var-exporter/Exception/ExceptionInterface.php16
-rw-r--r--vendor/symfony/var-exporter/Exception/LogicException.php16
-rw-r--r--vendor/symfony/var-exporter/Exception/NotInstantiableTypeException.php20
-rw-r--r--vendor/symfony/var-exporter/Hydrator.php78
-rw-r--r--vendor/symfony/var-exporter/Instantiator.php59
-rw-r--r--vendor/symfony/var-exporter/Internal/Exporter.php418
-rw-r--r--vendor/symfony/var-exporter/Internal/Hydrator.php299
-rw-r--r--vendor/symfony/var-exporter/Internal/LazyObjectRegistry.php138
-rw-r--r--vendor/symfony/var-exporter/Internal/LazyObjectState.php97
-rw-r--r--vendor/symfony/var-exporter/Internal/LazyObjectTrait.php34
-rw-r--r--vendor/symfony/var-exporter/Internal/Reference.php28
-rw-r--r--vendor/symfony/var-exporter/Internal/Registry.php142
-rw-r--r--vendor/symfony/var-exporter/Internal/Values.php25
-rw-r--r--vendor/symfony/var-exporter/LICENSE19
-rw-r--r--vendor/symfony/var-exporter/LazyGhostTrait.php352
-rw-r--r--vendor/symfony/var-exporter/LazyObjectInterface.php32
-rw-r--r--vendor/symfony/var-exporter/LazyProxyTrait.php359
-rw-r--r--vendor/symfony/var-exporter/ProxyHelper.php413
-rw-r--r--vendor/symfony/var-exporter/README.md137
-rw-r--r--vendor/symfony/var-exporter/VarExporter.php114
-rw-r--r--vendor/symfony/var-exporter/composer.json33
23 files changed, 2874 insertions, 0 deletions
diff --git a/vendor/symfony/var-exporter/CHANGELOG.md b/vendor/symfony/var-exporter/CHANGELOG.md
new file mode 100644
index 0000000..fdca002
--- /dev/null
+++ b/vendor/symfony/var-exporter/CHANGELOG.md
@@ -0,0 +1,25 @@
1CHANGELOG
2=========
3
46.4
5---
6
7 * Deprecate per-property lazy-initializers
8
96.2
10---
11
12 * Add support for lazy ghost objects and virtual proxies
13 * Add `Hydrator::hydrate()`
14 * Preserve PHP references also when using `Hydrator::hydrate()` or `Instantiator::instantiate()`
15 * Add support for hydrating from native (array) casts
16
175.1.0
18-----
19
20 * added argument `array &$foundClasses` to `VarExporter::export()` to ease with preloading exported values
21
224.2.0
23-----
24
25 * added the component
diff --git a/vendor/symfony/var-exporter/Exception/ClassNotFoundException.php b/vendor/symfony/var-exporter/Exception/ClassNotFoundException.php
new file mode 100644
index 0000000..379a765
--- /dev/null
+++ b/vendor/symfony/var-exporter/Exception/ClassNotFoundException.php
@@ -0,0 +1,20 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\VarExporter\Exception;
13
14class ClassNotFoundException extends \Exception implements ExceptionInterface
15{
16 public function __construct(string $class, ?\Throwable $previous = null)
17 {
18 parent::__construct(sprintf('Class "%s" not found.', $class), 0, $previous);
19 }
20}
diff --git a/vendor/symfony/var-exporter/Exception/ExceptionInterface.php b/vendor/symfony/var-exporter/Exception/ExceptionInterface.php
new file mode 100644
index 0000000..adfaed4
--- /dev/null
+++ b/vendor/symfony/var-exporter/Exception/ExceptionInterface.php
@@ -0,0 +1,16 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\VarExporter\Exception;
13
14interface ExceptionInterface extends \Throwable
15{
16}
diff --git a/vendor/symfony/var-exporter/Exception/LogicException.php b/vendor/symfony/var-exporter/Exception/LogicException.php
new file mode 100644
index 0000000..619d055
--- /dev/null
+++ b/vendor/symfony/var-exporter/Exception/LogicException.php
@@ -0,0 +1,16 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\VarExporter\Exception;
13
14class LogicException extends \LogicException implements ExceptionInterface
15{
16}
diff --git a/vendor/symfony/var-exporter/Exception/NotInstantiableTypeException.php b/vendor/symfony/var-exporter/Exception/NotInstantiableTypeException.php
new file mode 100644
index 0000000..b9ba225
--- /dev/null
+++ b/vendor/symfony/var-exporter/Exception/NotInstantiableTypeException.php
@@ -0,0 +1,20 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\VarExporter\Exception;
13
14class NotInstantiableTypeException extends \Exception implements ExceptionInterface
15{
16 public function __construct(string $type, ?\Throwable $previous = null)
17 {
18 parent::__construct(sprintf('Type "%s" is not instantiable.', $type), 0, $previous);
19 }
20}
diff --git a/vendor/symfony/var-exporter/Hydrator.php b/vendor/symfony/var-exporter/Hydrator.php
new file mode 100644
index 0000000..5f456fb
--- /dev/null
+++ b/vendor/symfony/var-exporter/Hydrator.php
@@ -0,0 +1,78 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\VarExporter;
13
14use Symfony\Component\VarExporter\Internal\Hydrator as InternalHydrator;
15
16/**
17 * Utility class to hydrate the properties of an object.
18 *
19 * @author Nicolas Grekas <p@tchwork.com>
20 */
21final class Hydrator
22{
23 /**
24 * Sets the properties of an object, including private and protected ones.
25 *
26 * For example:
27 *
28 * // Sets the public or protected $object->propertyName property
29 * Hydrator::hydrate($object, ['propertyName' => $propertyValue]);
30 *
31 * // Sets a private property defined on its parent Bar class:
32 * Hydrator::hydrate($object, ["\0Bar\0privateBarProperty" => $propertyValue]);
33 *
34 * // Alternative way to set the private $object->privateBarProperty property
35 * Hydrator::hydrate($object, [], [
36 * Bar::class => ['privateBarProperty' => $propertyValue],
37 * ]);
38 *
39 * Instances of ArrayObject, ArrayIterator and SplObjectStorage can be hydrated
40 * by using the special "\0" property name to define their internal value:
41 *
42 * // Hydrates an SplObjectStorage where $info1 is attached to $obj1, etc.
43 * Hydrator::hydrate($object, ["\0" => [$obj1, $info1, $obj2, $info2...]]);
44 *
45 * // Hydrates an ArrayObject populated with $inputArray
46 * Hydrator::hydrate($object, ["\0" => [$inputArray]]);
47 *
48 * @template T of object
49 *
50 * @param T $instance The object to hydrate
51 * @param array<string, mixed> $properties The properties to set on the instance
52 * @param array<class-string, array<string, mixed>> $scopedProperties The properties to set on the instance,
53 * keyed by their declaring class
54 *
55 * @return T
56 */
57 public static function hydrate(object $instance, array $properties = [], array $scopedProperties = []): object
58 {
59 if ($properties) {
60 $class = $instance::class;
61 $propertyScopes = InternalHydrator::$propertyScopes[$class] ??= InternalHydrator::getPropertyScopes($class);
62
63 foreach ($properties as $name => &$value) {
64 [$scope, $name, $readonlyScope] = $propertyScopes[$name] ?? [$class, $name, $class];
65 $scopedProperties[$readonlyScope ?? $scope][$name] = &$value;
66 }
67 unset($value);
68 }
69
70 foreach ($scopedProperties as $scope => $properties) {
71 if ($properties) {
72 (InternalHydrator::$simpleHydrators[$scope] ??= InternalHydrator::getSimpleHydrator($scope))($properties, $instance);
73 }
74 }
75
76 return $instance;
77 }
78}
diff --git a/vendor/symfony/var-exporter/Instantiator.php b/vendor/symfony/var-exporter/Instantiator.php
new file mode 100644
index 0000000..10200c0
--- /dev/null
+++ b/vendor/symfony/var-exporter/Instantiator.php
@@ -0,0 +1,59 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\VarExporter;
13
14use Symfony\Component\VarExporter\Exception\ExceptionInterface;
15use Symfony\Component\VarExporter\Exception\NotInstantiableTypeException;
16use Symfony\Component\VarExporter\Internal\Registry;
17
18/**
19 * A utility class to create objects without calling their constructor.
20 *
21 * @author Nicolas Grekas <p@tchwork.com>
22 */
23final class Instantiator
24{
25 /**
26 * Creates an object and sets its properties without calling its constructor nor any other methods.
27 *
28 * @see Hydrator::hydrate() for examples
29 *
30 * @template T of object
31 *
32 * @param class-string<T> $class The class of the instance to create
33 * @param array<string, mixed> $properties The properties to set on the instance
34 * @param array<class-string, array<string, mixed>> $scopedProperties The properties to set on the instance,
35 * keyed by their declaring class
36 *
37 * @return T
38 *
39 * @throws ExceptionInterface When the instance cannot be created
40 */
41 public static function instantiate(string $class, array $properties = [], array $scopedProperties = []): object
42 {
43 $reflector = Registry::$reflectors[$class] ??= Registry::getClassReflector($class);
44
45 if (Registry::$cloneable[$class]) {
46 $instance = clone Registry::$prototypes[$class];
47 } elseif (Registry::$instantiableWithoutConstructor[$class]) {
48 $instance = $reflector->newInstanceWithoutConstructor();
49 } elseif (null === Registry::$prototypes[$class]) {
50 throw new NotInstantiableTypeException($class);
51 } elseif ($reflector->implementsInterface('Serializable') && !method_exists($class, '__unserialize')) {
52 $instance = unserialize('C:'.\strlen($class).':"'.$class.'":0:{}');
53 } else {
54 $instance = unserialize('O:'.\strlen($class).':"'.$class.'":0:{}');
55 }
56
57 return $properties || $scopedProperties ? Hydrator::hydrate($instance, $properties, $scopedProperties) : $instance;
58 }
59}
diff --git a/vendor/symfony/var-exporter/Internal/Exporter.php b/vendor/symfony/var-exporter/Internal/Exporter.php
new file mode 100644
index 0000000..9f4f593
--- /dev/null
+++ b/vendor/symfony/var-exporter/Internal/Exporter.php
@@ -0,0 +1,418 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\VarExporter\Internal;
13
14use Symfony\Component\VarExporter\Exception\NotInstantiableTypeException;
15
16/**
17 * @author Nicolas Grekas <p@tchwork.com>
18 *
19 * @internal
20 */
21class Exporter
22{
23 /**
24 * Prepares an array of values for VarExporter.
25 *
26 * For performance this method is public and has no type-hints.
27 *
28 * @param array &$values
29 * @param \SplObjectStorage $objectsPool
30 * @param array &$refsPool
31 * @param int &$objectsCount
32 * @param bool &$valuesAreStatic
33 *
34 * @return array
35 *
36 * @throws NotInstantiableTypeException When a value cannot be serialized
37 */
38 public static function prepare($values, $objectsPool, &$refsPool, &$objectsCount, &$valuesAreStatic)
39 {
40 $refs = $values;
41 foreach ($values as $k => $value) {
42 if (\is_resource($value)) {
43 throw new NotInstantiableTypeException(get_resource_type($value).' resource');
44 }
45 $refs[$k] = $objectsPool;
46
47 if ($isRef = !$valueIsStatic = $values[$k] !== $objectsPool) {
48 $values[$k] = &$value; // Break hard references to make $values completely
49 unset($value); // independent from the original structure
50 $refs[$k] = $value = $values[$k];
51 if ($value instanceof Reference && 0 > $value->id) {
52 $valuesAreStatic = false;
53 ++$value->count;
54 continue;
55 }
56 $refsPool[] = [&$refs[$k], $value, &$value];
57 $refs[$k] = $values[$k] = new Reference(-\count($refsPool), $value);
58 }
59
60 if (\is_array($value)) {
61 if ($value) {
62 $value = self::prepare($value, $objectsPool, $refsPool, $objectsCount, $valueIsStatic);
63 }
64 goto handle_value;
65 } elseif (!\is_object($value) || $value instanceof \UnitEnum) {
66 goto handle_value;
67 }
68
69 $valueIsStatic = false;
70 if (isset($objectsPool[$value])) {
71 ++$objectsCount;
72 $value = new Reference($objectsPool[$value][0]);
73 goto handle_value;
74 }
75
76 $class = $value::class;
77 $reflector = Registry::$reflectors[$class] ??= Registry::getClassReflector($class);
78 $properties = [];
79
80 if ($reflector->hasMethod('__serialize')) {
81 if (!$reflector->getMethod('__serialize')->isPublic()) {
82 throw new \Error(sprintf('Call to %s method "%s::__serialize()".', $reflector->getMethod('__serialize')->isProtected() ? 'protected' : 'private', $class));
83 }
84
85 if (!\is_array($serializeProperties = $value->__serialize())) {
86 throw new \TypeError($class.'::__serialize() must return an array');
87 }
88
89 if ($reflector->hasMethod('__unserialize')) {
90 $properties = $serializeProperties;
91 } else {
92 foreach ($serializeProperties as $n => $v) {
93 $c = $reflector->hasProperty($n) && ($p = $reflector->getProperty($n))->isReadOnly() ? $p->class : 'stdClass';
94 $properties[$c][$n] = $v;
95 }
96 }
97
98 goto prepare_value;
99 }
100
101 $sleep = null;
102 $proto = Registry::$prototypes[$class];
103
104 if (($value instanceof \ArrayIterator || $value instanceof \ArrayObject) && null !== $proto) {
105 // ArrayIterator and ArrayObject need special care because their "flags"
106 // option changes the behavior of the (array) casting operator.
107 [$arrayValue, $properties] = self::getArrayObjectProperties($value, $proto);
108
109 // populates Registry::$prototypes[$class] with a new instance
110 Registry::getClassReflector($class, Registry::$instantiableWithoutConstructor[$class], Registry::$cloneable[$class]);
111 } elseif ($value instanceof \SplObjectStorage && Registry::$cloneable[$class] && null !== $proto) {
112 // By implementing Serializable, SplObjectStorage breaks
113 // internal references; let's deal with it on our own.
114 foreach (clone $value as $v) {
115 $properties[] = $v;
116 $properties[] = $value[$v];
117 }
118 $properties = ['SplObjectStorage' => ["\0" => $properties]];
119 $arrayValue = (array) $value;
120 } elseif ($value instanceof \Serializable
121 || $value instanceof \__PHP_Incomplete_Class
122 ) {
123 ++$objectsCount;
124 $objectsPool[$value] = [$id = \count($objectsPool), serialize($value), [], 0];
125 $value = new Reference($id);
126 goto handle_value;
127 } else {
128 if (method_exists($class, '__sleep')) {
129 if (!\is_array($sleep = $value->__sleep())) {
130 trigger_error('serialize(): __sleep should return an array only containing the names of instance-variables to serialize', \E_USER_NOTICE);
131 $value = null;
132 goto handle_value;
133 }
134 $sleep = array_flip($sleep);
135 }
136
137 $arrayValue = (array) $value;
138 }
139
140 $proto = (array) $proto;
141
142 foreach ($arrayValue as $name => $v) {
143 $i = 0;
144 $n = (string) $name;
145 if ('' === $n || "\0" !== $n[0]) {
146 $c = $reflector->hasProperty($n) && ($p = $reflector->getProperty($n))->isReadOnly() ? $p->class : 'stdClass';
147 } elseif ('*' === $n[1]) {
148 $n = substr($n, 3);
149 $c = $reflector->getProperty($n)->class;
150 if ('Error' === $c) {
151 $c = 'TypeError';
152 } elseif ('Exception' === $c) {
153 $c = 'ErrorException';
154 }
155 } else {
156 $i = strpos($n, "\0", 2);
157 $c = substr($n, 1, $i - 1);
158 $n = substr($n, 1 + $i);
159 }
160 if (null !== $sleep) {
161 if (!isset($sleep[$name]) && (!isset($sleep[$n]) || ($i && $c !== $class))) {
162 unset($arrayValue[$name]);
163 continue;
164 }
165 unset($sleep[$name], $sleep[$n]);
166 }
167 if (!\array_key_exists($name, $proto) || $proto[$name] !== $v || "\x00Error\x00trace" === $name || "\x00Exception\x00trace" === $name) {
168 $properties[$c][$n] = $v;
169 }
170 }
171 if ($sleep) {
172 foreach ($sleep as $n => $v) {
173 trigger_error(sprintf('serialize(): "%s" returned as member variable from __sleep() but does not exist', $n), \E_USER_NOTICE);
174 }
175 }
176 if (method_exists($class, '__unserialize')) {
177 $properties = $arrayValue;
178 }
179
180 prepare_value:
181 $objectsPool[$value] = [$id = \count($objectsPool)];
182 $properties = self::prepare($properties, $objectsPool, $refsPool, $objectsCount, $valueIsStatic);
183 ++$objectsCount;
184 $objectsPool[$value] = [$id, $class, $properties, method_exists($class, '__unserialize') ? -$objectsCount : (method_exists($class, '__wakeup') ? $objectsCount : 0)];
185
186 $value = new Reference($id);
187
188 handle_value:
189 if ($isRef) {
190 unset($value); // Break the hard reference created above
191 } elseif (!$valueIsStatic) {
192 $values[$k] = $value;
193 }
194 $valuesAreStatic = $valueIsStatic && $valuesAreStatic;
195 }
196
197 return $values;
198 }
199
200 public static function export($value, $indent = '')
201 {
202 switch (true) {
203 case \is_int($value) || \is_float($value): return var_export($value, true);
204 case [] === $value: return '[]';
205 case false === $value: return 'false';
206 case true === $value: return 'true';
207 case null === $value: return 'null';
208 case '' === $value: return "''";
209 case $value instanceof \UnitEnum: return '\\'.ltrim(var_export($value, true), '\\');
210 }
211
212 if ($value instanceof Reference) {
213 if (0 <= $value->id) {
214 return '$o['.$value->id.']';
215 }
216 if (!$value->count) {
217 return self::export($value->value, $indent);
218 }
219 $value = -$value->id;
220
221 return '&$r['.$value.']';
222 }
223 $subIndent = $indent.' ';
224
225 if (\is_string($value)) {
226 $code = sprintf("'%s'", addcslashes($value, "'\\"));
227
228 $code = preg_replace_callback("/((?:[\\0\\r\\n]|\u{202A}|\u{202B}|\u{202D}|\u{202E}|\u{2066}|\u{2067}|\u{2068}|\u{202C}|\u{2069})++)(.)/", function ($m) use ($subIndent) {
229 $m[1] = sprintf('\'."%s".\'', str_replace(
230 ["\0", "\r", "\n", "\u{202A}", "\u{202B}", "\u{202D}", "\u{202E}", "\u{2066}", "\u{2067}", "\u{2068}", "\u{202C}", "\u{2069}", '\n\\'],
231 ['\0', '\r', '\n', '\u{202A}', '\u{202B}', '\u{202D}', '\u{202E}', '\u{2066}', '\u{2067}', '\u{2068}', '\u{202C}', '\u{2069}', '\n"'."\n".$subIndent.'."\\'],
232 $m[1]
233 ));
234
235 if ("'" === $m[2]) {
236 return substr($m[1], 0, -2);
237 }
238
239 if (str_ends_with($m[1], 'n".\'')) {
240 return substr_replace($m[1], "\n".$subIndent.".'".$m[2], -2);
241 }
242
243 return $m[1].$m[2];
244 }, $code, -1, $count);
245
246 if ($count && str_starts_with($code, "''.")) {
247 $code = substr($code, 3);
248 }
249
250 return $code;
251 }
252
253 if (\is_array($value)) {
254 $j = -1;
255 $code = '';
256 foreach ($value as $k => $v) {
257 $code .= $subIndent;
258 if (!\is_int($k) || 1 !== $k - $j) {
259 $code .= self::export($k, $subIndent).' => ';
260 }
261 if (\is_int($k) && $k > $j) {
262 $j = $k;
263 }
264 $code .= self::export($v, $subIndent).",\n";
265 }
266
267 return "[\n".$code.$indent.']';
268 }
269
270 if ($value instanceof Values) {
271 $code = $subIndent."\$r = [],\n";
272 foreach ($value->values as $k => $v) {
273 $code .= $subIndent.'$r['.$k.'] = '.self::export($v, $subIndent).",\n";
274 }
275
276 return "[\n".$code.$indent.']';
277 }
278
279 if ($value instanceof Registry) {
280 return self::exportRegistry($value, $indent, $subIndent);
281 }
282
283 if ($value instanceof Hydrator) {
284 return self::exportHydrator($value, $indent, $subIndent);
285 }
286
287 throw new \UnexpectedValueException(sprintf('Cannot export value of type "%s".', get_debug_type($value)));
288 }
289
290 private static function exportRegistry(Registry $value, string $indent, string $subIndent): string
291 {
292 $code = '';
293 $serializables = [];
294 $seen = [];
295 $prototypesAccess = 0;
296 $factoriesAccess = 0;
297 $r = '\\'.Registry::class;
298 $j = -1;
299
300 foreach ($value->classes as $k => $class) {
301 if (':' === ($class[1] ?? null)) {
302 $serializables[$k] = $class;
303 continue;
304 }
305 if (!Registry::$instantiableWithoutConstructor[$class]) {
306 if (is_subclass_of($class, 'Serializable') && !method_exists($class, '__unserialize')) {
307 $serializables[$k] = 'C:'.\strlen($class).':"'.$class.'":0:{}';
308 } else {
309 $serializables[$k] = 'O:'.\strlen($class).':"'.$class.'":0:{}';
310 }
311 if (is_subclass_of($class, 'Throwable')) {
312 $eol = is_subclass_of($class, 'Error') ? "\0Error\0" : "\0Exception\0";
313 $serializables[$k] = substr_replace($serializables[$k], '1:{s:'.(5 + \strlen($eol)).':"'.$eol.'trace";a:0:{}}', -4);
314 }
315 continue;
316 }
317 $code .= $subIndent.(1 !== $k - $j ? $k.' => ' : '');
318 $j = $k;
319 $eol = ",\n";
320 $c = '['.self::export($class).']';
321
322 if ($seen[$class] ?? false) {
323 if (Registry::$cloneable[$class]) {
324 ++$prototypesAccess;
325 $code .= 'clone $p'.$c;
326 } else {
327 ++$factoriesAccess;
328 $code .= '$f'.$c.'()';
329 }
330 } else {
331 $seen[$class] = true;
332 if (Registry::$cloneable[$class]) {
333 $code .= 'clone ('.($prototypesAccess++ ? '$p' : '($p = &'.$r.'::$prototypes)').$c.' ?? '.$r.'::p';
334 } else {
335 $code .= '('.($factoriesAccess++ ? '$f' : '($f = &'.$r.'::$factories)').$c.' ?? '.$r.'::f';
336 $eol = '()'.$eol;
337 }
338 $code .= '('.substr($c, 1, -1).'))';
339 }
340 $code .= $eol;
341 }
342
343 if (1 === $prototypesAccess) {
344 $code = str_replace('($p = &'.$r.'::$prototypes)', $r.'::$prototypes', $code);
345 }
346 if (1 === $factoriesAccess) {
347 $code = str_replace('($f = &'.$r.'::$factories)', $r.'::$factories', $code);
348 }
349 if ('' !== $code) {
350 $code = "\n".$code.$indent;
351 }
352
353 if ($serializables) {
354 $code = $r.'::unserialize(['.$code.'], '.self::export($serializables, $indent).')';
355 } else {
356 $code = '['.$code.']';
357 }
358
359 return '$o = '.$code;
360 }
361
362 private static function exportHydrator(Hydrator $value, string $indent, string $subIndent): string
363 {
364 $code = '';
365 foreach ($value->properties as $class => $properties) {
366 $code .= $subIndent.' '.self::export($class).' => '.self::export($properties, $subIndent.' ').",\n";
367 }
368
369 $code = [
370 self::export($value->registry, $subIndent),
371 self::export($value->values, $subIndent),
372 '' !== $code ? "[\n".$code.$subIndent.']' : '[]',
373 self::export($value->value, $subIndent),
374 self::export($value->wakeups, $subIndent),
375 ];
376
377 return '\\'.$value::class."::hydrate(\n".$subIndent.implode(",\n".$subIndent, $code)."\n".$indent.')';
378 }
379
380 /**
381 * @param \ArrayIterator|\ArrayObject $value
382 * @param \ArrayIterator|\ArrayObject $proto
383 */
384 private static function getArrayObjectProperties($value, $proto): array
385 {
386 $reflector = $value instanceof \ArrayIterator ? 'ArrayIterator' : 'ArrayObject';
387 $reflector = Registry::$reflectors[$reflector] ??= Registry::getClassReflector($reflector);
388
389 $properties = [
390 $arrayValue = (array) $value,
391 $reflector->getMethod('getFlags')->invoke($value),
392 $value instanceof \ArrayObject ? $reflector->getMethod('getIteratorClass')->invoke($value) : 'ArrayIterator',
393 ];
394
395 $reflector = $reflector->getMethod('setFlags');
396 $reflector->invoke($proto, \ArrayObject::STD_PROP_LIST);
397
398 if ($properties[1] & \ArrayObject::STD_PROP_LIST) {
399 $reflector->invoke($value, 0);
400 $properties[0] = (array) $value;
401 } else {
402 $reflector->invoke($value, \ArrayObject::STD_PROP_LIST);
403 $arrayValue = (array) $value;
404 }
405 $reflector->invoke($value, $properties[1]);
406
407 if ([[], 0, 'ArrayIterator'] === $properties) {
408 $properties = [];
409 } else {
410 if ('ArrayIterator' === $properties[2]) {
411 unset($properties[2]);
412 }
413 $properties = [$reflector->class => ["\0" => $properties]];
414 }
415
416 return [$arrayValue, $properties];
417 }
418}
diff --git a/vendor/symfony/var-exporter/Internal/Hydrator.php b/vendor/symfony/var-exporter/Internal/Hydrator.php
new file mode 100644
index 0000000..65fdcd1
--- /dev/null
+++ b/vendor/symfony/var-exporter/Internal/Hydrator.php
@@ -0,0 +1,299 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\VarExporter\Internal;
13
14use Symfony\Component\VarExporter\Exception\ClassNotFoundException;
15
16/**
17 * @author Nicolas Grekas <p@tchwork.com>
18 *
19 * @internal
20 */
21class Hydrator
22{
23 public static array $hydrators = [];
24 public static array $simpleHydrators = [];
25 public static array $propertyScopes = [];
26
27 public function __construct(
28 public readonly Registry $registry,
29 public readonly ?Values $values,
30 public readonly array $properties,
31 public readonly mixed $value,
32 public readonly array $wakeups,
33 ) {
34 }
35
36 public static function hydrate($objects, $values, $properties, $value, $wakeups)
37 {
38 foreach ($properties as $class => $vars) {
39 (self::$hydrators[$class] ??= self::getHydrator($class))($vars, $objects);
40 }
41 foreach ($wakeups as $k => $v) {
42 if (\is_array($v)) {
43 $objects[-$k]->__unserialize($v);
44 } else {
45 $objects[$v]->__wakeup();
46 }
47 }
48
49 return $value;
50 }
51
52 public static function getHydrator($class)
53 {
54 $baseHydrator = self::$hydrators['stdClass'] ??= static function ($properties, $objects) {
55 foreach ($properties as $name => $values) {
56 foreach ($values as $i => $v) {
57 $objects[$i]->$name = $v;
58 }
59 }
60 };
61
62 switch ($class) {
63 case 'stdClass':
64 return $baseHydrator;
65
66 case 'ErrorException':
67 return $baseHydrator->bindTo(null, new class() extends \ErrorException {
68 });
69
70 case 'TypeError':
71 return $baseHydrator->bindTo(null, new class() extends \Error {
72 });
73
74 case 'SplObjectStorage':
75 return static function ($properties, $objects) {
76 foreach ($properties as $name => $values) {
77 if ("\0" === $name) {
78 foreach ($values as $i => $v) {
79 for ($j = 0; $j < \count($v); ++$j) {
80 $objects[$i]->attach($v[$j], $v[++$j]);
81 }
82 }
83 continue;
84 }
85 foreach ($values as $i => $v) {
86 $objects[$i]->$name = $v;
87 }
88 }
89 };
90 }
91
92 if (!class_exists($class) && !interface_exists($class, false) && !trait_exists($class, false)) {
93 throw new ClassNotFoundException($class);
94 }
95 $classReflector = new \ReflectionClass($class);
96
97 switch ($class) {
98 case 'ArrayIterator':
99 case 'ArrayObject':
100 $constructor = $classReflector->getConstructor()->invokeArgs(...);
101
102 return static function ($properties, $objects) use ($constructor) {
103 foreach ($properties as $name => $values) {
104 if ("\0" !== $name) {
105 foreach ($values as $i => $v) {
106 $objects[$i]->$name = $v;
107 }
108 }
109 }
110 foreach ($properties["\0"] ?? [] as $i => $v) {
111 $constructor($objects[$i], $v);
112 }
113 };
114 }
115
116 if (!$classReflector->isInternal()) {
117 return $baseHydrator->bindTo(null, $class);
118 }
119
120 if ($classReflector->name !== $class) {
121 return self::$hydrators[$classReflector->name] ??= self::getHydrator($classReflector->name);
122 }
123
124 $propertySetters = [];
125 foreach ($classReflector->getProperties() as $propertyReflector) {
126 if (!$propertyReflector->isStatic()) {
127 $propertySetters[$propertyReflector->name] = $propertyReflector->setValue(...);
128 }
129 }
130
131 if (!$propertySetters) {
132 return $baseHydrator;
133 }
134
135 return static function ($properties, $objects) use ($propertySetters) {
136 foreach ($properties as $name => $values) {
137 if ($setValue = $propertySetters[$name] ?? null) {
138 foreach ($values as $i => $v) {
139 $setValue($objects[$i], $v);
140 }
141 continue;
142 }
143 foreach ($values as $i => $v) {
144 $objects[$i]->$name = $v;
145 }
146 }
147 };
148 }
149
150 public static function getSimpleHydrator($class)
151 {
152 $baseHydrator = self::$simpleHydrators['stdClass'] ??= (function ($properties, $object) {
153 $readonly = (array) $this;
154
155 foreach ($properties as $name => &$value) {
156 $object->$name = $value;
157
158 if (!($readonly[$name] ?? false)) {
159 $object->$name = &$value;
160 }
161 }
162 })->bindTo(new \stdClass());
163
164 switch ($class) {
165 case 'stdClass':
166 return $baseHydrator;
167
168 case 'ErrorException':
169 return $baseHydrator->bindTo(new \stdClass(), new class() extends \ErrorException {
170 });
171
172 case 'TypeError':
173 return $baseHydrator->bindTo(new \stdClass(), new class() extends \Error {
174 });
175
176 case 'SplObjectStorage':
177 return static function ($properties, $object) {
178 foreach ($properties as $name => &$value) {
179 if ("\0" !== $name) {
180 $object->$name = $value;
181 $object->$name = &$value;
182 continue;
183 }
184 for ($i = 0; $i < \count($value); ++$i) {
185 $object->attach($value[$i], $value[++$i]);
186 }
187 }
188 };
189 }
190
191 if (!class_exists($class) && !interface_exists($class, false) && !trait_exists($class, false)) {
192 throw new ClassNotFoundException($class);
193 }
194 $classReflector = new \ReflectionClass($class);
195
196 switch ($class) {
197 case 'ArrayIterator':
198 case 'ArrayObject':
199 $constructor = $classReflector->getConstructor()->invokeArgs(...);
200
201 return static function ($properties, $object) use ($constructor) {
202 foreach ($properties as $name => &$value) {
203 if ("\0" === $name) {
204 $constructor($object, $value);
205 } else {
206 $object->$name = $value;
207 $object->$name = &$value;
208 }
209 }
210 };
211 }
212
213 if (!$classReflector->isInternal()) {
214 $readonly = new \stdClass();
215 foreach ($classReflector->getProperties(\ReflectionProperty::IS_READONLY) as $propertyReflector) {
216 if ($class === $propertyReflector->class) {
217 $readonly->{$propertyReflector->name} = true;
218 }
219 }
220
221 return $baseHydrator->bindTo($readonly, $class);
222 }
223
224 if ($classReflector->name !== $class) {
225 return self::$simpleHydrators[$classReflector->name] ??= self::getSimpleHydrator($classReflector->name);
226 }
227
228 $propertySetters = [];
229 foreach ($classReflector->getProperties() as $propertyReflector) {
230 if (!$propertyReflector->isStatic()) {
231 $propertySetters[$propertyReflector->name] = $propertyReflector->setValue(...);
232 }
233 }
234
235 if (!$propertySetters) {
236 return $baseHydrator;
237 }
238
239 return static function ($properties, $object) use ($propertySetters) {
240 foreach ($properties as $name => &$value) {
241 if ($setValue = $propertySetters[$name] ?? null) {
242 $setValue($object, $value);
243 } else {
244 $object->$name = $value;
245 $object->$name = &$value;
246 }
247 }
248 };
249 }
250
251 public static function getPropertyScopes($class): array
252 {
253 $propertyScopes = [];
254 $r = new \ReflectionClass($class);
255
256 foreach ($r->getProperties() as $property) {
257 $flags = $property->getModifiers();
258
259 if (\ReflectionProperty::IS_STATIC & $flags) {
260 continue;
261 }
262 $name = $property->name;
263
264 if (\ReflectionProperty::IS_PRIVATE & $flags) {
265 $readonlyScope = null;
266 if ($flags & \ReflectionProperty::IS_READONLY) {
267 $readonlyScope = $class;
268 }
269 $propertyScopes["\0$class\0$name"] = $propertyScopes[$name] = [$class, $name, $readonlyScope, $property];
270
271 continue;
272 }
273 $readonlyScope = null;
274 if ($flags & \ReflectionProperty::IS_READONLY) {
275 $readonlyScope = $property->class;
276 }
277 $propertyScopes[$name] = [$class, $name, $readonlyScope, $property];
278
279 if (\ReflectionProperty::IS_PROTECTED & $flags) {
280 $propertyScopes["\0*\0$name"] = $propertyScopes[$name];
281 }
282 }
283
284 while ($r = $r->getParentClass()) {
285 $class = $r->name;
286
287 foreach ($r->getProperties(\ReflectionProperty::IS_PRIVATE) as $property) {
288 if (!$property->isStatic()) {
289 $name = $property->name;
290 $readonlyScope = $property->isReadOnly() ? $class : null;
291 $propertyScopes["\0$class\0$name"] = [$class, $name, $readonlyScope, $property];
292 $propertyScopes[$name] ??= [$class, $name, $readonlyScope, $property];
293 }
294 }
295 }
296
297 return $propertyScopes;
298 }
299}
diff --git a/vendor/symfony/var-exporter/Internal/LazyObjectRegistry.php b/vendor/symfony/var-exporter/Internal/LazyObjectRegistry.php
new file mode 100644
index 0000000..f6450ce
--- /dev/null
+++ b/vendor/symfony/var-exporter/Internal/LazyObjectRegistry.php
@@ -0,0 +1,138 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\VarExporter\Internal;
13
14/**
15 * Stores the state of lazy objects and caches related reflection information.
16 *
17 * As a micro-optimization, this class uses no type declarations.
18 *
19 * @internal
20 */
21class LazyObjectRegistry
22{
23 /**
24 * @var array<class-string, \ReflectionClass>
25 */
26 public static array $classReflectors = [];
27
28 /**
29 * @var array<class-string, array<string, mixed>>
30 */
31 public static array $defaultProperties = [];
32
33 /**
34 * @var array<class-string, list<\Closure>>
35 */
36 public static array $classResetters = [];
37
38 /**
39 * @var array<class-string, array{get: \Closure, set: \Closure, isset: \Closure, unset: \Closure}>
40 */
41 public static array $classAccessors = [];
42
43 /**
44 * @var array<class-string, array{set: bool, isset: bool, unset: bool, clone: bool, serialize: bool, unserialize: bool, sleep: bool, wakeup: bool, destruct: bool, get: int}>
45 */
46 public static array $parentMethods = [];
47
48 public static ?\Closure $noInitializerState = null;
49
50 public static function getClassResetters($class)
51 {
52 $classProperties = [];
53
54 if ((self::$classReflectors[$class] ??= new \ReflectionClass($class))->isInternal()) {
55 $propertyScopes = [];
56 } else {
57 $propertyScopes = Hydrator::$propertyScopes[$class] ??= Hydrator::getPropertyScopes($class);
58 }
59
60 foreach ($propertyScopes as $key => [$scope, $name, $readonlyScope]) {
61 $propertyScopes[$k = "\0$scope\0$name"] ?? $propertyScopes[$k = "\0*\0$name"] ?? $k = $name;
62
63 if ($k === $key && "\0$class\0lazyObjectState" !== $k) {
64 $classProperties[$readonlyScope ?? $scope][$name] = $key;
65 }
66 }
67
68 $resetters = [];
69 foreach ($classProperties as $scope => $properties) {
70 $resetters[] = \Closure::bind(static function ($instance, $skippedProperties) use ($properties) {
71 foreach ($properties as $name => $key) {
72 if (!\array_key_exists($key, $skippedProperties)) {
73 unset($instance->$name);
74 }
75 }
76 }, null, $scope);
77 }
78
79 return $resetters;
80 }
81
82 public static function getClassAccessors($class)
83 {
84 return \Closure::bind(static fn () => [
85 'get' => static function &($instance, $name, $readonly) {
86 if (!$readonly) {
87 return $instance->$name;
88 }
89 $value = $instance->$name;
90
91 return $value;
92 },
93 'set' => static function ($instance, $name, $value) {
94 $instance->$name = $value;
95 },
96 'isset' => static fn ($instance, $name) => isset($instance->$name),
97 'unset' => static function ($instance, $name) {
98 unset($instance->$name);
99 },
100 ], null, \Closure::class === $class ? null : $class)();
101 }
102
103 public static function getParentMethods($class)
104 {
105 $parent = get_parent_class($class);
106 $methods = [];
107
108 foreach (['set', 'isset', 'unset', 'clone', 'serialize', 'unserialize', 'sleep', 'wakeup', 'destruct', 'get'] as $method) {
109 if (!$parent || !method_exists($parent, '__'.$method)) {
110 $methods[$method] = false;
111 } else {
112 $m = new \ReflectionMethod($parent, '__'.$method);
113 $methods[$method] = !$m->isAbstract() && !$m->isPrivate();
114 }
115 }
116
117 $methods['get'] = $methods['get'] ? ($m->returnsReference() ? 2 : 1) : 0;
118
119 return $methods;
120 }
121
122 public static function getScope($propertyScopes, $class, $property, $readonlyScope = null)
123 {
124 if (null === $readonlyScope && !isset($propertyScopes[$k = "\0$class\0$property"]) && !isset($propertyScopes[$k = "\0*\0$property"])) {
125 return null;
126 }
127 $frame = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT | \DEBUG_BACKTRACE_IGNORE_ARGS, 3)[2];
128
129 if (\ReflectionProperty::class === $scope = $frame['class'] ?? \Closure::class) {
130 $scope = $frame['object']->class;
131 }
132 if (null === $readonlyScope && '*' === $k[1] && ($class === $scope || (is_subclass_of($class, $scope) && !isset($propertyScopes["\0$scope\0$property"])))) {
133 return null;
134 }
135
136 return $scope;
137 }
138}
diff --git a/vendor/symfony/var-exporter/Internal/LazyObjectState.php b/vendor/symfony/var-exporter/Internal/LazyObjectState.php
new file mode 100644
index 0000000..5fc398e
--- /dev/null
+++ b/vendor/symfony/var-exporter/Internal/LazyObjectState.php
@@ -0,0 +1,97 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\VarExporter\Internal;
13
14use Symfony\Component\VarExporter\Hydrator as PublicHydrator;
15
16/**
17 * Keeps the state of lazy objects.
18 *
19 * As a micro-optimization, this class uses no type declarations.
20 *
21 * @internal
22 */
23class LazyObjectState
24{
25 public const STATUS_UNINITIALIZED_FULL = 1;
26 public const STATUS_UNINITIALIZED_PARTIAL = 2;
27 public const STATUS_INITIALIZED_FULL = 3;
28 public const STATUS_INITIALIZED_PARTIAL = 4;
29
30 /**
31 * @var self::STATUS_*
32 */
33 public int $status = self::STATUS_UNINITIALIZED_FULL;
34
35 public object $realInstance;
36
37 /**
38 * @param array<string, true> $skippedProperties
39 */
40 public function __construct(
41 public readonly \Closure $initializer,
42 public readonly array $skippedProperties = [],
43 ) {
44 }
45
46 public function initialize($instance, $propertyName, $propertyScope)
47 {
48 if (self::STATUS_UNINITIALIZED_FULL !== $this->status) {
49 return $this->status;
50 }
51
52 $this->status = self::STATUS_INITIALIZED_PARTIAL;
53
54 try {
55 if ($defaultProperties = array_diff_key(LazyObjectRegistry::$defaultProperties[$instance::class], $this->skippedProperties)) {
56 PublicHydrator::hydrate($instance, $defaultProperties);
57 }
58
59 ($this->initializer)($instance);
60 } catch (\Throwable $e) {
61 $this->status = self::STATUS_UNINITIALIZED_FULL;
62 $this->reset($instance);
63
64 throw $e;
65 }
66
67 return $this->status = self::STATUS_INITIALIZED_FULL;
68 }
69
70 public function reset($instance): void
71 {
72 $class = $instance::class;
73 $propertyScopes = Hydrator::$propertyScopes[$class] ??= Hydrator::getPropertyScopes($class);
74 $skippedProperties = $this->skippedProperties;
75 $properties = (array) $instance;
76
77 foreach ($propertyScopes as $key => [$scope, $name, $readonlyScope]) {
78 $propertyScopes[$k = "\0$scope\0$name"] ?? $propertyScopes[$k = "\0*\0$name"] ?? $k = $name;
79
80 if ($k === $key && (null !== $readonlyScope || !\array_key_exists($k, $properties))) {
81 $skippedProperties[$k] = true;
82 }
83 }
84
85 foreach (LazyObjectRegistry::$classResetters[$class] as $reset) {
86 $reset($instance, $skippedProperties);
87 }
88
89 foreach ((array) $instance as $name => $value) {
90 if ("\0" !== ($name[0] ?? '') && !\array_key_exists($name, $skippedProperties)) {
91 unset($instance->$name);
92 }
93 }
94
95 $this->status = self::STATUS_UNINITIALIZED_FULL;
96 }
97}
diff --git a/vendor/symfony/var-exporter/Internal/LazyObjectTrait.php b/vendor/symfony/var-exporter/Internal/LazyObjectTrait.php
new file mode 100644
index 0000000..4a6f232
--- /dev/null
+++ b/vendor/symfony/var-exporter/Internal/LazyObjectTrait.php
@@ -0,0 +1,34 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\VarExporter\Internal;
13
14use Symfony\Component\Serializer\Attribute\Ignore;
15
16if (\PHP_VERSION_ID >= 80300) {
17 /**
18 * @internal
19 */
20 trait LazyObjectTrait
21 {
22 #[Ignore]
23 private readonly LazyObjectState $lazyObjectState;
24 }
25} else {
26 /**
27 * @internal
28 */
29 trait LazyObjectTrait
30 {
31 #[Ignore]
32 private LazyObjectState $lazyObjectState;
33 }
34}
diff --git a/vendor/symfony/var-exporter/Internal/Reference.php b/vendor/symfony/var-exporter/Internal/Reference.php
new file mode 100644
index 0000000..2c7bd7b
--- /dev/null
+++ b/vendor/symfony/var-exporter/Internal/Reference.php
@@ -0,0 +1,28 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\VarExporter\Internal;
13
14/**
15 * @author Nicolas Grekas <p@tchwork.com>
16 *
17 * @internal
18 */
19class Reference
20{
21 public int $count = 0;
22
23 public function __construct(
24 public readonly int $id,
25 public readonly mixed $value = null,
26 ) {
27 }
28}
diff --git a/vendor/symfony/var-exporter/Internal/Registry.php b/vendor/symfony/var-exporter/Internal/Registry.php
new file mode 100644
index 0000000..9c41684
--- /dev/null
+++ b/vendor/symfony/var-exporter/Internal/Registry.php
@@ -0,0 +1,142 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\VarExporter\Internal;
13
14use Symfony\Component\VarExporter\Exception\ClassNotFoundException;
15use Symfony\Component\VarExporter\Exception\NotInstantiableTypeException;
16
17/**
18 * @author Nicolas Grekas <p@tchwork.com>
19 *
20 * @internal
21 */
22class Registry
23{
24 public static array $reflectors = [];
25 public static array $prototypes = [];
26 public static array $factories = [];
27 public static array $cloneable = [];
28 public static array $instantiableWithoutConstructor = [];
29
30 public function __construct(
31 public readonly array $classes,
32 ) {
33 }
34
35 public static function unserialize($objects, $serializables)
36 {
37 $unserializeCallback = ini_set('unserialize_callback_func', __CLASS__.'::getClassReflector');
38
39 try {
40 foreach ($serializables as $k => $v) {
41 $objects[$k] = unserialize($v);
42 }
43 } finally {
44 ini_set('unserialize_callback_func', $unserializeCallback);
45 }
46
47 return $objects;
48 }
49
50 public static function p($class)
51 {
52 self::getClassReflector($class, true, true);
53
54 return self::$prototypes[$class];
55 }
56
57 public static function f($class)
58 {
59 $reflector = self::$reflectors[$class] ??= self::getClassReflector($class, true, false);
60
61 return self::$factories[$class] = [$reflector, 'newInstanceWithoutConstructor'](...);
62 }
63
64 public static function getClassReflector($class, $instantiableWithoutConstructor = false, $cloneable = null)
65 {
66 if (!($isClass = class_exists($class)) && !interface_exists($class, false) && !trait_exists($class, false)) {
67 throw new ClassNotFoundException($class);
68 }
69 $reflector = new \ReflectionClass($class);
70
71 if ($instantiableWithoutConstructor) {
72 $proto = $reflector->newInstanceWithoutConstructor();
73 } elseif (!$isClass || $reflector->isAbstract()) {
74 throw new NotInstantiableTypeException($class);
75 } elseif ($reflector->name !== $class) {
76 $reflector = self::$reflectors[$name = $reflector->name] ??= self::getClassReflector($name, false, $cloneable);
77 self::$cloneable[$class] = self::$cloneable[$name];
78 self::$instantiableWithoutConstructor[$class] = self::$instantiableWithoutConstructor[$name];
79 self::$prototypes[$class] = self::$prototypes[$name];
80
81 return $reflector;
82 } else {
83 try {
84 $proto = $reflector->newInstanceWithoutConstructor();
85 $instantiableWithoutConstructor = true;
86 } catch (\ReflectionException) {
87 $proto = $reflector->implementsInterface('Serializable') && !method_exists($class, '__unserialize') ? 'C:' : 'O:';
88 if ('C:' === $proto && !$reflector->getMethod('unserialize')->isInternal()) {
89 $proto = null;
90 } else {
91 try {
92 $proto = @unserialize($proto.\strlen($class).':"'.$class.'":0:{}');
93 } catch (\Exception $e) {
94 if (__FILE__ !== $e->getFile()) {
95 throw $e;
96 }
97 throw new NotInstantiableTypeException($class, $e);
98 }
99 if (false === $proto) {
100 throw new NotInstantiableTypeException($class);
101 }
102 }
103 }
104 if (null !== $proto && !$proto instanceof \Throwable && !$proto instanceof \Serializable && !method_exists($class, '__sleep') && !method_exists($class, '__serialize')) {
105 try {
106 serialize($proto);
107 } catch (\Exception $e) {
108 throw new NotInstantiableTypeException($class, $e);
109 }
110 }
111 }
112
113 if (null === $cloneable) {
114 if (($proto instanceof \Reflector || $proto instanceof \ReflectionGenerator || $proto instanceof \ReflectionType || $proto instanceof \IteratorIterator || $proto instanceof \RecursiveIteratorIterator) && (!$proto instanceof \Serializable && !method_exists($proto, '__wakeup') && !method_exists($class, '__unserialize'))) {
115 throw new NotInstantiableTypeException($class);
116 }
117
118 $cloneable = $reflector->isCloneable() && !$reflector->hasMethod('__clone');
119 }
120
121 self::$cloneable[$class] = $cloneable;
122 self::$instantiableWithoutConstructor[$class] = $instantiableWithoutConstructor;
123 self::$prototypes[$class] = $proto;
124
125 if ($proto instanceof \Throwable) {
126 static $setTrace;
127
128 if (null === $setTrace) {
129 $setTrace = [
130 new \ReflectionProperty(\Error::class, 'trace'),
131 new \ReflectionProperty(\Exception::class, 'trace'),
132 ];
133 $setTrace[0] = $setTrace[0]->setValue(...);
134 $setTrace[1] = $setTrace[1]->setValue(...);
135 }
136
137 $setTrace[$proto instanceof \Exception]($proto, []);
138 }
139
140 return $reflector;
141 }
142}
diff --git a/vendor/symfony/var-exporter/Internal/Values.php b/vendor/symfony/var-exporter/Internal/Values.php
new file mode 100644
index 0000000..4f20a82
--- /dev/null
+++ b/vendor/symfony/var-exporter/Internal/Values.php
@@ -0,0 +1,25 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\VarExporter\Internal;
13
14/**
15 * @author Nicolas Grekas <p@tchwork.com>
16 *
17 * @internal
18 */
19class Values
20{
21 public function __construct(
22 public readonly array $values,
23 ) {
24 }
25}
diff --git a/vendor/symfony/var-exporter/LICENSE b/vendor/symfony/var-exporter/LICENSE
new file mode 100644
index 0000000..7536cae
--- /dev/null
+++ b/vendor/symfony/var-exporter/LICENSE
@@ -0,0 +1,19 @@
1Copyright (c) 2018-present Fabien Potencier
2
3Permission is hereby granted, free of charge, to any person obtaining a copy
4of this software and associated documentation files (the "Software"), to deal
5in the Software without restriction, including without limitation the rights
6to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7copies of the Software, and to permit persons to whom the Software is furnished
8to do so, subject to the following conditions:
9
10The above copyright notice and this permission notice shall be included in all
11copies or substantial portions of the Software.
12
13THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19THE SOFTWARE.
diff --git a/vendor/symfony/var-exporter/LazyGhostTrait.php b/vendor/symfony/var-exporter/LazyGhostTrait.php
new file mode 100644
index 0000000..fa82ced
--- /dev/null
+++ b/vendor/symfony/var-exporter/LazyGhostTrait.php
@@ -0,0 +1,352 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\VarExporter;
13
14use Symfony\Component\Serializer\Attribute\Ignore;
15use Symfony\Component\VarExporter\Internal\Hydrator;
16use Symfony\Component\VarExporter\Internal\LazyObjectRegistry as Registry;
17use Symfony\Component\VarExporter\Internal\LazyObjectState;
18use Symfony\Component\VarExporter\Internal\LazyObjectTrait;
19
20trait LazyGhostTrait
21{
22 use LazyObjectTrait;
23
24 /**
25 * Creates a lazy-loading ghost instance.
26 *
27 * Skipped properties should be indexed by their array-cast identifier, see
28 * https://php.net/manual/language.types.array#language.types.array.casting
29 *
30 * @param (\Closure(static):void $initializer The closure should initialize the object it receives as argument
31 * @param array<string, true>|null $skippedProperties An array indexed by the properties to skip, a.k.a. the ones
32 * that the initializer doesn't initialize, if any
33 * @param static|null $instance
34 */
35 public static function createLazyGhost(\Closure $initializer, ?array $skippedProperties = null, ?object $instance = null): static
36 {
37 if (self::class !== $class = $instance ? $instance::class : static::class) {
38 $skippedProperties["\0".self::class."\0lazyObjectState"] = true;
39 }
40
41 if (!isset(Registry::$defaultProperties[$class])) {
42 Registry::$classReflectors[$class] ??= new \ReflectionClass($class);
43 $instance ??= Registry::$classReflectors[$class]->newInstanceWithoutConstructor();
44 Registry::$defaultProperties[$class] ??= (array) $instance;
45 Registry::$classResetters[$class] ??= Registry::getClassResetters($class);
46
47 if (self::class === $class && \defined($class.'::LAZY_OBJECT_PROPERTY_SCOPES')) {
48 Hydrator::$propertyScopes[$class] ??= $class::LAZY_OBJECT_PROPERTY_SCOPES;
49 }
50 } else {
51 $instance ??= Registry::$classReflectors[$class]->newInstanceWithoutConstructor();
52 }
53
54 $instance->lazyObjectState = new LazyObjectState($initializer, $skippedProperties ??= []);
55
56 foreach (Registry::$classResetters[$class] as $reset) {
57 $reset($instance, $skippedProperties);
58 }
59
60 return $instance;
61 }
62
63 /**
64 * Returns whether the object is initialized.
65 *
66 * @param $partial Whether partially initialized objects should be considered as initialized
67 */
68 #[Ignore]
69 public function isLazyObjectInitialized(bool $partial = false): bool
70 {
71 if (!$state = $this->lazyObjectState ?? null) {
72 return true;
73 }
74
75 return LazyObjectState::STATUS_INITIALIZED_FULL === $state->status;
76 }
77
78 /**
79 * Forces initialization of a lazy object and returns it.
80 */
81 public function initializeLazyObject(): static
82 {
83 if (!$state = $this->lazyObjectState ?? null) {
84 return $this;
85 }
86
87 if (LazyObjectState::STATUS_UNINITIALIZED_FULL === $state->status) {
88 $state->initialize($this, '', null);
89 }
90
91 return $this;
92 }
93
94 /**
95 * @return bool Returns false when the object cannot be reset, ie when it's not a lazy object
96 */
97 public function resetLazyObject(): bool
98 {
99 if (!$state = $this->lazyObjectState ?? null) {
100 return false;
101 }
102
103 if (LazyObjectState::STATUS_UNINITIALIZED_FULL !== $state->status) {
104 $state->reset($this);
105 }
106
107 return true;
108 }
109
110 public function &__get($name): mixed
111 {
112 $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class);
113 $scope = null;
114
115 if ([$class, , $readonlyScope] = $propertyScopes[$name] ?? null) {
116 $scope = Registry::getScope($propertyScopes, $class, $name);
117 $state = $this->lazyObjectState ?? null;
118
119 if ($state && (null === $scope || isset($propertyScopes["\0$scope\0$name"]))) {
120 if (LazyObjectState::STATUS_INITIALIZED_FULL === $state->status) {
121 // Work around php/php-src#12695
122 $property = null === $scope ? $name : "\0$scope\0$name";
123 $property = $propertyScopes[$property][3]
124 ?? Hydrator::$propertyScopes[$this::class][$property][3] = new \ReflectionProperty($scope ?? $class, $name);
125 } else {
126 $property = null;
127 }
128
129 if ($property?->isInitialized($this) ?? LazyObjectState::STATUS_UNINITIALIZED_PARTIAL !== $state->initialize($this, $name, $readonlyScope ?? $scope)) {
130 goto get_in_scope;
131 }
132 }
133 }
134
135 if ($parent = (Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['get']) {
136 if (2 === $parent) {
137 return parent::__get($name);
138 }
139 $value = parent::__get($name);
140
141 return $value;
142 }
143
144 if (null === $class) {
145 $frame = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0];
146 trigger_error(sprintf('Undefined property: %s::$%s in %s on line %s', $this::class, $name, $frame['file'], $frame['line']), \E_USER_NOTICE);
147 }
148
149 get_in_scope:
150
151 try {
152 if (null === $scope) {
153 if (null === $readonlyScope) {
154 return $this->$name;
155 }
156 $value = $this->$name;
157
158 return $value;
159 }
160 $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope);
161
162 return $accessor['get']($this, $name, null !== $readonlyScope);
163 } catch (\Error $e) {
164 if (\Error::class !== $e::class || !str_starts_with($e->getMessage(), 'Cannot access uninitialized non-nullable property')) {
165 throw $e;
166 }
167
168 try {
169 if (null === $scope) {
170 $this->$name = [];
171
172 return $this->$name;
173 }
174
175 $accessor['set']($this, $name, []);
176
177 return $accessor['get']($this, $name, null !== $readonlyScope);
178 } catch (\Error) {
179 if (preg_match('/^Cannot access uninitialized non-nullable property ([^ ]++) by reference$/', $e->getMessage(), $matches)) {
180 throw new \Error('Typed property '.$matches[1].' must not be accessed before initialization', $e->getCode(), $e->getPrevious());
181 }
182
183 throw $e;
184 }
185 }
186 }
187
188 public function __set($name, $value): void
189 {
190 $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class);
191 $scope = null;
192
193 if ([$class, , $readonlyScope] = $propertyScopes[$name] ?? null) {
194 $scope = Registry::getScope($propertyScopes, $class, $name, $readonlyScope);
195 $state = $this->lazyObjectState ?? null;
196
197 if ($state && ($readonlyScope === $scope || isset($propertyScopes["\0$scope\0$name"]))
198 && LazyObjectState::STATUS_INITIALIZED_FULL !== $state->status
199 ) {
200 if (LazyObjectState::STATUS_UNINITIALIZED_FULL === $state->status) {
201 $state->initialize($this, $name, $readonlyScope ?? $scope);
202 }
203 goto set_in_scope;
204 }
205 }
206
207 if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['set']) {
208 parent::__set($name, $value);
209
210 return;
211 }
212
213 set_in_scope:
214
215 if (null === $scope) {
216 $this->$name = $value;
217 } else {
218 $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope);
219 $accessor['set']($this, $name, $value);
220 }
221 }
222
223 public function __isset($name): bool
224 {
225 $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class);
226 $scope = null;
227
228 if ([$class, , $readonlyScope] = $propertyScopes[$name] ?? null) {
229 $scope = Registry::getScope($propertyScopes, $class, $name);
230 $state = $this->lazyObjectState ?? null;
231
232 if ($state && (null === $scope || isset($propertyScopes["\0$scope\0$name"]))
233 && LazyObjectState::STATUS_INITIALIZED_FULL !== $state->status
234 && LazyObjectState::STATUS_UNINITIALIZED_PARTIAL !== $state->initialize($this, $name, $readonlyScope ?? $scope)
235 ) {
236 goto isset_in_scope;
237 }
238 }
239
240 if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['isset']) {
241 return parent::__isset($name);
242 }
243
244 isset_in_scope:
245
246 if (null === $scope) {
247 return isset($this->$name);
248 }
249 $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope);
250
251 return $accessor['isset']($this, $name);
252 }
253
254 public function __unset($name): void
255 {
256 $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class);
257 $scope = null;
258
259 if ([$class, , $readonlyScope] = $propertyScopes[$name] ?? null) {
260 $scope = Registry::getScope($propertyScopes, $class, $name, $readonlyScope);
261 $state = $this->lazyObjectState ?? null;
262
263 if ($state && ($readonlyScope === $scope || isset($propertyScopes["\0$scope\0$name"]))
264 && LazyObjectState::STATUS_INITIALIZED_FULL !== $state->status
265 ) {
266 if (LazyObjectState::STATUS_UNINITIALIZED_FULL === $state->status) {
267 $state->initialize($this, $name, $readonlyScope ?? $scope);
268 }
269 goto unset_in_scope;
270 }
271 }
272
273 if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['unset']) {
274 parent::__unset($name);
275
276 return;
277 }
278
279 unset_in_scope:
280
281 if (null === $scope) {
282 unset($this->$name);
283 } else {
284 $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope);
285 $accessor['unset']($this, $name);
286 }
287 }
288
289 public function __clone(): void
290 {
291 if ($state = $this->lazyObjectState ?? null) {
292 $this->lazyObjectState = clone $state;
293 }
294
295 if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['clone']) {
296 parent::__clone();
297 }
298 }
299
300 public function __serialize(): array
301 {
302 $class = self::class;
303
304 if ((Registry::$parentMethods[$class] ??= Registry::getParentMethods($class))['serialize']) {
305 $properties = parent::__serialize();
306 } else {
307 $this->initializeLazyObject();
308 $properties = (array) $this;
309 }
310 unset($properties["\0$class\0lazyObjectState"]);
311
312 if (Registry::$parentMethods[$class]['serialize'] || !Registry::$parentMethods[$class]['sleep']) {
313 return $properties;
314 }
315
316 $scope = get_parent_class($class);
317 $data = [];
318
319 foreach (parent::__sleep() as $name) {
320 $value = $properties[$k = $name] ?? $properties[$k = "\0*\0$name"] ?? $properties[$k = "\0$class\0$name"] ?? $properties[$k = "\0$scope\0$name"] ?? $k = null;
321
322 if (null === $k) {
323 trigger_error(sprintf('serialize(): "%s" returned as member variable from __sleep() but does not exist', $name), \E_USER_NOTICE);
324 } else {
325 $data[$k] = $value;
326 }
327 }
328
329 return $data;
330 }
331
332 public function __destruct()
333 {
334 $state = $this->lazyObjectState ?? null;
335
336 if (LazyObjectState::STATUS_UNINITIALIZED_FULL === $state?->status) {
337 return;
338 }
339
340 if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['destruct']) {
341 parent::__destruct();
342 }
343 }
344
345 #[Ignore]
346 private function setLazyObjectAsInitialized(bool $initialized): void
347 {
348 if ($state = $this->lazyObjectState ?? null) {
349 $state->status = $initialized ? LazyObjectState::STATUS_INITIALIZED_FULL : LazyObjectState::STATUS_UNINITIALIZED_FULL;
350 }
351 }
352}
diff --git a/vendor/symfony/var-exporter/LazyObjectInterface.php b/vendor/symfony/var-exporter/LazyObjectInterface.php
new file mode 100644
index 0000000..3670884
--- /dev/null
+++ b/vendor/symfony/var-exporter/LazyObjectInterface.php
@@ -0,0 +1,32 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\VarExporter;
13
14interface LazyObjectInterface
15{
16 /**
17 * Returns whether the object is initialized.
18 *
19 * @param $partial Whether partially initialized objects should be considered as initialized
20 */
21 public function isLazyObjectInitialized(bool $partial = false): bool;
22
23 /**
24 * Forces initialization of a lazy object and returns it.
25 */
26 public function initializeLazyObject(): object;
27
28 /**
29 * @return bool Returns false when the object cannot be reset, ie when it's not a lazy object
30 */
31 public function resetLazyObject(): bool;
32}
diff --git a/vendor/symfony/var-exporter/LazyProxyTrait.php b/vendor/symfony/var-exporter/LazyProxyTrait.php
new file mode 100644
index 0000000..17ba1db
--- /dev/null
+++ b/vendor/symfony/var-exporter/LazyProxyTrait.php
@@ -0,0 +1,359 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\VarExporter;
13
14use Symfony\Component\Serializer\Attribute\Ignore;
15use Symfony\Component\VarExporter\Hydrator as PublicHydrator;
16use Symfony\Component\VarExporter\Internal\Hydrator;
17use Symfony\Component\VarExporter\Internal\LazyObjectRegistry as Registry;
18use Symfony\Component\VarExporter\Internal\LazyObjectState;
19use Symfony\Component\VarExporter\Internal\LazyObjectTrait;
20
21trait LazyProxyTrait
22{
23 use LazyObjectTrait;
24
25 /**
26 * Creates a lazy-loading virtual proxy.
27 *
28 * @param \Closure():object $initializer Returns the proxied object
29 * @param static|null $instance
30 */
31 public static function createLazyProxy(\Closure $initializer, ?object $instance = null): static
32 {
33 if (self::class !== $class = $instance ? $instance::class : static::class) {
34 $skippedProperties = ["\0".self::class."\0lazyObjectState" => true];
35 }
36
37 if (!isset(Registry::$defaultProperties[$class])) {
38 Registry::$classReflectors[$class] ??= new \ReflectionClass($class);
39 $instance ??= Registry::$classReflectors[$class]->newInstanceWithoutConstructor();
40 Registry::$defaultProperties[$class] ??= (array) $instance;
41 Registry::$classResetters[$class] ??= Registry::getClassResetters($class);
42
43 if (self::class === $class && \defined($class.'::LAZY_OBJECT_PROPERTY_SCOPES')) {
44 Hydrator::$propertyScopes[$class] ??= $class::LAZY_OBJECT_PROPERTY_SCOPES;
45 }
46 } else {
47 $instance ??= Registry::$classReflectors[$class]->newInstanceWithoutConstructor();
48 }
49
50 $instance->lazyObjectState = new LazyObjectState($initializer);
51
52 foreach (Registry::$classResetters[$class] as $reset) {
53 $reset($instance, $skippedProperties ??= []);
54 }
55
56 return $instance;
57 }
58
59 /**
60 * Returns whether the object is initialized.
61 *
62 * @param $partial Whether partially initialized objects should be considered as initialized
63 */
64 #[Ignore]
65 public function isLazyObjectInitialized(bool $partial = false): bool
66 {
67 return !isset($this->lazyObjectState) || isset($this->lazyObjectState->realInstance) || Registry::$noInitializerState === $this->lazyObjectState->initializer;
68 }
69
70 /**
71 * Forces initialization of a lazy object and returns it.
72 */
73 public function initializeLazyObject(): parent
74 {
75 if ($state = $this->lazyObjectState ?? null) {
76 return $state->realInstance ??= ($state->initializer)();
77 }
78
79 return $this;
80 }
81
82 /**
83 * @return bool Returns false when the object cannot be reset, ie when it's not a lazy object
84 */
85 public function resetLazyObject(): bool
86 {
87 if (!isset($this->lazyObjectState) || Registry::$noInitializerState === $this->lazyObjectState->initializer) {
88 return false;
89 }
90
91 unset($this->lazyObjectState->realInstance);
92
93 return true;
94 }
95
96 public function &__get($name): mixed
97 {
98 $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class);
99 $scope = null;
100 $instance = $this;
101
102 if ([$class, , $readonlyScope] = $propertyScopes[$name] ?? null) {
103 $scope = Registry::getScope($propertyScopes, $class, $name);
104
105 if (null === $scope || isset($propertyScopes["\0$scope\0$name"])) {
106 if ($state = $this->lazyObjectState ?? null) {
107 $instance = $state->realInstance ??= ($state->initializer)();
108 }
109 $parent = 2;
110 goto get_in_scope;
111 }
112 }
113 $parent = (Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['get'];
114
115 if ($state = $this->lazyObjectState ?? null) {
116 $instance = $state->realInstance ??= ($state->initializer)();
117 } else {
118 if (2 === $parent) {
119 return parent::__get($name);
120 }
121 $value = parent::__get($name);
122
123 return $value;
124 }
125
126 if (!$parent && null === $class && !\array_key_exists($name, (array) $instance)) {
127 $frame = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0];
128 trigger_error(sprintf('Undefined property: %s::$%s in %s on line %s', $instance::class, $name, $frame['file'], $frame['line']), \E_USER_NOTICE);
129 }
130
131 get_in_scope:
132
133 try {
134 if (null === $scope) {
135 if (null === $readonlyScope && 1 !== $parent) {
136 return $instance->$name;
137 }
138 $value = $instance->$name;
139
140 return $value;
141 }
142 $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope);
143
144 return $accessor['get']($instance, $name, null !== $readonlyScope || 1 === $parent);
145 } catch (\Error $e) {
146 if (\Error::class !== $e::class || !str_starts_with($e->getMessage(), 'Cannot access uninitialized non-nullable property')) {
147 throw $e;
148 }
149
150 try {
151 if (null === $scope) {
152 $instance->$name = [];
153
154 return $instance->$name;
155 }
156
157 $accessor['set']($instance, $name, []);
158
159 return $accessor['get']($instance, $name, null !== $readonlyScope || 1 === $parent);
160 } catch (\Error) {
161 throw $e;
162 }
163 }
164 }
165
166 public function __set($name, $value): void
167 {
168 $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class);
169 $scope = null;
170 $instance = $this;
171
172 if ([$class, , $readonlyScope] = $propertyScopes[$name] ?? null) {
173 $scope = Registry::getScope($propertyScopes, $class, $name, $readonlyScope);
174
175 if ($readonlyScope === $scope || isset($propertyScopes["\0$scope\0$name"])) {
176 if ($state = $this->lazyObjectState ?? null) {
177 $instance = $state->realInstance ??= ($state->initializer)();
178 }
179 goto set_in_scope;
180 }
181 }
182
183 if ($state = $this->lazyObjectState ?? null) {
184 $instance = $state->realInstance ??= ($state->initializer)();
185 } elseif ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['set']) {
186 parent::__set($name, $value);
187
188 return;
189 }
190
191 set_in_scope:
192
193 if (null === $scope) {
194 $instance->$name = $value;
195 } else {
196 $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope);
197 $accessor['set']($instance, $name, $value);
198 }
199 }
200
201 public function __isset($name): bool
202 {
203 $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class);
204 $scope = null;
205 $instance = $this;
206
207 if ([$class] = $propertyScopes[$name] ?? null) {
208 $scope = Registry::getScope($propertyScopes, $class, $name);
209
210 if (null === $scope || isset($propertyScopes["\0$scope\0$name"])) {
211 if ($state = $this->lazyObjectState ?? null) {
212 $instance = $state->realInstance ??= ($state->initializer)();
213 }
214 goto isset_in_scope;
215 }
216 }
217
218 if ($state = $this->lazyObjectState ?? null) {
219 $instance = $state->realInstance ??= ($state->initializer)();
220 } elseif ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['isset']) {
221 return parent::__isset($name);
222 }
223
224 isset_in_scope:
225
226 if (null === $scope) {
227 return isset($instance->$name);
228 }
229 $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope);
230
231 return $accessor['isset']($instance, $name);
232 }
233
234 public function __unset($name): void
235 {
236 $propertyScopes = Hydrator::$propertyScopes[$this::class] ??= Hydrator::getPropertyScopes($this::class);
237 $scope = null;
238 $instance = $this;
239
240 if ([$class, , $readonlyScope] = $propertyScopes[$name] ?? null) {
241 $scope = Registry::getScope($propertyScopes, $class, $name, $readonlyScope);
242
243 if ($readonlyScope === $scope || isset($propertyScopes["\0$scope\0$name"])) {
244 if ($state = $this->lazyObjectState ?? null) {
245 $instance = $state->realInstance ??= ($state->initializer)();
246 }
247 goto unset_in_scope;
248 }
249 }
250
251 if ($state = $this->lazyObjectState ?? null) {
252 $instance = $state->realInstance ??= ($state->initializer)();
253 } elseif ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['unset']) {
254 parent::__unset($name);
255
256 return;
257 }
258
259 unset_in_scope:
260
261 if (null === $scope) {
262 unset($instance->$name);
263 } else {
264 $accessor = Registry::$classAccessors[$scope] ??= Registry::getClassAccessors($scope);
265 $accessor['unset']($instance, $name);
266 }
267 }
268
269 public function __clone(): void
270 {
271 if (!isset($this->lazyObjectState)) {
272 if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['clone']) {
273 parent::__clone();
274 }
275
276 return;
277 }
278
279 $this->lazyObjectState = clone $this->lazyObjectState;
280
281 if (isset($this->lazyObjectState->realInstance)) {
282 $this->lazyObjectState->realInstance = clone $this->lazyObjectState->realInstance;
283 }
284 }
285
286 public function __serialize(): array
287 {
288 $class = self::class;
289 $state = $this->lazyObjectState ?? null;
290
291 if (!$state && (Registry::$parentMethods[$class] ??= Registry::getParentMethods($class))['serialize']) {
292 $properties = parent::__serialize();
293 } else {
294 $properties = (array) $this;
295
296 if ($state) {
297 unset($properties["\0$class\0lazyObjectState"]);
298 $properties["\0$class\0lazyObjectReal"] = $state->realInstance ??= ($state->initializer)();
299 }
300 }
301
302 if ($state || Registry::$parentMethods[$class]['serialize'] || !Registry::$parentMethods[$class]['sleep']) {
303 return $properties;
304 }
305
306 $scope = get_parent_class($class);
307 $data = [];
308
309 foreach (parent::__sleep() as $name) {
310 $value = $properties[$k = $name] ?? $properties[$k = "\0*\0$name"] ?? $properties[$k = "\0$class\0$name"] ?? $properties[$k = "\0$scope\0$name"] ?? $k = null;
311
312 if (null === $k) {
313 trigger_error(sprintf('serialize(): "%s" returned as member variable from __sleep() but does not exist', $name), \E_USER_NOTICE);
314 } else {
315 $data[$k] = $value;
316 }
317 }
318
319 return $data;
320 }
321
322 public function __unserialize(array $data): void
323 {
324 $class = self::class;
325
326 if ($instance = $data["\0$class\0lazyObjectReal"] ?? null) {
327 unset($data["\0$class\0lazyObjectReal"]);
328
329 foreach (Registry::$classResetters[$class] ??= Registry::getClassResetters($class) as $reset) {
330 $reset($this, $data);
331 }
332
333 if ($data) {
334 PublicHydrator::hydrate($this, $data);
335 }
336 $this->lazyObjectState = new LazyObjectState(Registry::$noInitializerState ??= static fn () => throw new \LogicException('Lazy proxy has no initializer.'));
337 $this->lazyObjectState->realInstance = $instance;
338 } elseif ((Registry::$parentMethods[$class] ??= Registry::getParentMethods($class))['unserialize']) {
339 parent::__unserialize($data);
340 } else {
341 PublicHydrator::hydrate($this, $data);
342
343 if (Registry::$parentMethods[$class]['wakeup']) {
344 parent::__wakeup();
345 }
346 }
347 }
348
349 public function __destruct()
350 {
351 if (isset($this->lazyObjectState)) {
352 return;
353 }
354
355 if ((Registry::$parentMethods[self::class] ??= Registry::getParentMethods(self::class))['destruct']) {
356 parent::__destruct();
357 }
358 }
359}
diff --git a/vendor/symfony/var-exporter/ProxyHelper.php b/vendor/symfony/var-exporter/ProxyHelper.php
new file mode 100644
index 0000000..4cf0f65
--- /dev/null
+++ b/vendor/symfony/var-exporter/ProxyHelper.php
@@ -0,0 +1,413 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\VarExporter;
13
14use Symfony\Component\VarExporter\Exception\LogicException;
15use Symfony\Component\VarExporter\Internal\Hydrator;
16use Symfony\Component\VarExporter\Internal\LazyObjectRegistry;
17
18/**
19 * @author Nicolas Grekas <p@tchwork.com>
20 */
21final class ProxyHelper
22{
23 /**
24 * Helps generate lazy-loading ghost objects.
25 *
26 * @throws LogicException When the class is incompatible with ghost objects
27 */
28 public static function generateLazyGhost(\ReflectionClass $class): string
29 {
30 if (\PHP_VERSION_ID < 80300 && $class->isReadOnly()) {
31 throw new LogicException(sprintf('Cannot generate lazy ghost with PHP < 8.3: class "%s" is readonly.', $class->name));
32 }
33 if ($class->isFinal()) {
34 throw new LogicException(sprintf('Cannot generate lazy ghost: class "%s" is final.', $class->name));
35 }
36 if ($class->isInterface() || $class->isAbstract()) {
37 throw new LogicException(sprintf('Cannot generate lazy ghost: "%s" is not a concrete class.', $class->name));
38 }
39 if (\stdClass::class !== $class->name && $class->isInternal()) {
40 throw new LogicException(sprintf('Cannot generate lazy ghost: class "%s" is internal.', $class->name));
41 }
42 if ($class->hasMethod('__get') && 'mixed' !== (self::exportType($class->getMethod('__get')) ?? 'mixed')) {
43 throw new LogicException(sprintf('Cannot generate lazy ghost: return type of method "%s::__get()" should be "mixed".', $class->name));
44 }
45
46 static $traitMethods;
47 $traitMethods ??= (new \ReflectionClass(LazyGhostTrait::class))->getMethods();
48
49 foreach ($traitMethods as $method) {
50 if ($class->hasMethod($method->name) && $class->getMethod($method->name)->isFinal()) {
51 throw new LogicException(sprintf('Cannot generate lazy ghost: method "%s::%s()" is final.', $class->name, $method->name));
52 }
53 }
54
55 $parent = $class;
56 while ($parent = $parent->getParentClass()) {
57 if (\stdClass::class !== $parent->name && $parent->isInternal()) {
58 throw new LogicException(sprintf('Cannot generate lazy ghost: class "%s" extends "%s" which is internal.', $class->name, $parent->name));
59 }
60 }
61 $propertyScopes = self::exportPropertyScopes($class->name);
62
63 return <<<EOPHP
64 extends \\{$class->name} implements \Symfony\Component\VarExporter\LazyObjectInterface
65 {
66 use \Symfony\Component\VarExporter\LazyGhostTrait;
67
68 private const LAZY_OBJECT_PROPERTY_SCOPES = {$propertyScopes};
69 }
70
71 // Help opcache.preload discover always-needed symbols
72 class_exists(\Symfony\Component\VarExporter\Internal\Hydrator::class);
73 class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class);
74 class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectState::class);
75
76 EOPHP;
77 }
78
79 /**
80 * Helps generate lazy-loading virtual proxies.
81 *
82 * @param \ReflectionClass[] $interfaces
83 *
84 * @throws LogicException When the class is incompatible with virtual proxies
85 */
86 public static function generateLazyProxy(?\ReflectionClass $class, array $interfaces = []): string
87 {
88 if (!class_exists($class?->name ?? \stdClass::class, false)) {
89 throw new LogicException(sprintf('Cannot generate lazy proxy: "%s" is not a class.', $class->name));
90 }
91 if ($class?->isFinal()) {
92 throw new LogicException(sprintf('Cannot generate lazy proxy: class "%s" is final.', $class->name));
93 }
94 if (\PHP_VERSION_ID < 80300 && $class?->isReadOnly()) {
95 throw new LogicException(sprintf('Cannot generate lazy proxy with PHP < 8.3: class "%s" is readonly.', $class->name));
96 }
97
98 $methodReflectors = [$class?->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) ?? []];
99 foreach ($interfaces as $interface) {
100 if (!$interface->isInterface()) {
101 throw new LogicException(sprintf('Cannot generate lazy proxy: "%s" is not an interface.', $interface->name));
102 }
103 $methodReflectors[] = $interface->getMethods();
104 }
105 $methodReflectors = array_merge(...$methodReflectors);
106
107 $extendsInternalClass = false;
108 if ($parent = $class) {
109 do {
110 $extendsInternalClass = \stdClass::class !== $parent->name && $parent->isInternal();
111 } while (!$extendsInternalClass && $parent = $parent->getParentClass());
112 }
113 $methodsHaveToBeProxied = $extendsInternalClass;
114 $methods = [];
115
116 foreach ($methodReflectors as $method) {
117 if ('__get' !== strtolower($method->name) || 'mixed' === ($type = self::exportType($method) ?? 'mixed')) {
118 continue;
119 }
120 $methodsHaveToBeProxied = true;
121 $trait = new \ReflectionMethod(LazyProxyTrait::class, '__get');
122 $body = \array_slice(file($trait->getFileName()), $trait->getStartLine() - 1, $trait->getEndLine() - $trait->getStartLine());
123 $body[0] = str_replace('): mixed', '): '.$type, $body[0]);
124 $methods['__get'] = strtr(implode('', $body).' }', [
125 'Hydrator' => '\\'.Hydrator::class,
126 'Registry' => '\\'.LazyObjectRegistry::class,
127 ]);
128 break;
129 }
130
131 foreach ($methodReflectors as $method) {
132 if (($method->isStatic() && !$method->isAbstract()) || isset($methods[$lcName = strtolower($method->name)])) {
133 continue;
134 }
135 if ($method->isFinal()) {
136 if ($extendsInternalClass || $methodsHaveToBeProxied || method_exists(LazyProxyTrait::class, $method->name)) {
137 throw new LogicException(sprintf('Cannot generate lazy proxy: method "%s::%s()" is final.', $class->name, $method->name));
138 }
139 continue;
140 }
141 if (method_exists(LazyProxyTrait::class, $method->name) || ($method->isProtected() && !$method->isAbstract())) {
142 continue;
143 }
144
145 $signature = self::exportSignature($method, true, $args);
146 $parentCall = $method->isAbstract() ? "throw new \BadMethodCallException('Cannot forward abstract method \"{$method->class}::{$method->name}()\".')" : "parent::{$method->name}({$args})";
147
148 if ($method->isStatic()) {
149 $body = " $parentCall;";
150 } elseif (str_ends_with($signature, '): never') || str_ends_with($signature, '): void')) {
151 $body = <<<EOPHP
152 if (isset(\$this->lazyObjectState)) {
153 (\$this->lazyObjectState->realInstance ??= (\$this->lazyObjectState->initializer)())->{$method->name}({$args});
154 } else {
155 {$parentCall};
156 }
157 EOPHP;
158 } else {
159 if (!$methodsHaveToBeProxied && !$method->isAbstract()) {
160 // Skip proxying methods that might return $this
161 foreach (preg_split('/[()|&]++/', self::exportType($method) ?? 'static') as $type) {
162 if (\in_array($type = ltrim($type, '?'), ['static', 'object'], true)) {
163 continue 2;
164 }
165 foreach ([$class, ...$interfaces] as $r) {
166 if ($r && is_a($r->name, $type, true)) {
167 continue 3;
168 }
169 }
170 }
171 }
172
173 $body = <<<EOPHP
174 if (isset(\$this->lazyObjectState)) {
175 return (\$this->lazyObjectState->realInstance ??= (\$this->lazyObjectState->initializer)())->{$method->name}({$args});
176 }
177
178 return {$parentCall};
179 EOPHP;
180 }
181 $methods[$lcName] = " {$signature}\n {\n{$body}\n }";
182 }
183
184 $types = $interfaces = array_unique(array_column($interfaces, 'name'));
185 $interfaces[] = LazyObjectInterface::class;
186 $interfaces = implode(', \\', $interfaces);
187 $parent = $class ? ' extends \\'.$class->name : '';
188 array_unshift($types, $class ? 'parent' : '');
189 $type = ltrim(implode('&\\', $types), '&');
190
191 if (!$class) {
192 $trait = new \ReflectionMethod(LazyProxyTrait::class, 'initializeLazyObject');
193 $body = \array_slice(file($trait->getFileName()), $trait->getStartLine() - 1, $trait->getEndLine() - $trait->getStartLine());
194 $body[0] = str_replace('): parent', '): '.$type, $body[0]);
195 $methods = ['initializeLazyObject' => implode('', $body).' }'] + $methods;
196 }
197 $body = $methods ? "\n".implode("\n\n", $methods)."\n" : '';
198 $propertyScopes = $class ? self::exportPropertyScopes($class->name) : '[]';
199
200 if (
201 $class?->hasMethod('__unserialize')
202 && !$class->getMethod('__unserialize')->getParameters()[0]->getType()
203 ) {
204 // fix contravariance type problem when $class declares a `__unserialize()` method without typehint.
205 $lazyProxyTraitStatement = <<<EOPHP
206 use \Symfony\Component\VarExporter\LazyProxyTrait {
207 __unserialize as private __doUnserialize;
208 }
209 EOPHP;
210
211 $body .= <<<EOPHP
212
213 public function __unserialize(\$data): void
214 {
215 \$this->__doUnserialize(\$data);
216 }
217
218 EOPHP;
219 } else {
220 $lazyProxyTraitStatement = <<<EOPHP
221 use \Symfony\Component\VarExporter\LazyProxyTrait;
222 EOPHP;
223 }
224
225 return <<<EOPHP
226 {$parent} implements \\{$interfaces}
227 {
228 {$lazyProxyTraitStatement}
229
230 private const LAZY_OBJECT_PROPERTY_SCOPES = {$propertyScopes};
231 {$body}}
232
233 // Help opcache.preload discover always-needed symbols
234 class_exists(\Symfony\Component\VarExporter\Internal\Hydrator::class);
235 class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectRegistry::class);
236 class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectState::class);
237
238 EOPHP;
239 }
240
241 public static function exportSignature(\ReflectionFunctionAbstract $function, bool $withParameterTypes = true, ?string &$args = null): string
242 {
243 $byRefIndex = 0;
244 $args = '';
245 $param = null;
246 $parameters = [];
247 $namespace = $function instanceof \ReflectionMethod ? $function->class : $function->getNamespaceName().'\\';
248 $namespace = substr($namespace, 0, strrpos($namespace, '\\') ?: 0);
249 foreach ($function->getParameters() as $param) {
250 $parameters[] = ($param->getAttributes(\SensitiveParameter::class) ? '#[\SensitiveParameter] ' : '')
251 .($withParameterTypes && $param->hasType() ? self::exportType($param).' ' : '')
252 .($param->isPassedByReference() ? '&' : '')
253 .($param->isVariadic() ? '...' : '').'$'.$param->name
254 .($param->isOptional() && !$param->isVariadic() ? ' = '.self::exportDefault($param, $namespace) : '');
255 if ($param->isPassedByReference()) {
256 $byRefIndex = 1 + $param->getPosition();
257 }
258 $args .= ($param->isVariadic() ? '...$' : '$').$param->name.', ';
259 }
260
261 if (!$param || !$byRefIndex) {
262 $args = '...\func_get_args()';
263 } elseif ($param->isVariadic()) {
264 $args = substr($args, 0, -2);
265 } else {
266 $args = explode(', ', $args, 1 + $byRefIndex);
267 $args[$byRefIndex] = sprintf('...\array_slice(\func_get_args(), %d)', $byRefIndex);
268 $args = implode(', ', $args);
269 }
270
271 $signature = 'function '.($function->returnsReference() ? '&' : '')
272 .($function->isClosure() ? '' : $function->name).'('.implode(', ', $parameters).')';
273
274 if ($function instanceof \ReflectionMethod) {
275 $signature = ($function->isPublic() ? 'public ' : ($function->isProtected() ? 'protected ' : 'private '))
276 .($function->isStatic() ? 'static ' : '').$signature;
277 }
278 if ($function->hasReturnType()) {
279 $signature .= ': '.self::exportType($function);
280 }
281
282 static $getPrototype;
283 $getPrototype ??= (new \ReflectionMethod(\ReflectionMethod::class, 'getPrototype'))->invoke(...);
284
285 while ($function) {
286 if ($function->hasTentativeReturnType()) {
287 return '#[\ReturnTypeWillChange] '.$signature;
288 }
289
290 try {
291 $function = $function instanceof \ReflectionMethod && $function->isAbstract() ? false : $getPrototype($function);
292 } catch (\ReflectionException) {
293 break;
294 }
295 }
296
297 return $signature;
298 }
299
300 public static function exportType(\ReflectionFunctionAbstract|\ReflectionProperty|\ReflectionParameter $owner, bool $noBuiltin = false, ?\ReflectionType $type = null): ?string
301 {
302 if (!$type ??= $owner instanceof \ReflectionFunctionAbstract ? $owner->getReturnType() : $owner->getType()) {
303 return null;
304 }
305 $class = null;
306 $types = [];
307 if ($type instanceof \ReflectionUnionType) {
308 $reflectionTypes = $type->getTypes();
309 $glue = '|';
310 } elseif ($type instanceof \ReflectionIntersectionType) {
311 $reflectionTypes = $type->getTypes();
312 $glue = '&';
313 } else {
314 $reflectionTypes = [$type];
315 $glue = null;
316 }
317
318 foreach ($reflectionTypes as $type) {
319 if ($type instanceof \ReflectionIntersectionType) {
320 if ('' !== $name = '('.self::exportType($owner, $noBuiltin, $type).')') {
321 $types[] = $name;
322 }
323 continue;
324 }
325 $name = $type->getName();
326
327 if ($noBuiltin && $type->isBuiltin()) {
328 continue;
329 }
330 if (\in_array($name, ['parent', 'self'], true) && $class ??= $owner->getDeclaringClass()) {
331 $name = 'parent' === $name ? ($class->getParentClass() ?: null)?->name ?? 'parent' : $class->name;
332 }
333
334 $types[] = ($noBuiltin || $type->isBuiltin() || 'static' === $name ? '' : '\\').$name;
335 }
336
337 if (!$types) {
338 return '';
339 }
340 if (null === $glue) {
341 return (!$noBuiltin && $type->allowsNull() && !\in_array($name, ['mixed', 'null'], true) ? '?' : '').$types[0];
342 }
343 sort($types);
344
345 return implode($glue, $types);
346 }
347
348 private static function exportPropertyScopes(string $parent): string
349 {
350 $propertyScopes = Hydrator::$propertyScopes[$parent] ??= Hydrator::getPropertyScopes($parent);
351 uksort($propertyScopes, 'strnatcmp');
352 foreach ($propertyScopes as $k => $v) {
353 unset($propertyScopes[$k][3]);
354 }
355 $propertyScopes = VarExporter::export($propertyScopes);
356 $propertyScopes = str_replace(VarExporter::export($parent), 'parent::class', $propertyScopes);
357 $propertyScopes = preg_replace("/(?|(,)\n( ) |\n |,\n (\]))/", '$1$2', $propertyScopes);
358 $propertyScopes = str_replace("\n", "\n ", $propertyScopes);
359
360 return $propertyScopes;
361 }
362
363 private static function exportDefault(\ReflectionParameter $param, $namespace): string
364 {
365 $default = rtrim(substr(explode('$'.$param->name.' = ', (string) $param, 2)[1] ?? '', 0, -2));
366
367 if (\in_array($default, ['<default>', 'NULL'], true)) {
368 return 'null';
369 }
370 if (str_ends_with($default, "...'") && preg_match("/^'(?:[^'\\\\]*+(?:\\\\.)*+)*+'$/", $default)) {
371 return VarExporter::export($param->getDefaultValue());
372 }
373
374 $regexp = "/(\"(?:[^\"\\\\]*+(?:\\\\.)*+)*+\"|'(?:[^'\\\\]*+(?:\\\\.)*+)*+')/";
375 $parts = preg_split($regexp, $default, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY);
376
377 $regexp = '/([\[\( ]|^)([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z0-9_\x7f-\xff]++)*+)(\(?)(?!: )/';
378 $callback = (false !== strpbrk($default, "\\:('") && $class = $param->getDeclaringClass())
379 ? fn ($m) => $m[1].match ($m[2]) {
380 'new', 'false', 'true', 'null' => $m[2],
381 'NULL' => 'null',
382 'self' => '\\'.$class->name,
383 'namespace\\parent',
384 'parent' => ($parent = $class->getParentClass()) ? '\\'.$parent->name : 'parent',
385 default => self::exportSymbol($m[2], '(' !== $m[3], $namespace),
386 }.$m[3]
387 : fn ($m) => $m[1].match ($m[2]) {
388 'new', 'false', 'true', 'null', 'self', 'parent' => $m[2],
389 'NULL' => 'null',
390 default => self::exportSymbol($m[2], '(' !== $m[3], $namespace),
391 }.$m[3];
392
393 return implode('', array_map(fn ($part) => match ($part[0]) {
394 '"' => $part, // for internal classes only
395 "'" => false !== strpbrk($part, "\\\0\r\n") ? '"'.substr(str_replace(['$', "\0", "\r", "\n"], ['\$', '\0', '\r', '\n'], $part), 1, -1).'"' : $part,
396 default => preg_replace_callback($regexp, $callback, $part),
397 }, $parts));
398 }
399
400 private static function exportSymbol(string $symbol, bool $mightBeRootConst, string $namespace): string
401 {
402 if (!$mightBeRootConst
403 || false === ($ns = strrpos($symbol, '\\'))
404 || substr($symbol, 0, $ns) !== $namespace
405 || \defined($symbol)
406 || !\defined(substr($symbol, $ns + 1))
407 ) {
408 return '\\'.$symbol;
409 }
410
411 return '\\'.substr($symbol, $ns + 1);
412 }
413}
diff --git a/vendor/symfony/var-exporter/README.md b/vendor/symfony/var-exporter/README.md
new file mode 100644
index 0000000..7195270
--- /dev/null
+++ b/vendor/symfony/var-exporter/README.md
@@ -0,0 +1,137 @@
1VarExporter Component
2=====================
3
4The VarExporter component provides various tools to deal with the internal state
5of objects:
6
7- `VarExporter::export()` allows exporting any serializable PHP data structure to
8 plain PHP code. While doing so, it preserves all the semantics associated with
9 the serialization mechanism of PHP (`__wakeup`, `__sleep`, `Serializable`,
10 `__serialize`, `__unserialize`);
11- `Instantiator::instantiate()` creates an object and sets its properties without
12 calling its constructor nor any other methods;
13- `Hydrator::hydrate()` can set the properties of an existing object;
14- `Lazy*Trait` can make a class behave as a lazy-loading ghost or virtual proxy.
15
16VarExporter::export()
17---------------------
18
19The reason to use `VarExporter::export()` *vs* `serialize()` or
20[igbinary](https://github.com/igbinary/igbinary) is performance: thanks to
21OPcache, the resulting code is significantly faster and more memory efficient
22than using `unserialize()` or `igbinary_unserialize()`.
23
24Unlike `var_export()`, this works on any serializable PHP value.
25
26It also provides a few improvements over `var_export()`/`serialize()`:
27
28 * the output is PSR-2 compatible;
29 * the output can be re-indented without messing up with `\r` or `\n` in the data;
30 * missing classes throw a `ClassNotFoundException` instead of being unserialized
31 to `PHP_Incomplete_Class` objects;
32 * references involving `SplObjectStorage`, `ArrayObject` or `ArrayIterator`
33 instances are preserved;
34 * `Reflection*`, `IteratorIterator` and `RecursiveIteratorIterator` classes
35 throw an exception when being serialized (their unserialized version is broken
36 anyway, see https://bugs.php.net/76737).
37
38Instantiator and Hydrator
39-------------------------
40
41`Instantiator::instantiate($class)` creates an object of the given class without
42calling its constructor nor any other methods.
43
44`Hydrator::hydrate()` sets the properties of an existing object, including
45private and protected ones. For example:
46
47```php
48// Sets the public or protected $object->propertyName property
49Hydrator::hydrate($object, ['propertyName' => $propertyValue]);
50
51// Sets a private property defined on its parent Bar class:
52Hydrator::hydrate($object, ["\0Bar\0privateBarProperty" => $propertyValue]);
53
54// Alternative way to set the private $object->privateBarProperty property
55Hydrator::hydrate($object, [], [
56 Bar::class => ['privateBarProperty' => $propertyValue],
57]);
58```
59
60`Lazy*Trait`
61------------
62
63The component provides two lazy-loading patterns: ghost objects and virtual
64proxies (see https://martinfowler.com/eaaCatalog/lazyLoad.html for reference).
65
66Ghost objects work only with concrete and non-internal classes. In the generic
67case, they are not compatible with using factories in their initializer.
68
69Virtual proxies work with concrete, abstract or internal classes. They provide an
70API that looks like the actual objects and forward calls to them. They can cause
71identity problems because proxies might not be seen as equivalents to the actual
72objects they proxy.
73
74Because of this identity problem, ghost objects should be preferred when
75possible. Exceptions thrown by the `ProxyHelper` class can help decide when it
76can be used or not.
77
78Ghost objects and virtual proxies both provide implementations for the
79`LazyObjectInterface` which allows resetting them to their initial state or to
80forcibly initialize them when needed. Note that resetting a ghost object skips
81its read-only properties. You should use a virtual proxy to reset read-only
82properties.
83
84### `LazyGhostTrait`
85
86By using `LazyGhostTrait` either directly in your classes or by using
87`ProxyHelper::generateLazyGhost()`, you can make their instances lazy-loadable.
88This works by creating these instances empty and by computing their state only
89when accessing a property.
90
91```php
92class FooLazyGhost extends Foo
93{
94 use LazyGhostTrait;
95}
96
97$foo = FooLazyGhost::createLazyGhost(initializer: function (Foo $instance): void {
98 // [...] Use whatever heavy logic you need here
99 // to compute the $dependencies of the $instance
100 $instance->__construct(...$dependencies);
101 // [...] Call setters, etc. if needed
102});
103
104// $foo is now a lazy-loading ghost object. The initializer will
105// be called only when and if a *property* is accessed.
106```
107
108### `LazyProxyTrait`
109
110Alternatively, `LazyProxyTrait` can be used to create virtual proxies:
111
112```php
113$proxyCode = ProxyHelper::generateLazyProxy(new ReflectionClass(Foo::class));
114// $proxyCode contains the reference to LazyProxyTrait
115// and should be dumped into a file in production envs
116eval('class FooLazyProxy'.$proxyCode);
117
118$foo = FooLazyProxy::createLazyProxy(initializer: function (): Foo {
119 // [...] Use whatever heavy logic you need here
120 // to compute the $dependencies of the $instance
121 $instance = new Foo(...$dependencies);
122 // [...] Call setters, etc. if needed
123
124 return $instance;
125});
126// $foo is now a lazy-loading virtual proxy object. The initializer will
127// be called only when and if a *method* is called.
128```
129
130Resources
131---------
132
133 * [Documentation](https://symfony.com/doc/current/components/var_exporter.html)
134 * [Contributing](https://symfony.com/doc/current/contributing/index.html)
135 * [Report issues](https://github.com/symfony/symfony/issues) and
136 [send Pull Requests](https://github.com/symfony/symfony/pulls)
137 in the [main Symfony repository](https://github.com/symfony/symfony)
diff --git a/vendor/symfony/var-exporter/VarExporter.php b/vendor/symfony/var-exporter/VarExporter.php
new file mode 100644
index 0000000..22e9b51
--- /dev/null
+++ b/vendor/symfony/var-exporter/VarExporter.php
@@ -0,0 +1,114 @@
1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\VarExporter;
13
14use Symfony\Component\VarExporter\Exception\ExceptionInterface;
15use Symfony\Component\VarExporter\Internal\Exporter;
16use Symfony\Component\VarExporter\Internal\Hydrator;
17use Symfony\Component\VarExporter\Internal\Registry;
18use Symfony\Component\VarExporter\Internal\Values;
19
20/**
21 * Exports serializable PHP values to PHP code.
22 *
23 * VarExporter allows serializing PHP data structures to plain PHP code (like var_export())
24 * while preserving all the semantics associated with serialize() (unlike var_export()).
25 *
26 * By leveraging OPcache, the generated PHP code is faster than doing the same with unserialize().
27 *
28 * @author Nicolas Grekas <p@tchwork.com>
29 */
30final class VarExporter
31{
32 /**
33 * Exports a serializable PHP value to PHP code.
34 *
35 * @param bool &$isStaticValue Set to true after execution if the provided value is static, false otherwise
36 * @param array &$foundClasses Classes found in the value are added to this list as both keys and values
37 *
38 * @throws ExceptionInterface When the provided value cannot be serialized
39 */
40 public static function export(mixed $value, ?bool &$isStaticValue = null, array &$foundClasses = []): string
41 {
42 $isStaticValue = true;
43
44 if (!\is_object($value) && !(\is_array($value) && $value) && !\is_resource($value) || $value instanceof \UnitEnum) {
45 return Exporter::export($value);
46 }
47
48 $objectsPool = new \SplObjectStorage();
49 $refsPool = [];
50 $objectsCount = 0;
51
52 try {
53 $value = Exporter::prepare([$value], $objectsPool, $refsPool, $objectsCount, $isStaticValue)[0];
54 } finally {
55 $references = [];
56 foreach ($refsPool as $i => $v) {
57 if ($v[0]->count) {
58 $references[1 + $i] = $v[2];
59 }
60 $v[0] = $v[1];
61 }
62 }
63
64 if ($isStaticValue) {
65 return Exporter::export($value);
66 }
67
68 $classes = [];
69 $values = [];
70 $states = [];
71 foreach ($objectsPool as $i => $v) {
72 [, $class, $values[], $wakeup] = $objectsPool[$v];
73 $foundClasses[$class] = $classes[] = $class;
74
75 if (0 < $wakeup) {
76 $states[$wakeup] = $i;
77 } elseif (0 > $wakeup) {
78 $states[-$wakeup] = [$i, array_pop($values)];
79 $values[] = [];
80 }
81 }
82 ksort($states);
83
84 $wakeups = [null];
85 foreach ($states as $v) {
86 if (\is_array($v)) {
87 $wakeups[-$v[0]] = $v[1];
88 } else {
89 $wakeups[] = $v;
90 }
91 }
92
93 if (null === $wakeups[0]) {
94 unset($wakeups[0]);
95 }
96
97 $properties = [];
98 foreach ($values as $i => $vars) {
99 foreach ($vars as $class => $values) {
100 foreach ($values as $name => $v) {
101 $properties[$class][$name][$i] = $v;
102 }
103 }
104 }
105
106 if ($classes || $references) {
107 $value = new Hydrator(new Registry($classes), $references ? new Values($references) : null, $properties, $value, $wakeups);
108 } else {
109 $isStaticValue = true;
110 }
111
112 return Exporter::export($value);
113 }
114}
diff --git a/vendor/symfony/var-exporter/composer.json b/vendor/symfony/var-exporter/composer.json
new file mode 100644
index 0000000..f3a227e
--- /dev/null
+++ b/vendor/symfony/var-exporter/composer.json
@@ -0,0 +1,33 @@
1{
2 "name": "symfony/var-exporter",
3 "type": "library",
4 "description": "Allows exporting any serializable PHP data structure to plain PHP code",
5 "keywords": ["export", "serialize", "instantiate", "hydrate", "construct", "clone", "lazy-loading", "proxy"],
6 "homepage": "https://symfony.com",
7 "license": "MIT",
8 "authors": [
9 {
10 "name": "Nicolas Grekas",
11 "email": "p@tchwork.com"
12 },
13 {
14 "name": "Symfony Community",
15 "homepage": "https://symfony.com/contributors"
16 }
17 ],
18 "require": {
19 "php": ">=8.2"
20 },
21 "require-dev": {
22 "symfony/property-access": "^6.4|^7.0",
23 "symfony/serializer": "^6.4|^7.0",
24 "symfony/var-dumper": "^6.4|^7.0"
25 },
26 "autoload": {
27 "psr-4": { "Symfony\\Component\\VarExporter\\": "" },
28 "exclude-from-classmap": [
29 "/Tests/"
30 ]
31 },
32 "minimum-stability": "dev"
33}