composer package updates
[openemr.git] / vendor / doctrine / orm / lib / Doctrine / ORM / Proxy / ProxyFactory.php
blobb6e1743510db968bc3a9a25cdc8431d6236c795b
1 <?php
2 /*
3 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15 * This software consists of voluntary contributions made by many individuals
16 * and is licensed under the MIT license. For more information, see
17 * <http://www.doctrine-project.org>.
20 namespace Doctrine\ORM\Proxy;
22 use Doctrine\Common\Persistence\Mapping\ClassMetadata;
23 use Doctrine\Common\Proxy\AbstractProxyFactory;
24 use Doctrine\Common\Proxy\Proxy as BaseProxy;
25 use Doctrine\Common\Proxy\ProxyDefinition;
26 use Doctrine\Common\Proxy\ProxyGenerator;
27 use Doctrine\Common\Util\ClassUtils;
28 use Doctrine\ORM\EntityManagerInterface;
29 use Doctrine\ORM\Persisters\Entity\EntityPersister;
30 use Doctrine\ORM\EntityNotFoundException;
31 use Doctrine\ORM\Utility\IdentifierFlattener;
33 /**
34 * This factory is used to create proxy objects for entities at runtime.
36 * @author Roman Borschel <roman@code-factory.org>
37 * @author Giorgio Sironi <piccoloprincipeazzurro@gmail.com>
38 * @author Marco Pivetta <ocramius@gmail.com>
39 * @since 2.0
41 class ProxyFactory extends AbstractProxyFactory
43 /**
44 * @var EntityManagerInterface The EntityManager this factory is bound to.
46 private $em;
48 /**
49 * @var \Doctrine\ORM\UnitOfWork The UnitOfWork this factory uses to retrieve persisters
51 private $uow;
53 /**
54 * @var string
56 private $proxyNs;
58 /**
59 * The IdentifierFlattener used for manipulating identifiers
61 * @var \Doctrine\ORM\Utility\IdentifierFlattener
63 private $identifierFlattener;
65 /**
66 * Initializes a new instance of the <tt>ProxyFactory</tt> class that is
67 * connected to the given <tt>EntityManager</tt>.
69 * @param EntityManagerInterface $em The EntityManager the new factory works for.
70 * @param string $proxyDir The directory to use for the proxy classes. It must exist.
71 * @param string $proxyNs The namespace to use for the proxy classes.
72 * @param boolean|int $autoGenerate The strategy for automatically generating proxy classes. Possible
73 * values are constants of Doctrine\Common\Proxy\AbstractProxyFactory.
75 public function __construct(EntityManagerInterface $em, $proxyDir, $proxyNs, $autoGenerate = AbstractProxyFactory::AUTOGENERATE_NEVER)
77 $proxyGenerator = new ProxyGenerator($proxyDir, $proxyNs);
79 $proxyGenerator->setPlaceholder('baseProxyInterface', 'Doctrine\ORM\Proxy\Proxy');
80 parent::__construct($proxyGenerator, $em->getMetadataFactory(), $autoGenerate);
82 $this->em = $em;
83 $this->uow = $em->getUnitOfWork();
84 $this->proxyNs = $proxyNs;
85 $this->identifierFlattener = new IdentifierFlattener($this->uow, $em->getMetadataFactory());
88 /**
89 * {@inheritDoc}
91 protected function skipClass(ClassMetadata $metadata)
93 /* @var $metadata \Doctrine\ORM\Mapping\ClassMetadataInfo */
94 return $metadata->isMappedSuperclass
95 || $metadata->isEmbeddedClass
96 || $metadata->getReflectionClass()->isAbstract();
99 /**
100 * {@inheritDoc}
102 protected function createProxyDefinition($className)
104 $classMetadata = $this->em->getClassMetadata($className);
105 $entityPersister = $this->uow->getEntityPersister($className);
107 return new ProxyDefinition(
108 ClassUtils::generateProxyClassName($className, $this->proxyNs),
109 $classMetadata->getIdentifierFieldNames(),
110 $classMetadata->getReflectionProperties(),
111 $this->createInitializer($classMetadata, $entityPersister),
112 $this->createCloner($classMetadata, $entityPersister)
117 * Creates a closure capable of initializing a proxy
119 * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $classMetadata
120 * @param \Doctrine\ORM\Persisters\Entity\EntityPersister $entityPersister
122 * @return \Closure
124 * @throws \Doctrine\ORM\EntityNotFoundException
126 private function createInitializer(ClassMetadata $classMetadata, EntityPersister $entityPersister)
128 if ($classMetadata->getReflectionClass()->hasMethod('__wakeup')) {
129 return function (BaseProxy $proxy) use ($entityPersister, $classMetadata) {
130 $initializer = $proxy->__getInitializer();
131 $cloner = $proxy->__getCloner();
133 $proxy->__setInitializer(null);
134 $proxy->__setCloner(null);
136 if ($proxy->__isInitialized()) {
137 return;
140 $properties = $proxy->__getLazyProperties();
142 foreach ($properties as $propertyName => $property) {
143 if ( ! isset($proxy->$propertyName)) {
144 $proxy->$propertyName = $properties[$propertyName];
148 $proxy->__setInitialized(true);
149 $proxy->__wakeup();
151 $identifier = $classMetadata->getIdentifierValues($proxy);
153 if (null === $entityPersister->loadById($identifier, $proxy)) {
154 $proxy->__setInitializer($initializer);
155 $proxy->__setCloner($cloner);
156 $proxy->__setInitialized(false);
158 throw EntityNotFoundException::fromClassNameAndIdentifier(
159 $classMetadata->getName(),
160 $this->identifierFlattener->flattenIdentifier($classMetadata, $identifier)
166 return function (BaseProxy $proxy) use ($entityPersister, $classMetadata) {
167 $initializer = $proxy->__getInitializer();
168 $cloner = $proxy->__getCloner();
170 $proxy->__setInitializer(null);
171 $proxy->__setCloner(null);
173 if ($proxy->__isInitialized()) {
174 return;
177 $properties = $proxy->__getLazyProperties();
179 foreach ($properties as $propertyName => $property) {
180 if (!isset($proxy->$propertyName)) {
181 $proxy->$propertyName = $properties[$propertyName];
185 $proxy->__setInitialized(true);
187 $identifier = $classMetadata->getIdentifierValues($proxy);
189 if (null === $entityPersister->loadById($identifier, $proxy)) {
190 $proxy->__setInitializer($initializer);
191 $proxy->__setCloner($cloner);
192 $proxy->__setInitialized(false);
194 throw EntityNotFoundException::fromClassNameAndIdentifier(
195 $classMetadata->getName(),
196 $this->identifierFlattener->flattenIdentifier($classMetadata, $identifier)
203 * Creates a closure capable of finalizing state a cloned proxy
205 * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $classMetadata
206 * @param \Doctrine\ORM\Persisters\Entity\EntityPersister $entityPersister
208 * @return \Closure
210 * @throws \Doctrine\ORM\EntityNotFoundException
212 private function createCloner(ClassMetadata $classMetadata, EntityPersister $entityPersister)
214 return function (BaseProxy $proxy) use ($entityPersister, $classMetadata) {
215 if ($proxy->__isInitialized()) {
216 return;
219 $proxy->__setInitialized(true);
220 $proxy->__setInitializer(null);
222 $class = $entityPersister->getClassMetadata();
223 $identifier = $classMetadata->getIdentifierValues($proxy);
224 $original = $entityPersister->loadById($identifier);
226 if (null === $original) {
227 throw EntityNotFoundException::fromClassNameAndIdentifier(
228 $classMetadata->getName(),
229 $this->identifierFlattener->flattenIdentifier($classMetadata, $identifier)
233 foreach ($class->getReflectionProperties() as $property) {
234 if ( ! $class->hasField($property->name) && ! $class->hasAssociation($property->name)) {
235 continue;
238 $property->setAccessible(true);
239 $property->setValue($proxy, $property->getValue($original));