浏览代码

Merge pull request #372 from mitrae/master

Pull request: "fallback" option for Translatable annotation
Gediminas Morkevicius 13 年之前
父节点
当前提交
9ed48efd28

+ 2 - 1
lib/Gedmo/Mapping/Annotation/Translatable.php

@@ -18,6 +18,7 @@ use Doctrine\Common\Annotations\Annotation;
  */
 final class Translatable extends Annotation
 {
-
+    /** @var boolean */
+    public $fallback;
 }
 

+ 3 - 0
lib/Gedmo/Translatable/Mapping/Driver/Annotation.php

@@ -97,6 +97,9 @@ class Annotation implements AnnotationDriverInterface
                 }
                 // fields cannot be overrided and throws mapping exception
                 $config['fields'][] = $field;
+                if (isset($translatable->fallback)) {
+                    $config['fallback'][$field] = $translatable->fallback;
+                }
             }
             // locale property
             if ($locale = $this->reader->getPropertyAnnotation($property, self::LOCALE)) {

+ 5 - 0
lib/Gedmo/Translatable/Mapping/Driver/Xml.php

@@ -63,6 +63,11 @@ class Xml extends BaseXml
                 $field = $this->_getAttribute($mappingDoctrine, 'name');
                 if (isset($mapping->translatable)) {
                     $config['fields'][] = $field;
+                    /** @var \SimpleXmlElement $data */
+                    $data = $mapping->translatable;
+                    if ($this->_isAttributeSet($data, 'fallback')) {
+                        $config['fallback'][$field] = 'true' == $this->_getAttribute($data, 'fallback') ? true : false;
+                    }
                 }
             }
         }

+ 4 - 1
lib/Gedmo/Translatable/Mapping/Driver/Yaml.php

@@ -51,9 +51,12 @@ class Yaml extends File implements Driver
         if (isset($mapping['fields'])) {
             foreach ($mapping['fields'] as $field => $fieldMapping) {
                 if (isset($fieldMapping['gedmo'])) {
-                    if (in_array('translatable', $fieldMapping['gedmo'])) {
+                    if (in_array('translatable', $fieldMapping['gedmo']) || isset($fieldMapping['gedmo']['translatable'])) {
                         // fields cannot be overrided and throws mapping exception
                         $config['fields'][] = $field;
+                        if (isset($fieldMapping['gedmo']['translatable']['fallback'])) {
+                            $config['fallback'][$field] = $fieldMapping['gedmo']['translatable']['fallback'];
+                        }
                     }
                 }
             }

+ 3 - 1
lib/Gedmo/Translatable/Query/TreeWalker/TranslationWalker.php

@@ -305,7 +305,9 @@ class TranslationWalker extends SqlWalker
                 }
 
                 // Fallback to original if was asked for
-                if ($this->needsFallback()) {
+                if (($this->needsFallback() && (!isset($config['fallback'][$field]) || $config['fallback'][$field]))
+                    ||  (!$this->needsFallback() && isset($config['fallback'][$field]) && $config['fallback'][$field])
+                ) {
                     $substituteField = 'COALESCE('.$substituteField.', '.$originalField.')';
                 }
 

+ 4 - 1
lib/Gedmo/Translatable/TranslatableListener.php

@@ -412,7 +412,10 @@ class TranslatableListener extends MappedEventSubscriber
                     }
                 }
                 // update translation
-                if ($translated || !$this->translationFallback) {
+                if ($translated
+                    || (!$this->translationFallback && (!isset($config['fallback'][$field]) || !$config['fallback'][$field]))
+                    || ($this->translationFallback && isset($config['fallback'][$field]) && !$config['fallback'][$field])
+                ) {
                     $ea->setTranslationValue($object, $field, $translated);
                     // ensure clean changeset
                     $ea->setOriginalObjectProperty(

+ 5 - 1
schemas/orm/doctrine-extensions-mapping-2-1.xsd

@@ -67,7 +67,7 @@ people to push their own additional attributes/elements into the same field elem
   <!-- field -->
   <xs:element name="sluggable" type="gedmo:sluggable"/>
   <xs:element name="slug" type="gedmo:slug"/>
-  <xs:element name="translatable" type="gedmo:emptyType"/>
+  <xs:element name="translatable" type="gedmo:translatable"/>
   <xs:element name="timestampable" type="gedmo:timestampable"/>
   <xs:element name="versioned" type="gedmo:emptyType"/>
   <xs:element name="tree-left" type="gedmo:emptyType"/>
@@ -119,6 +119,10 @@ people to push their own additional attributes/elements into the same field elem
     <xs:attribute name="value" type="xs:string" use="optional" />
   </xs:complexType>
 
+  <xs:complexType name="translatable">
+    <xs:attribute name="fallback" type="xs:boolean" use="optional" />
+  </xs:complexType>
+
   <xs:complexType name="emptyType">
   </xs:complexType>
 

+ 5 - 1
schemas/orm/doctrine-extensions-mapping-2-2.xsd

@@ -29,7 +29,7 @@ people to push their own additional attributes/elements into the same field elem
   <xs:element name="soft-deleteable" type="gedmo:soft-deleteable"/>
   <!-- field -->
   <xs:element name="slug" type="gedmo:slug"/>
-  <xs:element name="translatable" type="gedmo:emptyType"/>
+  <xs:element name="translatable" type="gedmo:translatable"/>
   <xs:element name="timestampable" type="gedmo:timestampable"/>
   <xs:element name="versioned" type="gedmo:emptyType"/>
   <xs:element name="tree-left" type="gedmo:emptyType"/>
@@ -99,6 +99,10 @@ people to push their own additional attributes/elements into the same field elem
     <xs:attribute name="value" type="xs:string" use="optional" />
   </xs:complexType>
 
+  <xs:complexType name="translatable">
+    <xs:attribute name="fallback" type="xs:boolean" use="optional" />
+  </xs:complexType>
+
   <xs:complexType name="emptyType">
   </xs:complexType>
 

+ 6 - 0
tests/Gedmo/Mapping/Driver/Xml/Mapping.Fixture.Xml.Translatable.dcm.xml

@@ -15,6 +15,12 @@
         <field name="content" type="text">
             <gedmo:translatable/>
         </field>
+        <field name="author" type="text">
+            <gedmo:translatable fallback="true"/>
+        </field>
+        <field name="views" type="text">
+            <gedmo:translatable fallback="false"/>
+        </field>
 
         <gedmo:translation entity="Gedmo\Translatable\Entity\Translation" locale="locale"/>
 

+ 6 - 0
tests/Gedmo/Mapping/Driver/Yaml/Mapping.Fixture.Yaml.User.dcm.yml

@@ -22,6 +22,12 @@ Mapping\Fixture\Yaml\User:
       length: 128
       gedmo:
         - translatable
+    company:
+      type: string
+      length: 128
+      gedmo:
+        translatable:
+          fallback: true
   indexes:
     search_idx:
       columns: username

+ 4 - 0
tests/Gedmo/Mapping/Fixture/Xml/Translatable.php

@@ -11,4 +11,8 @@ class Translatable
     private $content;
 
     private $locale;
+
+    private $author;
+
+    private $views;
 }

+ 22 - 0
tests/Gedmo/Mapping/Fixture/Yaml/User.php

@@ -10,6 +10,8 @@ class User
 
     private $username;
 
+    private $company;
+
     private $localeField;
     /**
      * Get id
@@ -60,4 +62,24 @@ class User
     {
         return $this->username;
     }
+
+    /**
+     * Set company
+     *
+     * @param $company
+     */
+    public function setCompany($company)
+    {
+        $this->company = $company;
+    }
+
+    /**
+     * Get company
+     *
+     * @return string $company
+     */
+    public function getCompany()
+    {
+        return $this->company;
+    }
 }

+ 3 - 1
tests/Gedmo/Mapping/TranslatableMappingTest.php

@@ -60,10 +60,12 @@ class TranslatableMappingTest extends \PHPUnit_Framework_TestCase
         $this->assertArrayHasKey('translationClass', $config);
         $this->assertEquals('Translatable\Fixture\PersonTranslation', $config['translationClass']);
         $this->assertArrayHasKey('fields', $config);
-        $this->assertCount(2, $config['fields']);
+        $this->assertCount(3, $config['fields']);
         $this->assertEquals('password', $config['fields'][0]);
         $this->assertEquals('username', $config['fields'][1]);
         $this->assertArrayHasKey('locale', $config);
         $this->assertEquals('localeField', $config['locale']);
+        $this->assertCount(1, $config['fallback']);
+        $this->assertTrue($config['fallback']['company']);
     }
 }

+ 5 - 1
tests/Gedmo/Mapping/Xml/TranslatableMappingTest.php

@@ -64,8 +64,12 @@ class TranslatableMappingTest extends BaseTestCaseOM
         $this->assertEquals('locale', $config['locale']);
 
         $this->assertArrayHasKey('fields', $config);
-        $this->assertCount(2, $config['fields']);
+        $this->assertCount(4, $config['fields']);
         $this->assertTrue(in_array('title', $config['fields']));
         $this->assertTrue(in_array('content', $config['fields']));
+        $this->assertTrue(in_array('author', $config['fields']));
+        $this->assertTrue(in_array('views', $config['fields']));
+        $this->assertTrue($config['fallback']['author']);
+        $this->assertFalse($config['fallback']['views']);
     }
 }

+ 17 - 1
tests/Gedmo/Translatable/Fixture/Article.php

@@ -27,11 +27,17 @@ class Article implements Translatable
     private $content;
 
     /**
-     * @Gedmo\Translatable
+     * @Gedmo\Translatable(fallback=false)
      * @ORM\Column(name="views", type="integer", nullable=true)
      */
     private $views;
 
+    /**
+     * @Gedmo\Translatable(fallback=true)
+     * @ORM\Column(name="author", type="string", nullable=true)
+     */
+    private $author;
+
     /**
      * Used locale to override Translation listener`s locale
      * @Gedmo\Locale
@@ -93,4 +99,14 @@ class Article implements Translatable
     {
         return $this->views;
     }
+
+    public function setAuthor($author)
+    {
+        $this->author = $author;
+    }
+
+    public function getAuthor()
+    {
+        return $this->author;
+    }
 }

+ 30 - 0
tests/Gedmo/Translatable/TranslatableTest.php

@@ -247,6 +247,36 @@ class TranslatableTest extends BaseTestCaseORM
         $this->assertCount(1, $translations);
     }
 
+    /**
+     * @test
+     */
+    function shouldRespectFallbackOption()
+    {
+        $article = new Article;
+        $article->setTitle('Euro2012');
+        $article->setAuthor('Shevchenko');
+        $article->setViews(10);
+
+        $this->em->persist($article);
+        $this->em->flush();
+        $this->em->clear();
+
+        $this->translatableListener->setTranslatableLocale('ua_UA');
+        $this->translatableListener->setTranslationFallback(true);
+        $article = $this->em->find(self::ARTICLE, $article->getId());
+
+        $this->assertEquals('Euro2012', $article->getTitle());
+        $this->assertEquals('Shevchenko', $article->getAuthor());
+        $this->assertEmpty($article->getViews());
+
+        $this->em->clear();
+        $this->translatableListener->setTranslationFallback(false);
+        $article = $this->em->find(self::ARTICLE, $article->getId());
+        $this->assertEmpty($article->getTitle());
+        $this->assertEquals('Shevchenko', $article->getAuthor());
+        $this->assertEmpty($article->getViews());
+    }
+
     protected function getUsedEntityFixtures()
     {
         return array(

+ 39 - 4
tests/Gedmo/Translatable/TranslationQueryWalkerTest.php

@@ -187,6 +187,40 @@ class TranslationQueryWalkerTest extends BaseTestCaseORM
         $this->assertEquals('about food', $result[0]['content']);
     }
 
+    public function testSelectWithOptionalFallbackOnSimpleObjectHydration()
+    {
+        $this->em
+            ->getConfiguration()
+            ->expects($this->any())
+            ->method('getCustomHydrationMode')
+            ->with(TranslationWalker::HYDRATE_SIMPLE_OBJECT_TRANSLATION)
+            ->will($this->returnValue('Gedmo\\Translatable\\Hydrator\\ORM\\SimpleObjectHydrator'));
+
+        $dql = 'SELECT a FROM ' . self::ARTICLE . ' a';
+        $q = $this->em->createQuery($dql);
+        $q->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, self::TREE_WALKER_TRANSLATION);
+
+        $this->translatableListener->setTranslatableLocale('ru_ru');
+        $this->translatableListener->setTranslationFallback(false);
+
+        // simple object hydration
+        $this->startQueryLog();
+        $result = $q->getResult(Query::HYDRATE_SIMPLEOBJECT);
+        $this->assertEquals(1, $this->queryAnalyzer->getNumExecutedQueries());
+        $this->assertEquals('', $result[0]->getTitle());
+        $this->assertEquals('John Doe', $result[0]->getAuthor()); // optional fallback is true,  force fallback
+        $this->assertEquals(0, $result[0]->getViews());
+
+        $this->translatableListener->setTranslationFallback(true);
+        $this->queryAnalyzer->cleanUp();
+        $result = $q->getResult(Query::HYDRATE_SIMPLEOBJECT);
+        $this->assertEquals(1, $this->queryAnalyzer->getNumExecutedQueries());
+        //Default translation is en_us, so we expect the results in that locale
+        $this->assertEquals('Food', $result[0]->getTitle());
+        $this->assertEquals('John Doe', $result[0]->getAuthor());
+        $this->assertEquals(0, $result[0]->getViews()); // optional fallback is false,  thus no translation required
+    }
+
     /**
      * @test
      */
@@ -400,7 +434,7 @@ class TranslationQueryWalkerTest extends BaseTestCaseORM
         $result = $q->getArrayResult();
         $this->assertCount(1, $result);
         $food = $result[0];
-        $this->assertCount(5, $food);
+        $this->assertCount(6, $food);
         $this->assertEquals('Food', $food['title']);
         $this->assertEquals('about food', $food['content']);
         $comments = $food['comments'];
@@ -418,7 +452,7 @@ class TranslationQueryWalkerTest extends BaseTestCaseORM
         $result = $q->getArrayResult();
         $this->assertCount(1, $result);
         $food = $result[0];
-        $this->assertCount(5, $food);
+        $this->assertCount(6, $food);
         $this->assertEquals('Maistas', $food['title']);
         $this->assertEquals('apie maista', $food['content']);
         $comments = $food['comments'];
@@ -525,14 +559,14 @@ class TranslationQueryWalkerTest extends BaseTestCaseORM
         $result = $q->getArrayResult();
         $this->assertCount(1, $result);
         $food = $result[0];
-        $this->assertCount(4, $food);
+        $this->assertCount(5, $food);
         $this->assertEquals('Food', $food['title']);
         $this->assertEquals('about food', $food['content']);
         $this->translatableListener->setTranslatableLocale('lt_lt');
         $result = $q->getArrayResult();
         $this->assertCount(1, $result);
         $food = $result[0];
-        $this->assertCount(4, $food);
+        $this->assertCount(5, $food);
         $this->assertEquals('Maistas', $food['title']);
         $this->assertEquals('apie maista', $food['content']);
 
@@ -638,6 +672,7 @@ class TranslationQueryWalkerTest extends BaseTestCaseORM
         $food = new Article;
         $food->setTitle('Food');
         $food->setContent('about food');
+        $food->setAuthor('John Doe');
         $food->setViews(99);
 
         $goodFood = new Comment;