ソースを参照

Merge pull request #225 from denis-chmel/master

Please pull the fix of localizible integers sort order
Gediminas Morkevicius 13 年 前
コミット
5878e20861

+ 38 - 31
lib/Gedmo/Translatable/Query/TreeWalker/TranslationWalker.php

@@ -251,15 +251,19 @@ class TranslationWalker extends SqlWalker
      */
     private function prepareTranslatedComponents()
     {
-        $em = $this->getEntityManager();
         $q = $this->getQuery();
-        $ea = new TranslatableEventAdapter;
         $locale = $q->getHint(TranslationListener::HINT_TRANSLATABLE_LOCALE);
         if (!$locale) {
             // use from listener
             $locale = $this->listener->getListenerLocale();
         }
         $defaultLocale = $this->listener->getDefaultLocale();
+        if ($locale === $defaultLocale) {
+            // Skip preparation as there's no need to translate anything
+            return;
+        }
+        $em = $this->getEntityManager();
+        $ea = new TranslatableEventAdapter;
         $joinStrategy = $q->getHint(TranslationListener::HINT_INNER_JOIN) ? 'INNER' : 'LEFT';
 
         foreach ($this->translatedComponents as $dqlAlias => $comp) {
@@ -268,35 +272,38 @@ class TranslationWalker extends SqlWalker
             $transClass = $this->listener->getTranslationClass($ea, $meta->name);
             $transMeta = $em->getClassMetadata($transClass);
             $transTable = $transMeta->getQuotedTableName($this->platform);
-            if ($locale !== $defaultLocale) {
-                foreach ($config['fields'] as $field) {
-                    $compTableName = $meta->getQuotedTableName($this->platform);
-                    $compTblAlias = $this->getSQLTableAlias($compTableName, $dqlAlias);
-                    $tblAlias = $this->getSQLTableAlias('trans'.$compTblAlias.$field);
-                    $sql = " {$joinStrategy} JOIN ".$transTable.' '.$tblAlias;
-                    $sql .= ' ON '.$tblAlias.'.'.$transMeta->getQuotedColumnName('locale', $this->platform)
-                        .' = '.$this->conn->quote($locale);
-                    $sql .= ' AND '.$tblAlias.'.'.$transMeta->getQuotedColumnName('objectClass', $this->platform)
-                        .' = '.$this->conn->quote($meta->name);
-                    $sql .= ' AND '.$tblAlias.'.'.$transMeta->getQuotedColumnName('field', $this->platform)
-                        .' = '.$this->conn->quote($field);
-                    $identifier = $meta->getSingleIdentifierFieldName();
-                    $colName = $meta->getQuotedColumnName($identifier, $this->platform);
-                    $sql .= ' AND '.$tblAlias.'.'.$transMeta->getQuotedColumnName('foreignKey', $this->platform)
-                        .' = '.$compTblAlias.'.'.$colName;
-                    isset($this->components[$dqlAlias]) ? $this->components[$dqlAlias] .= $sql : $this->components[$dqlAlias] = $sql;
-                    if ($this->needsFallback()) {
-                        // COALESCE with the original record columns
-                        $this->replacements[$compTblAlias.'.'.$meta->getQuotedColumnName($field, $this->platform)]
-                            = 'COALESCE('.$tblAlias.'.'.$transMeta->getQuotedColumnName('content', $this->platform)
-                            .', '.$compTblAlias.'.'.$meta->getQuotedColumnName($field, $this->platform).')'
-                        ;
-                    } else {
-                        $this->replacements[$compTblAlias.'.'.$meta->getQuotedColumnName($field, $this->platform)]
-                            = $tblAlias.'.'.$transMeta->getQuotedColumnName('content', $this->platform)
-                        ;
-                    }
+            foreach ($config['fields'] as $field) {
+                $compTableName = $meta->getQuotedTableName($this->platform);
+                $compTblAlias = $this->getSQLTableAlias($compTableName, $dqlAlias);
+                $tblAlias = $this->getSQLTableAlias('trans'.$compTblAlias.$field);
+                $sql = " {$joinStrategy} JOIN ".$transTable.' '.$tblAlias;
+                $sql .= ' ON '.$tblAlias.'.'.$transMeta->getQuotedColumnName('locale', $this->platform)
+                    .' = '.$this->conn->quote($locale);
+                $sql .= ' AND '.$tblAlias.'.'.$transMeta->getQuotedColumnName('objectClass', $this->platform)
+                    .' = '.$this->conn->quote($meta->name);
+                $sql .= ' AND '.$tblAlias.'.'.$transMeta->getQuotedColumnName('field', $this->platform)
+                    .' = '.$this->conn->quote($field);
+                $identifier = $meta->getSingleIdentifierFieldName();
+                $colName = $meta->getQuotedColumnName($identifier, $this->platform);
+                $sql .= ' AND '.$tblAlias.'.'.$transMeta->getQuotedColumnName('foreignKey', $this->platform)
+                    .' = '.$compTblAlias.'.'.$colName;
+                isset($this->components[$dqlAlias]) ? $this->components[$dqlAlias] .= $sql : $this->components[$dqlAlias] = $sql;
+
+                $originalField = $compTblAlias.'.'.$meta->getQuotedColumnName($field, $this->platform);
+                $substituteField = $tblAlias . '.' . $transMeta->getQuotedColumnName('content', $this->platform);
+
+                // If original field is integer - treat translation as integer (for ORDER BY, WHERE, etc)
+                $fieldMapping = $meta->getFieldMapping($field);
+                if (in_array($fieldMapping["type"], array("integer", "bigint", "tinyint", "int"))) {
+                    $substituteField = 'CAST(' . $substituteField . ' AS SIGNED)';
                 }
+
+                // Fallback to original if was asked for
+                if ($this->needsFallback()) {
+                    $substituteField = 'COALESCE('.$substituteField.', '.$originalField.')';
+                }
+
+                $this->replacements[$originalField] = $substituteField;
             }
         }
     }
@@ -385,4 +392,4 @@ class TranslationWalker extends SqlWalker
         }
         return $str;
     }
-}
+}

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

@@ -26,6 +26,12 @@ class Article implements Translatable
      */
     private $content;
 
+    /**
+     * @Gedmo\Translatable
+     * @ORM\Column(name="views", type="integer", nullable=true)
+     */
+    private $views;
+
     /**
      * Used locale to override Translation listener`s locale
      * @Gedmo\Locale
@@ -77,4 +83,14 @@ class Article implements Translatable
     {
         $this->locale = $locale;
     }
-}
+
+    public function setViews ($views)
+    {
+        $this->views = $views;
+    }
+
+    public function getViews ()
+    {
+        return $this->views;
+    }
+}

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

@@ -348,6 +348,39 @@ class TranslationQueryWalkerTest extends BaseTestCaseORM
         $this->assertEquals('Moteris', $result[3]->getTitle());
     }
 
+    public function testSelectOrderedByTranslatableInteger()
+    {
+        // Given
+        $this->populateMore();
+        $dql = 'SELECT a.title, a.views FROM ' . self::ARTICLE . ' a';
+        $dql .= ' ORDER BY a.views';
+        $q = $this->em->createQuery($dql);
+        $q->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, self::TREE_WALKER_TRANSLATION);
+
+        // Test original
+        $this->translationListener->setTranslatableLocale('en_us');
+        $result = $q->getArrayResult();
+        array_walk($result, function($value, $key) use(&$result) {
+            // Make each record be a "Title - Views" string
+            $result[$key] = implode(" - ", $value);
+        });
+        $this->assertEquals(
+            array("Alfabet - 1", "Food - 99", "Cabbages - 2222", "Woman - 3333"), $result,
+            "Original of localizible integers should be sorted numerically"
+        );
+
+        $this->translationListener->setTranslatableLocale('lt_lt');
+        $result = $q->getArrayResult();
+        array_walk($result, function($value, $key) use(&$result) {
+            // Make each record be a "Title - Views" string
+            $result[$key] = implode(" - ", $value);
+        });
+        $this->assertEquals(
+            array("Moteris - 33", "Alfabetas - 111", "Maistas - 999", "Kopustai - 22222"), $result,
+            "Localized integers should be sorted numerically"
+        );
+    }
+
     public function testSelectSecondJoinedComponentTranslation()
     {
         $this->em
@@ -367,7 +400,7 @@ class TranslationQueryWalkerTest extends BaseTestCaseORM
         $result = $q->getArrayResult();
         $this->assertEquals(1, count($result));
         $food = $result[0];
-        $this->assertEquals(4, count($food));
+        $this->assertEquals(5, count($food));
         $this->assertEquals('Food', $food['title']);
         $this->assertEquals('about food', $food['content']);
         $comments = $food['comments'];
@@ -385,7 +418,7 @@ class TranslationQueryWalkerTest extends BaseTestCaseORM
         $result = $q->getArrayResult();
         $this->assertEquals(1, count($result));
         $food = $result[0];
-        $this->assertEquals(4, count($food));
+        $this->assertEquals(5, count($food));
         $this->assertEquals('Maistas', $food['title']);
         $this->assertEquals('apie maista', $food['content']);
         $comments = $food['comments'];
@@ -492,14 +525,14 @@ class TranslationQueryWalkerTest extends BaseTestCaseORM
         $result = $q->getArrayResult();
         $this->assertEquals(1, count($result));
         $food = $result[0];
-        $this->assertEquals(3, count($food));
+        $this->assertEquals(4, count($food));
         $this->assertEquals('Food', $food['title']);
         $this->assertEquals('about food', $food['content']);
         $this->translationListener->setTranslatableLocale('lt_lt');
         $result = $q->getArrayResult();
         $this->assertEquals(1, count($result));
         $food = $result[0];
-        $this->assertEquals(3, count($food));
+        $this->assertEquals(4, count($food));
         $this->assertEquals('Maistas', $food['title']);
         $this->assertEquals('apie maista', $food['content']);
 
@@ -556,14 +589,17 @@ class TranslationQueryWalkerTest extends BaseTestCaseORM
         $alfabet = new Article;
         $alfabet->setTitle('Alfabet');
         $alfabet->setContent('hey wtf!');
+        $alfabet->setViews(1);
 
         $woman = new Article;
         $woman->setTitle('Woman');
         $woman->setContent('i like them');
+        $woman->setViews(3333);
 
         $cabbages = new Article;
         $cabbages->setTitle('Cabbages');
         $cabbages->setContent('where went the woman?');
+        $cabbages->setViews(2222);
 
         $this->em->persist($alfabet);
         $this->em->persist($woman);
@@ -575,14 +611,17 @@ class TranslationQueryWalkerTest extends BaseTestCaseORM
         $alfabet = $repo->find(2);
         $alfabet->setTitle('Alfabetas');
         $alfabet->setContent('ei wtf!');
+        $alfabet->setViews(111);
 
         $woman = $repo->find(3);
         $woman->setTitle('Moteris');
         $woman->setContent('as megstu jas');
+        $woman->setViews(33);
 
         $cabbages = $repo->find(4);
         $cabbages->setTitle('Kopustai');
         $cabbages->setContent('kur dingo moteris?');
+        $cabbages->setViews(22222);
 
         $this->em->persist($alfabet);
         $this->em->persist($woman);
@@ -599,6 +638,7 @@ class TranslationQueryWalkerTest extends BaseTestCaseORM
         $food = new Article;
         $food->setTitle('Food');
         $food->setContent('about food');
+        $food->setViews(99);
 
         $goodFood = new Comment;
         $goodFood->setArticle($food);
@@ -620,6 +660,7 @@ class TranslationQueryWalkerTest extends BaseTestCaseORM
         $food = $repo->find(1);
         $food->setTitle('Maistas');
         $food->setContent('apie maista');
+        $food->setViews(999);
 
         $goodFood = $commentRepo->find(1);
         $goodFood->setArticle($food);