summaryrefslogtreecommitdiff
path: root/vendor/doctrine/persistence/src
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/doctrine/persistence/src')
-rw-r--r--vendor/doctrine/persistence/src/Persistence/AbstractManagerRegistry.php269
-rw-r--r--vendor/doctrine/persistence/src/Persistence/ConnectionRegistry.php41
-rw-r--r--vendor/doctrine/persistence/src/Persistence/Event/LifecycleEventArgs.php54
-rw-r--r--vendor/doctrine/persistence/src/Persistence/Event/LoadClassMetadataEventArgs.php61
-rw-r--r--vendor/doctrine/persistence/src/Persistence/Event/ManagerEventArgs.php39
-rw-r--r--vendor/doctrine/persistence/src/Persistence/Event/OnClearEventArgs.php42
-rw-r--r--vendor/doctrine/persistence/src/Persistence/Event/PreUpdateEventArgs.php110
-rw-r--r--vendor/doctrine/persistence/src/Persistence/ManagerRegistry.php89
-rw-r--r--vendor/doctrine/persistence/src/Persistence/Mapping/AbstractClassMetadataFactory.php499
-rw-r--r--vendor/doctrine/persistence/src/Persistence/Mapping/ClassMetadata.php141
-rw-r--r--vendor/doctrine/persistence/src/Persistence/Mapping/ClassMetadataFactory.php61
-rw-r--r--vendor/doctrine/persistence/src/Persistence/Mapping/Driver/ColocatedMappingDriver.php212
-rw-r--r--vendor/doctrine/persistence/src/Persistence/Mapping/Driver/DefaultFileLocator.php175
-rw-r--r--vendor/doctrine/persistence/src/Persistence/Mapping/Driver/FileDriver.php213
-rw-r--r--vendor/doctrine/persistence/src/Persistence/Mapping/Driver/FileLocator.php52
-rw-r--r--vendor/doctrine/persistence/src/Persistence/Mapping/Driver/MappingDriver.php43
-rw-r--r--vendor/doctrine/persistence/src/Persistence/Mapping/Driver/MappingDriverChain.php142
-rw-r--r--vendor/doctrine/persistence/src/Persistence/Mapping/Driver/PHPDriver.php49
-rw-r--r--vendor/doctrine/persistence/src/Persistence/Mapping/Driver/StaticPHPDriver.php132
-rw-r--r--vendor/doctrine/persistence/src/Persistence/Mapping/Driver/SymfonyFileLocator.php265
-rw-r--r--vendor/doctrine/persistence/src/Persistence/Mapping/MappingException.php88
-rw-r--r--vendor/doctrine/persistence/src/Persistence/Mapping/ProxyClassNameResolver.php19
-rw-r--r--vendor/doctrine/persistence/src/Persistence/Mapping/ReflectionService.php75
-rw-r--r--vendor/doctrine/persistence/src/Persistence/Mapping/RuntimeReflectionService.php111
-rw-r--r--vendor/doctrine/persistence/src/Persistence/Mapping/StaticReflectionService.php78
-rw-r--r--vendor/doctrine/persistence/src/Persistence/NotifyPropertyChanged.php22
-rw-r--r--vendor/doctrine/persistence/src/Persistence/ObjectManager.php145
-rw-r--r--vendor/doctrine/persistence/src/Persistence/ObjectManagerDecorator.php92
-rw-r--r--vendor/doctrine/persistence/src/Persistence/ObjectRepository.php73
-rw-r--r--vendor/doctrine/persistence/src/Persistence/PropertyChangedListener.php24
-rw-r--r--vendor/doctrine/persistence/src/Persistence/Proxy.php39
-rw-r--r--vendor/doctrine/persistence/src/Persistence/Reflection/EnumReflectionProperty.php181
-rw-r--r--vendor/doctrine/persistence/src/Persistence/Reflection/RuntimePublicReflectionProperty.php61
-rw-r--r--vendor/doctrine/persistence/src/Persistence/Reflection/RuntimeReflectionProperty.php87
-rw-r--r--vendor/doctrine/persistence/src/Persistence/Reflection/TypedNoDefaultReflectionProperty.php13
-rw-r--r--vendor/doctrine/persistence/src/Persistence/Reflection/TypedNoDefaultReflectionPropertyBase.php68
-rw-r--r--vendor/doctrine/persistence/src/Persistence/Reflection/TypedNoDefaultRuntimePublicReflectionProperty.php15
37 files changed, 3880 insertions, 0 deletions
diff --git a/vendor/doctrine/persistence/src/Persistence/AbstractManagerRegistry.php b/vendor/doctrine/persistence/src/Persistence/AbstractManagerRegistry.php
new file mode 100644
index 0000000..cc245ba
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/AbstractManagerRegistry.php
@@ -0,0 +1,269 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence;
6
7use InvalidArgumentException;
8use ReflectionClass;
9
10use function assert;
11use function sprintf;
12
13/**
14 * Abstract implementation of the ManagerRegistry contract.
15 */
16abstract class AbstractManagerRegistry implements ManagerRegistry
17{
18 /** @var string */
19 private $name;
20
21 /** @var array<string, string> */
22 private $connections;
23
24 /** @var array<string, string> */
25 private $managers;
26
27 /** @var string */
28 private $defaultConnection;
29
30 /** @var string */
31 private $defaultManager;
32
33 /**
34 * @var string
35 * @psalm-var class-string
36 */
37 private $proxyInterfaceName;
38
39 /**
40 * @param array<string, string> $connections
41 * @param array<string, string> $managers
42 * @psalm-param class-string $proxyInterfaceName
43 */
44 public function __construct(
45 string $name,
46 array $connections,
47 array $managers,
48 string $defaultConnection,
49 string $defaultManager,
50 string $proxyInterfaceName
51 ) {
52 $this->name = $name;
53 $this->connections = $connections;
54 $this->managers = $managers;
55 $this->defaultConnection = $defaultConnection;
56 $this->defaultManager = $defaultManager;
57 $this->proxyInterfaceName = $proxyInterfaceName;
58 }
59
60 /**
61 * Fetches/creates the given services.
62 *
63 * A service in this context is connection or a manager instance.
64 *
65 * @param string $name The name of the service.
66 *
67 * @return object The instance of the given service.
68 */
69 abstract protected function getService(string $name);
70
71 /**
72 * Resets the given services.
73 *
74 * A service in this context is connection or a manager instance.
75 *
76 * @param string $name The name of the service.
77 *
78 * @return void
79 */
80 abstract protected function resetService(string $name);
81
82 /**
83 * Gets the name of the registry.
84 *
85 * @return string
86 */
87 public function getName()
88 {
89 return $this->name;
90 }
91
92 /**
93 * {@inheritDoc}
94 */
95 public function getConnection(?string $name = null)
96 {
97 if ($name === null) {
98 $name = $this->defaultConnection;
99 }
100
101 if (! isset($this->connections[$name])) {
102 throw new InvalidArgumentException(
103 sprintf('Doctrine %s Connection named "%s" does not exist.', $this->name, $name)
104 );
105 }
106
107 return $this->getService($this->connections[$name]);
108 }
109
110 /**
111 * {@inheritDoc}
112 */
113 public function getConnectionNames()
114 {
115 return $this->connections;
116 }
117
118 /**
119 * {@inheritDoc}
120 */
121 public function getConnections()
122 {
123 $connections = [];
124 foreach ($this->connections as $name => $id) {
125 $connections[$name] = $this->getService($id);
126 }
127
128 return $connections;
129 }
130
131 /**
132 * {@inheritDoc}
133 */
134 public function getDefaultConnectionName()
135 {
136 return $this->defaultConnection;
137 }
138
139 /**
140 * {@inheritDoc}
141 */
142 public function getDefaultManagerName()
143 {
144 return $this->defaultManager;
145 }
146
147 /**
148 * {@inheritDoc}
149 *
150 * @throws InvalidArgumentException
151 */
152 public function getManager(?string $name = null)
153 {
154 if ($name === null) {
155 $name = $this->defaultManager;
156 }
157
158 if (! isset($this->managers[$name])) {
159 throw new InvalidArgumentException(
160 sprintf('Doctrine %s Manager named "%s" does not exist.', $this->name, $name)
161 );
162 }
163
164 $service = $this->getService($this->managers[$name]);
165 assert($service instanceof ObjectManager);
166
167 return $service;
168 }
169
170 /**
171 * {@inheritDoc}
172 */
173 public function getManagerForClass(string $class)
174 {
175 $proxyClass = new ReflectionClass($class);
176 if ($proxyClass->isAnonymous()) {
177 return null;
178 }
179
180 if ($proxyClass->implementsInterface($this->proxyInterfaceName)) {
181 $parentClass = $proxyClass->getParentClass();
182
183 if ($parentClass === false) {
184 return null;
185 }
186
187 $class = $parentClass->getName();
188 }
189
190 foreach ($this->managers as $id) {
191 $manager = $this->getService($id);
192 assert($manager instanceof ObjectManager);
193
194 if (! $manager->getMetadataFactory()->isTransient($class)) {
195 return $manager;
196 }
197 }
198
199 return null;
200 }
201
202 /**
203 * {@inheritDoc}
204 */
205 public function getManagerNames()
206 {
207 return $this->managers;
208 }
209
210 /**
211 * {@inheritDoc}
212 */
213 public function getManagers()
214 {
215 $managers = [];
216
217 foreach ($this->managers as $name => $id) {
218 $manager = $this->getService($id);
219 assert($manager instanceof ObjectManager);
220 $managers[$name] = $manager;
221 }
222
223 return $managers;
224 }
225
226 /**
227 * {@inheritDoc}
228 */
229 public function getRepository(
230 string $persistentObject,
231 ?string $persistentManagerName = null
232 ) {
233 return $this
234 ->selectManager($persistentObject, $persistentManagerName)
235 ->getRepository($persistentObject);
236 }
237
238 /**
239 * {@inheritDoc}
240 */
241 public function resetManager(?string $name = null)
242 {
243 if ($name === null) {
244 $name = $this->defaultManager;
245 }
246
247 if (! isset($this->managers[$name])) {
248 throw new InvalidArgumentException(sprintf('Doctrine %s Manager named "%s" does not exist.', $this->name, $name));
249 }
250
251 // force the creation of a new document manager
252 // if the current one is closed
253 $this->resetService($this->managers[$name]);
254
255 return $this->getManager($name);
256 }
257
258 /** @psalm-param class-string $persistentObject */
259 private function selectManager(
260 string $persistentObject,
261 ?string $persistentManagerName = null
262 ): ObjectManager {
263 if ($persistentManagerName !== null) {
264 return $this->getManager($persistentManagerName);
265 }
266
267 return $this->getManagerForClass($persistentObject) ?? $this->getManager();
268 }
269}
diff --git a/vendor/doctrine/persistence/src/Persistence/ConnectionRegistry.php b/vendor/doctrine/persistence/src/Persistence/ConnectionRegistry.php
new file mode 100644
index 0000000..59d9a74
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/ConnectionRegistry.php
@@ -0,0 +1,41 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence;
6
7/**
8 * Contract covering connection for a Doctrine persistence layer ManagerRegistry class to implement.
9 */
10interface ConnectionRegistry
11{
12 /**
13 * Gets the default connection name.
14 *
15 * @return string The default connection name.
16 */
17 public function getDefaultConnectionName();
18
19 /**
20 * Gets the named connection.
21 *
22 * @param string|null $name The connection name (null for the default one).
23 *
24 * @return object
25 */
26 public function getConnection(?string $name = null);
27
28 /**
29 * Gets an array of all registered connections.
30 *
31 * @return array<string, object> An array of Connection instances.
32 */
33 public function getConnections();
34
35 /**
36 * Gets all connection names.
37 *
38 * @return array<string, string> An array of connection names.
39 */
40 public function getConnectionNames();
41}
diff --git a/vendor/doctrine/persistence/src/Persistence/Event/LifecycleEventArgs.php b/vendor/doctrine/persistence/src/Persistence/Event/LifecycleEventArgs.php
new file mode 100644
index 0000000..1654de4
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/Event/LifecycleEventArgs.php
@@ -0,0 +1,54 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence\Event;
6
7use Doctrine\Common\EventArgs;
8use Doctrine\Persistence\ObjectManager;
9
10/**
11 * Lifecycle Events are triggered by the UnitOfWork during lifecycle transitions
12 * of entities.
13 *
14 * @template-covariant TObjectManager of ObjectManager
15 */
16class LifecycleEventArgs extends EventArgs
17{
18 /**
19 * @var ObjectManager
20 * @psalm-var TObjectManager
21 */
22 private $objectManager;
23
24 /** @var object */
25 private $object;
26
27 /** @psalm-param TObjectManager $objectManager */
28 public function __construct(object $object, ObjectManager $objectManager)
29 {
30 $this->object = $object;
31 $this->objectManager = $objectManager;
32 }
33
34 /**
35 * Retrieves the associated object.
36 *
37 * @return object
38 */
39 public function getObject()
40 {
41 return $this->object;
42 }
43
44 /**
45 * Retrieves the associated ObjectManager.
46 *
47 * @return ObjectManager
48 * @psalm-return TObjectManager
49 */
50 public function getObjectManager()
51 {
52 return $this->objectManager;
53 }
54}
diff --git a/vendor/doctrine/persistence/src/Persistence/Event/LoadClassMetadataEventArgs.php b/vendor/doctrine/persistence/src/Persistence/Event/LoadClassMetadataEventArgs.php
new file mode 100644
index 0000000..aa92d5d
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/Event/LoadClassMetadataEventArgs.php
@@ -0,0 +1,61 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence\Event;
6
7use Doctrine\Common\EventArgs;
8use Doctrine\Persistence\Mapping\ClassMetadata;
9use Doctrine\Persistence\ObjectManager;
10
11/**
12 * Class that holds event arguments for a loadMetadata event.
13 *
14 * @template-covariant TClassMetadata of ClassMetadata<object>
15 * @template-covariant TObjectManager of ObjectManager
16 */
17class LoadClassMetadataEventArgs extends EventArgs
18{
19 /**
20 * @var ClassMetadata
21 * @psalm-var TClassMetadata
22 */
23 private $classMetadata;
24
25 /**
26 * @var ObjectManager
27 * @psalm-var TObjectManager
28 */
29 private $objectManager;
30
31 /**
32 * @psalm-param TClassMetadata $classMetadata
33 * @psalm-param TObjectManager $objectManager
34 */
35 public function __construct(ClassMetadata $classMetadata, ObjectManager $objectManager)
36 {
37 $this->classMetadata = $classMetadata;
38 $this->objectManager = $objectManager;
39 }
40
41 /**
42 * Retrieves the associated ClassMetadata.
43 *
44 * @return ClassMetadata
45 * @psalm-return TClassMetadata
46 */
47 public function getClassMetadata()
48 {
49 return $this->classMetadata;
50 }
51
52 /**
53 * Retrieves the associated ObjectManager.
54 *
55 * @return TObjectManager
56 */
57 public function getObjectManager()
58 {
59 return $this->objectManager;
60 }
61}
diff --git a/vendor/doctrine/persistence/src/Persistence/Event/ManagerEventArgs.php b/vendor/doctrine/persistence/src/Persistence/Event/ManagerEventArgs.php
new file mode 100644
index 0000000..5156013
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/Event/ManagerEventArgs.php
@@ -0,0 +1,39 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence\Event;
6
7use Doctrine\Common\EventArgs;
8use Doctrine\Persistence\ObjectManager;
9
10/**
11 * Provides event arguments for the preFlush event.
12 *
13 * @template-covariant TObjectManager of ObjectManager
14 */
15class ManagerEventArgs extends EventArgs
16{
17 /**
18 * @var ObjectManager
19 * @psalm-var TObjectManager
20 */
21 private $objectManager;
22
23 /** @psalm-param TObjectManager $objectManager */
24 public function __construct(ObjectManager $objectManager)
25 {
26 $this->objectManager = $objectManager;
27 }
28
29 /**
30 * Retrieves the associated ObjectManager.
31 *
32 * @return ObjectManager
33 * @psalm-return TObjectManager
34 */
35 public function getObjectManager()
36 {
37 return $this->objectManager;
38 }
39}
diff --git a/vendor/doctrine/persistence/src/Persistence/Event/OnClearEventArgs.php b/vendor/doctrine/persistence/src/Persistence/Event/OnClearEventArgs.php
new file mode 100644
index 0000000..519a887
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/Event/OnClearEventArgs.php
@@ -0,0 +1,42 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence\Event;
6
7use Doctrine\Common\EventArgs;
8use Doctrine\Persistence\ObjectManager;
9
10/**
11 * Provides event arguments for the onClear event.
12 *
13 * @template-covariant TObjectManager of ObjectManager
14 */
15class OnClearEventArgs extends EventArgs
16{
17 /**
18 * @var ObjectManager
19 * @psalm-var TObjectManager
20 */
21 private $objectManager;
22
23 /**
24 * @param ObjectManager $objectManager The object manager.
25 * @psalm-param TObjectManager $objectManager
26 */
27 public function __construct(ObjectManager $objectManager)
28 {
29 $this->objectManager = $objectManager;
30 }
31
32 /**
33 * Retrieves the associated ObjectManager.
34 *
35 * @return ObjectManager
36 * @psalm-return TObjectManager
37 */
38 public function getObjectManager()
39 {
40 return $this->objectManager;
41 }
42}
diff --git a/vendor/doctrine/persistence/src/Persistence/Event/PreUpdateEventArgs.php b/vendor/doctrine/persistence/src/Persistence/Event/PreUpdateEventArgs.php
new file mode 100644
index 0000000..95ecbd4
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/Event/PreUpdateEventArgs.php
@@ -0,0 +1,110 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence\Event;
6
7use Doctrine\Persistence\ObjectManager;
8use InvalidArgumentException;
9
10use function get_class;
11use function sprintf;
12
13/**
14 * Class that holds event arguments for a preUpdate event.
15 *
16 * @template-covariant TObjectManager of ObjectManager
17 * @extends LifecycleEventArgs<TObjectManager>
18 */
19class PreUpdateEventArgs extends LifecycleEventArgs
20{
21 /** @var array<string, array<int, mixed>> */
22 private $entityChangeSet;
23
24 /**
25 * @param array<string, array<int, mixed>> $changeSet
26 * @psalm-param TObjectManager $objectManager
27 */
28 public function __construct(object $entity, ObjectManager $objectManager, array &$changeSet)
29 {
30 parent::__construct($entity, $objectManager);
31
32 $this->entityChangeSet = &$changeSet;
33 }
34
35 /**
36 * Retrieves the entity changeset.
37 *
38 * @return array<string, array<int, mixed>>
39 */
40 public function getEntityChangeSet()
41 {
42 return $this->entityChangeSet;
43 }
44
45 /**
46 * Checks if field has a changeset.
47 *
48 * @return bool
49 */
50 public function hasChangedField(string $field)
51 {
52 return isset($this->entityChangeSet[$field]);
53 }
54
55 /**
56 * Gets the old value of the changeset of the changed field.
57 *
58 * @return mixed
59 */
60 public function getOldValue(string $field)
61 {
62 $this->assertValidField($field);
63
64 return $this->entityChangeSet[$field][0];
65 }
66
67 /**
68 * Gets the new value of the changeset of the changed field.
69 *
70 * @return mixed
71 */
72 public function getNewValue(string $field)
73 {
74 $this->assertValidField($field);
75
76 return $this->entityChangeSet[$field][1];
77 }
78
79 /**
80 * Sets the new value of this field.
81 *
82 * @param mixed $value
83 *
84 * @return void
85 */
86 public function setNewValue(string $field, $value)
87 {
88 $this->assertValidField($field);
89
90 $this->entityChangeSet[$field][1] = $value;
91 }
92
93 /**
94 * Asserts the field exists in changeset.
95 *
96 * @return void
97 *
98 * @throws InvalidArgumentException
99 */
100 private function assertValidField(string $field)
101 {
102 if (! isset($this->entityChangeSet[$field])) {
103 throw new InvalidArgumentException(sprintf(
104 'Field "%s" is not a valid field of the entity "%s" in PreUpdateEventArgs.',
105 $field,
106 get_class($this->getObject())
107 ));
108 }
109 }
110}
diff --git a/vendor/doctrine/persistence/src/Persistence/ManagerRegistry.php b/vendor/doctrine/persistence/src/Persistence/ManagerRegistry.php
new file mode 100644
index 0000000..46599a5
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/ManagerRegistry.php
@@ -0,0 +1,89 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence;
6
7/**
8 * Contract covering object managers for a Doctrine persistence layer ManagerRegistry class to implement.
9 */
10interface ManagerRegistry extends ConnectionRegistry
11{
12 /**
13 * Gets the default object manager name.
14 *
15 * @return string The default object manager name.
16 */
17 public function getDefaultManagerName();
18
19 /**
20 * Gets a named object manager.
21 *
22 * @param string|null $name The object manager name (null for the default one).
23 *
24 * @return ObjectManager
25 */
26 public function getManager(?string $name = null);
27
28 /**
29 * Gets an array of all registered object managers.
30 *
31 * @return array<string, ObjectManager> An array of ObjectManager instances
32 */
33 public function getManagers();
34
35 /**
36 * Resets a named object manager.
37 *
38 * This method is useful when an object manager has been closed
39 * because of a rollbacked transaction AND when you think that
40 * it makes sense to get a new one to replace the closed one.
41 *
42 * Be warned that you will get a brand new object manager as
43 * the existing one is not useable anymore. This means that any
44 * other object with a dependency on this object manager will
45 * hold an obsolete reference. You can inject the registry instead
46 * to avoid this problem.
47 *
48 * @param string|null $name The object manager name (null for the default one).
49 *
50 * @return ObjectManager
51 */
52 public function resetManager(?string $name = null);
53
54 /**
55 * Gets all object manager names and associated service IDs. A service ID
56 * is a string that allows to obtain an object manager, typically from a
57 * PSR-11 container.
58 *
59 * @return array<string,string> An array with object manager names as keys,
60 * and service IDs as values.
61 */
62 public function getManagerNames();
63
64 /**
65 * Gets the ObjectRepository for a persistent object.
66 *
67 * @param string $persistentObject The name of the persistent object.
68 * @param string|null $persistentManagerName The object manager name (null for the default one).
69 * @psalm-param class-string<T> $persistentObject
70 *
71 * @return ObjectRepository
72 * @psalm-return ObjectRepository<T>
73 *
74 * @template T of object
75 */
76 public function getRepository(
77 string $persistentObject,
78 ?string $persistentManagerName = null
79 );
80
81 /**
82 * Gets the object manager associated with a given class.
83 *
84 * @param class-string $class A persistent object class name.
85 *
86 * @return ObjectManager|null
87 */
88 public function getManagerForClass(string $class);
89}
diff --git a/vendor/doctrine/persistence/src/Persistence/Mapping/AbstractClassMetadataFactory.php b/vendor/doctrine/persistence/src/Persistence/Mapping/AbstractClassMetadataFactory.php
new file mode 100644
index 0000000..e8f6aca
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/Mapping/AbstractClassMetadataFactory.php
@@ -0,0 +1,499 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence\Mapping;
6
7use Doctrine\Persistence\Mapping\Driver\MappingDriver;
8use Doctrine\Persistence\Proxy;
9use Psr\Cache\CacheItemPoolInterface;
10use ReflectionClass;
11use ReflectionException;
12
13use function array_combine;
14use function array_keys;
15use function array_map;
16use function array_reverse;
17use function array_unshift;
18use function assert;
19use function class_exists;
20use function ltrim;
21use function str_replace;
22use function strpos;
23use function strrpos;
24use function substr;
25
26/**
27 * The ClassMetadataFactory is used to create ClassMetadata objects that contain all the
28 * metadata mapping informations of a class which describes how a class should be mapped
29 * to a relational database.
30 *
31 * This class was abstracted from the ORM ClassMetadataFactory.
32 *
33 * @template CMTemplate of ClassMetadata
34 * @template-implements ClassMetadataFactory<CMTemplate>
35 */
36abstract class AbstractClassMetadataFactory implements ClassMetadataFactory
37{
38 /**
39 * Salt used by specific Object Manager implementation.
40 *
41 * @var string
42 */
43 protected $cacheSalt = '__CLASSMETADATA__';
44
45 /** @var CacheItemPoolInterface|null */
46 private $cache;
47
48 /**
49 * @var array<string, ClassMetadata>
50 * @psalm-var CMTemplate[]
51 */
52 private $loadedMetadata = [];
53
54 /** @var bool */
55 protected $initialized = false;
56
57 /** @var ReflectionService|null */
58 private $reflectionService = null;
59
60 /** @var ProxyClassNameResolver|null */
61 private $proxyClassNameResolver = null;
62
63 public function setCache(CacheItemPoolInterface $cache): void
64 {
65 $this->cache = $cache;
66 }
67
68 final protected function getCache(): ?CacheItemPoolInterface
69 {
70 return $this->cache;
71 }
72
73 /**
74 * Returns an array of all the loaded metadata currently in memory.
75 *
76 * @return ClassMetadata[]
77 * @psalm-return CMTemplate[]
78 */
79 public function getLoadedMetadata()
80 {
81 return $this->loadedMetadata;
82 }
83
84 /**
85 * {@inheritDoc}
86 */
87 public function getAllMetadata()
88 {
89 if (! $this->initialized) {
90 $this->initialize();
91 }
92
93 $driver = $this->getDriver();
94 $metadata = [];
95 foreach ($driver->getAllClassNames() as $className) {
96 $metadata[] = $this->getMetadataFor($className);
97 }
98
99 return $metadata;
100 }
101
102 public function setProxyClassNameResolver(ProxyClassNameResolver $resolver): void
103 {
104 $this->proxyClassNameResolver = $resolver;
105 }
106
107 /**
108 * Lazy initialization of this stuff, especially the metadata driver,
109 * since these are not needed at all when a metadata cache is active.
110 *
111 * @return void
112 */
113 abstract protected function initialize();
114
115 /**
116 * Returns the mapping driver implementation.
117 *
118 * @return MappingDriver
119 */
120 abstract protected function getDriver();
121
122 /**
123 * Wakes up reflection after ClassMetadata gets unserialized from cache.
124 *
125 * @psalm-param CMTemplate $class
126 *
127 * @return void
128 */
129 abstract protected function wakeupReflection(
130 ClassMetadata $class,
131 ReflectionService $reflService
132 );
133
134 /**
135 * Initializes Reflection after ClassMetadata was constructed.
136 *
137 * @psalm-param CMTemplate $class
138 *
139 * @return void
140 */
141 abstract protected function initializeReflection(
142 ClassMetadata $class,
143 ReflectionService $reflService
144 );
145
146 /**
147 * Checks whether the class metadata is an entity.
148 *
149 * This method should return false for mapped superclasses or embedded classes.
150 *
151 * @psalm-param CMTemplate $class
152 *
153 * @return bool
154 */
155 abstract protected function isEntity(ClassMetadata $class);
156
157 /**
158 * Removes the prepended backslash of a class string to conform with how php outputs class names
159 *
160 * @psalm-param class-string $className
161 *
162 * @psalm-return class-string
163 */
164 private function normalizeClassName(string $className): string
165 {
166 return ltrim($className, '\\');
167 }
168
169 /**
170 * {@inheritDoc}
171 *
172 * @throws ReflectionException
173 * @throws MappingException
174 */
175 public function getMetadataFor(string $className)
176 {
177 $className = $this->normalizeClassName($className);
178
179 if (isset($this->loadedMetadata[$className])) {
180 return $this->loadedMetadata[$className];
181 }
182
183 if (class_exists($className, false) && (new ReflectionClass($className))->isAnonymous()) {
184 throw MappingException::classIsAnonymous($className);
185 }
186
187 if (! class_exists($className, false) && strpos($className, ':') !== false) {
188 throw MappingException::nonExistingClass($className);
189 }
190
191 $realClassName = $this->getRealClass($className);
192
193 if (isset($this->loadedMetadata[$realClassName])) {
194 // We do not have the alias name in the map, include it
195 return $this->loadedMetadata[$className] = $this->loadedMetadata[$realClassName];
196 }
197
198 try {
199 if ($this->cache !== null) {
200 $cached = $this->cache->getItem($this->getCacheKey($realClassName))->get();
201 if ($cached instanceof ClassMetadata) {
202 /** @psalm-var CMTemplate $cached */
203 $this->loadedMetadata[$realClassName] = $cached;
204
205 $this->wakeupReflection($cached, $this->getReflectionService());
206 } else {
207 $loadedMetadata = $this->loadMetadata($realClassName);
208 $classNames = array_combine(
209 array_map([$this, 'getCacheKey'], $loadedMetadata),
210 $loadedMetadata
211 );
212
213 foreach ($this->cache->getItems(array_keys($classNames)) as $item) {
214 if (! isset($classNames[$item->getKey()])) {
215 continue;
216 }
217
218 $item->set($this->loadedMetadata[$classNames[$item->getKey()]]);
219 $this->cache->saveDeferred($item);
220 }
221
222 $this->cache->commit();
223 }
224 } else {
225 $this->loadMetadata($realClassName);
226 }
227 } catch (MappingException $loadingException) {
228 $fallbackMetadataResponse = $this->onNotFoundMetadata($realClassName);
229
230 if ($fallbackMetadataResponse === null) {
231 throw $loadingException;
232 }
233
234 $this->loadedMetadata[$realClassName] = $fallbackMetadataResponse;
235 }
236
237 if ($className !== $realClassName) {
238 // We do not have the alias name in the map, include it
239 $this->loadedMetadata[$className] = $this->loadedMetadata[$realClassName];
240 }
241
242 return $this->loadedMetadata[$className];
243 }
244
245 /**
246 * {@inheritDoc}
247 */
248 public function hasMetadataFor(string $className)
249 {
250 $className = $this->normalizeClassName($className);
251
252 return isset($this->loadedMetadata[$className]);
253 }
254
255 /**
256 * Sets the metadata descriptor for a specific class.
257 *
258 * NOTE: This is only useful in very special cases, like when generating proxy classes.
259 *
260 * @psalm-param class-string $className
261 * @psalm-param CMTemplate $class
262 *
263 * @return void
264 */
265 public function setMetadataFor(string $className, ClassMetadata $class)
266 {
267 $this->loadedMetadata[$this->normalizeClassName($className)] = $class;
268 }
269
270 /**
271 * Gets an array of parent classes for the given entity class.
272 *
273 * @psalm-param class-string $name
274 *
275 * @return string[]
276 * @psalm-return list<class-string>
277 */
278 protected function getParentClasses(string $name)
279 {
280 // Collect parent classes, ignoring transient (not-mapped) classes.
281 $parentClasses = [];
282
283 foreach (array_reverse($this->getReflectionService()->getParentClasses($name)) as $parentClass) {
284 if ($this->getDriver()->isTransient($parentClass)) {
285 continue;
286 }
287
288 $parentClasses[] = $parentClass;
289 }
290
291 return $parentClasses;
292 }
293
294 /**
295 * Loads the metadata of the class in question and all it's ancestors whose metadata
296 * is still not loaded.
297 *
298 * Important: The class $name does not necessarily exist at this point here.
299 * Scenarios in a code-generation setup might have access to XML/YAML
300 * Mapping files without the actual PHP code existing here. That is why the
301 * {@see \Doctrine\Persistence\Mapping\ReflectionService} interface
302 * should be used for reflection.
303 *
304 * @param string $name The name of the class for which the metadata should get loaded.
305 * @psalm-param class-string $name
306 *
307 * @return array<int, string>
308 * @psalm-return list<string>
309 */
310 protected function loadMetadata(string $name)
311 {
312 if (! $this->initialized) {
313 $this->initialize();
314 }
315
316 $loaded = [];
317
318 $parentClasses = $this->getParentClasses($name);
319 $parentClasses[] = $name;
320
321 // Move down the hierarchy of parent classes, starting from the topmost class
322 $parent = null;
323 $rootEntityFound = false;
324 $visited = [];
325 $reflService = $this->getReflectionService();
326
327 foreach ($parentClasses as $className) {
328 if (isset($this->loadedMetadata[$className])) {
329 $parent = $this->loadedMetadata[$className];
330
331 if ($this->isEntity($parent)) {
332 $rootEntityFound = true;
333
334 array_unshift($visited, $className);
335 }
336
337 continue;
338 }
339
340 $class = $this->newClassMetadataInstance($className);
341 $this->initializeReflection($class, $reflService);
342
343 $this->doLoadMetadata($class, $parent, $rootEntityFound, $visited);
344
345 $this->loadedMetadata[$className] = $class;
346
347 $parent = $class;
348
349 if ($this->isEntity($class)) {
350 $rootEntityFound = true;
351
352 array_unshift($visited, $className);
353 }
354
355 $this->wakeupReflection($class, $reflService);
356
357 $loaded[] = $className;
358 }
359
360 return $loaded;
361 }
362
363 /**
364 * Provides a fallback hook for loading metadata when loading failed due to reflection/mapping exceptions
365 *
366 * Override this method to implement a fallback strategy for failed metadata loading
367 *
368 * @return ClassMetadata|null
369 * @psalm-return CMTemplate|null
370 */
371 protected function onNotFoundMetadata(string $className)
372 {
373 return null;
374 }
375
376 /**
377 * Actually loads the metadata from the underlying metadata.
378 *
379 * @param bool $rootEntityFound True when there is another entity (non-mapped superclass) class above the current class in the PHP class hierarchy.
380 * @param list<class-string> $nonSuperclassParents All parent class names that are not marked as mapped superclasses, with the direct parent class being the first and the root entity class the last element.
381 * @psalm-param CMTemplate $class
382 * @psalm-param CMTemplate|null $parent
383 *
384 * @return void
385 */
386 abstract protected function doLoadMetadata(
387 ClassMetadata $class,
388 ?ClassMetadata $parent,
389 bool $rootEntityFound,
390 array $nonSuperclassParents
391 );
392
393 /**
394 * Creates a new ClassMetadata instance for the given class name.
395 *
396 * @psalm-param class-string<T> $className
397 *
398 * @return ClassMetadata<T>
399 * @psalm-return CMTemplate
400 *
401 * @template T of object
402 */
403 abstract protected function newClassMetadataInstance(string $className);
404
405 /**
406 * {@inheritDoc}
407 */
408 public function isTransient(string $className)
409 {
410 if (! $this->initialized) {
411 $this->initialize();
412 }
413
414 if (class_exists($className, false) && (new ReflectionClass($className))->isAnonymous()) {
415 return false;
416 }
417
418 if (! class_exists($className, false) && strpos($className, ':') !== false) {
419 throw MappingException::nonExistingClass($className);
420 }
421
422 /** @psalm-var class-string $className */
423 return $this->getDriver()->isTransient($className);
424 }
425
426 /**
427 * Sets the reflectionService.
428 *
429 * @return void
430 */
431 public function setReflectionService(ReflectionService $reflectionService)
432 {
433 $this->reflectionService = $reflectionService;
434 }
435
436 /**
437 * Gets the reflection service associated with this metadata factory.
438 *
439 * @return ReflectionService
440 */
441 public function getReflectionService()
442 {
443 if ($this->reflectionService === null) {
444 $this->reflectionService = new RuntimeReflectionService();
445 }
446
447 return $this->reflectionService;
448 }
449
450 protected function getCacheKey(string $realClassName): string
451 {
452 return str_replace('\\', '__', $realClassName) . $this->cacheSalt;
453 }
454
455 /**
456 * Gets the real class name of a class name that could be a proxy.
457 *
458 * @psalm-param class-string<Proxy<T>>|class-string<T> $class
459 *
460 * @psalm-return class-string<T>
461 *
462 * @template T of object
463 */
464 private function getRealClass(string $class): string
465 {
466 if ($this->proxyClassNameResolver === null) {
467 $this->createDefaultProxyClassNameResolver();
468 }
469
470 assert($this->proxyClassNameResolver !== null);
471
472 return $this->proxyClassNameResolver->resolveClassName($class);
473 }
474
475 private function createDefaultProxyClassNameResolver(): void
476 {
477 $this->proxyClassNameResolver = new class implements ProxyClassNameResolver {
478 /**
479 * @psalm-param class-string<Proxy<T>>|class-string<T> $className
480 *
481 * @psalm-return class-string<T>
482 *
483 * @template T of object
484 */
485 public function resolveClassName(string $className): string
486 {
487 $pos = strrpos($className, '\\' . Proxy::MARKER . '\\');
488
489 if ($pos === false) {
490 /** @psalm-var class-string<T> */
491 return $className;
492 }
493
494 /** @psalm-var class-string<T> */
495 return substr($className, $pos + Proxy::MARKER_LENGTH + 2);
496 }
497 };
498 }
499}
diff --git a/vendor/doctrine/persistence/src/Persistence/Mapping/ClassMetadata.php b/vendor/doctrine/persistence/src/Persistence/Mapping/ClassMetadata.php
new file mode 100644
index 0000000..f407ba3
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/Mapping/ClassMetadata.php
@@ -0,0 +1,141 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence\Mapping;
6
7use ReflectionClass;
8
9/**
10 * Contract for a Doctrine persistence layer ClassMetadata class to implement.
11 *
12 * @template-covariant T of object
13 */
14interface ClassMetadata
15{
16 /**
17 * Gets the fully-qualified class name of this persistent class.
18 *
19 * @return string
20 * @psalm-return class-string<T>
21 */
22 public function getName();
23
24 /**
25 * Gets the mapped identifier field name.
26 *
27 * The returned structure is an array of the identifier field names.
28 *
29 * @return array<int, string>
30 * @psalm-return list<string>
31 */
32 public function getIdentifier();
33
34 /**
35 * Gets the ReflectionClass instance for this mapped class.
36 *
37 * @return ReflectionClass<T>
38 */
39 public function getReflectionClass();
40
41 /**
42 * Checks if the given field name is a mapped identifier for this class.
43 *
44 * @return bool
45 */
46 public function isIdentifier(string $fieldName);
47
48 /**
49 * Checks if the given field is a mapped property for this class.
50 *
51 * @return bool
52 */
53 public function hasField(string $fieldName);
54
55 /**
56 * Checks if the given field is a mapped association for this class.
57 *
58 * @return bool
59 */
60 public function hasAssociation(string $fieldName);
61
62 /**
63 * Checks if the given field is a mapped single valued association for this class.
64 *
65 * @return bool
66 */
67 public function isSingleValuedAssociation(string $fieldName);
68
69 /**
70 * Checks if the given field is a mapped collection valued association for this class.
71 *
72 * @return bool
73 */
74 public function isCollectionValuedAssociation(string $fieldName);
75
76 /**
77 * A numerically indexed list of field names of this persistent class.
78 *
79 * This array includes identifier fields if present on this class.
80 *
81 * @return array<int, string>
82 */
83 public function getFieldNames();
84
85 /**
86 * Returns an array of identifier field names numerically indexed.
87 *
88 * @return array<int, string>
89 */
90 public function getIdentifierFieldNames();
91
92 /**
93 * Returns a numerically indexed list of association names of this persistent class.
94 *
95 * This array includes identifier associations if present on this class.
96 *
97 * @return array<int, string>
98 */
99 public function getAssociationNames();
100
101 /**
102 * Returns a type name of this field.
103 *
104 * This type names can be implementation specific but should at least include the php types:
105 * integer, string, boolean, float/double, datetime.
106 *
107 * @return string|null
108 */
109 public function getTypeOfField(string $fieldName);
110
111 /**
112 * Returns the target class name of the given association.
113 *
114 * @return string|null
115 * @psalm-return class-string|null
116 */
117 public function getAssociationTargetClass(string $assocName);
118
119 /**
120 * Checks if the association is the inverse side of a bidirectional association.
121 *
122 * @return bool
123 */
124 public function isAssociationInverseSide(string $assocName);
125
126 /**
127 * Returns the target field of the owning side of the association.
128 *
129 * @return string
130 */
131 public function getAssociationMappedByTargetField(string $assocName);
132
133 /**
134 * Returns the identifier of this object as an array with field name as key.
135 *
136 * Has to return an empty array if no identifier isset.
137 *
138 * @return array<string, mixed>
139 */
140 public function getIdentifierValues(object $object);
141}
diff --git a/vendor/doctrine/persistence/src/Persistence/Mapping/ClassMetadataFactory.php b/vendor/doctrine/persistence/src/Persistence/Mapping/ClassMetadataFactory.php
new file mode 100644
index 0000000..28b8303
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/Mapping/ClassMetadataFactory.php
@@ -0,0 +1,61 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence\Mapping;
6
7/**
8 * Contract for a Doctrine persistence layer ClassMetadata class to implement.
9 *
10 * @template T of ClassMetadata
11 */
12interface ClassMetadataFactory
13{
14 /**
15 * Forces the factory to load the metadata of all classes known to the underlying
16 * mapping driver.
17 *
18 * @return ClassMetadata[] The ClassMetadata instances of all mapped classes.
19 * @psalm-return list<T>
20 */
21 public function getAllMetadata();
22
23 /**
24 * Gets the class metadata descriptor for a class.
25 *
26 * @param class-string $className The name of the class.
27 *
28 * @return ClassMetadata
29 * @psalm-return T
30 */
31 public function getMetadataFor(string $className);
32
33 /**
34 * Checks whether the factory has the metadata for a class loaded already.
35 *
36 * @param class-string $className
37 *
38 * @return bool TRUE if the metadata of the class in question is already loaded, FALSE otherwise.
39 */
40 public function hasMetadataFor(string $className);
41
42 /**
43 * Sets the metadata descriptor for a specific class.
44 *
45 * @param class-string $className
46 * @psalm-param T $class
47 *
48 * @return void
49 */
50 public function setMetadataFor(string $className, ClassMetadata $class);
51
52 /**
53 * Returns whether the class with the specified name should have its metadata loaded.
54 * This is only the case if it is either mapped directly or as a MappedSuperclass.
55 *
56 * @psalm-param class-string $className
57 *
58 * @return bool
59 */
60 public function isTransient(string $className);
61}
diff --git a/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/ColocatedMappingDriver.php b/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/ColocatedMappingDriver.php
new file mode 100644
index 0000000..e85ba70
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/ColocatedMappingDriver.php
@@ -0,0 +1,212 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence\Mapping\Driver;
6
7use Doctrine\Persistence\Mapping\MappingException;
8use FilesystemIterator;
9use RecursiveDirectoryIterator;
10use RecursiveIteratorIterator;
11use RecursiveRegexIterator;
12use ReflectionClass;
13use RegexIterator;
14
15use function array_merge;
16use function array_unique;
17use function assert;
18use function get_declared_classes;
19use function in_array;
20use function is_dir;
21use function preg_match;
22use function preg_quote;
23use function realpath;
24use function str_replace;
25use function strpos;
26
27/**
28 * The ColocatedMappingDriver reads the mapping metadata located near the code.
29 */
30trait ColocatedMappingDriver
31{
32 /**
33 * The paths where to look for mapping files.
34 *
35 * @var array<int, string>
36 */
37 protected $paths = [];
38
39 /**
40 * The paths excluded from path where to look for mapping files.
41 *
42 * @var array<int, string>
43 */
44 protected $excludePaths = [];
45
46 /**
47 * The file extension of mapping documents.
48 *
49 * @var string
50 */
51 protected $fileExtension = '.php';
52
53 /**
54 * Cache for getAllClassNames().
55 *
56 * @var array<int, string>|null
57 * @psalm-var list<class-string>|null
58 */
59 protected $classNames;
60
61 /**
62 * Appends lookup paths to metadata driver.
63 *
64 * @param array<int, string> $paths
65 *
66 * @return void
67 */
68 public function addPaths(array $paths)
69 {
70 $this->paths = array_unique(array_merge($this->paths, $paths));
71 }
72
73 /**
74 * Retrieves the defined metadata lookup paths.
75 *
76 * @return array<int, string>
77 */
78 public function getPaths()
79 {
80 return $this->paths;
81 }
82
83 /**
84 * Append exclude lookup paths to metadata driver.
85 *
86 * @param string[] $paths
87 *
88 * @return void
89 */
90 public function addExcludePaths(array $paths)
91 {
92 $this->excludePaths = array_unique(array_merge($this->excludePaths, $paths));
93 }
94
95 /**
96 * Retrieve the defined metadata lookup exclude paths.
97 *
98 * @return array<int, string>
99 */
100 public function getExcludePaths()
101 {
102 return $this->excludePaths;
103 }
104
105 /**
106 * Gets the file extension used to look for mapping files under.
107 *
108 * @return string
109 */
110 public function getFileExtension()
111 {
112 return $this->fileExtension;
113 }
114
115 /**
116 * Sets the file extension used to look for mapping files under.
117 *
118 * @return void
119 */
120 public function setFileExtension(string $fileExtension)
121 {
122 $this->fileExtension = $fileExtension;
123 }
124
125 /**
126 * {@inheritDoc}
127 *
128 * Returns whether the class with the specified name is transient. Only non-transient
129 * classes, that is entities and mapped superclasses, should have their metadata loaded.
130 *
131 * @psalm-param class-string $className
132 *
133 * @return bool
134 */
135 abstract public function isTransient(string $className);
136
137 /**
138 * Gets the names of all mapped classes known to this driver.
139 *
140 * @return string[] The names of all mapped classes known to this driver.
141 * @psalm-return list<class-string>
142 */
143 public function getAllClassNames()
144 {
145 if ($this->classNames !== null) {
146 return $this->classNames;
147 }
148
149 if ($this->paths === []) {
150 throw MappingException::pathRequiredForDriver(static::class);
151 }
152
153 $classes = [];
154 $includedFiles = [];
155
156 foreach ($this->paths as $path) {
157 if (! is_dir($path)) {
158 throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path);
159 }
160
161 $iterator = new RegexIterator(
162 new RecursiveIteratorIterator(
163 new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS),
164 RecursiveIteratorIterator::LEAVES_ONLY
165 ),
166 '/^.+' . preg_quote($this->fileExtension) . '$/i',
167 RecursiveRegexIterator::GET_MATCH
168 );
169
170 foreach ($iterator as $file) {
171 $sourceFile = $file[0];
172
173 if (preg_match('(^phar:)i', $sourceFile) === 0) {
174 $sourceFile = realpath($sourceFile);
175 }
176
177 foreach ($this->excludePaths as $excludePath) {
178 $realExcludePath = realpath($excludePath);
179 assert($realExcludePath !== false);
180 $exclude = str_replace('\\', '/', $realExcludePath);
181 $current = str_replace('\\', '/', $sourceFile);
182
183 if (strpos($current, $exclude) !== false) {
184 continue 2;
185 }
186 }
187
188 require_once $sourceFile;
189
190 $includedFiles[] = $sourceFile;
191 }
192 }
193
194 $declared = get_declared_classes();
195
196 foreach ($declared as $className) {
197 $rc = new ReflectionClass($className);
198
199 $sourceFile = $rc->getFileName();
200
201 if (! in_array($sourceFile, $includedFiles, true) || $this->isTransient($className)) {
202 continue;
203 }
204
205 $classes[] = $className;
206 }
207
208 $this->classNames = $classes;
209
210 return $classes;
211 }
212}
diff --git a/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/DefaultFileLocator.php b/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/DefaultFileLocator.php
new file mode 100644
index 0000000..9b00e74
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/DefaultFileLocator.php
@@ -0,0 +1,175 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence\Mapping\Driver;
6
7use Doctrine\Persistence\Mapping\MappingException;
8use RecursiveDirectoryIterator;
9use RecursiveIteratorIterator;
10
11use function array_merge;
12use function array_unique;
13use function assert;
14use function is_dir;
15use function is_file;
16use function is_string;
17use function str_replace;
18
19use const DIRECTORY_SEPARATOR;
20
21/**
22 * Locates the file that contains the metadata information for a given class name.
23 *
24 * This behavior is independent of the actual content of the file. It just detects
25 * the file which is responsible for the given class name.
26 */
27class DefaultFileLocator implements FileLocator
28{
29 /**
30 * The paths where to look for mapping files.
31 *
32 * @var array<int, string>
33 */
34 protected $paths = [];
35
36 /**
37 * The file extension of mapping documents.
38 *
39 * @var string|null
40 */
41 protected $fileExtension;
42
43 /**
44 * Initializes a new FileDriver that looks in the given path(s) for mapping
45 * documents and operates in the specified operating mode.
46 *
47 * @param string|array<int, string> $paths One or multiple paths where mapping documents
48 * can be found.
49 * @param string|null $fileExtension The file extension of mapping documents,
50 * usually prefixed with a dot.
51 */
52 public function __construct($paths, ?string $fileExtension = null)
53 {
54 $this->addPaths((array) $paths);
55 $this->fileExtension = $fileExtension;
56 }
57
58 /**
59 * Appends lookup paths to metadata driver.
60 *
61 * @param array<int, string> $paths
62 *
63 * @return void
64 */
65 public function addPaths(array $paths)
66 {
67 $this->paths = array_unique(array_merge($this->paths, $paths));
68 }
69
70 /**
71 * Retrieves the defined metadata lookup paths.
72 *
73 * @return array<int, string>
74 */
75 public function getPaths()
76 {
77 return $this->paths;
78 }
79
80 /**
81 * Gets the file extension used to look for mapping files under.
82 *
83 * @return string|null
84 */
85 public function getFileExtension()
86 {
87 return $this->fileExtension;
88 }
89
90 /**
91 * Sets the file extension used to look for mapping files under.
92 *
93 * @param string|null $fileExtension The file extension to set.
94 *
95 * @return void
96 */
97 public function setFileExtension(?string $fileExtension)
98 {
99 $this->fileExtension = $fileExtension;
100 }
101
102 /**
103 * {@inheritDoc}
104 */
105 public function findMappingFile(string $className)
106 {
107 $fileName = str_replace('\\', '.', $className) . $this->fileExtension;
108
109 // Check whether file exists
110 foreach ($this->paths as $path) {
111 if (is_file($path . DIRECTORY_SEPARATOR . $fileName)) {
112 return $path . DIRECTORY_SEPARATOR . $fileName;
113 }
114 }
115
116 throw MappingException::mappingFileNotFound($className, $fileName);
117 }
118
119 /**
120 * {@inheritDoc}
121 */
122 public function getAllClassNames(string $globalBasename)
123 {
124 if ($this->paths === []) {
125 return [];
126 }
127
128 $classes = [];
129
130 foreach ($this->paths as $path) {
131 if (! is_dir($path)) {
132 throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path);
133 }
134
135 $iterator = new RecursiveIteratorIterator(
136 new RecursiveDirectoryIterator($path),
137 RecursiveIteratorIterator::LEAVES_ONLY
138 );
139
140 foreach ($iterator as $file) {
141 $fileName = $file->getBasename($this->fileExtension);
142
143 if ($fileName === $file->getBasename() || $fileName === $globalBasename) {
144 continue;
145 }
146
147 // NOTE: All files found here means classes are not transient!
148
149 assert(is_string($fileName));
150 /** @psalm-var class-string */
151 $class = str_replace('.', '\\', $fileName);
152 $classes[] = $class;
153 }
154 }
155
156 return $classes;
157 }
158
159 /**
160 * {@inheritDoc}
161 */
162 public function fileExists(string $className)
163 {
164 $fileName = str_replace('\\', '.', $className) . $this->fileExtension;
165
166 // Check whether file exists
167 foreach ($this->paths as $path) {
168 if (is_file($path . DIRECTORY_SEPARATOR . $fileName)) {
169 return true;
170 }
171 }
172
173 return false;
174 }
175}
diff --git a/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/FileDriver.php b/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/FileDriver.php
new file mode 100644
index 0000000..c116233
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/FileDriver.php
@@ -0,0 +1,213 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence\Mapping\Driver;
6
7use Doctrine\Persistence\Mapping\ClassMetadata;
8use Doctrine\Persistence\Mapping\MappingException;
9
10use function array_keys;
11use function array_merge;
12use function array_unique;
13use function array_values;
14use function is_file;
15use function str_replace;
16
17/**
18 * Base driver for file-based metadata drivers.
19 *
20 * A file driver operates in a mode where it loads the mapping files of individual
21 * classes on demand. This requires the user to adhere to the convention of 1 mapping
22 * file per class and the file names of the mapping files must correspond to the full
23 * class name, including namespace, with the namespace delimiters '\', replaced by dots '.'.
24 *
25 * @template T
26 */
27abstract class FileDriver implements MappingDriver
28{
29 /** @var FileLocator */
30 protected $locator;
31
32 /**
33 * @var mixed[]|null
34 * @psalm-var array<class-string, T>|null
35 */
36 protected $classCache;
37
38 /** @var string */
39 protected $globalBasename = '';
40
41 /**
42 * Initializes a new FileDriver that looks in the given path(s) for mapping
43 * documents and operates in the specified operating mode.
44 *
45 * @param string|array<int, string>|FileLocator $locator A FileLocator or one/multiple paths
46 * where mapping documents can be found.
47 */
48 public function __construct($locator, ?string $fileExtension = null)
49 {
50 if ($locator instanceof FileLocator) {
51 $this->locator = $locator;
52 } else {
53 $this->locator = new DefaultFileLocator((array) $locator, $fileExtension);
54 }
55 }
56
57 /**
58 * Sets the global basename.
59 *
60 * @return void
61 */
62 public function setGlobalBasename(string $file)
63 {
64 $this->globalBasename = $file;
65 }
66
67 /**
68 * Retrieves the global basename.
69 *
70 * @return string|null
71 */
72 public function getGlobalBasename()
73 {
74 return $this->globalBasename;
75 }
76
77 /**
78 * Gets the element of schema meta data for the class from the mapping file.
79 * This will lazily load the mapping file if it is not loaded yet.
80 *
81 * @psalm-param class-string $className
82 *
83 * @return T The element of schema meta data.
84 *
85 * @throws MappingException
86 */
87 public function getElement(string $className)
88 {
89 if ($this->classCache === null) {
90 $this->initialize();
91 }
92
93 if (isset($this->classCache[$className])) {
94 return $this->classCache[$className];
95 }
96
97 $result = $this->loadMappingFile($this->locator->findMappingFile($className));
98
99 if (! isset($result[$className])) {
100 throw MappingException::invalidMappingFile(
101 $className,
102 str_replace('\\', '.', $className) . $this->locator->getFileExtension()
103 );
104 }
105
106 $this->classCache[$className] = $result[$className];
107
108 return $result[$className];
109 }
110
111 /**
112 * {@inheritDoc}
113 */
114 public function isTransient(string $className)
115 {
116 if ($this->classCache === null) {
117 $this->initialize();
118 }
119
120 if (isset($this->classCache[$className])) {
121 return false;
122 }
123
124 return ! $this->locator->fileExists($className);
125 }
126
127 /**
128 * {@inheritDoc}
129 */
130 public function getAllClassNames()
131 {
132 if ($this->classCache === null) {
133 $this->initialize();
134 }
135
136 if ($this->classCache === []) {
137 return $this->locator->getAllClassNames($this->globalBasename);
138 }
139
140 /** @psalm-var array<class-string, ClassMetadata<object>> $classCache */
141 $classCache = $this->classCache;
142
143 /** @var list<class-string> $keys */
144 $keys = array_keys($classCache);
145
146 return array_values(array_unique(array_merge(
147 $keys,
148 $this->locator->getAllClassNames($this->globalBasename)
149 )));
150 }
151
152 /**
153 * Loads a mapping file with the given name and returns a map
154 * from class/entity names to their corresponding file driver elements.
155 *
156 * @param string $file The mapping file to load.
157 *
158 * @return mixed[]
159 * @psalm-return array<class-string, T>
160 */
161 abstract protected function loadMappingFile(string $file);
162
163 /**
164 * Initializes the class cache from all the global files.
165 *
166 * Using this feature adds a substantial performance hit to file drivers as
167 * more metadata has to be loaded into memory than might actually be
168 * necessary. This may not be relevant to scenarios where caching of
169 * metadata is in place, however hits very hard in scenarios where no
170 * caching is used.
171 *
172 * @return void
173 */
174 protected function initialize()
175 {
176 $this->classCache = [];
177 if ($this->globalBasename === '') {
178 return;
179 }
180
181 foreach ($this->locator->getPaths() as $path) {
182 $file = $path . '/' . $this->globalBasename . $this->locator->getFileExtension();
183 if (! is_file($file)) {
184 continue;
185 }
186
187 $this->classCache = array_merge(
188 $this->classCache,
189 $this->loadMappingFile($file)
190 );
191 }
192 }
193
194 /**
195 * Retrieves the locator used to discover mapping files by className.
196 *
197 * @return FileLocator
198 */
199 public function getLocator()
200 {
201 return $this->locator;
202 }
203
204 /**
205 * Sets the locator used to discover mapping files by className.
206 *
207 * @return void
208 */
209 public function setLocator(FileLocator $locator)
210 {
211 $this->locator = $locator;
212 }
213}
diff --git a/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/FileLocator.php b/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/FileLocator.php
new file mode 100644
index 0000000..e57d539
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/FileLocator.php
@@ -0,0 +1,52 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence\Mapping\Driver;
6
7/**
8 * Locates the file that contains the metadata information for a given class name.
9 *
10 * This behavior is independent of the actual content of the file. It just detects
11 * the file which is responsible for the given class name.
12 */
13interface FileLocator
14{
15 /**
16 * Locates mapping file for the given class name.
17 *
18 * @return string
19 */
20 public function findMappingFile(string $className);
21
22 /**
23 * Gets all class names that are found with this file locator.
24 *
25 * @param string $globalBasename Passed to allow excluding the basename.
26 *
27 * @return array<int, string>
28 * @psalm-return list<class-string>
29 */
30 public function getAllClassNames(string $globalBasename);
31
32 /**
33 * Checks if a file can be found for this class name.
34 *
35 * @return bool
36 */
37 public function fileExists(string $className);
38
39 /**
40 * Gets all the paths that this file locator looks for mapping files.
41 *
42 * @return array<int, string>
43 */
44 public function getPaths();
45
46 /**
47 * Gets the file extension that mapping files are suffixed with.
48 *
49 * @return string|null
50 */
51 public function getFileExtension();
52}
diff --git a/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/MappingDriver.php b/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/MappingDriver.php
new file mode 100644
index 0000000..9b6f0c8
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/MappingDriver.php
@@ -0,0 +1,43 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence\Mapping\Driver;
6
7use Doctrine\Persistence\Mapping\ClassMetadata;
8
9/**
10 * Contract for metadata drivers.
11 */
12interface MappingDriver
13{
14 /**
15 * Loads the metadata for the specified class into the provided container.
16 *
17 * @psalm-param class-string<T> $className
18 * @psalm-param ClassMetadata<T> $metadata
19 *
20 * @return void
21 *
22 * @template T of object
23 */
24 public function loadMetadataForClass(string $className, ClassMetadata $metadata);
25
26 /**
27 * Gets the names of all mapped classes known to this driver.
28 *
29 * @return array<int, string> The names of all mapped classes known to this driver.
30 * @psalm-return list<class-string>
31 */
32 public function getAllClassNames();
33
34 /**
35 * Returns whether the class with the specified name should have its metadata loaded.
36 * This is only the case if it is either mapped as an Entity or a MappedSuperclass.
37 *
38 * @psalm-param class-string $className
39 *
40 * @return bool
41 */
42 public function isTransient(string $className);
43}
diff --git a/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/MappingDriverChain.php b/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/MappingDriverChain.php
new file mode 100644
index 0000000..8563dd2
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/MappingDriverChain.php
@@ -0,0 +1,142 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence\Mapping\Driver;
6
7use Doctrine\Persistence\Mapping\ClassMetadata;
8use Doctrine\Persistence\Mapping\MappingException;
9
10use function array_keys;
11use function spl_object_hash;
12use function strpos;
13
14/**
15 * The DriverChain allows you to add multiple other mapping drivers for
16 * certain namespaces.
17 */
18class MappingDriverChain implements MappingDriver
19{
20 /**
21 * The default driver.
22 *
23 * @var MappingDriver|null
24 */
25 private $defaultDriver;
26
27 /** @var array<string, MappingDriver> */
28 private $drivers = [];
29
30 /**
31 * Gets the default driver.
32 *
33 * @return MappingDriver|null
34 */
35 public function getDefaultDriver()
36 {
37 return $this->defaultDriver;
38 }
39
40 /**
41 * Set the default driver.
42 *
43 * @return void
44 */
45 public function setDefaultDriver(MappingDriver $driver)
46 {
47 $this->defaultDriver = $driver;
48 }
49
50 /**
51 * Adds a nested driver.
52 *
53 * @return void
54 */
55 public function addDriver(MappingDriver $nestedDriver, string $namespace)
56 {
57 $this->drivers[$namespace] = $nestedDriver;
58 }
59
60 /**
61 * Gets the array of nested drivers.
62 *
63 * @return array<string, MappingDriver> $drivers
64 */
65 public function getDrivers()
66 {
67 return $this->drivers;
68 }
69
70 /**
71 * {@inheritDoc}
72 */
73 public function loadMetadataForClass(string $className, ClassMetadata $metadata)
74 {
75 foreach ($this->drivers as $namespace => $driver) {
76 if (strpos($className, $namespace) === 0) {
77 $driver->loadMetadataForClass($className, $metadata);
78
79 return;
80 }
81 }
82
83 if ($this->defaultDriver !== null) {
84 $this->defaultDriver->loadMetadataForClass($className, $metadata);
85
86 return;
87 }
88
89 throw MappingException::classNotFoundInNamespaces($className, array_keys($this->drivers));
90 }
91
92 /**
93 * {@inheritDoc}
94 */
95 public function getAllClassNames()
96 {
97 $classNames = [];
98 $driverClasses = [];
99
100 foreach ($this->drivers as $namespace => $driver) {
101 $oid = spl_object_hash($driver);
102
103 if (! isset($driverClasses[$oid])) {
104 $driverClasses[$oid] = $driver->getAllClassNames();
105 }
106
107 foreach ($driverClasses[$oid] as $className) {
108 if (strpos($className, $namespace) !== 0) {
109 continue;
110 }
111
112 $classNames[$className] = true;
113 }
114 }
115
116 if ($this->defaultDriver !== null) {
117 foreach ($this->defaultDriver->getAllClassNames() as $className) {
118 $classNames[$className] = true;
119 }
120 }
121
122 return array_keys($classNames);
123 }
124
125 /**
126 * {@inheritDoc}
127 */
128 public function isTransient(string $className)
129 {
130 foreach ($this->drivers as $namespace => $driver) {
131 if (strpos($className, $namespace) === 0) {
132 return $driver->isTransient($className);
133 }
134 }
135
136 if ($this->defaultDriver !== null) {
137 return $this->defaultDriver->isTransient($className);
138 }
139
140 return true;
141 }
142}
diff --git a/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/PHPDriver.php b/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/PHPDriver.php
new file mode 100644
index 0000000..1c1ab9c
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/PHPDriver.php
@@ -0,0 +1,49 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence\Mapping\Driver;
6
7use Doctrine\Persistence\Mapping\ClassMetadata;
8
9/**
10 * The PHPDriver includes php files which just populate ClassMetadataInfo
11 * instances with plain PHP code.
12 *
13 * @template-extends FileDriver<ClassMetadata<object>>
14 */
15class PHPDriver extends FileDriver
16{
17 /**
18 * @var ClassMetadata
19 * @psalm-var ClassMetadata<object>
20 */
21 protected $metadata;
22
23 /** @param string|array<int, string>|FileLocator $locator */
24 public function __construct($locator)
25 {
26 parent::__construct($locator, '.php');
27 }
28
29 /**
30 * {@inheritDoc}
31 */
32 public function loadMetadataForClass(string $className, ClassMetadata $metadata)
33 {
34 $this->metadata = $metadata;
35
36 $this->loadMappingFile($this->locator->findMappingFile($className));
37 }
38
39 /**
40 * {@inheritDoc}
41 */
42 protected function loadMappingFile(string $file)
43 {
44 $metadata = $this->metadata;
45 include $file;
46
47 return [$metadata->getName() => $metadata];
48 }
49}
diff --git a/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/StaticPHPDriver.php b/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/StaticPHPDriver.php
new file mode 100644
index 0000000..bbcff75
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/StaticPHPDriver.php
@@ -0,0 +1,132 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence\Mapping\Driver;
6
7use Doctrine\Persistence\Mapping\ClassMetadata;
8use Doctrine\Persistence\Mapping\MappingException;
9use RecursiveDirectoryIterator;
10use RecursiveIteratorIterator;
11use ReflectionClass;
12
13use function array_merge;
14use function array_unique;
15use function get_declared_classes;
16use function in_array;
17use function is_dir;
18use function method_exists;
19use function realpath;
20
21/**
22 * The StaticPHPDriver calls a static loadMetadata() method on your entity
23 * classes where you can manually populate the ClassMetadata instance.
24 */
25class StaticPHPDriver implements MappingDriver
26{
27 /**
28 * Paths of entity directories.
29 *
30 * @var array<int, string>
31 */
32 private $paths = [];
33
34 /**
35 * Map of all class names.
36 *
37 * @var array<int, string>
38 * @psalm-var list<class-string>
39 */
40 private $classNames;
41
42 /** @param array<int, string>|string $paths */
43 public function __construct($paths)
44 {
45 $this->addPaths((array) $paths);
46 }
47
48 /**
49 * @param array<int, string> $paths
50 *
51 * @return void
52 */
53 public function addPaths(array $paths)
54 {
55 $this->paths = array_unique(array_merge($this->paths, $paths));
56 }
57
58 /**
59 * {@inheritDoc}
60 */
61 public function loadMetadataForClass(string $className, ClassMetadata $metadata)
62 {
63 $className::loadMetadata($metadata);
64 }
65
66 /**
67 * {@inheritDoc}
68 *
69 * @todo Same code exists in ColocatedMappingDriver, should we re-use it
70 * somehow or not worry about it?
71 */
72 public function getAllClassNames()
73 {
74 if ($this->classNames !== null) {
75 return $this->classNames;
76 }
77
78 if ($this->paths === []) {
79 throw MappingException::pathRequiredForDriver(static::class);
80 }
81
82 $classes = [];
83 $includedFiles = [];
84
85 foreach ($this->paths as $path) {
86 if (! is_dir($path)) {
87 throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path);
88 }
89
90 $iterator = new RecursiveIteratorIterator(
91 new RecursiveDirectoryIterator($path),
92 RecursiveIteratorIterator::LEAVES_ONLY
93 );
94
95 foreach ($iterator as $file) {
96 if ($file->getBasename('.php') === $file->getBasename()) {
97 continue;
98 }
99
100 $sourceFile = realpath($file->getPathName());
101 require_once $sourceFile;
102 $includedFiles[] = $sourceFile;
103 }
104 }
105
106 $declared = get_declared_classes();
107
108 foreach ($declared as $className) {
109 $rc = new ReflectionClass($className);
110
111 $sourceFile = $rc->getFileName();
112
113 if (! in_array($sourceFile, $includedFiles, true) || $this->isTransient($className)) {
114 continue;
115 }
116
117 $classes[] = $className;
118 }
119
120 $this->classNames = $classes;
121
122 return $classes;
123 }
124
125 /**
126 * {@inheritDoc}
127 */
128 public function isTransient(string $className)
129 {
130 return ! method_exists($className, 'loadMetadata');
131 }
132}
diff --git a/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/SymfonyFileLocator.php b/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/SymfonyFileLocator.php
new file mode 100644
index 0000000..428d5fb
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/SymfonyFileLocator.php
@@ -0,0 +1,265 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence\Mapping\Driver;
6
7use Doctrine\Persistence\Mapping\MappingException;
8use InvalidArgumentException;
9use RecursiveDirectoryIterator;
10use RecursiveIteratorIterator;
11use RuntimeException;
12
13use function array_keys;
14use function array_merge;
15use function assert;
16use function is_dir;
17use function is_file;
18use function is_int;
19use function realpath;
20use function sprintf;
21use function str_replace;
22use function strlen;
23use function strpos;
24use function strrpos;
25use function strtr;
26use function substr;
27
28use const DIRECTORY_SEPARATOR;
29
30/**
31 * The Symfony File Locator makes a simplifying assumptions compared
32 * to the DefaultFileLocator. By assuming paths only contain entities of a certain
33 * namespace the mapping files consists of the short classname only.
34 */
35class SymfonyFileLocator implements FileLocator
36{
37 /**
38 * The paths where to look for mapping files.
39 *
40 * @var array<int, string>
41 */
42 protected $paths = [];
43
44 /**
45 * A map of mapping directory path to namespace prefix used to expand class shortnames.
46 *
47 * @var array<string, string>
48 */
49 protected $prefixes = [];
50
51 /**
52 * File extension that is searched for.
53 *
54 * @var string|null
55 */
56 protected $fileExtension;
57
58 /**
59 * Represents PHP namespace delimiters when looking for files
60 *
61 * @var string
62 */
63 private $nsSeparator;
64
65 /**
66 * @param array<string, string> $prefixes
67 * @param string $nsSeparator String which would be used when converting FQCN
68 * to filename and vice versa. Should not be empty
69 */
70 public function __construct(
71 array $prefixes,
72 string $fileExtension = '',
73 string $nsSeparator = '.'
74 ) {
75 $this->addNamespacePrefixes($prefixes);
76 $this->fileExtension = $fileExtension;
77
78 if ($nsSeparator === '') {
79 throw new InvalidArgumentException('Namespace separator should not be empty');
80 }
81
82 $this->nsSeparator = $nsSeparator;
83 }
84
85 /**
86 * Adds Namespace Prefixes.
87 *
88 * @param array<string, string> $prefixes
89 *
90 * @return void
91 */
92 public function addNamespacePrefixes(array $prefixes)
93 {
94 $this->prefixes = array_merge($this->prefixes, $prefixes);
95 $this->paths = array_merge($this->paths, array_keys($prefixes));
96 }
97
98 /**
99 * Gets Namespace Prefixes.
100 *
101 * @return string[]
102 */
103 public function getNamespacePrefixes()
104 {
105 return $this->prefixes;
106 }
107
108 /**
109 * {@inheritDoc}
110 */
111 public function getPaths()
112 {
113 return $this->paths;
114 }
115
116 /**
117 * {@inheritDoc}
118 */
119 public function getFileExtension()
120 {
121 return $this->fileExtension;
122 }
123
124 /**
125 * Sets the file extension used to look for mapping files under.
126 *
127 * @param string $fileExtension The file extension to set.
128 *
129 * @return void
130 */
131 public function setFileExtension(string $fileExtension)
132 {
133 $this->fileExtension = $fileExtension;
134 }
135
136 /**
137 * {@inheritDoc}
138 */
139 public function fileExists(string $className)
140 {
141 $defaultFileName = str_replace('\\', $this->nsSeparator, $className) . $this->fileExtension;
142 foreach ($this->paths as $path) {
143 if (! isset($this->prefixes[$path])) {
144 // global namespace class
145 if (is_file($path . DIRECTORY_SEPARATOR . $defaultFileName)) {
146 return true;
147 }
148
149 continue;
150 }
151
152 $prefix = $this->prefixes[$path];
153
154 if (strpos($className, $prefix . '\\') !== 0) {
155 continue;
156 }
157
158 $filename = $path . '/' . strtr(substr($className, strlen($prefix) + 1), '\\', $this->nsSeparator) . $this->fileExtension;
159
160 if (is_file($filename)) {
161 return true;
162 }
163 }
164
165 return false;
166 }
167
168 /**
169 * {@inheritDoc}
170 */
171 public function getAllClassNames(?string $globalBasename = null)
172 {
173 if ($this->paths === []) {
174 return [];
175 }
176
177 $classes = [];
178
179 foreach ($this->paths as $path) {
180 if (! is_dir($path)) {
181 throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path);
182 }
183
184 $iterator = new RecursiveIteratorIterator(
185 new RecursiveDirectoryIterator($path),
186 RecursiveIteratorIterator::LEAVES_ONLY
187 );
188
189 foreach ($iterator as $file) {
190 $fileName = $file->getBasename($this->fileExtension);
191
192 if ($fileName === $file->getBasename() || $fileName === $globalBasename) {
193 continue;
194 }
195
196 // NOTE: All files found here means classes are not transient!
197 if (isset($this->prefixes[$path])) {
198 // Calculate namespace suffix for given prefix as a relative path from basepath to file path
199 $nsSuffix = strtr(
200 substr($this->realpath($file->getPath()), strlen($this->realpath($path))),
201 $this->nsSeparator,
202 '\\'
203 );
204
205 /** @psalm-var class-string */
206 $class = $this->prefixes[$path] . str_replace(DIRECTORY_SEPARATOR, '\\', $nsSuffix) . '\\' . str_replace($this->nsSeparator, '\\', $fileName);
207 } else {
208 /** @psalm-var class-string */
209 $class = str_replace($this->nsSeparator, '\\', $fileName);
210 }
211
212 $classes[] = $class;
213 }
214 }
215
216 return $classes;
217 }
218
219 /**
220 * {@inheritDoc}
221 */
222 public function findMappingFile(string $className)
223 {
224 $defaultFileName = str_replace('\\', $this->nsSeparator, $className) . $this->fileExtension;
225 foreach ($this->paths as $path) {
226 if (! isset($this->prefixes[$path])) {
227 if (is_file($path . DIRECTORY_SEPARATOR . $defaultFileName)) {
228 return $path . DIRECTORY_SEPARATOR . $defaultFileName;
229 }
230
231 continue;
232 }
233
234 $prefix = $this->prefixes[$path];
235
236 if (strpos($className, $prefix . '\\') !== 0) {
237 continue;
238 }
239
240 $filename = $path . '/' . strtr(substr($className, strlen($prefix) + 1), '\\', $this->nsSeparator) . $this->fileExtension;
241 if (is_file($filename)) {
242 return $filename;
243 }
244 }
245
246 $pos = strrpos($className, '\\');
247 assert(is_int($pos));
248
249 throw MappingException::mappingFileNotFound(
250 $className,
251 substr($className, $pos + 1) . $this->fileExtension
252 );
253 }
254
255 private function realpath(string $path): string
256 {
257 $realpath = realpath($path);
258
259 if ($realpath === false) {
260 throw new RuntimeException(sprintf('Could not get realpath for %s', $path));
261 }
262
263 return $realpath;
264 }
265}
diff --git a/vendor/doctrine/persistence/src/Persistence/Mapping/MappingException.php b/vendor/doctrine/persistence/src/Persistence/Mapping/MappingException.php
new file mode 100644
index 0000000..f0bc4eb
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/Mapping/MappingException.php
@@ -0,0 +1,88 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence\Mapping;
6
7use Exception;
8
9use function implode;
10use function sprintf;
11
12/**
13 * A MappingException indicates that something is wrong with the mapping setup.
14 */
15class MappingException extends Exception
16{
17 /**
18 * @param array<int, string> $namespaces
19 *
20 * @return self
21 */
22 public static function classNotFoundInNamespaces(
23 string $className,
24 array $namespaces
25 ) {
26 return new self(sprintf(
27 "The class '%s' was not found in the chain configured namespaces %s",
28 $className,
29 implode(', ', $namespaces)
30 ));
31 }
32
33 /** @param class-string $driverClassName */
34 public static function pathRequiredForDriver(string $driverClassName): self
35 {
36 return new self(sprintf(
37 'Specifying the paths to your entities is required when using %s to retrieve all class names.',
38 $driverClassName
39 ));
40 }
41
42 /** @return self */
43 public static function fileMappingDriversRequireConfiguredDirectoryPath(
44 ?string $path = null
45 ) {
46 if ($path !== null) {
47 $path = '[' . $path . ']';
48 }
49
50 return new self(sprintf(
51 'File mapping drivers must have a valid directory path, ' .
52 'however the given path %s seems to be incorrect!',
53 (string) $path
54 ));
55 }
56
57 /** @return self */
58 public static function mappingFileNotFound(string $entityName, string $fileName)
59 {
60 return new self(sprintf(
61 "No mapping file found named '%s' for class '%s'.",
62 $fileName,
63 $entityName
64 ));
65 }
66
67 /** @return self */
68 public static function invalidMappingFile(string $entityName, string $fileName)
69 {
70 return new self(sprintf(
71 "Invalid mapping file '%s' for class '%s'.",
72 $fileName,
73 $entityName
74 ));
75 }
76
77 /** @return self */
78 public static function nonExistingClass(string $className)
79 {
80 return new self(sprintf("Class '%s' does not exist", $className));
81 }
82
83 /** @param class-string $className */
84 public static function classIsAnonymous(string $className): self
85 {
86 return new self(sprintf('Class "%s" is anonymous', $className));
87 }
88}
diff --git a/vendor/doctrine/persistence/src/Persistence/Mapping/ProxyClassNameResolver.php b/vendor/doctrine/persistence/src/Persistence/Mapping/ProxyClassNameResolver.php
new file mode 100644
index 0000000..2801d90
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/Mapping/ProxyClassNameResolver.php
@@ -0,0 +1,19 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence\Mapping;
6
7use Doctrine\Persistence\Proxy;
8
9interface ProxyClassNameResolver
10{
11 /**
12 * @psalm-param class-string<Proxy<T>>|class-string<T> $className
13 *
14 * @psalm-return class-string<T>
15 *
16 * @template T of object
17 */
18 public function resolveClassName(string $className): string;
19}
diff --git a/vendor/doctrine/persistence/src/Persistence/Mapping/ReflectionService.php b/vendor/doctrine/persistence/src/Persistence/Mapping/ReflectionService.php
new file mode 100644
index 0000000..9484e1f
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/Mapping/ReflectionService.php
@@ -0,0 +1,75 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence\Mapping;
6
7use ReflectionClass;
8use ReflectionProperty;
9
10/**
11 * Very simple reflection service abstraction.
12 *
13 * This is required inside metadata layers that may require either
14 * static or runtime reflection.
15 */
16interface ReflectionService
17{
18 /**
19 * Returns an array of the parent classes (not interfaces) for the given class.
20 *
21 * @psalm-param class-string $class
22 *
23 * @return string[]
24 * @psalm-return class-string[]
25 *
26 * @throws MappingException
27 */
28 public function getParentClasses(string $class);
29
30 /**
31 * Returns the shortname of a class.
32 *
33 * @psalm-param class-string $class
34 *
35 * @return string
36 */
37 public function getClassShortName(string $class);
38
39 /**
40 * @psalm-param class-string $class
41 *
42 * @return string
43 */
44 public function getClassNamespace(string $class);
45
46 /**
47 * Returns a reflection class instance or null.
48 *
49 * @psalm-param class-string<T> $class
50 *
51 * @return ReflectionClass|null
52 * @psalm-return ReflectionClass<T>|null
53 *
54 * @template T of object
55 */
56 public function getClass(string $class);
57
58 /**
59 * Returns an accessible property (setAccessible(true)) or null.
60 *
61 * @psalm-param class-string $class
62 *
63 * @return ReflectionProperty|null
64 */
65 public function getAccessibleProperty(string $class, string $property);
66
67 /**
68 * Checks if the class have a public method with the given name.
69 *
70 * @psalm-param class-string $class
71 *
72 * @return bool
73 */
74 public function hasPublicMethod(string $class, string $method);
75}
diff --git a/vendor/doctrine/persistence/src/Persistence/Mapping/RuntimeReflectionService.php b/vendor/doctrine/persistence/src/Persistence/Mapping/RuntimeReflectionService.php
new file mode 100644
index 0000000..399e057
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/Mapping/RuntimeReflectionService.php
@@ -0,0 +1,111 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence\Mapping;
6
7use Doctrine\Persistence\Reflection\RuntimeReflectionProperty;
8use Doctrine\Persistence\Reflection\TypedNoDefaultReflectionProperty;
9use ReflectionClass;
10use ReflectionException;
11use ReflectionMethod;
12
13use function array_key_exists;
14use function assert;
15use function class_exists;
16use function class_parents;
17use function phpversion;
18use function version_compare;
19
20/**
21 * PHP Runtime Reflection Service.
22 */
23class RuntimeReflectionService implements ReflectionService
24{
25 /** @var bool */
26 private $supportsTypedPropertiesWorkaround;
27
28 public function __construct()
29 {
30 $this->supportsTypedPropertiesWorkaround = version_compare(phpversion(), '7.4.0') >= 0;
31 }
32
33 /**
34 * {@inheritDoc}
35 */
36 public function getParentClasses(string $class)
37 {
38 if (! class_exists($class)) {
39 throw MappingException::nonExistingClass($class);
40 }
41
42 $parents = class_parents($class);
43
44 assert($parents !== false);
45
46 return $parents;
47 }
48
49 /**
50 * {@inheritDoc}
51 */
52 public function getClassShortName(string $class)
53 {
54 $reflectionClass = new ReflectionClass($class);
55
56 return $reflectionClass->getShortName();
57 }
58
59 /**
60 * {@inheritDoc}
61 */
62 public function getClassNamespace(string $class)
63 {
64 $reflectionClass = new ReflectionClass($class);
65
66 return $reflectionClass->getNamespaceName();
67 }
68
69 /**
70 * @psalm-param class-string<T> $class
71 *
72 * @return ReflectionClass
73 * @psalm-return ReflectionClass<T>
74 *
75 * @template T of object
76 */
77 public function getClass(string $class)
78 {
79 return new ReflectionClass($class);
80 }
81
82 /**
83 * {@inheritDoc}
84 */
85 public function getAccessibleProperty(string $class, string $property)
86 {
87 $reflectionProperty = new RuntimeReflectionProperty($class, $property);
88
89 if ($this->supportsTypedPropertiesWorkaround && ! array_key_exists($property, $this->getClass($class)->getDefaultProperties())) {
90 $reflectionProperty = new TypedNoDefaultReflectionProperty($class, $property);
91 }
92
93 $reflectionProperty->setAccessible(true);
94
95 return $reflectionProperty;
96 }
97
98 /**
99 * {@inheritDoc}
100 */
101 public function hasPublicMethod(string $class, string $method)
102 {
103 try {
104 $reflectionMethod = new ReflectionMethod($class, $method);
105 } catch (ReflectionException $e) {
106 return false;
107 }
108
109 return $reflectionMethod->isPublic();
110 }
111}
diff --git a/vendor/doctrine/persistence/src/Persistence/Mapping/StaticReflectionService.php b/vendor/doctrine/persistence/src/Persistence/Mapping/StaticReflectionService.php
new file mode 100644
index 0000000..c9f2147
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/Mapping/StaticReflectionService.php
@@ -0,0 +1,78 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence\Mapping;
6
7use function strpos;
8use function strrev;
9use function strrpos;
10use function substr;
11
12/**
13 * PHP Runtime Reflection Service.
14 */
15class StaticReflectionService implements ReflectionService
16{
17 /**
18 * {@inheritDoc}
19 */
20 public function getParentClasses(string $class)
21 {
22 return [];
23 }
24
25 /**
26 * {@inheritDoc}
27 */
28 public function getClassShortName(string $class)
29 {
30 $nsSeparatorLastPosition = strrpos($class, '\\');
31
32 if ($nsSeparatorLastPosition !== false) {
33 $class = substr($class, $nsSeparatorLastPosition + 1);
34 }
35
36 return $class;
37 }
38
39 /**
40 * {@inheritDoc}
41 */
42 public function getClassNamespace(string $class)
43 {
44 $namespace = '';
45
46 if (strpos($class, '\\') !== false) {
47 $namespace = strrev(substr(strrev($class), (int) strpos(strrev($class), '\\') + 1));
48 }
49
50 return $namespace;
51 }
52
53 /**
54 * {@inheritDoc}
55 *
56 * @return null
57 */
58 public function getClass(string $class)
59 {
60 return null;
61 }
62
63 /**
64 * {@inheritDoc}
65 */
66 public function getAccessibleProperty(string $class, string $property)
67 {
68 return null;
69 }
70
71 /**
72 * {@inheritDoc}
73 */
74 public function hasPublicMethod(string $class, string $method)
75 {
76 return true;
77 }
78}
diff --git a/vendor/doctrine/persistence/src/Persistence/NotifyPropertyChanged.php b/vendor/doctrine/persistence/src/Persistence/NotifyPropertyChanged.php
new file mode 100644
index 0000000..8eecf9b
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/NotifyPropertyChanged.php
@@ -0,0 +1,22 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence;
6
7/**
8 * Interface for classes that notify event listeners of changes to their managed properties.
9 *
10 * This interface is implemented by objects that manually want to notify their object manager or
11 * other listeners when properties change, instead of relying on the object manager to compute
12 * property changes itself when changes are to be persisted.
13 */
14interface NotifyPropertyChanged
15{
16 /**
17 * Adds a listener that wants to be notified about property changes.
18 *
19 * @return void
20 */
21 public function addPropertyChangedListener(PropertyChangedListener $listener);
22}
diff --git a/vendor/doctrine/persistence/src/Persistence/ObjectManager.php b/vendor/doctrine/persistence/src/Persistence/ObjectManager.php
new file mode 100644
index 0000000..efac5c3
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/ObjectManager.php
@@ -0,0 +1,145 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence;
6
7use Doctrine\Persistence\Mapping\ClassMetadata;
8use Doctrine\Persistence\Mapping\ClassMetadataFactory;
9
10/**
11 * Contract for a Doctrine persistence layer ObjectManager class to implement.
12 *
13 * @method bool isUninitializedObject(mixed $value) Implementing this method will be mandatory in version 4.
14 */
15interface ObjectManager
16{
17 /**
18 * Finds an object by its identifier.
19 *
20 * This is just a convenient shortcut for getRepository($className)->find($id).
21 *
22 * @param string $className The class name of the object to find.
23 * @param mixed $id The identity of the object to find.
24 * @psalm-param class-string<T> $className
25 *
26 * @return object|null The found object.
27 * @psalm-return T|null
28 *
29 * @template T of object
30 */
31 public function find(string $className, $id);
32
33 /**
34 * Tells the ObjectManager to make an instance managed and persistent.
35 *
36 * The object will be entered into the database as a result of the flush operation.
37 *
38 * NOTE: The persist operation always considers objects that are not yet known to
39 * this ObjectManager as NEW. Do not pass detached objects to the persist operation.
40 *
41 * @param object $object The instance to make managed and persistent.
42 *
43 * @return void
44 */
45 public function persist(object $object);
46
47 /**
48 * Removes an object instance.
49 *
50 * A removed object will be removed from the database as a result of the flush operation.
51 *
52 * @param object $object The object instance to remove.
53 *
54 * @return void
55 */
56 public function remove(object $object);
57
58 /**
59 * Clears the ObjectManager. All objects that are currently managed
60 * by this ObjectManager become detached.
61 *
62 * @return void
63 */
64 public function clear();
65
66 /**
67 * Detaches an object from the ObjectManager, causing a managed object to
68 * become detached. Unflushed changes made to the object if any
69 * (including removal of the object), will not be synchronized to the database.
70 * Objects which previously referenced the detached object will continue to
71 * reference it.
72 *
73 * @param object $object The object to detach.
74 *
75 * @return void
76 */
77 public function detach(object $object);
78
79 /**
80 * Refreshes the persistent state of an object from the database,
81 * overriding any local changes that have not yet been persisted.
82 *
83 * @param object $object The object to refresh.
84 *
85 * @return void
86 */
87 public function refresh(object $object);
88
89 /**
90 * Flushes all changes to objects that have been queued up to now to the database.
91 * This effectively synchronizes the in-memory state of managed objects with the
92 * database.
93 *
94 * @return void
95 */
96 public function flush();
97
98 /**
99 * Gets the repository for a class.
100 *
101 * @psalm-param class-string<T> $className
102 *
103 * @psalm-return ObjectRepository<T>
104 *
105 * @template T of object
106 */
107 public function getRepository(string $className);
108
109 /**
110 * Returns the ClassMetadata descriptor for a class.
111 *
112 * The class name must be the fully-qualified class name without a leading backslash
113 * (as it is returned by get_class($obj)).
114 *
115 * @psalm-param class-string<T> $className
116 *
117 * @psalm-return ClassMetadata<T>
118 *
119 * @template T of object
120 */
121 public function getClassMetadata(string $className);
122
123 /**
124 * Gets the metadata factory used to gather the metadata of classes.
125 *
126 * @psalm-return ClassMetadataFactory<ClassMetadata<object>>
127 */
128 public function getMetadataFactory();
129
130 /**
131 * Helper method to initialize a lazy loading proxy or persistent collection.
132 *
133 * This method is a no-op for other objects.
134 *
135 * @return void
136 */
137 public function initializeObject(object $obj);
138
139 /**
140 * Checks if the object is part of the current UnitOfWork and therefore managed.
141 *
142 * @return bool
143 */
144 public function contains(object $object);
145}
diff --git a/vendor/doctrine/persistence/src/Persistence/ObjectManagerDecorator.php b/vendor/doctrine/persistence/src/Persistence/ObjectManagerDecorator.php
new file mode 100644
index 0000000..8c038b8
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/ObjectManagerDecorator.php
@@ -0,0 +1,92 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence;
6
7use Doctrine\Persistence\Mapping\ClassMetadata;
8use Doctrine\Persistence\Mapping\ClassMetadataFactory;
9
10/**
11 * Base class to simplify ObjectManager decorators
12 *
13 * @template-covariant TObjectManager of ObjectManager
14 */
15abstract class ObjectManagerDecorator implements ObjectManager
16{
17 /** @var TObjectManager */
18 protected $wrapped;
19
20 /**
21 * {@inheritDoc}
22 */
23 public function find(string $className, $id)
24 {
25 return $this->wrapped->find($className, $id);
26 }
27
28 public function persist(object $object)
29 {
30 $this->wrapped->persist($object);
31 }
32
33 public function remove(object $object)
34 {
35 $this->wrapped->remove($object);
36 }
37
38 public function clear(): void
39 {
40 $this->wrapped->clear();
41 }
42
43 public function detach(object $object)
44 {
45 $this->wrapped->detach($object);
46 }
47
48 public function refresh(object $object)
49 {
50 $this->wrapped->refresh($object);
51 }
52
53 public function flush()
54 {
55 $this->wrapped->flush();
56 }
57
58 /**
59 * {@inheritDoc}
60 */
61 public function getRepository(string $className)
62 {
63 return $this->wrapped->getRepository($className);
64 }
65
66 /**
67 * {@inheritDoc}
68 */
69 public function getClassMetadata(string $className)
70 {
71 return $this->wrapped->getClassMetadata($className);
72 }
73
74 /** @psalm-return ClassMetadataFactory<ClassMetadata<object>> */
75 public function getMetadataFactory()
76 {
77 return $this->wrapped->getMetadataFactory();
78 }
79
80 public function initializeObject(object $obj)
81 {
82 $this->wrapped->initializeObject($obj);
83 }
84
85 /**
86 * {@inheritDoc}
87 */
88 public function contains(object $object)
89 {
90 return $this->wrapped->contains($object);
91 }
92}
diff --git a/vendor/doctrine/persistence/src/Persistence/ObjectRepository.php b/vendor/doctrine/persistence/src/Persistence/ObjectRepository.php
new file mode 100644
index 0000000..a714731
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/ObjectRepository.php
@@ -0,0 +1,73 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence;
6
7use UnexpectedValueException;
8
9/**
10 * Contract for a Doctrine persistence layer ObjectRepository class to implement.
11 *
12 * @template-covariant T of object
13 */
14interface ObjectRepository
15{
16 /**
17 * Finds an object by its primary key / identifier.
18 *
19 * @param mixed $id The identifier.
20 *
21 * @return object|null The object.
22 * @psalm-return T|null
23 */
24 public function find($id);
25
26 /**
27 * Finds all objects in the repository.
28 *
29 * @return array<int, object> The objects.
30 * @psalm-return T[]
31 */
32 public function findAll();
33
34 /**
35 * Finds objects by a set of criteria.
36 *
37 * Optionally sorting and limiting details can be passed. An implementation may throw
38 * an UnexpectedValueException if certain values of the sorting or limiting details are
39 * not supported.
40 *
41 * @param array<string, mixed> $criteria
42 * @param array<string, string>|null $orderBy
43 * @psalm-param array<string, 'asc'|'desc'|'ASC'|'DESC'>|null $orderBy
44 *
45 * @return array<int, object> The objects.
46 * @psalm-return T[]
47 *
48 * @throws UnexpectedValueException
49 */
50 public function findBy(
51 array $criteria,
52 ?array $orderBy = null,
53 ?int $limit = null,
54 ?int $offset = null
55 );
56
57 /**
58 * Finds a single object by a set of criteria.
59 *
60 * @param array<string, mixed> $criteria The criteria.
61 *
62 * @return object|null The object.
63 * @psalm-return T|null
64 */
65 public function findOneBy(array $criteria);
66
67 /**
68 * Returns the class name of the object managed by the repository.
69 *
70 * @psalm-return class-string<T>
71 */
72 public function getClassName();
73}
diff --git a/vendor/doctrine/persistence/src/Persistence/PropertyChangedListener.php b/vendor/doctrine/persistence/src/Persistence/PropertyChangedListener.php
new file mode 100644
index 0000000..6b50707
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/PropertyChangedListener.php
@@ -0,0 +1,24 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence;
6
7/**
8 * Contract for classes that are potential listeners of a {@see NotifyPropertyChanged}
9 * implementor.
10 */
11interface PropertyChangedListener
12{
13 /**
14 * Collect information about a property change.
15 *
16 * @param object $sender The object on which the property changed.
17 * @param string $propertyName The name of the property that changed.
18 * @param mixed $oldValue The old value of the property that changed.
19 * @param mixed $newValue The new value of the property that changed.
20 *
21 * @return void
22 */
23 public function propertyChanged(object $sender, string $propertyName, $oldValue, $newValue);
24}
diff --git a/vendor/doctrine/persistence/src/Persistence/Proxy.php b/vendor/doctrine/persistence/src/Persistence/Proxy.php
new file mode 100644
index 0000000..2c02f23
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/Proxy.php
@@ -0,0 +1,39 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence;
6
7/**
8 * Interface for proxy classes.
9 *
10 * @template T of object
11 */
12interface Proxy
13{
14 /**
15 * Marker for Proxy class names.
16 */
17 public const MARKER = '__CG__';
18
19 /**
20 * Length of the proxy marker.
21 */
22 public const MARKER_LENGTH = 6;
23
24 /**
25 * Initializes this proxy if its not yet initialized.
26 *
27 * Acts as a no-op if already initialized.
28 *
29 * @return void
30 */
31 public function __load();
32
33 /**
34 * Returns whether this proxy is initialized or not.
35 *
36 * @return bool
37 */
38 public function __isInitialized();
39}
diff --git a/vendor/doctrine/persistence/src/Persistence/Reflection/EnumReflectionProperty.php b/vendor/doctrine/persistence/src/Persistence/Reflection/EnumReflectionProperty.php
new file mode 100644
index 0000000..114b9db
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/Reflection/EnumReflectionProperty.php
@@ -0,0 +1,181 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence\Reflection;
6
7use BackedEnum;
8use ReflectionClass;
9use ReflectionProperty;
10use ReflectionType;
11use ReturnTypeWillChange;
12
13use function array_map;
14use function is_array;
15use function reset;
16
17/**
18 * PHP Enum Reflection Property - special override for backed enums.
19 */
20class EnumReflectionProperty extends ReflectionProperty
21{
22 /** @var ReflectionProperty */
23 private $originalReflectionProperty;
24
25 /** @var class-string<BackedEnum> */
26 private $enumType;
27
28 /** @param class-string<BackedEnum> $enumType */
29 public function __construct(ReflectionProperty $originalReflectionProperty, string $enumType)
30 {
31 $this->originalReflectionProperty = $originalReflectionProperty;
32 $this->enumType = $enumType;
33 }
34
35 /**
36 * {@inheritDoc}
37 *
38 * @psalm-external-mutation-free
39 */
40 public function getDeclaringClass(): ReflectionClass
41 {
42 return $this->originalReflectionProperty->getDeclaringClass();
43 }
44
45 /**
46 * {@inheritDoc}
47 *
48 * @psalm-external-mutation-free
49 */
50 public function getName(): string
51 {
52 return $this->originalReflectionProperty->getName();
53 }
54
55 /**
56 * {@inheritDoc}
57 *
58 * @psalm-external-mutation-free
59 */
60 public function getType(): ?ReflectionType
61 {
62 return $this->originalReflectionProperty->getType();
63 }
64
65 /**
66 * {@inheritDoc}
67 */
68 public function getAttributes(?string $name = null, int $flags = 0): array
69 {
70 return $this->originalReflectionProperty->getAttributes($name, $flags);
71 }
72
73 /**
74 * {@inheritDoc}
75 *
76 * Converts enum instance to its value.
77 *
78 * @param object|null $object
79 *
80 * @return int|string|int[]|string[]|null
81 */
82 #[ReturnTypeWillChange]
83 public function getValue($object = null)
84 {
85 if ($object === null) {
86 return null;
87 }
88
89 $enum = $this->originalReflectionProperty->getValue($object);
90
91 if ($enum === null) {
92 return null;
93 }
94
95 return $this->fromEnum($enum);
96 }
97
98 /**
99 * Converts enum value to enum instance.
100 *
101 * @param object $object
102 * @param mixed $value
103 */
104 public function setValue($object, $value = null): void
105 {
106 if ($value !== null) {
107 $value = $this->toEnum($value);
108 }
109
110 $this->originalReflectionProperty->setValue($object, $value);
111 }
112
113 /**
114 * @param BackedEnum|BackedEnum[] $enum
115 *
116 * @return ($enum is BackedEnum ? (string|int) : (string[]|int[]))
117 */
118 private function fromEnum($enum)
119 {
120 if (is_array($enum)) {
121 return array_map(static function (BackedEnum $enum) {
122 return $enum->value;
123 }, $enum);
124 }
125
126 return $enum->value;
127 }
128
129 /**
130 * @param int|string|int[]|string[]|BackedEnum|BackedEnum[] $value
131 *
132 * @return ($value is int|string|BackedEnum ? BackedEnum : BackedEnum[])
133 */
134 private function toEnum($value)
135 {
136 if ($value instanceof BackedEnum) {
137 return $value;
138 }
139
140 if (is_array($value)) {
141 $v = reset($value);
142 if ($v instanceof BackedEnum) {
143 return $value;
144 }
145
146 return array_map([$this->enumType, 'from'], $value);
147 }
148
149 return $this->enumType::from($value);
150 }
151
152 /**
153 * {@inheritDoc}
154 *
155 * @psalm-external-mutation-free
156 */
157 public function getModifiers(): int
158 {
159 return $this->originalReflectionProperty->getModifiers();
160 }
161
162 /**
163 * {@inheritDoc}
164 *
165 * @psalm-external-mutation-free
166 */
167 public function getDocComment(): string|false
168 {
169 return $this->originalReflectionProperty->getDocComment();
170 }
171
172 /**
173 * {@inheritDoc}
174 *
175 * @psalm-external-mutation-free
176 */
177 public function isPrivate(): bool
178 {
179 return $this->originalReflectionProperty->isPrivate();
180 }
181}
diff --git a/vendor/doctrine/persistence/src/Persistence/Reflection/RuntimePublicReflectionProperty.php b/vendor/doctrine/persistence/src/Persistence/Reflection/RuntimePublicReflectionProperty.php
new file mode 100644
index 0000000..e2367ec
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/Reflection/RuntimePublicReflectionProperty.php
@@ -0,0 +1,61 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence\Reflection;
6
7use Doctrine\Common\Proxy\Proxy;
8use ReflectionProperty;
9use ReturnTypeWillChange;
10
11/**
12 * PHP Runtime Reflection Public Property - special overrides for public properties.
13 *
14 * @deprecated since version 3.1, use RuntimeReflectionProperty instead.
15 */
16class RuntimePublicReflectionProperty extends ReflectionProperty
17{
18 /**
19 * {@inheritDoc}
20 *
21 * Returns the value of a public property without calling
22 * `__get` on the provided $object if it exists.
23 *
24 * @return mixed
25 */
26 #[ReturnTypeWillChange]
27 public function getValue($object = null)
28 {
29 return $object !== null ? ((array) $object)[$this->getName()] ?? null : parent::getValue();
30 }
31
32 /**
33 * {@inheritDoc}
34 *
35 * Avoids triggering lazy loading via `__set` if the provided object
36 * is a {@see \Doctrine\Common\Proxy\Proxy}.
37 *
38 * @link https://bugs.php.net/bug.php?id=63463
39 *
40 * @param object|null $object
41 * @param mixed $value
42 *
43 * @return void
44 */
45 #[ReturnTypeWillChange]
46 public function setValue($object, $value = null)
47 {
48 if (! ($object instanceof Proxy && ! $object->__isInitialized())) {
49 parent::setValue($object, $value);
50
51 return;
52 }
53
54 $originalInitializer = $object->__getInitializer();
55 $object->__setInitializer(null);
56
57 parent::setValue($object, $value);
58
59 $object->__setInitializer($originalInitializer);
60 }
61}
diff --git a/vendor/doctrine/persistence/src/Persistence/Reflection/RuntimeReflectionProperty.php b/vendor/doctrine/persistence/src/Persistence/Reflection/RuntimeReflectionProperty.php
new file mode 100644
index 0000000..5f52056
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/Reflection/RuntimeReflectionProperty.php
@@ -0,0 +1,87 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence\Reflection;
6
7use Doctrine\Common\Proxy\Proxy as CommonProxy;
8use Doctrine\Persistence\Proxy;
9use ReflectionProperty;
10use ReturnTypeWillChange;
11
12use function ltrim;
13use function method_exists;
14
15/**
16 * PHP Runtime Reflection Property.
17 *
18 * Avoids triggering lazy loading if the provided object
19 * is a {@see \Doctrine\Persistence\Proxy}.
20 */
21class RuntimeReflectionProperty extends ReflectionProperty
22{
23 /** @var string */
24 private $key;
25
26 /** @param class-string $class */
27 public function __construct(string $class, string $name)
28 {
29 parent::__construct($class, $name);
30
31 $this->key = $this->isPrivate() ? "\0" . ltrim($class, '\\') . "\0" . $name : ($this->isProtected() ? "\0*\0" . $name : $name);
32 }
33
34 /**
35 * {@inheritDoc}
36 *
37 * @return mixed
38 */
39 #[ReturnTypeWillChange]
40 public function getValue($object = null)
41 {
42 if ($object === null) {
43 return parent::getValue($object);
44 }
45
46 return ((array) $object)[$this->key] ?? null;
47 }
48
49 /**
50 * {@inheritDoc}
51 *
52 * @param object|null $object
53 * @param mixed $value
54 *
55 * @return void
56 */
57 #[ReturnTypeWillChange]
58 public function setValue($object, $value = null)
59 {
60 if (! ($object instanceof Proxy && ! $object->__isInitialized())) {
61 parent::setValue($object, $value);
62
63 return;
64 }
65
66 if ($object instanceof CommonProxy) {
67 $originalInitializer = $object->__getInitializer();
68 $object->__setInitializer(null);
69
70 parent::setValue($object, $value);
71
72 $object->__setInitializer($originalInitializer);
73
74 return;
75 }
76
77 if (! method_exists($object, '__setInitialized')) {
78 return;
79 }
80
81 $object->__setInitialized(true);
82
83 parent::setValue($object, $value);
84
85 $object->__setInitialized(false);
86 }
87}
diff --git a/vendor/doctrine/persistence/src/Persistence/Reflection/TypedNoDefaultReflectionProperty.php b/vendor/doctrine/persistence/src/Persistence/Reflection/TypedNoDefaultReflectionProperty.php
new file mode 100644
index 0000000..5e70620
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/Reflection/TypedNoDefaultReflectionProperty.php
@@ -0,0 +1,13 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence\Reflection;
6
7/**
8 * PHP Typed No Default Reflection Property - special override for typed properties without a default value.
9 */
10class TypedNoDefaultReflectionProperty extends RuntimeReflectionProperty
11{
12 use TypedNoDefaultReflectionPropertyBase;
13}
diff --git a/vendor/doctrine/persistence/src/Persistence/Reflection/TypedNoDefaultReflectionPropertyBase.php b/vendor/doctrine/persistence/src/Persistence/Reflection/TypedNoDefaultReflectionPropertyBase.php
new file mode 100644
index 0000000..fff68a4
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/Reflection/TypedNoDefaultReflectionPropertyBase.php
@@ -0,0 +1,68 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence\Reflection;
6
7use Closure;
8use ReturnTypeWillChange;
9
10use function assert;
11
12/**
13 * PHP Typed No Default Reflection Property Base - special override for typed properties without a default value.
14 *
15 * @internal since version 3.1
16 */
17trait TypedNoDefaultReflectionPropertyBase
18{
19 /**
20 * {@inheritDoc}
21 *
22 * Checks that a typed property is initialized before accessing its value.
23 * This is necessary to avoid PHP error "Error: Typed property must not be accessed before initialization".
24 * Should be used only for reflecting typed properties without a default value.
25 *
26 * @param object|null $object
27 *
28 * @return mixed
29 */
30 #[ReturnTypeWillChange]
31 public function getValue($object = null)
32 {
33 return $object !== null && $this->isInitialized($object) ? parent::getValue($object) : null;
34 }
35
36 /**
37 * {@inheritDoc}
38 *
39 * Works around the problem with setting typed no default properties to
40 * NULL which is not supported, instead unset() to uninitialize.
41 *
42 * @link https://github.com/doctrine/orm/issues/7999
43 *
44 * @param object|null $object
45 *
46 * @return void
47 */
48 #[ReturnTypeWillChange]
49 public function setValue($object, $value = null)
50 {
51 if ($value === null && $this->hasType() && ! $this->getType()->allowsNull()) {
52 $propertyName = $this->getName();
53
54 $unsetter = function () use ($propertyName): void {
55 unset($this->$propertyName);
56 };
57 $unsetter = $unsetter->bindTo($object, $this->getDeclaringClass()->getName());
58
59 assert($unsetter instanceof Closure);
60
61 $unsetter();
62
63 return;
64 }
65
66 parent::setValue($object, $value);
67 }
68}
diff --git a/vendor/doctrine/persistence/src/Persistence/Reflection/TypedNoDefaultRuntimePublicReflectionProperty.php b/vendor/doctrine/persistence/src/Persistence/Reflection/TypedNoDefaultRuntimePublicReflectionProperty.php
new file mode 100644
index 0000000..181172f
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/Reflection/TypedNoDefaultRuntimePublicReflectionProperty.php
@@ -0,0 +1,15 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence\Reflection;
6
7/**
8 * PHP Typed No Default Runtime Public Reflection Property - special override for public typed properties without a default value.
9 *
10 * @deprecated since version 3.1, use TypedNoDefaultReflectionProperty instead.
11 */
12class TypedNoDefaultRuntimePublicReflectionProperty extends RuntimePublicReflectionProperty
13{
14 use TypedNoDefaultReflectionPropertyBase;
15}