|
4 | 4 |
|
5 | 5 | namespace Tempest\Http\Cookie; |
6 | 6 |
|
| 7 | +use InvalidArgumentException; |
7 | 8 | use Stringable; |
8 | 9 | use Tempest\DateTime\DateTimeInterface; |
9 | 10 |
|
@@ -32,6 +33,14 @@ public function __construct( |
32 | 33 | public ?SameSite $sameSite = null, |
33 | 34 | ) {} |
34 | 35 |
|
| 36 | + public function withValue(string $value): self |
| 37 | + { |
| 38 | + $clone = clone $this; |
| 39 | + $clone->value = $value; |
| 40 | + |
| 41 | + return $clone; |
| 42 | + } |
| 43 | + |
35 | 44 | public function __toString(): string |
36 | 45 | { |
37 | 46 | $parts = [ |
@@ -78,4 +87,49 @@ public function getExpiresAtTime(): ?int |
78 | 87 |
|
79 | 88 | return null; |
80 | 89 | } |
| 90 | + |
| 91 | + /** |
| 92 | + * Creates acookie from the `Set-Cookie` header. |
| 93 | + */ |
| 94 | + public static function createFromString(string $string): self |
| 95 | + { |
| 96 | + if (! ($attributes = preg_split('/\s*;\s*/', $string, -1, PREG_SPLIT_NO_EMPTY))) { |
| 97 | + throw new InvalidArgumentException(sprintf('The raw value of the `Set Cookie` header `%s` could not be parsed.', $string)); |
| 98 | + } |
| 99 | + |
| 100 | + $nameAndValue = explode('=', array_shift($attributes), 2); |
| 101 | + $cookie = ['name' => $nameAndValue[0], 'value' => isset($nameAndValue[1]) ? urldecode($nameAndValue[1]) : '']; |
| 102 | + |
| 103 | + while ($attribute = array_shift($attributes)) { |
| 104 | + $attribute = explode('=', $attribute, 2); |
| 105 | + $attributeName = strtolower($attribute[0]); |
| 106 | + $attributeValue = $attribute[1] ?? null; |
| 107 | + |
| 108 | + if (in_array($attributeName, ['expires', 'domain', 'path', 'samesite'], true)) { |
| 109 | + $cookie[$attributeName] = $attributeValue; |
| 110 | + continue; |
| 111 | + } |
| 112 | + |
| 113 | + if (in_array($attributeName, ['secure', 'httponly'], true)) { |
| 114 | + $cookie[$attributeName] = true; |
| 115 | + continue; |
| 116 | + } |
| 117 | + |
| 118 | + if ($attributeName === 'max-age') { |
| 119 | + $cookie['expires'] = time() + ((int) $attributeValue); |
| 120 | + } |
| 121 | + } |
| 122 | + |
| 123 | + return new Cookie( |
| 124 | + key: $cookie['name'], |
| 125 | + value: $cookie['value'] ?? null, |
| 126 | + expiresAt: isset($cookie['expires']) ? ((int) $cookie['expires']) : null, |
| 127 | + maxAge: isset($cookie['max-age']) ? ((int) $cookie['max-age']) : null, |
| 128 | + domain: $cookie['domain'] ?? null, |
| 129 | + path: $cookie['path'] ?? '/', |
| 130 | + secure: isset($cookie['secure']) && $cookie['secure'] === true, |
| 131 | + httpOnly: isset($cookie['httponly']) && $cookie['httponly'] === true, |
| 132 | + sameSite: isset($cookie['samesite']) ? SameSite::from($cookie['samesite']) : null, |
| 133 | + ); |
| 134 | + } |
81 | 135 | } |
0 commit comments