Browse Source

Add cookie collection methods to ServerRequest.

I've chosen to not use CookieCollection as the internal storage as
keeping the public property in-sync would be hard/impossible. This
approach also avoid eagerly allocating memory for the cookie collection
and the cookie objects.
Mark Story 9 years ago
parent
commit
13353f7713
2 changed files with 81 additions and 0 deletions
  1. 40 0
      src/Http/ServerRequest.php
  2. 41 0
      tests/TestCase/Http/ServerRequestTest.php

+ 40 - 0
src/Http/ServerRequest.php

@@ -17,6 +17,7 @@ namespace Cake\Http;
 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;
@@ -1606,6 +1607,45 @@ class ServerRequest implements ArrayAccess, ServerRequestInterface
     }
 
     /**
+     * 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.
      *
      * @return array An array of cookie data.

+ 41 - 0
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;
@@ -3081,6 +3083,45 @@ XML;
     }
 
     /**
+     * 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
      *
      * @return void