Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Added ProxyReferenceRepository #65

Closed
wants to merge 25 commits into from

3 participants

@guilhermeblanco

Implemented a cached version of ReferenceRepository.

...rine/Common/DataFixtures/ProxyReferenceRepository.php
((7 lines not shown))
+ * 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;
+
+use Doctrine\Common\DataFixtures\ReferenceRepository;
@stof Collaborator
stof added a note

this use statement is useless. The class is already in the same namespace.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
...rine/Common/DataFixtures/ProxyReferenceRepository.php
((30 lines not shown))
+ * @since Doctrine ORM 2.2
+ *
+ * @author Anthon Pang <anthonp@nationalfibre.net>
+ */
+class ProxyReferenceRepository extends ReferenceRepository
+{
+ /**
+ * Serialize reference repository
+ *
+ * @return string
+ */
+ public function serialize() {
+ $simpleReferences = array();
+
+ foreach ($this->getReferences() as $name => $reference) {
+ $className = str_replace('Proxies\\__CG__\\', '', get_class($reference));
@stof Collaborator
stof added a note

if you want to get the original class name, you should probably use Doctrine\Common\Util\ClassUtils

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
...rine/Common/DataFixtures/ProxyReferenceRepository.php
((26 lines not shown))
+ *
+ * Allow data fixture references and identities to be persisted when cached data fixtures
+ * are pre-loaded, for example, by LiipFunctionalTestBundle\Test\WebTestCase loadFixtures().
+ *
+ * @since Doctrine ORM 2.2
+ *
+ * @author Anthon Pang <anthonp@nationalfibre.net>
+ */
+class ProxyReferenceRepository extends ReferenceRepository
+{
+ /**
+ * Serialize reference repository
+ *
+ * @return string
+ */
+ public function serialize() {
@stof Collaborator
stof added a note

CS issue: the curly brace should be on its own line

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
...rine/Common/DataFixtures/ProxyReferenceRepository.php
((76 lines not shown))
+
+ $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)
+ {
+ $serializedData = file_get_contents($baseCacheName . '.ser');
@stof Collaborator
stof added a note

what if the file does not exist ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@stof
Collaborator

you should also add some tests

@robocoder

I'll add unit tests and squash the commits later.

...rine/Common/DataFixtures/ProxyReferenceRepository.php
((28 lines not shown))
+ * @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 ( ! $reference instanceof \Doctrine\ORM\Proxy\Proxy) {
@stof Collaborator
stof added a note

This is wrong here. DataFixtures is in the Common namespace. It should not depend on the ORM (this code is broken for the ODMs currently).

Thus, all ODMs are now using Doctrine Common 2.2 as their requirement AFAIK so you should do the ClassUtils call first, without any assumption on the proxy (it checks it internally anyway), and eventually provide a fallback for the older ORM as done here but I'm not even sure it is necessary (we could mark this feature as requirement the ORM 2.2 as 2.1 will soon be marked as receiving only security fixes and no more bug fixes)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@robocoder robocoder drop dependency on ORM from getRealClass(), but the fallback for earl…
…ier Doctrine versions is potentially problematic if the real class name ends in Proxy
89bd12f
@robocoder

@guilhermeblanco please close this PR; I've consolidated the commits into PR #66

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 20, 2012
  1. @robocoder
  2. @robocoder
  3. @robocoder
  4. @robocoder

    add missing use statements

    robocoder authored
  5. @robocoder
  6. @robocoder

    missing use

    robocoder authored
  7. @robocoder

    missing use

    robocoder authored
  8. @robocoder

    fix missing use

    robocoder authored
  9. @robocoder
  10. @robocoder
  11. @robocoder
Commits on Apr 27, 2012
  1. @robocoder

    Loader.php: add hasFixture()

    robocoder authored
  2. @robocoder
  3. @robocoder
  4. @robocoder
  5. @robocoder

    revert last commit

    robocoder authored
  6. @robocoder
  7. @robocoder

    fix typo

    robocoder authored
Commits on May 8, 2012
  1. @guilhermeblanco

    CS fixes.

    guilhermeblanco authored
  2. @robocoder
  3. @robocoder
  4. @robocoder
  5. @robocoder
  6. @robocoder

    add unit test

    robocoder authored
Commits on May 9, 2012
  1. @robocoder

    drop dependency on ORM from getRealClass(), but the fallback for earl…

    robocoder authored www-data committed
    …ier Doctrine versions is potentially problematic if the real class name ends in Proxy
This page is out of date. Refresh to see the latest.
View
12 lib/Doctrine/Common/DataFixtures/Loader.php
@@ -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
View
131 lib/Doctrine/Common/DataFixtures/ProxyReferenceRepository.php
@@ -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);
+ }
+}
View
122 tests/Doctrine/Tests/Common/DataFixtures/ProxyReferenceRepositoryTest.php
@@ -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);
+ }
+}
Something went wrong with that request. Please try again.