Added ProxyReferenceRepository #65

Closed
wants to merge 25 commits into
from
Commits
+265 −0
Split
@@ -108,6 +108,18 @@ public function loadFromDirectory($dir)
}
/**
+ * Has fixture?
+ *
+ * @param FixtureInterface $fixture
+ *
+ * @return boolean
+ */
+ public function hasFixture($fixture)
+ {
+ return isset($this->fixtures[get_class($fixture)]);
+ }
+
+ /**
* Add a fixture object instance to the loader.
*
* @param FixtureInterface $fixture
@@ -0,0 +1,131 @@
+<?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 LGPL. For more information, see
+ * <http://www.doctrine-project.org>.
+ */
+
+namespace Doctrine\Common\DataFixtures;
+
+/**
+ * Proxy reference repository
+ *
+ * Allow data fixture references and identities to be persisted when cached data fixtures
+ * are pre-loaded, for example, by LiipFunctionalTestBundle\Test\WebTestCase loadFixtures().
+ *
+ * @author Anthon Pang <anthonp@nationalfibre.net>
+ */
+class ProxyReferenceRepository extends ReferenceRepository
+{
+ /**
+ * Get real class name of a reference that could be a proxy
+ *
+ * @param mixed $reference Reference
+ *
+ * @return string
+ */
+ protected function getRealClass($reference)
+ {
+ $className = get_class($reference);
+
+ if (\Doctrine\Common\Version::compare('2.2.0') === -1) {
+ return \Doctrine\Common\Util\ClassUtils::getRealClass($className);
+ }
+
+ if (substr($className, -5) === 'Proxy') {
+ return substr($className, 0, -5);
+ }
+
+ return $className;
+ }
+
+ /**
+ * Serialize reference repository
+ *
+ * @return string
+ */
+ public function serialize()
+ {
+ $simpleReferences = array();
+
+ foreach ($this->getReferences() as $name => $reference) {
+ $className = $this->getRealClass($reference);
+
+ $simpleReferences[$name] = array($className, $reference->getId());
+ }
+
+ $serializedData = json_encode(array(
+ 'references' => $simpleReferences,
+ 'identities' => $this->getIdentities(),
+ ));
+
+ return $serializedData;
+ }
+
+ /**
+ * Unserialize reference repository
+ *
+ * @param string $serializedData Serialized data
+ */
+ public function unserialize($serializedData)
+ {
+ $repositoryData = json_decode($serializedData, true);
+ $references = $repositoryData['references'];
+
+ foreach ($references as $name => $proxyReference) {
+ $this->setReference(
+ $name,
+ $this->getManager()->getReference(
+ $proxyReference[0], // entity class name
+ $proxyReference[1] // id
+ )
+ );
+ }
+
+ $identities = $repositoryData['identities'];
+
+ foreach ($identities as $name => $identity) {
+ $this->setReferenceIdentity($name, $identity);
+ }
+ }
+
+ /**
+ * Load data fixture reference repository
+ *
+ * @param string $baseCacheName Base cache name
+ */
+ public function load($baseCacheName)
+ {
+ $filename = $baseCacheName . '.ser';
+
+ if ( ! file_exists($filename) || ($serializedData = file_get_contents($filename)) === false) {
+ return;
+ }
+
+ $this->unserialize($serializedData);
+ }
+
+ /**
+ * Save data fixture reference repository
+ *
+ * @param string $baseCacheName Base cache name
+ */
+ public function save($baseCacheName)
+ {
+ $serializedData = $this->serialize();
+
+ file_put_contents($baseCacheName . '.ser', $serializedData);
+ }
+}
@@ -0,0 +1,122 @@
+<?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 LGPL. For more information, see
+ * <http://www.doctrine-project.org>.
+ */
+
+namespace Doctrine\Tests\Common\DataFixtures;
+
+use Doctrine\Common\DataFixtures\ProxyReferenceRepository;
+use Doctrine\Common\DataFixtures\Event\Listener\ORMReferenceListener;
+use Doctrine\ORM\Tools\SchemaTool;
+use Doctrine\ORM\Proxy\Proxy;
+
+require_once __DIR__.'/TestInit.php';
+
+/**
+ * Test ProxyReferenceRepository.
+ *
+ * @author Gediminas Morkevicius <gediminas.morkevicius@gmail.com>
+ * @author Anthon Pang <anthonp@nationalfibre.net>
+ */
+class ProxyReferenceRepositoryTest extends BaseTest
+{
+ const TEST_ENTITY_ROLE = 'Doctrine\Tests\Common\DataFixtures\TestEntity\Role';
+
+ public function testReferenceEntry()
+ {
+ $em = $this->getMockAnnotationReaderEntityManager();
+ $role = new TestEntity\Role;
+ $role->setName('admin');
+ $meta = $em->getClassMetadata(self::TEST_ENTITY_ROLE);
+ $meta->getReflectionProperty('id')->setValue($role, 1);
+
+ $referenceRepo = new ProxyReferenceRepository($em);
+ $referenceRepo->addReference('test', $role);
+
+ $references = $referenceRepo->getReferences();
+ $this->assertEquals(1, count($references));
+ $this->assertArrayHasKey('test', $references);
+ $this->assertInstanceOf(self::TEST_ENTITY_ROLE, $references['test']);
+ }
+
+ public function testReferenceIdentityPopulation()
+ {
+ $em = $this->getMockSqliteEntityManager();
+ $referenceRepository = $this->getMockBuilder('Doctrine\Common\DataFixtures\ProxyReferenceRepository')
+ ->setConstructorArgs(array($em))
+ ->getMock();
+ $em->getEventManager()->addEventSubscriber(
+ new ORMReferenceListener($referenceRepository)
+ );
+ $schemaTool = new SchemaTool($em);
+ $schemaTool->dropSchema(array());
+ $schemaTool->createSchema(array(
+ $em->getClassMetadata(self::TEST_ENTITY_ROLE)
+ ));
+
+ $referenceRepository->expects($this->once())
+ ->method('addReference')
+ ->with('admin-role');
+
+ $referenceRepository->expects($this->once())
+ ->method('getReferenceName')
+ ->will($this->returnValue('admin-role'));
+
+ $referenceRepository->expects($this->once())
+ ->method('setReferenceIdentity')
+ ->with('admin-role', array('id' => 1));
+
+ $roleFixture = new TestFixtures\RoleFixture;
+ $roleFixture->setReferenceRepository($referenceRepository);
+ $roleFixture->load($em);
+ }
+
+ public function testReferenceReconstruction()
+ {
+ $em = $this->getMockSqliteEntityManager();
+ $referenceRepository = new ProxyReferenceRepository($em);
+ $listener = new ORMReferenceListener($referenceRepository);
+ $em->getEventManager()->addEventSubscriber($listener);
+
+ $schemaTool = new SchemaTool($em);
+ $schemaTool->dropSchema(array());
+ $schemaTool->createSchema(array(
+ $em->getClassMetadata(self::TEST_ENTITY_ROLE)
+ ));
+ $roleFixture = new TestFixtures\RoleFixture;
+ $roleFixture->setReferenceRepository($referenceRepository);
+
+ $roleFixture->load($em);
+ // first test against managed state
+ $ref = $referenceRepository->getReference('admin-role');
+ $this->assertFalse($ref instanceof Proxy);
+
+ // now test reference reconstruction from identity
+ $em->clear();
+ $ref = $referenceRepository->getReference('admin-role');
+ $this->assertTrue($ref instanceof Proxy);
+
+ // test reference reconstruction from serialized data
+ $serializedData = $referenceRepository->serialize();
+
+ $referenceRepository = new ProxyReferenceRepository($em);
+ $referenceRepository->unserialize($serializedData);
+
+ $ref = $referenceRepository->getReference('admin-role');
+ $this->assertTrue($ref instanceof Proxy);
+ }
+}