فهرست منبع

[translatable] more usefult translation uery hints, closes #200

Gedi 13 سال پیش
والد
کامیت
4c900aec2d

+ 26 - 12
lib/Gedmo/Translatable/Query/TreeWalker/TranslationWalker.php

@@ -32,28 +32,31 @@ class TranslationWalker extends SqlWalker
 {
     /**
      * Name for translation fallback hint
+     *
+     * @internal
      */
-    const HINT_TRANSLATION_FALLBACKS = 'translation_fallbacks';
+    const HINT_TRANSLATION_FALLBACKS = '__gedmo.translatable.stored.fallbacks';
 
     /**
      * Name for translation listener hint
+     *
+     * @internal
      */
-    const HINT_TRANSLATION_LISTENER = 'translation_listener';
-
-    /**
-     * Customized object hydrator name
-     */
-    const HYDRATE_OBJECT_TRANSLATION = 'object_translation_hydrator';
+    const HINT_TRANSLATION_LISTENER = '__gedmo.translatable.listener';
 
     /**
      * Customized object hydrator name
+     *
+     * @internal
      */
-    const HYDRATE_ARRAY_TRANSLATION = 'array_translation_hydrator';
+    const HYDRATE_OBJECT_TRANSLATION = '__gedmo.translatable.object.hydrator';
 
     /**
      * Customized object hydrator name
+     *
+     * @internal
      */
-    const HYDRATE_SIMPLE_OBJECT_TRANSLATION = 'simple_object_translation_hydrator';
+    const HYDRATE_SIMPLE_OBJECT_TRANSLATION = '__gedmo.translatable.simple_object.hydrator';
 
     /**
      * Stores all component references from select clause
@@ -266,9 +269,15 @@ class TranslationWalker extends SqlWalker
     private function prepareTranslatedComponents()
     {
         $em = $this->getEntityManager();
+        $q = $this->getQuery();
         $ea = new TranslatableEventAdapter;
-        $locale = $this->listener->getListenerLocale();
+        $locale = $q->getHint(TranslationListener::HINT_TRANSLATABLE_LOCALE);
+        if (!$locale) {
+            // use from listener
+            $locale = $this->listener->getListenerLocale();
+        }
         $defaultLocale = $this->listener->getDefaultLocale();
+        $joinStrategy = $q->getHint(TranslationListener::HINT_INNER_JOIN) ? 'INNER' : 'LEFT';
 
         foreach ($this->translatedComponents as $dqlAlias => $comp) {
             $meta = $comp['metadata'];
@@ -281,7 +290,7 @@ class TranslationWalker extends SqlWalker
                     $compTableName = $meta->getQuotedTableName($this->platform);
                     $compTblAlias = $this->getSQLTableAlias($compTableName, $dqlAlias);
                     $tblAlias = $this->getSQLTableAlias('trans'.$compTblAlias.$field);
-                    $sql = ' LEFT JOIN '.$transTable.' '.$tblAlias;
+                    $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)
@@ -317,7 +326,12 @@ class TranslationWalker extends SqlWalker
     private function needsFallback()
     {
         $q = $this->getQuery();
-        return $this->listener->getTranslationFallback()
+        $fallback = $q->getHint(TranslationListener::HINT_FALLBACK);
+        if (false === $fallback) {
+            // non overrided
+            $fallback = $this->listener->getTranslationFallback();
+        }
+        return (bool)$fallback
             && $q->getHydrationMode() !== Query::HYDRATE_SCALAR
             && $q->getHydrationMode() !== Query::HYDRATE_SINGLE_SCALAR;
     }

+ 16 - 0
lib/Gedmo/Translatable/TranslationListener.php

@@ -28,6 +28,22 @@ use Doctrine\Common\EventArgs,
  */
 class TranslationListener extends MappedEventSubscriber
 {
+    /**
+     * Query hint to override the fallback of translations
+     * integer 1 for true, 0 false
+     */
+    const HINT_FALLBACK = 'gedmo.translatable.fallback';
+
+    /**
+     * Query hint to override the fallback locale
+     */
+    const HINT_TRANSLATABLE_LOCALE = 'gedmo.translatable.locale';
+
+    /**
+     * Query hint to use inner join strategy for translations
+     */
+    const HINT_INNER_JOIN = 'gedmo.translatable.inner_join.translations';
+
     /**
      * Locale which is set on this listener.
      * If Entity being translated has locale defined it

+ 55 - 0
tests/Gedmo/Translatable/TranslationQueryWalkerTest.php

@@ -160,6 +160,43 @@ class TranslationQueryWalkerTest extends BaseTestCaseORM
         $this->assertEquals('about food', $result[0]['content']);
     }
 
+    /**
+     * @test
+     */
+    public function shouldBeAbleToUseInnerJoinStrategyForTranslations()
+    {
+        $dql = 'SELECT a FROM ' . self::ARTICLE . ' a';
+        $q = $this->em->createQuery($dql);
+        $q->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, self::TREE_WALKER_TRANSLATION);
+        $q->setHint(TranslationListener::HINT_INNER_JOIN, true);
+
+        $this->translationListener->setTranslatableLocale('ru_ru');
+        $this->translationListener->setTranslationFallback(false);
+
+        // array hydration
+        $result = $q->getArrayResult();
+        $this->assertEquals(0, count($result));
+    }
+
+    /**
+     * @test
+     */
+    public function shouldBeAbleToOverrideTranslatableLocale()
+    {
+        $dql = 'SELECT a FROM ' . self::ARTICLE . ' a';
+        $q = $this->em->createQuery($dql);
+        $q->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, self::TREE_WALKER_TRANSLATION);
+        $q->setHint(TranslationListener::HINT_TRANSLATABLE_LOCALE, 'lt_lt');
+
+        $this->translationListener->setTranslatableLocale('ru_ru');
+        $this->translationListener->setTranslationFallback(false);
+
+        // array hydration
+        $result = $q->getArrayResult();
+        $this->assertEquals(1, count($result));
+        $this->assertEquals('Maistas', $result[0]['title']);
+    }
+
     public function testSelectWithTranslationFallbackOnObjectHydration()
     {
         $this->em
@@ -190,6 +227,24 @@ class TranslationQueryWalkerTest extends BaseTestCaseORM
         //Default translation is en_us, so we expect the results in that locale
         $this->assertEquals('Food', $result[0]->getTitle());
         $this->assertEquals('about food', $result[0]->getContent());
+
+        // test fallback hint
+        $this->translationListener->setTranslationFallback(false);
+        $q->setHint(TranslationListener::HINT_FALLBACK, 1);
+
+        $result = $q->getResult();
+        //Default translation is en_us, so we expect the results in that locale
+        $this->assertEquals('Food', $result[0]->getTitle());
+        $this->assertEquals('about food', $result[0]->getContent());
+
+        // test fallback hint
+        $this->translationListener->setTranslationFallback(true);
+        $q->setHint(TranslationListener::HINT_FALLBACK, 0);
+
+        $result = $q->getResult();
+        //Default translation is en_us, so we expect the results in that locale
+        $this->assertEquals('', $result[0]->getTitle());
+        $this->assertEquals('', $result[0]->getContent());
     }
 
     public function testSelectCountStatement()