Jelajahi Sumber

[translatable] fix translation query walker to support query cache, closes #207

gedi 13 tahun lalu
induk
melakukan
57c69b05e7

+ 30 - 3
lib/Gedmo/Translatable/Hydrator/ORM/ObjectHydrator.php

@@ -2,7 +2,7 @@
 
 namespace Gedmo\Translatable\Hydrator\ORM;
 
-use Gedmo\Translatable\Query\TreeWalker\TranslationWalker;
+use Gedmo\Translatable\TranslationListener;
 use Doctrine\ORM\Internal\Hydration\ObjectHydrator as BaseObjectHydrator;
 
 /**
@@ -25,7 +25,7 @@ class ObjectHydrator extends BaseObjectHydrator
      */
     protected function _hydrateAll()
     {
-        $listener = $this->_hints[TranslationWalker::HINT_TRANSLATION_LISTENER];
+        $listener = $this->getTranslationListener();
         $listener->setSkipOnLoad(true);
         $result = parent::_hydrateAll();
         $listener->setSkipOnLoad(false);
@@ -38,10 +38,37 @@ class ObjectHydrator extends BaseObjectHydrator
      */
     protected function hydrateAllData()
     {
-        $listener = $this->_hints[TranslationWalker::HINT_TRANSLATION_LISTENER];
+        $listener = $this->getTranslationListener();
         $listener->setSkipOnLoad(true);
         $result = parent::hydrateAllData();
         $listener->setSkipOnLoad(false);
         return $result;
     }
+
+    /**
+     * Get the currently used TranslationListener
+     *
+     * @throws \Gedmo\Exception\RuntimeException - if listener is not found
+     * @return TranslationListener
+     */
+    protected function getTranslationListener()
+    {
+        $translationListener = null;
+        foreach ($this->_em->getEventManager()->getListeners() as $event => $listeners) {
+            foreach ($listeners as $hash => $listener) {
+                if ($listener instanceof TranslationListener) {
+                    $translationListener = $listener;
+                    break;
+                }
+            }
+            if ($translationListener) {
+                break;
+            }
+        }
+
+        if (is_null($translationListener)) {
+            throw new \Gedmo\Exception\RuntimeException('The translation listener could not be found');
+        }
+        return $translationListener;
+    }
 }

+ 30 - 3
lib/Gedmo/Translatable/Hydrator/ORM/SimpleObjectHydrator.php

@@ -2,7 +2,7 @@
 
 namespace Gedmo\Translatable\Hydrator\ORM;
 
-use Gedmo\Translatable\Query\TreeWalker\TranslationWalker;
+use Gedmo\Translatable\TranslationListener;
 use Doctrine\ORM\Internal\Hydration\SimpleObjectHydrator as BaseSimpleObjectHydrator;
 
 /**
@@ -25,7 +25,7 @@ class SimpleObjectHydrator extends BaseSimpleObjectHydrator
      */
     protected function _hydrateAll()
     {
-        $listener = $this->_hints[TranslationWalker::HINT_TRANSLATION_LISTENER];
+        $listener = $this->getTranslationListener();
         $listener->setSkipOnLoad(true);
         $result = parent::_hydrateAll();
         $listener->setSkipOnLoad(false);
@@ -38,10 +38,37 @@ class SimpleObjectHydrator extends BaseSimpleObjectHydrator
      */
     protected function hydrateAllData()
     {
-        $listener = $this->_hints[TranslationWalker::HINT_TRANSLATION_LISTENER];
+        $listener = $this->getTranslationListener();
         $listener->setSkipOnLoad(true);
         $result = parent::hydrateAllData();
         $listener->setSkipOnLoad(false);
         return $result;
     }
+
+    /**
+     * Get the currently used TranslationListener
+     *
+     * @throws \Gedmo\Exception\RuntimeException - if listener is not found
+     * @return TranslationListener
+     */
+    protected function getTranslationListener()
+    {
+        $translationListener = null;
+        foreach ($this->_em->getEventManager()->getListeners() as $event => $listeners) {
+            foreach ($listeners as $hash => $listener) {
+                if ($listener instanceof TranslationListener) {
+                    $translationListener = $listener;
+                    break;
+                }
+            }
+            if ($translationListener) {
+                break;
+            }
+        }
+
+        if (is_null($translationListener)) {
+            throw new \Gedmo\Exception\RuntimeException('The translation listener could not be found');
+        }
+        return $translationListener;
+    }
 }

+ 0 - 17
lib/Gedmo/Translatable/Query/TreeWalker/TranslationWalker.php

@@ -37,13 +37,6 @@ class TranslationWalker extends SqlWalker
      */
     const HINT_TRANSLATION_FALLBACKS = '__gedmo.translatable.stored.fallbacks';
 
-    /**
-     * Name for translation listener hint
-     *
-     * @internal
-     */
-    const HINT_TRANSLATION_LISTENER = '__gedmo.translatable.listener';
-
     /**
      * Customized object hydrator name
      *
@@ -65,14 +58,6 @@ class TranslationWalker extends SqlWalker
      */
     private $translatedComponents = array();
 
-    /**
-     * Current TranslationListener instance used
-     * in EntityManager
-     *
-     * @var TranslationListener
-     */
-    private $listener;
-
     /**
      * DBAL database platform
      *
@@ -137,8 +122,6 @@ class TranslationWalker extends SqlWalker
         }
 
         $hydrationMode = $this->getQuery()->getHydrationMode();
-
-        $this->getQuery()->setHint(self::HINT_TRANSLATION_LISTENER, $this->listener);
         if ($hydrationMode === Query::HYDRATE_OBJECT) {
             $this->getQuery()->setHydrationMode(self::HYDRATE_OBJECT_TRANSLATION);
             $this->getEntityManager()->getConfiguration()->addCustomHydrationMode(

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

@@ -41,6 +41,33 @@ class TranslationQueryWalkerTest extends BaseTestCaseORM
         $this->populate();
     }
 
+    /**
+     * @test
+     */
+    function shouldHandleQueryCache()
+    {
+        $cache = new \Doctrine\Common\Cache\ArrayCache();
+        $this->em
+            ->getConfiguration()
+            ->expects($this->any())
+            ->method('getQueryCacheImpl')
+            ->will($this->returnValue($cache))
+        ;
+        $dql = 'SELECT a FROM ' . self::ARTICLE . ' a';
+        $q = $this->em->createQuery($dql);
+        $q->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, self::TREE_WALKER_TRANSLATION);
+
+        // array hydration
+        $this->translationListener->setTranslatableLocale('en_us');
+        $result = $q->getArrayResult();
+        $this->assertEquals(1, count($result));
+
+        $q2 = clone $q;
+        $q2->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, self::TREE_WALKER_TRANSLATION);
+        $result = $q->getArrayResult();
+        $this->assertEquals(1, count($result));
+    }
+
     public function testSubselectByTranslatedField()
     {
         $this->populateMore();