diff --git a/src/Http/ServerRequest.php b/src/Http/ServerRequest.php index 90c29138d95..ce1c47c2ec9 100644 --- a/src/Http/ServerRequest.php +++ b/src/Http/ServerRequest.php @@ -17,6 +17,7 @@ use ArrayAccess; use BadMethodCallException; use Cake\Core\Configure; +use Cake\Http\Cookie\CookieCollection; use Cake\Network\Exception\MethodNotAllowedException; use Cake\Network\Session; use Cake\Utility\Hash; @@ -1605,6 +1606,45 @@ public function getCookie($key, $default = null) return Hash::get($this->cookies, $key, $default); } + /** + * Get a cookie collection based on the request's cookies + * + * The CookieCollection lets you interact with request cookies using + * `\Cake\Http\Cookie\Cookie` objects and can make converting request cookies + * into response cookies easier. + * + * This method will create a new cookie collection each time it is called. + * This is an optimization that allows fewer objects to be allocated until + * the more complex CookieCollection is needed. In general you should prefer + * `getCookie()` and `getCookieParams()` over this method. Using a CookieCollection + * is ideal if your cookies contain complex JSON encoded data. + * + * @return \Cake\Http\Cookie\CookieCollection + */ + public function getCookieCollection() + { + return CookieCollection::createFromServerRequest($this); + } + + /** + * Replace the cookies in the request with those contained in + * the provided CookieCollection. + * + * @param \Cake\Http\Cookie\CookieCollection $cookies The cookie collection + * @return static + */ + public function withCookieCollection(CookieCollection $cookies) + { + $new = clone $this; + $values = []; + foreach ($cookies as $cookie) { + $values[$cookie->getName()] = $cookie->getValue(); + } + $new->cookies = $values; + + return $new; + } + /** * Get all the cookie data from the request. * diff --git a/tests/TestCase/Http/ServerRequestTest.php b/tests/TestCase/Http/ServerRequestTest.php index 4a771db6ffc..cbc01541d03 100644 --- a/tests/TestCase/Http/ServerRequestTest.php +++ b/tests/TestCase/Http/ServerRequestTest.php @@ -15,6 +15,8 @@ namespace Cake\Test\TestCase\Http; use Cake\Core\Configure; +use Cake\Http\Cookie\Cookie; +use Cake\Http\Cookie\CookieCollection; use Cake\Http\ServerRequest; use Cake\Http\ServerRequestFactory; use Cake\Network\Exception\MethodNotAllowedException; @@ -3080,6 +3082,45 @@ public function testWithCookieParams() $this->assertSame(['remember_me' => 1], $new->getCookieParams()); } + /** + * Test getting a cookie collection from a request. + * + * @return void + */ + public function testGetCookieCollection() + { + $cookies = [ + 'remember_me' => '1', + 'color' => 'blue' + ]; + $request = new ServerRequest(['cookies' => $cookies]); + + $cookies = $request->getCookieCollection(); + $this->assertInstanceOf(CookieCollection::class, $cookies); + $this->assertCount(2, $cookies); + $this->assertSame('1', $cookies->get('remember_me')->getValue()); + $this->assertSame('blue', $cookies->get('color')->getValue()); + } + + /** + * Test replacing cookies from a collection + * + * @return void + */ + public function testWithCookieCollection() + { + $cookies = new CookieCollection([new Cookie('remember_me', 1), new Cookie('color', 'red')]); + $request = new ServerRequest(['cookies' => ['bad' => 'goaway']]); + $new = $request->withCookieCollection($cookies); + $this->assertNotSame($new, $request, 'Should clone'); + + $this->assertSame(['bad' => 'goaway'], $request->getCookieParams()); + $this->assertSame(['remember_me' => 1, 'color' => 'red'], $new->getCookieParams()); + $cookies = $new->getCookieCollection(); + $this->assertCount(2, $cookies); + $this->assertSame('red', $cookies->get('color')->getValue()); + } + /** * TestAllowMethod *