Browse Source

Fix optional parameters with default values

The container based argument builder was setting these parameters to
null before these changes.
Mark Story 5 years ago
parent
commit
85dc6feca4

+ 4 - 1
src/Controller/ControllerFactory.php

@@ -118,8 +118,11 @@ class ControllerFactory implements ControllerFactoryInterface
             // Primitive types are passed args as they can't be looked up in the container.
             // We only handle strings currently.
             if ($typeName === 'string') {
-                if (count($passed) || !$type->allowsNull()) {
+                $defaultValue = $parameter->getDefaultValue();
+                if (count($passed)) {
                     $args[$position] = array_shift($passed);
+                } elseif ($defaultValue) {
+                    $args[$position] = $defaultValue;
                 } else {
                     $args[$position] = null;
                 }

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

@@ -631,4 +631,28 @@ class ControllerFactoryTest extends TestCase
         $this->assertNotNull($data);
         $this->assertSame(['one', 'two'], $data->args);
     }
+
+    /**
+     * Test that default parameters work for controller methods
+     *
+     * @return void
+     */
+    public function testInvokeOptionalStringParam()
+    {
+        $request = new ServerRequest([
+            'url' => 'test_plugin_three/dependencies/optionalString',
+            'params' => [
+                'plugin' => null,
+                'controller' => 'Dependencies',
+                'action' => 'optionalString',
+            ],
+        ]);
+        $controller = $this->factory->create($request);
+
+        $result = $this->factory->invoke($controller);
+        $data = json_decode((string)$result->getBody());
+
+        $this->assertNotNull($data);
+        $this->assertSame('default val', $data->str);
+    }
 }

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

@@ -27,6 +27,11 @@ class DependenciesController extends Controller
         $this->inject = $inject;
     }
 
+    public function optionalString(string $str = 'default val')
+    {
+        return $this->response->withStringBody(json_encode(compact('str')));
+    }
+
     public function optionalDep($any = null, ?string $str = null, ?stdClass $dep = null)
     {
         return $this->response->withStringBody(json_encode(compact('dep', 'any', 'str')));