Browse Source

Don't throw an exception for unsupported types.

If the ControllerFactory encounters a method argument type like union type which it
cannot use for conversion, it no longer throws an exception and passes the value as is.

Backport fixes from #17338 to 4.x
ADmad 2 years ago
parent
commit
7551b8c19d

+ 0 - 11
src/Controller/ControllerFactory.php

@@ -160,17 +160,6 @@ class ControllerFactory implements ControllerFactoryInterface, RequestHandlerInt
         $function = new ReflectionFunction($action);
         foreach ($function->getParameters() as $parameter) {
             $type = $parameter->getType();
-            if ($type && !$type instanceof ReflectionNamedType) {
-                // Only single types are supported
-                throw new InvalidParameterException([
-                    'template' => 'unsupported_type',
-                    'parameter' => $parameter->getName(),
-                    'controller' => $this->controller->getName(),
-                    'action' => $this->controller->getRequest()->getParam('action'),
-                    'prefix' => $this->controller->getRequest()->getParam('prefix'),
-                    'plugin' => $this->controller->getRequest()->getParam('plugin'),
-                ]);
-            }
 
             // Check for dependency injection for classes
             if ($type instanceof ReflectionNamedType && !$type->isBuiltin()) {

+ 22 - 0
tests/TestCase/Controller/ControllerFactoryTest.php

@@ -879,6 +879,28 @@ class ControllerFactoryTest extends TestCase
         $this->factory->invoke($controller);
     }
 
+    /**
+     * Test using an unsupported reflection type.
+     */
+    public function testInvokePassedParamUnsupportedReflectionType(): void
+    {
+        $request = new ServerRequest([
+            'url' => 'test_plugin_three/dependencies/unsupportedTypedUnion',
+            'params' => [
+                'plugin' => null,
+                'controller' => 'Dependencies',
+                'action' => 'typedUnion',
+                'pass' => ['1'],
+            ],
+        ]);
+        $controller = $this->factory->create($request);
+
+        $result = $this->factory->invoke($controller);
+        $data = json_decode((string)$result->getBody(), true);
+
+        $this->assertSame(['one' => '1'], $data);
+    }
+
     public function testMiddleware(): void
     {
         $request = new ServerRequest([

+ 5 - 0
tests/test_app/TestApp/Controller/DependenciesController.php

@@ -61,6 +61,11 @@ class DependenciesController extends Controller
         return $this->response->withStringBody(json_encode(compact('one')));
     }
 
+    public function typedUnion(string|int $one)
+    {
+        return $this->response->withStringBody(json_encode(compact('one')));
+    }
+
     /**
      * @param mixed $any
      * @return \Cake\Http\Response