Browse Source

Merge pull request #9352 from cakephp/request-setters

Add immutable setters for data and params
Mark Story 9 years ago
parent
commit
8cbb8a5b8f
2 changed files with 139 additions and 0 deletions
  1. 42 0
      src/Network/Request.php
  2. 97 0
      tests/TestCase/Network/RequestTest.php

+ 42 - 0
src/Network/Request.php

@@ -1195,6 +1195,9 @@ class Request implements ArrayAccess
      * $request->data('Post.title', 'New post!');
      * ```
      *
+     * As of 3.4.0, the setter mode of this method is *deprecated*.
+     * Use `withData` instead.
+     *
      * You can write to any value, even paths/keys that do not exist, and the arrays
      * will be created for you.
      *
@@ -1219,6 +1222,9 @@ class Request implements ArrayAccess
     /**
      * Safely access the values in $this->params.
      *
+     * As of 3.4.0, the setter mode of this method is *deprecated*.
+     * Use `withParam` instead.
+     *
      * @param string $name The name of the parameter to get.
      * @return mixed|$this The value of the provided parameter. Will
      *   return false if the parameter doesn't exist or is falsey.
@@ -1379,6 +1385,42 @@ class Request implements ArrayAccess
     }
 
     /**
+     * Update the request with a new request data element.
+     *
+     * Returns an updated request object. This method returns
+     * a *new* request object and does not mutate the request in-place.
+     *
+     * @param string $name The dot separated path to insert $value at.
+     * @param mixed $value The value to insert into the request data.
+     * @return static
+     */
+    public function withData($name, $value)
+    {
+        $copy = clone $this;
+        $copy->data = Hash::insert($copy->data, $name, $value);
+
+        return $copy;
+    }
+
+    /**
+     * Update the request with a new routing parameter
+     *
+     * Returns an updated request object. This method returns
+     * a *new* request object and does not mutate the request in-place.
+     *
+     * @param string $name The dot separated path to insert $value at.
+     * @param mixed $value The value to insert into the the request parameters.
+     * @return static
+     */
+    public function withParam($name, $value)
+    {
+        $copy = clone $this;
+        $copy->params = Hash::insert($copy->params, $name, $value);
+
+        return $copy;
+    }
+
+    /**
      * Array access read implementation
      *
      * @param string $name Name of the key being accessed.

+ 97 - 0
tests/TestCase/Network/RequestTest.php

@@ -2542,6 +2542,103 @@ XML;
     }
 
     /**
+     * Test updating params in a psr7 fashion.
+     *
+     * @return void
+     */
+    public function testWithParam()
+    {
+        $request = new Request([
+            'params' => ['controller' => 'Articles']
+        ]);
+        $result = $request->withParam('action', 'view');
+        $this->assertNotSame($result, $request, 'New instance should be made');
+        $this->assertFalse($request->param('action'), 'No side-effect on original');
+        $this->assertSame('view', $result->param('action'));
+
+        $result = $request->withParam('action', 'index')
+            ->withParam('plugin', 'DebugKit')
+            ->withParam('prefix', 'Admin');
+        $this->assertNotSame($result, $request, 'New instance should be made');
+        $this->assertFalse($request->param('action'), 'No side-effect on original');
+        $this->assertSame('index', $result->param('action'));
+        $this->assertSame('DebugKit', $result->param('plugin'));
+        $this->assertSame('Admin', $result->param('prefix'));
+    }
+
+    /**
+     * Test updating POST data in a psr7 fashion.
+     *
+     * @return void
+     */
+    public function testWithData()
+    {
+        $request = new Request([
+            'post' => [
+                'Model' => [
+                    'field' => 'value'
+                ]
+            ]
+        ]);
+        $result = $request->withData('Model.new_value', 'new value');
+        $this->assertNull($request->data('Model.new_value'), 'Original request should not change.');
+        $this->assertNotSame($result, $request);
+        $this->assertEquals('new value', $result->data('Model.new_value'));
+        $this->assertEquals('new value', $result->data['Model']['new_value']);
+        $this->assertEquals('value', $result->data('Model.field'));
+    }
+
+    /**
+     * Test updating POST data when keys don't exist
+     *
+     * @return void
+     */
+    public function testWithDataMissingIntermediaryKeys()
+    {
+        $request = new Request([
+            'post' => [
+                'Model' => [
+                    'field' => 'value'
+                ]
+            ]
+        ]);
+        $result = $request->withData('Model.field.new_value', 'new value');
+        $this->assertEquals(
+            'new value',
+            $result->data('Model.field.new_value')
+        );
+        $this->assertEquals(
+            'new value',
+            $result->data['Model']['field']['new_value']
+        );
+    }
+
+    /**
+     * Test updating POST data with falsey values
+     *
+     * @return void
+     */
+    public function testWithDataFalseyValues()
+    {
+        $request = new Request([
+            'post' => []
+        ]);
+        $result = $request->withData('false', false)
+            ->withData('null', null)
+            ->withData('empty_string', '')
+            ->withData('zero', 0)
+            ->withData('zero_string', '0');
+        $expected = [
+            'false' => false,
+            'null' => null,
+            'empty_string' => '',
+            'zero' => 0,
+            'zero_string' => '0'
+        ];
+        $this->assertSame($expected, $result->data());
+    }
+
+    /**
      * loadEnvironment method
      *
      * @param array $env