8000 [HttpFoundation] added withers to Cookie class · symfony/symfony@b80a2ae · GitHub
[go: up one dir, main page]

Skip to content

Commit b80a2ae

Browse files
committed
[HttpFoundation] added withers to Cookie class
1 parent 0c6d64b commit b80a2ae

File tree

3 files changed

+295
-47
lines changed

3 files changed

+295
-47
lines changed

src/Symfony/Component/HttpFoundation/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
CHANGELOG
22
=========
33

4+
5.2.0
5+
-----
6+
7+
* added `Cookie::withName`, `Cookie::withValue`, `Cookie::withDomain`, `Cookie::withExpiresTime`,
8+
`Cookie::withPath`, `Cookie::withSecure`, `Cookie::withHttpOnly`, `Cookie::withRaw`,
9+
`Cookie::withSameSite`
10+
411
5.1.0
512
-----
613

src/Symfony/Component/HttpFoundation/Cookie.php

Lines changed: 174 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@ class Cookie
2323
const SAMESITE_STRICT = 'strict';
2424

2525
protected $name;
26-
protected $value;
27-
protected $domain;
28-
protected $expire;
29-
protected $path;
30-
protected $secure;
31-
protected $httpOnly;
32-
33-
private $raw;
26+
protected $value = null;
27+
protected $domain = null;
28+
protected $expire = 0;
29+
protected $path = '/';
30+
protected $secure = null;
31+
protected $httpOnly = true;
32+
33+
private $raw = false;
3434
private $sameSite;
3535
private $secureDefault = false;
3636

@@ -90,46 +90,17 @@ public static function create(string $name, string $value = null, $expire = 0, ?
9090
*/
9191
public function __construct(string $name, string $value = null, $expire = 0, ?string $path = '/', string $domain = null, bool $secure = null, bool $httpOnly = true, bool $raw = false, ?string $sameSite = 'lax')
9292
{
93-
// from PHP source code
94-
if ($raw && false !== strpbrk($name, self::$reservedCharsList)) {
95-
throw new \InvalidArgumentException(sprintf('The cookie name "%s" contains invalid characters.', $name));
96-
}
97-
98-
if (empty($name)) {
99-
throw new \InvalidArgumentException('The cookie name cannot be empty.');
100-
}
101-
102-
// convert expiration time to a Unix timestamp
103-
if ($expire instanceof \DateTimeInterface) {
104-
$expire = $expire->format('U');
105-
} elseif (!is_numeric($expire)) {
106-
$expire = strtotime($expire);
107-
108-
if (false === $expire) {
109-
throw new \InvalidArgumentException('The cookie expiration time is not valid.');
110-
}
111-
}
93+
$this->raw = $raw;
11294

95+
$this->validateName($name);
11396
$this->name = $name;
11497
$this->value = $value;
98+
$this->expire = $this->normalizeExpiresTime($expire);
99+
$this->path< F438 /span> = $this->normalizePath($path);
115100
$this->domain = $domain;
116-
$this->expire = 0 < $expire ? (int) $expire : 0;
117-
$this->path = empty($path) ? '/' : $path;
118101
$this->secure = $secure;
119102
$this->httpOnly = $httpOnly;
120-
$this->raw = $raw;
121-
122-
if ('' === $sameSite) {
123-
$sameSite = null;
124-
} elseif (null !== $sameSite) {
125-
$sameSite = strtolower($sameSite);
126-
}
127-
128-
if (!\in_array($sameSite, [self::SAMESITE_LAX, self::SAMESITE_STRICT, self::SAMESITE_NONE, null], true)) {
129-
throw new \InvalidArgumentException('The "sameSite" parameter value is not valid.');
130-
}
131-
132-
$this->sameSite = $sameSite;
103+
$this->sameSite = $this->normalizeSameSite($sameSite);
133104
}
134105

135106
/**
@@ -190,6 +161,33 @@ public function getName()
190161
return $this->name;
191162
}
192163

164+
/**
165+
* Creates a cookie copy with a new name.
166+
*
167+
* @throws \InvalidArgumentException
168+
*/
169+
public function withName(string $name): self
170+
{
171+
$this->validateName($name);
172+
173+
$cookie = clone $this;
174+
$cookie->name = $name;
175+
176+
return $cookie;
177+
}
178+
179+
private function validateName(string $name): void
180+
{
181+
// from PHP source code
182+
if ($this->isRaw() && false !== strpbrk($name, self::$reservedCharsList)) {
183+
throw new \InvalidArgumentException(sprintf('The cookie name "%s" contains invalid characters.', $name));
184+
}
185+
186+
if (empty($name)) {
187+
throw new \InvalidArgumentException('The cookie name cannot be empty.');
188+
}
189+
}
190+
193191
/**
194192
* Gets the value of the cookie.
195193
*
@@ -200,6 +198,17 @@ public function getValue()
200198
return $this->value;
201199
}
202200

201+
/**
202+
* Creates a cookie copy with a new value.
203+
*/
204+
public function withValue(string $value = null): self
205+
{
206+
$cookie = clone $this;
207+
$cookie->value = $value;
208+
209+
return $cookie;
210+
}
211+
203212
/**
204213
* Gets the domain that the cookie is available to.
205214
*
@@ -210,6 +219,17 @@ public function getDomain()
210219
return $this->domain;
211220
}
212221

222+
/**
223+
* Creates a cookie copy with a new domain that the cookie is available to.
224+
*/
225+
public function withDomain(string $domain = null): self
226+
{
227+
$cookie = clone $this;
228+
$cookie->domain = $domain;
229+
230+
return $cookie;
231+
}
232+
213233
/**
214234
* Gets the time the cookie expires.
215235
*
@@ -220,6 +240,39 @@ public function getExpiresTime()
220240
return $this->expire;
221241
}
222242

243+
/**
244+
* Creates a cookie copy with a new time the cookie expires.
245+
*
246+
* @param int|string|\DateTimeInterface $expire
247+
*
248+
* @throws \InvalidArgumentException
249+
*/
250+
public function withExpiresTime($expire = 0): self
251+
{
252+
$expire = $this->normalizeExpiresTime($expire);
253+
254+
$cookie = clone $this;
255+
$cookie->expire = $expire;
256+
257+
return $cookie;
258+
}
259+
260+
private function normalizeExpiresTime($expire = 0): int
261+
{
262+
// convert expiration time to a Unix timestamp
263+
if ($expire instanceof \DateTimeInterface) {
264+
$expire = $expire->format('U');
265+
} elseif (!is_numeric($expire)) {
266+
$expire = strtotime($expire);
267+
268+
if (false === $expire) {
269+
throw new \InvalidArgumentException('The cookie expiration time is not valid.');
270+
}
271+
}
272+
273+
return 0 < $expire ? (int) $expire : 0;
274+
}
275+
223276
/**
224277
* Gets the max-age attribute.
225278
*
@@ -242,6 +295,22 @@ public function getPath()
242295
return $this->path;
243296
}
244297

298+
/**
299+
* Creates a cookie copy with a new path on the server in which the cookie will be available on.
300+
*/
301+
public function withPath(?string $path): self
302+
{
303+
$cookie = clone $this;
304+
$cookie->path = $this->normalizePath($path);
305+
306+
return $cookie;
307+
}
308+
309+
private function normalizePath(?string $path): string
310+
{
311+
return empty($path) ? '/' : $path;
312+
}
313+
245314
/**
246315
* Checks whether the cookie should only be transmitted over a secure HTTPS connection from the client.
247316
*
@@ -252,6 +321,17 @@ public function isSecure()
252321
return $this->secure ?? $this->secureDefault;
253322
}
254323

324+
/**
325+
* Creates a cookie copy that only be transmitted over a secure HTTPS connection from the client.
326+
*/
327+
public function withSecure(bool $secure = null): self
328+
{
329+
$cookie = clone $this;
330+
$cookie->secure = $secure;
331+
332+
return $cookie;
333+
}
334+
255335
/**
256336
* Checks whether the cookie will be made accessible only through the HTTP protocol.
257337
*
@@ -262,6 +342,17 @@ public function isHttpOnly()
262342
return $this->httpOnly;
263343
}
264344

345+
/**
346+
* Creates a cookie copy that be accessible only through the HTTP protocol.
347+
*/
348+
public function withHttpOnly(bool $httpOnly = true): self
349+
{
350+
$cookie = clone $this;
351+
$cookie->httpOnly = $httpOnly;
352+
353+
return $cookie;
354+
}
355+
265356
/**
266357
* Whether this cookie is about to be cleared.
267358
*
@@ -282,6 +373,17 @@ public function isRaw()
282373
return $this->raw;
283374
}
284375

376+
/**
377+
* Creates a cookie copy that uses url encoding.
378+
*/
379+
public function withRaw(bool $raw = false): self
380+
{
381+
$cookie = clone $this;
382+
$cookie->raw = $raw;
383+
384+
return $cookie;
385+
}
386+
285387
/**
286388
* Gets the SameSite attribute.
287389
*
@@ -292,6 +394,36 @@ public function getSameSite()
292394
return $this->sameSite;
293395
}
294396

397+
/**
398+
* Creates a cookie copy with SameSite attribute.
399+
*
400+
* @throws \InvalidArgumentException
401+
*/
402+
public function withSameSite(?string $sameSite = 'lax'): self
403+
{
404+
$sameSite = $this->normalizeSameSite($sameSite);
405+
406+
$cookie = clone $this;
407+
$cookie->sameSite = $sameSite;
408+
409+
return $cookie;
410+
}
411+
412+
private function normalizeSameSite(?string $sameSite = 'lax'): ?string
413+
{
414+
if ('' === $sameSite) {
415+
$sameSite = null;
416+
} elseif (null !== $sameSite) {
417+
$sameSite = strtolower($sameSite);
418+
}
419+
420+
if (!\in_array($sameSite, [self::SAMESITE_LAX, self::SAMESITE_STRICT, self::SAMESITE_NONE, null], true)) {
421+
throw new \InvalidArgumentException('The "sameSite" parameter value is not valid.');
422+
}
423+
424+
return $sameSite;
425+
}
426+
295427
/**
296428
* @param bool $default The default value of the "secure" flag when it is set to null
297429
*/

0 commit comments

Comments
 (0)
0