浏览代码

Minor fix. Issue #438
- fix for translation repository case
- added test for TranslationRepository
- fixed sequence bug in listenter & amended test to reproduce both situations

Vitaliy Demidov 12 年之前
父节点
当前提交
5587b9a35e

+ 4 - 0
lib/Gedmo/Translatable/Entity/Repository/TranslationRepository.php

@@ -83,6 +83,10 @@ class TranslationRepository extends EntityRepository
                 $transMeta->getReflectionProperty('objectClass')->setValue($trans, $objectClass);
                 $transMeta->getReflectionProperty('field')->setValue($trans, $field);
                 $transMeta->getReflectionProperty('locale')->setValue($trans, $locale);
+                if ($listener->getDefaultLocale() != $listener->getTranslatableLocale($entity, $meta) &&
+                    $locale === $listener->getDefaultLocale()) {
+                    $listener->setTranslationInDefaultLocale(spl_object_hash($entity), $trans);
+                }
             }
             $type = Type::getType($meta->getTypeOfField($field));
             $transformed = $type->convertToDatabaseValue($value, $this->_em->getConnection()->getDatabasePlatform());

+ 60 - 8
lib/Gedmo/Translatable/TranslatableListener.php

@@ -105,6 +105,13 @@ class TranslatableListener extends MappedEventSubscriber
      */
     private $persistDefaultLocaleTranslation = false;
 
+    /**
+     * Tracks translation object for default locale
+     *
+     * @var array
+     */
+    private $translationInDefaultLocale = array();
+
     /**
      * Specifies the list of events to listen
      *
@@ -479,7 +486,6 @@ class TranslatableListener extends MappedEventSubscriber
         $uow = $om->getUnitOfWork();
         $oid = spl_object_hash($object);
         $changeSet = $ea->getObjectChangeSet($uow, $object);
-
         $translatableFields = $config['fields'];
         foreach ($translatableFields as $field) {
             $wasPersistedSeparetely = false;
@@ -489,14 +495,18 @@ class TranslatableListener extends MappedEventSubscriber
                 continue; // locale is same and nothing changed
             }
             $translation = null;
-            $translationInDefaultLocale = null;
+            foreach ($ea->getScheduledObjectInsertions($uow) as $trans) {
+                if ($locale !== $this->defaultLocale
+                    && get_class($trans) === $translationClass
+                    && $trans->getLocale() === $this->defaultLocale
+                    && $trans->getObject() === $object) {
+                    $this->setTranslationInDefaultLocale($oid, $trans);
+                    break;
+                }
+            }
             // lookup persisted translations
             if ($ea->usesPersonalTranslation($translationClass)) {
                 foreach ($ea->getScheduledObjectInsertions($uow) as $trans) {
-                    if ($locale !== $this->defaultLocale && get_class($trans) === $translationClass &&
-                        $trans->getLocale() === $this->defaultLocale) {
-                        $translationInDefaultLocale = $trans;
-                    }
                     $wasPersistedSeparetely = get_class($trans) === $translationClass
                         && $trans->getLocale() === $locale
                         && $trans->getField() === $field
@@ -559,12 +569,13 @@ class TranslatableListener extends MappedEventSubscriber
                 }
             }
 
-            if ($isInsert && $translationInDefaultLocale !== null) {
+            if ($isInsert && $this->getTranslationInDefaultLocale($oid) !== null) {
                 // We can't rely on object field value which is created in non default locale.
                 // If we provide translation for default locale as well, the latter is considered to be trusted
                 // and object content should be overridden.
-                $wrapped->setPropertyValue($field, $translationInDefaultLocale->getContent());
+                $wrapped->setPropertyValue($field, $this->getTranslationInDefaultLocale($oid)->getContent());
                 $ea->recomputeSingleObjectChangeset($uow, $meta, $object);
+                $this->removeTranslationInDefaultLocale($oid);
             }
         }
         $this->translatedInLocale[$oid] = $locale;
@@ -594,4 +605,45 @@ class TranslatableListener extends MappedEventSubscriber
             }
         }
     }
+
+    /**
+     * Sets translation object which represents translation in default language.
+     *
+     * @param    string    $oid     hash of basic entity
+     * @param    mixed     $trans   Translation object
+     */
+    public function setTranslationInDefaultLocale($oid, $trans)
+    {
+        $this->translationInDefaultLocale[$oid] = $trans;
+    }
+
+    /**
+     * Removes translation object which represents translation in default language.
+     * This is for internal use only.
+     *
+     * @param string    $oid     hash of the basic entity
+     */
+    private function removeTranslationInDefaultLocale($oid)
+    {
+        if (isset($this->translationInDefaultLocale[$oid])) {
+            unset($this->translationInDefaultLocale[$oid]);
+        }
+    }
+
+    /**
+     * Gets translation object which represents translation in default language.
+     * This is for internal use only.
+     *
+     * @param    string    $oid   hash of the basic entity
+     * @return   mixed     Returns translation object if it exists or NULL otherwise
+     */
+    private function getTranslationInDefaultLocale($oid)
+    {
+        if (array_key_exists($oid, $this->translationInDefaultLocale)) {
+            $ret = $this->translationInDefaultLocale[$oid];
+        } else {
+            $ret = null;
+        }
+        return $ret;
+    }
 }

+ 29 - 0
tests/Gedmo/Translatable/EntityTranslationTableTest.php

@@ -72,6 +72,35 @@ class EntityTranslationTableTest extends BaseTestCaseORM
         $this->translatableListener->setTranslatableLocale('en_us');
     }
 
+    /**
+     * Covers issue #438
+     * @test
+     */
+    function shouldPersistDefaultLocaleValue()
+    {
+        $this->translatableListener->setPersistDefaultLocaleTranslation(true);
+        $this->translatableListener->setTranslatableLocale('de');
+        $person = new Person;
+        $person->setName('de');
+
+        $repo = $this->em->getRepository(self::TRANSLATION);
+        $repo
+            ->translate($person, 'name', 'de', 'de')
+            ->translate($person, 'name', 'en_us', 'en_us')
+        ;
+        $this->em->persist($person);
+        $this->em->flush();
+
+        $this->translatableListener->setTranslatableLocale('en_us');
+        $articles = $this->em->createQuery('SELECT p FROM ' . self::PERSON . ' p')->getArrayResult();
+        $this->assertEquals('en_us', $articles[0]['name']);
+        $trans = $this->em->createQuery('SELECT t FROM ' . self::TRANSLATION . ' t')->getArrayResult();
+        $this->assertCount(2, $trans);
+        foreach ($trans as $item) {
+            $this->assertEquals($item['locale'], $item['content']);
+        }
+    }
+
     protected function getUsedEntityFixtures()
     {
         return array(

+ 9 - 12
tests/Gedmo/Translatable/PersonalTranslationTest.php

@@ -134,19 +134,9 @@ class PersonalTranslationTest extends BaseTestCaseORM
     function shouldPersistDefaultLocaleValue()
     {
         $this->translatableListener->setTranslatableLocale('de');
-        $this->translatableListener->setDefaultLocale('en');
         $article = new Article;
         $article->setTitle('de');
 
-        $enTranslation = new PersonalArticleTranslation;
-        $enTranslation
-            ->setField('title')
-            ->setContent('en')
-            ->setObject($article)
-            ->setLocale('en')
-        ;
-        $this->em->persist($enTranslation);
-
         $deTranslation = new PersonalArticleTranslation;
         $deTranslation
             ->setField('title')
@@ -156,13 +146,20 @@ class PersonalTranslationTest extends BaseTestCaseORM
         ;
         $this->em->persist($deTranslation);
 
+        $enTranslation = new PersonalArticleTranslation;
+        $enTranslation
+            ->setField('title')
+            ->setContent('en')
+            ->setObject($article)
+            ->setLocale('en')
+        ;
+        $this->em->persist($enTranslation);
+
         $this->em->persist($article);
         $this->em->flush();
 
-        $this->startQueryLog();
         $this->translatableListener->setTranslatableLocale('en');
         $articles = $this->em->createQuery('SELECT t FROM '.self::ARTICLE.' t')->getArrayResult();
-        $sqlQueriesExecuted = $this->queryAnalyzer->getExecutedQueries();
         $this->assertEquals('en', $articles[0]['title']);
         $trans = $this->em->createQuery('SELECT t FROM '.self::TRANSLATION.' t')->getArrayResult();
         $this->assertCount(2, $trans);