Browse Source

Fix requestAction() not working with middleware.

The unit tests for requestAction all setup the necessary global state.
Which is why they were passing while in reality the code failed. While
this feature is deprecated and unloved, it should continue doing the
thing it has always done.

Refs #9505
Mark Story 9 years ago
parent
commit
d7d0e22ac6

+ 20 - 0
src/Routing/RequestActionTrait.php

@@ -17,6 +17,8 @@ use Cake\Core\Configure;
 use Cake\Network\Request;
 use Cake\Network\Response;
 use Cake\Network\Session;
+use Cake\Routing\Filter\ControllerFactoryFilter;
+use Cake\Routing\Filter\RoutingFilter;
 
 /**
  * Provides the requestAction() method for doing sub-requests
@@ -154,6 +156,24 @@ trait RequestActionTrait
         $request = new Request($params);
         $request->addParams($extra);
         $dispatcher = DispatcherFactory::create();
+
+        // If an application is using PSR7 middleware,
+        // we need to 'fix' their missing dispatcher filters.
+        $needed = [
+            'routing' => RoutingFilter::class,
+            'controller' => ControllerFactoryFilter::class
+        ];
+        foreach ($dispatcher->filters() as $filter) {
+            if ($filter instanceof RoutingFilter) {
+                unset($needed['routing']);
+            }
+            if ($filter instanceof ControllerFactoryFilter) {
+                unset($needed['controller']);
+            }
+        }
+        foreach ($needed as $class) {
+            $dispatcher->addFilter(new $class);
+        }
         $result = $dispatcher->dispatch($request, new Response());
         Router::popRequest();
 

+ 15 - 1
tests/TestCase/Routing/RequestActionTraitTest.php

@@ -25,7 +25,6 @@ use Cake\Utility\Security;
  */
 class RequestActionTraitTest extends TestCase
 {
-
     /**
      * fixtures
      *
@@ -421,4 +420,19 @@ class RequestActionTraitTest extends TestCase
         );
         $this->assertEquals('bar', $result);
     }
+
+    /**
+     * requestAction relies on both the RoutingFilter and ControllerFactory
+     * filters being connected. Ensure it can correct the missing state.
+     *
+     * @return void
+     */
+    public function testRequestActionAddsRequiredFilters()
+    {
+        DispatcherFactory::clear();
+
+        $result = $this->object->requestAction('/request_action/test_request_action');
+        $expected = 'This is a test';
+        $this->assertEquals($expected, $result);
+    }
 }