123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696 |
- <?php
- /*
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * This software consists of voluntary contributions made by many individuals
- * and is licensed under the MIT license. For more information, see
- * <http://www.doctrine-project.org>.
- */
- namespace Doctrine\Tests\Common\Proxy;
- use Doctrine\Common\Proxy\ProxyGenerator;
- use Doctrine\Common\Proxy\Proxy;
- use Doctrine\Common\Proxy\Exception\UnexpectedValueException;
- use Doctrine\Common\Persistence\Mapping\ClassMetadata;
- use PHPUnit_Framework_TestCase;
- /**
- * Test the generated proxies behavior. These tests make assumptions about the structure of LazyLoadableObject
- *
- * @author Marco Pivetta <ocramius@gmail.com>
- */
- class ProxyLogicTest extends PHPUnit_Framework_TestCase
- {
- /**
- * @var \PHPUnit_Framework_MockObject_MockObject
- */
- protected $proxyLoader;
- /**
- * @var ClassMetadata
- */
- protected $lazyLoadableObjectMetadata;
- /**
- * @var LazyLoadableObject|Proxy
- */
- protected $lazyObject;
- protected $identifier = array(
- 'publicIdentifierField' => 'publicIdentifierFieldValue',
- 'protectedIdentifierField' => 'protectedIdentifierFieldValue',
- );
- /**
- * @var \PHPUnit_Framework_MockObject_MockObject|Callable
- */
- protected $initializerCallbackMock;
- /**
- * {@inheritDoc}
- */
- public function setUp()
- {
- $this->proxyLoader = $loader = $this->getMock('stdClass', array('load'), array(), '', false);
- $this->initializerCallbackMock = $this->getMock('stdClass', array('__invoke'));
- $identifier = $this->identifier;
- $this->lazyLoadableObjectMetadata = $metadata = new LazyLoadableObjectClassMetadata();
- // emulating what should happen in a proxy factory
- $cloner = function (LazyLoadableObject $proxy) use ($loader, $identifier, $metadata) {
- /* @var $proxy LazyLoadableObject|Proxy */
- if ($proxy->__isInitialized()) {
- return;
- }
- $proxy->__setInitialized(true);
- $proxy->__setInitializer(null);
- $original = $loader->load($identifier);
- if (null === $original) {
- throw new UnexpectedValueException();
- }
- foreach ($metadata->getReflectionClass()->getProperties() as $reflProperty) {
- $propertyName = $reflProperty->getName();
- if ($metadata->hasField($propertyName) || $metadata->hasAssociation($propertyName)) {
- $reflProperty->setAccessible(true);
- $reflProperty->setValue($proxy, $reflProperty->getValue($original));
- }
- }
- };
- $proxyClassName = 'Doctrine\Tests\Common\ProxyProxy\__CG__\Doctrine\Tests\Common\Proxy\LazyLoadableObject';
- // creating the proxy class
- if (!class_exists($proxyClassName, false)) {
- $proxyGenerator = new ProxyGenerator(__DIR__ . '/generated', __NAMESPACE__ . 'Proxy', true);
- $proxyGenerator->generateProxyClass($metadata);
- require_once $proxyGenerator->getProxyFileName($metadata->getName());
- }
- $this->lazyObject = new $proxyClassName($this->getClosure($this->initializerCallbackMock), $cloner);
- // setting identifiers in the proxy via reflection
- foreach ($metadata->getIdentifierFieldNames() as $idField) {
- $prop = $metadata->getReflectionClass()->getProperty($idField);
- $prop->setAccessible(true);
- $prop->setValue($this->lazyObject, $identifier[$idField]);
- }
- $this->assertFalse($this->lazyObject->__isInitialized());
- }
- public function testFetchingPublicIdentifierDoesNotCauseLazyLoading()
- {
- $this->configureInitializerMock(0);
- $this->assertSame('publicIdentifierFieldValue', $this->lazyObject->publicIdentifierField);
- }
- public function testFetchingIdentifiersViaPublicGetterDoesNotCauseLazyLoading()
- {
- $this->configureInitializerMock(0);
- $this->assertSame('protectedIdentifierFieldValue', $this->lazyObject->getProtectedIdentifierField());
- }
- public function testCallingMethodCausesLazyLoading()
- {
- $this->configureInitializerMock(
- 1,
- array($this->lazyObject, 'testInitializationTriggeringMethod', array()),
- function (Proxy $proxy) {
- $proxy->__setInitializer(null);
- }
- );
- $this->lazyObject->testInitializationTriggeringMethod();
- $this->lazyObject->testInitializationTriggeringMethod();
- }
- public function testFetchingPublicFieldsCausesLazyLoading()
- {
- $test = $this;
- $this->configureInitializerMock(
- 1,
- array($this->lazyObject, '__get', array('publicPersistentField')),
- function () use ($test) {
- $test->setProxyValue('publicPersistentField', 'loadedValue');
- }
- );
- $this->assertSame('loadedValue', $this->lazyObject->publicPersistentField);
- $this->assertSame('loadedValue', $this->lazyObject->publicPersistentField);
- }
- public function testFetchingPublicAssociationCausesLazyLoading()
- {
- $test = $this;
- $this->configureInitializerMock(
- 1,
- array($this->lazyObject, '__get', array('publicAssociation')),
- function () use ($test) {
- $test->setProxyValue('publicAssociation', 'loadedAssociation');
- }
- );
- $this->assertSame('loadedAssociation', $this->lazyObject->publicAssociation);
- $this->assertSame('loadedAssociation', $this->lazyObject->publicAssociation);
- }
- public function testFetchingProtectedAssociationViaPublicGetterCausesLazyLoading()
- {
- $this->configureInitializerMock(
- 1,
- array($this->lazyObject, 'getProtectedAssociation', array()),
- function (Proxy $proxy) {
- $proxy->__setInitializer(null);
- }
- );
- $this->assertSame('protectedAssociationValue', $this->lazyObject->getProtectedAssociation());
- $this->assertSame('protectedAssociationValue', $this->lazyObject->getProtectedAssociation());
- }
- public function testLazyLoadingTriggeredOnlyAtFirstPublicPropertyRead()
- {
- $test = $this;
- $this->configureInitializerMock(
- 1,
- array($this->lazyObject, '__get', array('publicPersistentField')),
- function () use ($test) {
- $test->setProxyValue('publicPersistentField', 'loadedValue');
- $test->setProxyValue('publicAssociation', 'publicAssociationValue');
- }
- );
- $this->assertSame('loadedValue', $this->lazyObject->publicPersistentField);
- $this->assertSame('publicAssociationValue', $this->lazyObject->publicAssociation);
- }
- public function testNoticeWhenReadingNonExistentPublicProperties()
- {
- $this->configureInitializerMock(0);
- $class = get_class($this->lazyObject);
- $this->setExpectedException(
- 'PHPUnit_Framework_Error_Notice',
- 'Undefined property: ' . $class . '::$non_existing_property'
- );
- $this->lazyObject->non_existing_property;
- }
- public function testFalseWhenCheckingNonExistentProperty()
- {
- $this->configureInitializerMock(0);
- $this->assertFalse(isset($this->lazyObject->non_existing_property));
- }
- public function testNoErrorWhenSettingNonExistentProperty()
- {
- $this->configureInitializerMock(0);
- $this->lazyObject->non_existing_property = 'now has a value';
- $this->assertSame('now has a value', $this->lazyObject->non_existing_property);
- }
- public function testCloningCallsClonerWithClonedObject()
- {
- $lazyObject = $this->lazyObject;
- $test = $this;
- $cb = $this->getMock('stdClass', array('cb'));
- $cb
- ->expects($this->once())
- ->method('cb')
- ->will($this->returnCallback(function (LazyLoadableObject $proxy) use ($lazyObject, $test) {
- /* @var $proxy LazyLoadableObject|Proxy */
- $test->assertNotSame($proxy, $lazyObject);
- $proxy->__setInitializer(null);
- $proxy->publicAssociation = 'clonedAssociation';
- }));
- $this->lazyObject->__setCloner($this->getClosure(array($cb, 'cb')));
- $cloned = clone $this->lazyObject;
- $this->assertSame('clonedAssociation', $cloned->publicAssociation);
- $this->assertNotSame($cloned, $lazyObject, 'a clone of the lazy object is retrieved');
- }
- public function testFetchingTransientPropertiesWillNotTriggerLazyLoading()
- {
- $this->configureInitializerMock(0);
- $this->assertSame(
- 'publicTransientFieldValue',
- $this->lazyObject->publicTransientField,
- 'fetching public transient field won\'t trigger lazy loading'
- );
- $property = $this
- ->lazyLoadableObjectMetadata
- ->getReflectionClass()
- ->getProperty('protectedTransientField');
- $property->setAccessible(true);
- $this->assertSame(
- 'protectedTransientFieldValue',
- $property->getValue($this->lazyObject),
- 'fetching protected transient field via reflection won\'t trigger lazy loading'
- );
- }
- /**
- * Provided to guarantee backwards compatibility
- */
- public function testLoadProxyMethod()
- {
- $this->configureInitializerMock(2, array($this->lazyObject, '__load', array()));
- $this->lazyObject->__load();
- $this->lazyObject->__load();
- }
- public function testLoadingWithPersisterWillBeTriggeredOnlyOnce()
- {
- $this
- ->proxyLoader
- ->expects($this->once())
- ->method('load')
- ->with(
- array(
- 'publicIdentifierField' => 'publicIdentifierFieldValue',
- 'protectedIdentifierField' => 'protectedIdentifierFieldValue',
- ),
- $this->lazyObject
- )
- ->will($this->returnCallback(function ($id, LazyLoadableObject $lazyObject) {
- // setting a value to verify that the persister can actually set something in the object
- $lazyObject->publicAssociation = $id['publicIdentifierField'] . '-test';
- return true;
- }));
- $this->lazyObject->__setInitializer($this->getSuggestedInitializerImplementation());
- $this->lazyObject->__load();
- $this->lazyObject->__load();
- $this->assertSame('publicIdentifierFieldValue-test', $this->lazyObject->publicAssociation);
- }
- public function testFailedLoadingWillThrowException()
- {
- $this->proxyLoader->expects($this->any())->method('load')->will($this->returnValue(null));
- $this->setExpectedException('UnexpectedValueException');
- $this->lazyObject->__setInitializer($this->getSuggestedInitializerImplementation());
- $this->lazyObject->__load();
- }
- public function testCloningWithPersister()
- {
- $this->lazyObject->publicTransientField = 'should-not-change';
- $this
- ->proxyLoader
- ->expects($this->exactly(2))
- ->method('load')
- ->with(array(
- 'publicIdentifierField' => 'publicIdentifierFieldValue',
- 'protectedIdentifierField' => 'protectedIdentifierFieldValue',
- ))
- ->will($this->returnCallback(function () {
- $blueprint = new LazyLoadableObject();
- $blueprint->publicPersistentField = 'checked-persistent-field';
- $blueprint->publicAssociation = 'checked-association-field';
- $blueprint->publicTransientField = 'checked-transient-field';
- return $blueprint;
- }));
- $firstClone = clone $this->lazyObject;
- $this->assertSame(
- 'checked-persistent-field',
- $firstClone->publicPersistentField,
- 'Persistent fields are cloned correctly'
- );
- $this->assertSame(
- 'checked-association-field',
- $firstClone->publicAssociation,
- 'Associations are cloned correctly'
- );
- $this->assertSame(
- 'should-not-change',
- $firstClone->publicTransientField,
- 'Transient fields are not overwritten'
- );
- $secondClone = clone $this->lazyObject;
- $this->assertSame(
- 'checked-persistent-field',
- $secondClone->publicPersistentField,
- 'Persistent fields are cloned correctly'
- );
- $this->assertSame(
- 'checked-association-field',
- $secondClone->publicAssociation,
- 'Associations are cloned correctly'
- );
- $this->assertSame(
- 'should-not-change',
- $secondClone->publicTransientField,
- 'Transient fields are not overwritten'
- );
- // those should not trigger lazy loading
- $firstClone->__load();
- $secondClone->__load();
- }
- public function testNotInitializedProxyUnserialization()
- {
- $this->configureInitializerMock();
- $serialized = serialize($this->lazyObject);
- /* @var $unserialized LazyLoadableObject|Proxy */
- $unserialized = unserialize($serialized);
- $reflClass = $this->lazyLoadableObjectMetadata->getReflectionClass();
- $this->assertFalse($unserialized->__isInitialized(), 'serialization didn\'t cause intialization');
- // Checking identifiers
- $this->assertSame('publicIdentifierFieldValue', $unserialized->publicIdentifierField, 'identifiers are kept');
- $protectedIdentifierField = $reflClass->getProperty('protectedIdentifierField');
- $protectedIdentifierField->setAccessible(true);
- $this->assertSame(
- 'protectedIdentifierFieldValue',
- $protectedIdentifierField->getValue($unserialized),
- 'identifiers are kept'
- );
- // Checking transient fields
- $this->assertSame(
- 'publicTransientFieldValue',
- $unserialized->publicTransientField,
- 'transient fields are kept'
- );
- $protectedTransientField = $reflClass->getProperty('protectedTransientField');
- $protectedTransientField->setAccessible(true);
- $this->assertSame(
- 'protectedTransientFieldValue',
- $protectedTransientField->getValue($unserialized),
- 'transient fields are kept'
- );
- // Checking persistent fields
- $this->assertSame(
- 'publicPersistentFieldValue',
- $unserialized->publicPersistentField,
- 'persistent fields are kept'
- );
- $protectedPersistentField = $reflClass->getProperty('protectedPersistentField');
- $protectedPersistentField->setAccessible(true);
- $this->assertSame(
- 'protectedPersistentFieldValue',
- $protectedPersistentField->getValue($unserialized),
- 'persistent fields are kept'
- );
- // Checking associations
- $this->assertSame('publicAssociationValue', $unserialized->publicAssociation, 'associations are kept');
- $protectedAssociationField = $reflClass->getProperty('protectedAssociation');
- $protectedAssociationField->setAccessible(true);
- $this->assertSame(
- 'protectedAssociationValue',
- $protectedAssociationField->getValue($unserialized),
- 'associations are kept'
- );
- }
- public function testInitializedProxyUnserialization()
- {
- // persister will retrieve the lazy object itself, so that we don't have to re-define all field values
- $this->proxyLoader->expects($this->once())->method('load')->will($this->returnValue($this->lazyObject));
- $this->lazyObject->__setInitializer($this->getSuggestedInitializerImplementation());
- $this->lazyObject->__load();
- $serialized = serialize($this->lazyObject);
- $reflClass = $this->lazyLoadableObjectMetadata->getReflectionClass();
- /* @var $unserialized LazyLoadableObject|Proxy */
- $unserialized = unserialize($serialized);
- $this->assertTrue($unserialized->__isInitialized(), 'serialization didn\'t cause intialization');
- // Checking transient fields
- $this->assertSame(
- 'publicTransientFieldValue',
- $unserialized->publicTransientField,
- 'transient fields are kept'
- );
- $protectedTransientField = $reflClass->getProperty('protectedTransientField');
- $protectedTransientField->setAccessible(true);
- $this->assertSame(
- 'protectedTransientFieldValue',
- $protectedTransientField->getValue($unserialized),
- 'transient fields are kept'
- );
- // Checking persistent fields
- $this->assertSame(
- 'publicPersistentFieldValue',
- $unserialized->publicPersistentField,
- 'persistent fields are kept'
- );
- $protectedPersistentField = $reflClass->getProperty('protectedPersistentField');
- $protectedPersistentField->setAccessible(true);
- $this->assertSame(
- 'protectedPersistentFieldValue',
- $protectedPersistentField->getValue($unserialized),
- 'persistent fields are kept'
- );
- // Checking identifiers
- $this->assertSame(
- 'publicIdentifierFieldValue',
- $unserialized->publicIdentifierField,
- 'identifiers are kept'
- );
- $protectedIdentifierField = $reflClass->getProperty('protectedIdentifierField');
- $protectedIdentifierField->setAccessible(true);
- $this->assertSame(
- 'protectedIdentifierFieldValue',
- $protectedIdentifierField->getValue($unserialized),
- 'identifiers are kept'
- );
- // Checking associations
- $this->assertSame('publicAssociationValue', $unserialized->publicAssociation, 'associations are kept');
- $protectedAssociationField = $reflClass->getProperty('protectedAssociation');
- $protectedAssociationField->setAccessible(true);
- $this->assertSame(
- 'protectedAssociationValue',
- $protectedAssociationField->getValue($unserialized),
- 'associations are kept'
- );
- }
- public function testInitializationRestoresDefaultPublicLazyLoadedFieldValues()
- {
- // setting noop persister
- $this->proxyLoader->expects($this->once())->method('load')->will($this->returnValue($this->lazyObject));
- $this->lazyObject->__setInitializer($this->getSuggestedInitializerImplementation());
- $this->assertSame(
- 'publicPersistentFieldValue',
- $this->lazyObject->publicPersistentField,
- 'Persistent field is restored to default value'
- );
- $this->assertSame(
- 'publicAssociationValue',
- $this->lazyObject->publicAssociation,
- 'Association is restored to default value'
- );
- }
- public function testSettingPublicFieldsCausesLazyLoading()
- {
- $test = $this;
- $this->configureInitializerMock(
- 1,
- array($this->lazyObject, '__set', array('publicPersistentField', 'newPublicPersistentFieldValue')),
- function () use ($test) {
- $test->setProxyValue('publicPersistentField', 'overrideValue');
- $test->setProxyValue('publicAssociation', 'newAssociationValue');
- }
- );
- $this->lazyObject->publicPersistentField = 'newPublicPersistentFieldValue';
- $this->assertSame('newPublicPersistentFieldValue', $this->lazyObject->publicPersistentField);
- $this->assertSame('newAssociationValue', $this->lazyObject->publicAssociation);
- }
- public function testSettingPublicAssociationCausesLazyLoading()
- {
- $test = $this;
- $this->configureInitializerMock(
- 1,
- array($this->lazyObject, '__set', array('publicAssociation', 'newPublicAssociationValue')),
- function () use ($test) {
- $test->setProxyValue('publicPersistentField', 'newPublicPersistentFieldValue');
- $test->setProxyValue('publicAssociation', 'overrideValue');
- }
- );
- $this->lazyObject->publicAssociation = 'newPublicAssociationValue';
- $this->assertSame('newPublicAssociationValue', $this->lazyObject->publicAssociation);
- $this->assertSame('newPublicPersistentFieldValue', $this->lazyObject->publicPersistentField);
- }
- public function testCheckingPublicFieldsCausesLazyLoading()
- {
- $test = $this;
- $this->configureInitializerMock(
- 1,
- array($this->lazyObject, '__isset', array('publicPersistentField')),
- function () use ($test) {
- $test->setProxyValue('publicPersistentField', null);
- $test->setProxyValue('publicAssociation', 'setPublicAssociation');
- }
- );
- $this->assertFalse(isset($this->lazyObject->publicPersistentField));
- $this->assertNull($this->lazyObject->publicPersistentField);
- $this->assertTrue(isset($this->lazyObject->publicAssociation));
- $this->assertSame('setPublicAssociation', $this->lazyObject->publicAssociation);
- }
- public function testCheckingPublicAssociationCausesLazyLoading()
- {
- $test = $this;
- $this->configureInitializerMock(
- 1,
- array($this->lazyObject, '__isset', array('publicAssociation')),
- function () use ($test) {
- $test->setProxyValue('publicPersistentField', 'newPersistentFieldValue');
- $test->setProxyValue('publicAssociation', 'setPublicAssociation');
- }
- );
- $this->assertTrue(isset($this->lazyObject->publicAssociation));
- $this->assertSame('setPublicAssociation', $this->lazyObject->publicAssociation);
- $this->assertTrue(isset($this->lazyObject->publicPersistentField));
- $this->assertSame('newPersistentFieldValue', $this->lazyObject->publicPersistentField);
- }
- /**
- * Converts a given callable into a closure
- *
- * @param callable $callable
- * @return \Closure
- */
- public function getClosure($callable) {
- return function () use ($callable) {
- call_user_func_array($callable, func_get_args());
- };
- }
- /**
- * Configures the current initializer callback mock with provided matcher params
- *
- * @param int $expectedCallCount the number of invocations to be expected. If a value< 0 is provided, `any` is used
- * @param array $callParamsMatch an ordered array of parameters to be expected
- * @param callable $callbackClosure a return callback closure
- *
- * @return \PHPUnit_Framework_MockObject_MockObject|
- */
- protected function configureInitializerMock(
- $expectedCallCount = 0,
- array $callParamsMatch = null,
- \Closure $callbackClosure = null
- ) {
- if (!$expectedCallCount) {
- $invocationCountMatcher = $this->exactly((int) $expectedCallCount);
- } else {
- $invocationCountMatcher = $expectedCallCount < 0 ? $this->any() : $this->exactly($expectedCallCount);
- }
- $invocationMocker = $this->initializerCallbackMock->expects($invocationCountMatcher)->method('__invoke');
- if (null !== $callParamsMatch) {
- call_user_func_array(array($invocationMocker, 'with'), $callParamsMatch);
- }
- if ($callbackClosure) {
- $invocationMocker->will($this->returnCallback($callbackClosure));
- }
- }
- /**
- * Sets a value in the current proxy object without triggering lazy loading through `__set`
- *
- * @link https://bugs.php.net/bug.php?id=63463
- *
- * @param string $property
- * @param mixed $value
- */
- public function setProxyValue($property, $value)
- {
- $reflectionProperty = new \ReflectionProperty($this->lazyObject, $property);
- $initializer = $this->lazyObject->__getInitializer();
- // disabling initializer since setting `publicPersistentField` triggers `__set`/`__get`
- $this->lazyObject->__setInitializer(null);
- $reflectionProperty->setValue($this->lazyObject, $value);
- $this->lazyObject->__setInitializer($initializer);
- }
- /**
- * Retrieves the suggested implementation of an initializer that proxy factories in O*M
- * are currently following, and that should be used to initialize the current proxy object
- *
- * @return \Closure
- */
- protected function getSuggestedInitializerImplementation()
- {
- $loader = $this->proxyLoader;
- $identifier = $this->identifier;
- return function (LazyLoadableObject $proxy) use ($loader, $identifier) {
- /* @var $proxy LazyLoadableObject|Proxy */
- $proxy->__setInitializer(null);
- $proxy->__setCloner(null);
- if ($proxy->__isInitialized()) {
- return;
- }
- $properties = $proxy->__getLazyProperties();
- foreach ($properties as $propertyName => $property) {
- if (!isset($proxy->$propertyName)) {
- $proxy->$propertyName = $properties[$propertyName];
- }
- }
- $proxy->__setInitialized(true);
- if (method_exists($proxy, '__wakeup')) {
- $proxy->__wakeup();
- }
- if (null === $loader->load($identifier, $proxy)) {
- throw new \UnexpectedValueException('Couldn\'t load');
- }
- };
- }
- }
|