瀏覽代碼

[translatable] handle inheritance, closes #266

gedi 13 年之前
父節點
當前提交
5e359b9e1b

+ 7 - 7
lib/Gedmo/Translatable/Mapping/Event/Adapter/ODM.php

@@ -46,7 +46,7 @@ final class ODM extends BaseAdapterODM implements TranslatableAdapter
     /**
      * {@inheritDoc}
      */
-    public function loadTranslations($object, $translationClass, $locale)
+    public function loadTranslations($object, $translationClass, $locale, $objectClass)
     {
         $dm = $this->getObjectManager();
         $wrapped = AbstractWrapper::wrap($object, $dm);
@@ -86,7 +86,7 @@ final class ODM extends BaseAdapterODM implements TranslatableAdapter
                 ->createQueryBuilder($translationClass)
                 ->field('foreignKey')->equals($wrapped->getIdentifier())
                 ->field('locale')->equals($locale)
-                ->field('objectClass')->equals($wrapped->getMetadata()->name)
+                ->field('objectClass')->equals($objectClass)
                 ->getQuery()
             ;
         }
@@ -101,7 +101,7 @@ final class ODM extends BaseAdapterODM implements TranslatableAdapter
     /**
      * {@inheritDoc}
      */
-    public function findTranslation(AbstractWrapper $wrapped, $locale, $field, $translationClass)
+    public function findTranslation(AbstractWrapper $wrapped, $locale, $field, $translationClass, $objectClass)
     {
         $dm = $this->getObjectManager();
         $qb = $dm
@@ -114,7 +114,7 @@ final class ODM extends BaseAdapterODM implements TranslatableAdapter
             $qb->field('object.$id')->equals($wrapped->getIdentifier());
         } else {
             $qb->field('foreignKey')->equals($wrapped->getIdentifier());
-            $qb->field('objectClass')->equals($wrapped->getMetadata()->name);
+            $qb->field('objectClass')->equals($objectClass);
         }
         $q = $qb->getQuery();
         $result = $q->execute();
@@ -127,7 +127,7 @@ final class ODM extends BaseAdapterODM implements TranslatableAdapter
     /**
      * {@inheritDoc}
      */
-    public function removeAssociatedTranslations(AbstractWrapper $wrapped, $transClass)
+    public function removeAssociatedTranslations(AbstractWrapper $wrapped, $transClass, $objectClass)
     {
         $dm = $this->getObjectManager();
         $qb = $dm
@@ -138,7 +138,7 @@ final class ODM extends BaseAdapterODM implements TranslatableAdapter
             $qb->field('object.$id')->equals($wrapped->getIdentifier());
         } else {
             $qb->field('foreignKey')->equals($wrapped->getIdentifier());
-            $qb->field('objectClass')->equals($wrapped->getMetadata()->name);
+            $qb->field('objectClass')->equals($objectClass);
         }
         $q = $qb->getQuery();
         return $q->execute();
@@ -195,4 +195,4 @@ final class ODM extends BaseAdapterODM implements TranslatableAdapter
         $value = $type->convertToPHPValue($value);
         $wrapped->setPropertyValue($field, $value);
     }
-}
+}

+ 6 - 8
lib/Gedmo/Translatable/Mapping/Event/Adapter/ORM.php

@@ -3,7 +3,6 @@
 namespace Gedmo\Translatable\Mapping\Event\Adapter;
 
 use Doctrine\DBAL\Types\Type;
-use Doctrine\ORM\Proxy\Proxy;
 use Doctrine\ORM\Query;
 use Doctrine\ORM\Mapping\ClassMetadataInfo;
 use Gedmo\Mapping\Event\Adapter\ORM as BaseAdapterORM;
@@ -46,7 +45,7 @@ final class ORM extends BaseAdapterORM implements TranslatableAdapter
     /**
      * {@inheritDoc}
      */
-    public function loadTranslations($object, $translationClass, $locale)
+    public function loadTranslations($object, $translationClass, $locale, $objectClass)
     {
         $em = $this->getObjectManager();
         $wrapped = AbstractWrapper::wrap($object, $em);
@@ -92,7 +91,6 @@ final class ORM extends BaseAdapterORM implements TranslatableAdapter
             $dql .= ' AND t.locale = :locale';
             $dql .= ' AND t.objectClass = :objectClass';
             // fetch results
-            $objectClass = $wrapped->getMetadata()->name;
             $q = $em->createQuery($dql);
             $q->setParameters(compact('objectId', 'locale', 'objectClass'));
             $result = $q->getArrayResult();
@@ -103,7 +101,7 @@ final class ORM extends BaseAdapterORM implements TranslatableAdapter
     /**
      * {@inheritDoc}
      */
-    public function findTranslation(AbstractWrapper $wrapped, $locale, $field, $translationClass)
+    public function findTranslation(AbstractWrapper $wrapped, $locale, $field, $translationClass, $objectClass)
     {
         $em = $this->getObjectManager();
         // first look in identityMap, will save one SELECT query
@@ -146,7 +144,7 @@ final class ORM extends BaseAdapterORM implements TranslatableAdapter
             $qb->andWhere('trans.foreignKey = :objectId');
             $qb->andWhere('trans.objectClass = :objectClass');
             $qb->setParameter('objectId', $wrapped->getIdentifier());
-            $qb->setParameter('objectClass', $wrapped->getMetadata()->name);
+            $qb->setParameter('objectClass', $objectClass);
         }
         $q = $qb->getQuery();
         $q->setMaxResults(1);
@@ -161,7 +159,7 @@ final class ORM extends BaseAdapterORM implements TranslatableAdapter
     /**
      * {@inheritDoc}
      */
-    public function removeAssociatedTranslations(AbstractWrapper $wrapped, $transClass)
+    public function removeAssociatedTranslations(AbstractWrapper $wrapped, $transClass, $objectClass)
     {
         $qb = $this
             ->getObjectManager()
@@ -177,7 +175,7 @@ final class ORM extends BaseAdapterORM implements TranslatableAdapter
                 'trans.objectClass = :class'
             );
             $qb->setParameter('objectId', $wrapped->getIdentifier());
-            $qb->setParameter('class', $wrapped->getMetadata()->name);
+            $qb->setParameter('class', $objectClass);
         }
         return $qb->getQuery()->getSingleScalarResult();
     }
@@ -230,4 +228,4 @@ final class ORM extends BaseAdapterORM implements TranslatableAdapter
         $value = $type->convertToPHPValue($value, $em->getConnection()->getDatabasePlatform());
         $wrapped->setPropertyValue($field, $value);
     }
-}
+}

+ 7 - 4
lib/Gedmo/Translatable/Mapping/Event/TranslatableAdapter.php

@@ -39,9 +39,10 @@ interface TranslatableAdapter extends AdapterInterface
      * @param object $object
      * @param string $translationClass
      * @param string $locale
+     * @param string $objectClass
      * @return array
      */
-    function loadTranslations($object, $translationClass, $locale);
+    function loadTranslations($object, $translationClass, $locale, $objectClass);
 
     /**
      * Search for existing translation record
@@ -50,18 +51,20 @@ interface TranslatableAdapter extends AdapterInterface
      * @param string $locale
      * @param string $field
      * @param string $translationClass
+     * @param string $objectClass
      * @return mixed - null if nothing is found, Translation otherwise
      */
-    function findTranslation(AbstractWrapper $wrapped, $locale, $field, $translationClass);
+    function findTranslation(AbstractWrapper $wrapped, $locale, $field, $translationClass, $objectClass);
 
     /**
      * Removes all associated translations for given object
      *
      * AbstractWrapper $wrapped
      * @param string $transClass
+     * @param string $objectClass
      * @return void
      */
-    function removeAssociatedTranslations(AbstractWrapper $wrapped, $transClass);
+    function removeAssociatedTranslations(AbstractWrapper $wrapped, $transClass, $objectClass);
 
     /**
      * Inserts the translation record
@@ -91,4 +94,4 @@ interface TranslatableAdapter extends AdapterInterface
      * @param mixed $value
      */
     function setTranslationValue($object, $field, $value);
-}
+}

+ 9 - 7
lib/Gedmo/Translatable/TranslatableListener.php

@@ -324,7 +324,7 @@ class TranslatableListener extends MappedEventSubscriber
             if (isset($config['fields'])) {
                 $wrapped = AbstractWrapper::wrap($object, $om);
                 $transClass = $this->getTranslationClass($ea, $meta->name);
-                $ea->removeAssociatedTranslations($wrapped, $transClass);
+                $ea->removeAssociatedTranslations($wrapped, $transClass, $config['useObjectClass']);
             }
         }
     }
@@ -372,7 +372,6 @@ class TranslatableListener extends MappedEventSubscriber
         $object = $ea->getObject();
         $meta = $om->getClassMetadata(get_class($object));
         $config = $this->getConfiguration($om, $meta->name);
-        $translationClass = $this->getTranslationClass($ea, $meta->name);
         if (isset($config['fields'])) {
             $locale = $this->getTranslatableLocale($object, $meta);
             $oid = spl_object_hash($object);
@@ -385,10 +384,12 @@ class TranslatableListener extends MappedEventSubscriber
 
         if (isset($config['fields']) && $locale !== $this->defaultLocale) {
             // fetch translations
+            $translationClass = $this->getTranslationClass($ea, $config['useObjectClass']);
             $result = $ea->loadTranslations(
                 $object,
                 $translationClass,
-                $locale
+                $locale,
+                $config['useObjectClass']
             );
             // translate object's translatable properties
             foreach ($config['fields'] as $field) {
@@ -453,7 +454,7 @@ class TranslatableListener extends MappedEventSubscriber
         $meta = $wrapped->getMetadata();
         $config = $this->getConfiguration($om, $meta->name);
         // no need cache, metadata is loaded only once in MetadataFactoryClass
-        $translationClass = $this->getTranslationClass($ea, $meta->name);
+        $translationClass = $this->getTranslationClass($ea, $config['useObjectClass']);
         $translationMetadata = $om->getClassMetadata($translationClass);
 
         // check for the availability of the primary key
@@ -494,7 +495,8 @@ class TranslatableListener extends MappedEventSubscriber
                     $wrapped,
                     $locale,
                     $field,
-                    $translationClass
+                    $translationClass,
+                    $config['useObjectClass']
                 );
             }
             // create new translation if translation not already created and locale is differentent from default locale, otherwise, we have the date in the original record
@@ -508,7 +510,7 @@ class TranslatableListener extends MappedEventSubscriber
                 if ($ea->usesPersonalTranslation($translationClass)) {
                     $translation->setObject($object);
                 } else {
-                    $translation->setObjectClass($meta->name);
+                    $translation->setObjectClass($config['useObjectClass']);
                     $translation->setForeignKey($objectId);
                 }
             }
@@ -559,4 +561,4 @@ class TranslatableListener extends MappedEventSubscriber
             }
         }
     }
-}
+}

+ 40 - 41
tests/Gedmo/Translatable/InheritanceTest.php

@@ -4,8 +4,11 @@ namespace Gedmo\Translatable;
 
 use Doctrine\Common\EventManager;
 use Tool\BaseTestCaseORM;
-use Doctrine\Common\Util\Debug,
-    Translatable\Fixture\TemplatedArticle;
+use Doctrine\ORM\Query;
+use Translatable\Fixture\File;
+use Translatable\Fixture\Image;
+use Translatable\Fixture\TemplatedArticle;
+use Gedmo\Translatable\Query\TreeWalker\TranslationWalker;
 
 /**
  * These are tests for translatable behavior
@@ -22,6 +25,8 @@ class InheritanceTest extends BaseTestCaseORM
     const FILE = 'Translatable\\Fixture\\File';
     const IMAGE = 'Translatable\\Fixture\\Image';
 
+    const TREE_WALKER_TRANSLATION = 'Gedmo\\Translatable\\Query\\TreeWalker\\TranslationWalker';
+
     private $translatableListener;
 
     protected function setUp()
@@ -30,14 +35,17 @@ class InheritanceTest extends BaseTestCaseORM
 
         $evm = new EventManager;
         $this->translatableListener = new TranslatableListener();
-        $this->translatableListener->setTranslatableLocale('en_us');
-        $this->translatableListener->setDefaultLocale('en_us');
+        $this->translatableListener->setTranslatableLocale('en');
+        $this->translatableListener->setDefaultLocale('en');
         $evm->addEventSubscriber($this->translatableListener);
 
         $this->getMockSqliteEntityManager($evm);
     }
 
-    public function testTranslations()
+    /**
+     * @test
+     */
+    function shouldHandleMappedSuperclass()
     {
         $article = new TemplatedArticle();
         $article->setName('name in en');
@@ -56,7 +64,7 @@ class InheritanceTest extends BaseTestCaseORM
 
         // test second translations
         $article = $this->em->getRepository(self::ARTICLE)->find(1);
-        $this->translatableListener->setTranslatableLocale('de_de');
+        $this->translatableListener->setTranslatableLocale('de');
         $article->setName('name in de');
         $article->setContent('content in de');
         $article->setTitle('title in de');
@@ -67,27 +75,28 @@ class InheritanceTest extends BaseTestCaseORM
 
         $translations = $repo->findTranslations($article);
         $this->assertEquals(1, count($translations));
-        $this->assertArrayHasKey('de_de', $translations);
-
-        $this->assertArrayHasKey('name', $translations['de_de']);
-        $this->assertEquals('name in de', $translations['de_de']['name']);
+        $this->assertArrayHasKey('de', $translations);
 
-        $this->assertArrayHasKey('title', $translations['de_de']);
-        $this->assertEquals('title in de', $translations['de_de']['title']);
+        $this->assertArrayHasKey('name', $translations['de']);
+        $this->assertEquals('name in de', $translations['de']['name']);
 
-        $this->assertArrayHasKey('content', $translations['de_de']);
-        $this->assertEquals('content in de', $translations['de_de']['content']);
+        $this->assertArrayHasKey('title', $translations['de']);
+        $this->assertEquals('title in de', $translations['de']['title']);
 
-        $this->translatableListener->setTranslatableLocale('en_us');
+        $this->assertArrayHasKey('content', $translations['de']);
+        $this->assertEquals('content in de', $translations['de']['content']);
     }
 
-    public function testInheritedTable()
+    /**
+     * @test
+     */
+    function shouldHandleInheritedTranslationsThroughBaseObjectClass()
     {
-        $file = new \Translatable\Fixture\File;
+        $file = new File;
         $file->setSize(500);
         $file->setName('file en');
 
-        $image = new \Translatable\Fixture\Image;
+        $image = new Image;
         $image->setMime('mime en');
         $image->setName('image en');
         $image->setSize(445);
@@ -95,13 +104,10 @@ class InheritanceTest extends BaseTestCaseORM
         $this->em->persist($file);
         $this->em->persist($image);
         $this->em->flush();
-        $this->em->clear();
 
-        $this->translatableListener->setTranslatableLocale('de_de');
-        $file = $this->em->getRepository(self::FILE)->findOneByName('file en');
+        $this->translatableListener->setTranslatableLocale('de');
         $file->setName('file de');
 
-        $image = $this->em->getRepository(self::IMAGE)->findOneByName('image en');
         $image->setName('image de');
         $image->setMime('mime de');
 
@@ -109,28 +115,21 @@ class InheritanceTest extends BaseTestCaseORM
         $this->em->persist($image);
         $this->em->flush();
         $this->em->clear();
-        $this->translatableListener->setTranslatableLocale('en_us');
-
-        $repo = $this->em->getRepository(self::TRANSLATION);
-        $this->assertTrue($repo instanceof Entity\Repository\TranslationRepository);
 
-        $translations = $repo->findTranslations($file);
-        $this->assertEquals(1, count($translations));
-
-        $this->assertArrayHasKey('de_de', $translations);
-
-        $this->assertArrayHasKey('name', $translations['de_de']);
-        $this->assertEquals('file de', $translations['de_de']['name']);
-
-        $translations = $repo->findTranslations($image);
-        $this->assertEquals(1, count($translations));
+        $dql = 'SELECT f FROM ' . self::FILE . ' f';
+        $q = $this->em->createQuery($dql);
+        $q->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, self::TREE_WALKER_TRANSLATION);
 
-        $this->assertArrayHasKey('de_de', $translations);
+        $files = $q->getArrayResult();
+        $this->assertEquals(2, count($files));
+        $this->assertEquals('image de', $files[0]['name']);
+        $this->assertEquals('file de', $files[1]['name']);
 
-        $this->assertArrayHasKey('name', $translations['de_de']);
-        $this->assertEquals('image de', $translations['de_de']['name']);
-        $this->assertArrayHasKey('mime', $translations['de_de']);
-        $this->assertEquals('mime de', $translations['de_de']['mime']);
+        // test loading in locale
+        $images = $this->em->getRepository(self::IMAGE)->findAll();
+        $this->assertEquals(1, count($images));
+        $this->assertEquals('image de', $images[0]->getName());
+        $this->assertEquals('mime de', $images[0]->getMime());
     }
 
     protected function getUsedEntityFixtures()