@@ -32,6 +32,7 @@ class Cookie
32
32
33
33
private bool $ raw ;
34
34
private ?string $ sameSite = null ;
35
+ private bool $ partitioned = false ;
35
36
private bool $ secureDefault = false ;
36
37
37
38
private const RESERVED_CHARS_LIST = "=,; \t\r\n\v\f" ;
@@ -51,6 +52,7 @@ public static function fromString(string $cookie, bool $decode = false): static
51
52
'httponly ' => false ,
52
53
'raw ' => !$ decode ,
53
54
'samesite ' => null ,
55
+ 'partitioned ' => false ,
54
56
];
55
57
56
58
$ parts = HeaderUtils::split ($ cookie , ';= ' );
@@ -66,17 +68,20 @@ public static function fromString(string $cookie, bool $decode = false): static
66
68
$ data ['expires ' ] = time () + (int ) $ data ['max-age ' ];
67
69
}
68
70
69
- return new static ($ name , $ value , $ data ['expires ' ], $ data ['path ' ], $ data ['domain ' ], $ data ['secure ' ], $ data ['httponly ' ], $ data ['raw ' ], $ data ['samesite ' ]);
71
+ return new static ($ name , $ value , $ data ['expires ' ], $ data ['path ' ], $ data ['domain ' ], $ data ['secure ' ], $ data ['httponly ' ], $ data ['raw ' ], $ data ['samesite ' ], $ data [ ' partitioned ' ] );
70
72
}
71
73
72
74
/**
73
75
* @see self::__construct
74
76
*
75
77
* @param self::SAMESITE_*|''|null $sameSite
78
+ * @param bool $partitioned
76
79
*/
77
- public static function create (string $ name , string $ value = null , int |string |\DateTimeInterface $ expire = 0 , ?string $ path = '/ ' , string $ domain = null , bool $ secure = null , bool $ httpOnly = true , bool $ raw = false , ?string $sameSite = self ::SAMESITE_LAX ): self
80
+ public static function create (string $ name , string $ value = null , int |string |\DateTimeInterface $ expire = 0 , ?string $ path = '/ ' , string $ domain = null , bool $ secure = null , bool $ httpOnly = true , bool $ raw = false , ?string $ sameSite = self ::SAMESITE_LAX /* , bool $partitioned = false */ ): self
78
81
{
79
- return new self ($ name , $ value , $ expire , $ path , $ domain , $ secure , $ httpOnly , $ raw , $ sameSite );
82
+ $ partitioned = 9 < \func_num_args () ? func_get_arg (9 ) : false ;
83
+
84
+ return new self ($ name , $ value , $ expire , $ path , $ domain , $ secure , $ httpOnly , $ raw , $ sameSite , $ partitioned );
80
85
}
81
86
82
87
/**
@@ -92,7 +97,7 @@ public static function create(string $name, string $value = null, int|string|\Da
92
97
*
93
98
* @throws \InvalidArgumentException
94
99
*/
95
- public function __construct (string $ name , string $ value = null , int |string |\DateTimeInterface $ expire = 0 , ?string $ path = '/ ' , string $ domain = null , bool $ secure = null , bool $ httpOnly = true , bool $ raw = false , ?string $ sameSite = self ::SAMESITE_LAX )
100
+ public function __construct (string $ name , string $ value = null , int |string |\DateTimeInterface $ expire = 0 , ?string $ path = '/ ' , string $ domain = null , bool $ secure = null , bool $ httpOnly = true , bool $ raw = false , ?string $ sameSite = self ::SAMESITE_LAX , bool $ partitioned = false )
96
101
{
97
102
// from PHP source code
98
103
if ($ raw && false !== strpbrk ($ name , self ::RESERVED_CHARS_LIST )) {
@@ -112,6 +117,7 @@ public function __construct(string $name, string $value = null, int|string|\Date
112
117
$ this ->httpOnly = $ httpOnly ;
113
118
$ this ->raw = $ raw ;
114
119
$ this ->sameSite = $ this ->withSameSite ($ sameSite )->sameSite ;
120
+ $ this ->partitioned = $ partitioned ;
115
121
}
116
122
117
123
/**
@@ -237,6 +243,17 @@ public function withSameSite(?string $sameSite): static
237
243
return $ cookie ;
238
244
}
239
245
246
+ /**
247
+ * Creates a cookie copy that is only accessible by a dedicated first party in cross-site context.
248
+ */
249
+ public function withPartitioned (bool $ partitioned = true ): static
250
+ {
251
+ $ cookie = clone $ this ;
252
+ $ cookie ->partitioned = $ partitioned ;
253
+
254
+ return $ cookie ;
255
+ }
256
+
240
257
/**
241
258
* Returns the cookie as a string.
242
259
*/
@@ -268,18 +285,22 @@ public function __toString(): string
268
285
$ str .= '; domain= ' .$ this ->getDomain ();
269
286
}
270
287
271
- if (true === $ this ->isSecure ()) {
288
+ if ($ this ->isSecure ()) {
272
289
$ str .= '; secure ' ;
273
290
}
274
291
275
- if (true === $ this ->isHttpOnly ()) {
292
+ if ($ this ->isHttpOnly ()) {
276
293
$ str .= '; httponly ' ;
277
294
}
278
295
279
296
if (null !== $ this ->getSameSite ()) {
280
297
$ str .= '; samesite= ' .$ this ->getSameSite ();
281
298
}
282
299
300
+ if ($ this ->isPartitioned ()) {
301
+ $ str .= '; partitioned ' ;
302
+ }
303
+
283
304
return $ str ;
284
305
}
285
306
@@ -365,6 +386,14 @@ public function isRaw(): bool
365
386
return $ this ->raw ;
366
387
}
367
388
389
+ /**
390
+ * Checks whether the cookie should only be accessible by a dedicated first party in cross-site context.
391
+ */
392
+ public function isPartitioned (): bool
393
+ {
394
+ return $ this ->partitioned ;
395
+ }
396
+
368
397
/**
369
398
* @return self::SAMESITE_*|null
370
399
*/
0 commit comments