Passed
Pull Request — master (#27)
by Anatoly
05:58 queued 01:43
created
src/Header/RefreshHeader.php 2 patches
Indentation   +61 added lines, -61 removed lines patch added patch discarded remove patch
@@ -31,72 +31,72 @@
 block discarded – undo
31 31
 class RefreshHeader extends Header
32 32
 {
33 33
 
34
-    /**
35
-     * @var int
36
-     */
37
-    private int $delay;
34
+	/**
35
+	 * @var int
36
+	 */
37
+	private int $delay;
38 38
 
39
-    /**
40
-     * @var UriInterface
41
-     */
42
-    private UriInterface $uri;
39
+	/**
40
+	 * @var UriInterface
41
+	 */
42
+	private UriInterface $uri;
43 43
 
44
-    /**
45
-     * Constructor of the class
46
-     *
47
-     * @param int $delay
48
-     * @param mixed $uri
49
-     *
50
-     * @throws InvalidUriException
51
-     *         If the URI isn't valid.
52
-     *
53
-     * @throws InvalidHeaderValueException
54
-     *         If the delay isn't valid.
55
-     */
56
-    public function __construct(int $delay, $uri)
57
-    {
58
-        $this->validateDelay($delay);
44
+	/**
45
+	 * Constructor of the class
46
+	 *
47
+	 * @param int $delay
48
+	 * @param mixed $uri
49
+	 *
50
+	 * @throws InvalidUriException
51
+	 *         If the URI isn't valid.
52
+	 *
53
+	 * @throws InvalidHeaderValueException
54
+	 *         If the delay isn't valid.
55
+	 */
56
+	public function __construct(int $delay, $uri)
57
+	{
58
+		$this->validateDelay($delay);
59 59
 
60
-        $uri = Uri::create($uri);
60
+		$uri = Uri::create($uri);
61 61
 
62
-        $this->delay = $delay;
63
-        $this->uri = $uri;
64
-    }
62
+		$this->delay = $delay;
63
+		$this->uri = $uri;
64
+	}
65 65
 
66
-    /**
67
-     * {@inheritdoc}
68
-     */
69
-    public function getFieldName(): string
70
-    {
71
-        return 'Refresh';
72
-    }
66
+	/**
67
+	 * {@inheritdoc}
68
+	 */
69
+	public function getFieldName(): string
70
+	{
71
+		return 'Refresh';
72
+	}
73 73
 
74
-    /**
75
-     * {@inheritdoc}
76
-     */
77
-    public function getFieldValue(): string
78
-    {
79
-        return sprintf('%d; url=%s', $this->delay, $this->uri->__toString());
80
-    }
74
+	/**
75
+	 * {@inheritdoc}
76
+	 */
77
+	public function getFieldValue(): string
78
+	{
79
+		return sprintf('%d; url=%s', $this->delay, $this->uri->__toString());
80
+	}
81 81
 
82
-    /**
83
-     * Validates the redirection delay
84
-     *
85
-     * @param int $delay
86
-     *
87
-     * @return void
88
-     *
89
-     * @throws InvalidHeaderValueException
90
-     *         If the delay isn't valid.
91
-     */
92
-    private function validateDelay(int $delay): void
93
-    {
94
-        if (! ($delay >= 0)) {
95
-            throw new InvalidHeaderValueException(sprintf(
96
-                'The delay "%2$d" for the header "%1$s" is not valid',
97
-                $this->getFieldName(),
98
-                $delay
99
-            ));
100
-        }
101
-    }
82
+	/**
83
+	 * Validates the redirection delay
84
+	 *
85
+	 * @param int $delay
86
+	 *
87
+	 * @return void
88
+	 *
89
+	 * @throws InvalidHeaderValueException
90
+	 *         If the delay isn't valid.
91
+	 */
92
+	private function validateDelay(int $delay): void
93
+	{
94
+		if (! ($delay >= 0)) {
95
+			throw new InvalidHeaderValueException(sprintf(
96
+				'The delay "%2$d" for the header "%1$s" is not valid',
97
+				$this->getFieldName(),
98
+				$delay
99
+			));
100
+		}
101
+	}
102 102
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -91,7 +91,7 @@
 block discarded – undo
91 91
      */
92 92
     private function validateDelay(int $delay): void
93 93
     {
94
-        if (! ($delay >= 0)) {
94
+        if (!($delay >= 0)) {
95 95
             throw new InvalidHeaderValueException(sprintf(
96 96
                 'The delay "%2$d" for the header "%1$s" is not valid',
97 97
                 $this->getFieldName(),
Please login to merge, or discard this patch.
src/Header/AccessControlAllowHeadersHeader.php 1 patch
Indentation   +32 added lines, -32 removed lines patch added patch discarded remove patch
@@ -28,41 +28,41 @@
 block discarded – undo
28 28
 class AccessControlAllowHeadersHeader extends Header
29 29
 {
30 30
 
31
-    /**
32
-     * @var list<string>
33
-     */
34
-    private array $headers;
31
+	/**
32
+	 * @var list<string>
33
+	 */
34
+	private array $headers;
35 35
 
36
-    /**
37
-     * Constructor of the class
38
-     *
39
-     * @param string ...$headers
40
-     *
41
-     * @throws InvalidHeaderValueException
42
-     *         If one of the header names isn't valid.
43
-     */
44
-    public function __construct(string ...$headers)
45
-    {
46
-        /** @var list<string> $headers */
36
+	/**
37
+	 * Constructor of the class
38
+	 *
39
+	 * @param string ...$headers
40
+	 *
41
+	 * @throws InvalidHeaderValueException
42
+	 *         If one of the header names isn't valid.
43
+	 */
44
+	public function __construct(string ...$headers)
45
+	{
46
+		/** @var list<string> $headers */
47 47
 
48
-        $this->validateToken(...$headers);
48
+		$this->validateToken(...$headers);
49 49
 
50
-        $this->headers = $headers;
51
-    }
50
+		$this->headers = $headers;
51
+	}
52 52
 
53
-    /**
54
-     * {@inheritdoc}
55
-     */
56
-    public function getFieldName(): string
57
-    {
58
-        return 'Access-Control-Allow-Headers';
59
-    }
53
+	/**
54
+	 * {@inheritdoc}
55
+	 */
56
+	public function getFieldName(): string
57
+	{
58
+		return 'Access-Control-Allow-Headers';
59
+	}
60 60
 
61
-    /**
62
-     * {@inheritdoc}
63
-     */
64
-    public function getFieldValue(): string
65
-    {
66
-        return implode(', ', $this->headers);
67
-    }
61
+	/**
62
+	 * {@inheritdoc}
63
+	 */
64
+	public function getFieldValue(): string
65
+	{
66
+		return implode(', ', $this->headers);
67
+	}
68 68
 }
Please login to merge, or discard this patch.
src/Header/ContentEncodingHeader.php 1 patch
Indentation   +41 added lines, -41 removed lines patch added patch discarded remove patch
@@ -28,51 +28,51 @@
 block discarded – undo
28 28
 class ContentEncodingHeader extends Header
29 29
 {
30 30
 
31
-    /**
32
-     * Directives
33
-     *
34
-     * @var string
35
-     */
36
-    public const GZIP = 'gzip';
37
-    public const COMPRESS = 'compress';
38
-    public const DEFLATE = 'deflate';
39
-    public const BR = 'br';
31
+	/**
32
+	 * Directives
33
+	 *
34
+	 * @var string
35
+	 */
36
+	public const GZIP = 'gzip';
37
+	public const COMPRESS = 'compress';
38
+	public const DEFLATE = 'deflate';
39
+	public const BR = 'br';
40 40
 
41
-    /**
42
-     * @var list<string>
43
-     */
44
-    private array $directives;
41
+	/**
42
+	 * @var list<string>
43
+	 */
44
+	private array $directives;
45 45
 
46
-    /**
47
-     * Constructor of the class
48
-     *
49
-     * @param string ...$directives
50
-     *
51
-     * @throws InvalidHeaderValueException
52
-     *         If one of the directives isn't valid.
53
-     */
54
-    public function __construct(string ...$directives)
55
-    {
56
-        /** @var list<string> $directives */
46
+	/**
47
+	 * Constructor of the class
48
+	 *
49
+	 * @param string ...$directives
50
+	 *
51
+	 * @throws InvalidHeaderValueException
52
+	 *         If one of the directives isn't valid.
53
+	 */
54
+	public function __construct(string ...$directives)
55
+	{
56
+		/** @var list<string> $directives */
57 57
 
58
-        $this->validateToken(...$directives);
58
+		$this->validateToken(...$directives);
59 59
 
60
-        $this->directives = $directives;
61
-    }
60
+		$this->directives = $directives;
61
+	}
62 62
 
63
-    /**
64
-     * {@inheritdoc}
65
-     */
66
-    public function getFieldName(): string
67
-    {
68
-        return 'Content-Encoding';
69
-    }
63
+	/**
64
+	 * {@inheritdoc}
65
+	 */
66
+	public function getFieldName(): string
67
+	{
68
+		return 'Content-Encoding';
69
+	}
70 70
 
71
-    /**
72
-     * {@inheritdoc}
73
-     */
74
-    public function getFieldValue(): string
75
-    {
76
-        return implode(', ', $this->directives);
77
-    }
71
+	/**
72
+	 * {@inheritdoc}
73
+	 */
74
+	public function getFieldValue(): string
75
+	{
76
+		return implode(', ', $this->directives);
77
+	}
78 78
 }
Please login to merge, or discard this patch.
src/Header/CacheControlHeader.php 1 patch
Indentation   +41 added lines, -41 removed lines patch added patch discarded remove patch
@@ -29,52 +29,52 @@
 block discarded – undo
29 29
 class CacheControlHeader extends Header
30 30
 {
31 31
 
32
-    /**
33
-     * @var array<string, string>
34
-     */
35
-    private array $parameters;
32
+	/**
33
+	 * @var array<string, string>
34
+	 */
35
+	private array $parameters;
36 36
 
37
-    /**
38
-     * Constructor of the class
39
-     *
40
-     * @param array<array-key, mixed> $parameters
41
-     *
42
-     * @throws InvalidHeaderValueParameterException
43
-     *         If the parameters aren't valid.
44
-     */
45
-    public function __construct(array $parameters)
46
-    {
47
-        $parameters = $this->validateParameters($parameters);
37
+	/**
38
+	 * Constructor of the class
39
+	 *
40
+	 * @param array<array-key, mixed> $parameters
41
+	 *
42
+	 * @throws InvalidHeaderValueParameterException
43
+	 *         If the parameters aren't valid.
44
+	 */
45
+	public function __construct(array $parameters)
46
+	{
47
+		$parameters = $this->validateParameters($parameters);
48 48
 
49
-        $this->parameters = $parameters;
50
-    }
49
+		$this->parameters = $parameters;
50
+	}
51 51
 
52
-    /**
53
-     * {@inheritdoc}
54
-     */
55
-    public function getFieldName(): string
56
-    {
57
-        return 'Cache-Control';
58
-    }
52
+	/**
53
+	 * {@inheritdoc}
54
+	 */
55
+	public function getFieldName(): string
56
+	{
57
+		return 'Cache-Control';
58
+	}
59 59
 
60
-    /**
61
-     * {@inheritdoc}
62
-     */
63
-    public function getFieldValue(): string
64
-    {
65
-        $segments = [];
66
-        foreach ($this->parameters as $name => $value) {
67
-            // the construction <foo=> isn't valid...
68
-            if ($value === '') {
69
-                $segments[] = $name;
70
-                continue;
71
-            }
60
+	/**
61
+	 * {@inheritdoc}
62
+	 */
63
+	public function getFieldValue(): string
64
+	{
65
+		$segments = [];
66
+		foreach ($this->parameters as $name => $value) {
67
+			// the construction <foo=> isn't valid...
68
+			if ($value === '') {
69
+				$segments[] = $name;
70
+				continue;
71
+			}
72 72
 
73
-            $format = $this->isToken($value) ? '%s=%s' : '%s="%s"';
73
+			$format = $this->isToken($value) ? '%s=%s' : '%s="%s"';
74 74
 
75
-            $segments[] = sprintf($format, $name, $value);
76
-        }
75
+			$segments[] = sprintf($format, $name, $value);
76
+		}
77 77
 
78
-        return implode(', ', $segments);
79
-    }
78
+		return implode(', ', $segments);
79
+	}
80 80
 }
Please login to merge, or discard this patch.
src/Header/SetCookieHeader.php 1 patch
Indentation   +239 added lines, -239 removed lines patch added patch discarded remove patch
@@ -35,243 +35,243 @@
 block discarded – undo
35 35
 class SetCookieHeader extends Header
36 36
 {
37 37
 
38
-    /**
39
-     * Cookies are not sent on normal cross-site subrequests, but
40
-     * are sent when a user is navigating to the origin site.
41
-     *
42
-     * This is the default cookie value if SameSite has not been
43
-     * explicitly specified in recent browser versions..
44
-     *
45
-     * @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite#lax
46
-     *
47
-     * @var string
48
-     */
49
-    public const SAME_SITE_LAX = 'Lax';
50
-
51
-    /**
52
-     * Cookies will only be sent in a first-party context and not
53
-     * be sent along with requests initiated by third party websites.
54
-     *
55
-     * @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite#strict
56
-     *
57
-     * @var string
58
-     */
59
-    public const SAME_SITE_STRICT = 'Strict';
60
-
61
-    /**
62
-     * Cookies will be sent in all contexts, i.e. in responses to
63
-     * both first-party and cross-site requests.
64
-     *
65
-     * If SameSite=None is set, the cookie Secure attribute must
66
-     * also be set (or the cookie will be blocked).
67
-     *
68
-     * @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite#none
69
-     *
70
-     * @var string
71
-     */
72
-    public const SAME_SITE_NONE = 'None';
73
-
74
-    /**
75
-     * Cookie option keys
76
-     *
77
-     * @var string
78
-     */
79
-    public const OPTION_KEY_PATH = 'path';
80
-    public const OPTION_KEY_DOMAIN = 'domain';
81
-    public const OPTION_KEY_SECURE = 'secure';
82
-    public const OPTION_KEY_HTTP_ONLY = 'httpOnly';
83
-    public const OPTION_KEY_SAMESITE = 'sameSite';
84
-
85
-    /**
86
-     * Default cookie options
87
-     *
88
-     * @var array{
89
-     *        path?: ?string,
90
-     *        domain?: ?string,
91
-     *        secure?: ?bool,
92
-     *        httpOnly?: ?bool,
93
-     *        sameSite?: ?string
94
-     *      }
95
-     */
96
-    protected static array $defaultOptions = [
97
-        self::OPTION_KEY_PATH      => '/',
98
-        self::OPTION_KEY_DOMAIN    => null,
99
-        self::OPTION_KEY_SECURE    => null,
100
-        self::OPTION_KEY_HTTP_ONLY => true,
101
-        self::OPTION_KEY_SAMESITE  => self::SAME_SITE_LAX,
102
-    ];
103
-
104
-    /**
105
-     * The cookie name
106
-     *
107
-     * @var string
108
-     */
109
-    private string $name;
110
-
111
-    /**
112
-     * The cookie value
113
-     *
114
-     * @var string
115
-     */
116
-    private string $value;
117
-
118
-    /**
119
-     * The cookie expiration date
120
-     *
121
-     * @var DateTimeInterface|null
122
-     */
123
-    private ?DateTimeInterface $expires;
124
-
125
-    /**
126
-     * The cookie options
127
-     *
128
-     * @var array{
129
-     *        path?: ?string,
130
-     *        domain?: ?string,
131
-     *        secure?: ?bool,
132
-     *        httpOnly?: ?bool,
133
-     *        sameSite?: ?string
134
-     *      }
135
-     */
136
-    private array $options;
137
-
138
-    /**
139
-     * Constructor of the class
140
-     *
141
-     * @param string $name
142
-     * @param string $value
143
-     * @param DateTimeInterface|null $expires
144
-     * @param array{path?: ?string, domain?: ?string, secure?: ?bool, httpOnly?: ?bool, sameSite?: ?string} $options
145
-     *
146
-     * @throws InvalidHeaderValueException
147
-     *         If one of the parameters isn't valid.
148
-     */
149
-    public function __construct(string $name, string $value, ?DateTimeInterface $expires = null, array $options = [])
150
-    {
151
-        $this->validateCookieName($name);
152
-
153
-        if (isset($options[self::OPTION_KEY_PATH])) {
154
-            $this->validateCookieOption(self::OPTION_KEY_PATH, $options[self::OPTION_KEY_PATH]);
155
-        }
156
-
157
-        if (isset($options[self::OPTION_KEY_DOMAIN])) {
158
-            $this->validateCookieOption(self::OPTION_KEY_DOMAIN, $options[self::OPTION_KEY_DOMAIN]);
159
-        }
160
-
161
-        if (isset($options[self::OPTION_KEY_SAMESITE])) {
162
-            $this->validateCookieOption(self::OPTION_KEY_SAMESITE, $options[self::OPTION_KEY_SAMESITE]);
163
-        }
164
-
165
-        if ($value === '') {
166
-            $value = 'deleted';
167
-            $expires = new DateTimeImmutable('1 year ago');
168
-        }
169
-
170
-        $options += static::$defaultOptions;
171
-
172
-        $this->name = $name;
173
-        $this->value = $value;
174
-        $this->expires = $expires;
175
-        $this->options = $options;
176
-    }
177
-
178
-    /**
179
-     * {@inheritdoc}
180
-     */
181
-    public function getFieldName(): string
182
-    {
183
-        return 'Set-Cookie';
184
-    }
185
-
186
-    /**
187
-     * {@inheritdoc}
188
-     */
189
-    public function getFieldValue(): string
190
-    {
191
-        $name = rawurlencode($this->name);
192
-        $value = rawurlencode($this->value);
193
-        $result = sprintf('%s=%s', $name, $value);
194
-
195
-        if (isset($this->expires)) {
196
-            $result .= '; Expires=' . $this->formatDateTime($this->expires);
197
-            $result .= '; Max-Age=' . max($this->expires->getTimestamp() - time(), 0);
198
-        }
199
-
200
-        if (isset($this->options[self::OPTION_KEY_PATH])) {
201
-            $result .= '; Path=' . $this->options[self::OPTION_KEY_PATH];
202
-        }
203
-
204
-        if (isset($this->options[self::OPTION_KEY_DOMAIN])) {
205
-            $result .= '; Domain=' . $this->options[self::OPTION_KEY_DOMAIN];
206
-        }
207
-
208
-        if (isset($this->options[self::OPTION_KEY_SECURE]) && $this->options[self::OPTION_KEY_SECURE]) {
209
-            $result .= '; Secure';
210
-        }
211
-
212
-        if (isset($this->options[self::OPTION_KEY_HTTP_ONLY]) && $this->options[self::OPTION_KEY_HTTP_ONLY]) {
213
-            $result .= '; HttpOnly';
214
-        }
215
-
216
-        if (isset($this->options[self::OPTION_KEY_SAMESITE])) {
217
-            $result .= '; SameSite=' . $this->options[self::OPTION_KEY_SAMESITE];
218
-        }
219
-
220
-        return $result;
221
-    }
222
-
223
-    /**
224
-     * Validates the given cookie name
225
-     *
226
-     * @param string $name
227
-     *
228
-     * @return void
229
-     *
230
-     * @throws InvalidHeaderValueException
231
-     *         If the cookie name isn't valid.
232
-     */
233
-    private function validateCookieName(string $name): void
234
-    {
235
-        if ('' === $name) {
236
-            throw new InvalidHeaderValueException('Cookie name cannot be empty');
237
-        }
238
-
239
-        // https://github.com/php/php-src/blob/02a5335b710aa36cd0c3108bfb9c6f7a57d40000/ext/standard/head.c#L93
240
-        if (strpbrk($name, "=,; \t\r\n\013\014") !== false) {
241
-            throw new InvalidHeaderValueException(sprintf(
242
-                'The cookie name "%s" contains prohibited characters',
243
-                $name
244
-            ));
245
-        }
246
-    }
247
-
248
-    /**
249
-     * Validates the given cookie option
250
-     *
251
-     * @param string $validKey
252
-     * @param mixed $value
253
-     *
254
-     * @return void
255
-     *
256
-     * @throws InvalidHeaderValueException
257
-     *         If the cookie option isn't valid.
258
-     */
259
-    private function validateCookieOption(string $validKey, $value): void
260
-    {
261
-        if (!is_string($value)) {
262
-            throw new InvalidHeaderValueException(sprintf(
263
-                'The cookie option "%s" must be a string',
264
-                $validKey
265
-            ));
266
-        }
267
-
268
-        // https://github.com/php/php-src/blob/02a5335b710aa36cd0c3108bfb9c6f7a57d40000/ext/standard/head.c#L103
269
-        // https://github.com/php/php-src/blob/02a5335b710aa36cd0c3108bfb9c6f7a57d40000/ext/standard/head.c#L108
270
-        if (strpbrk($value, ",; \t\r\n\013\014") !== false) {
271
-            throw new InvalidHeaderValueException(sprintf(
272
-                'The cookie option "%s" contains prohibited characters',
273
-                $validKey
274
-            ));
275
-        }
276
-    }
38
+	/**
39
+	 * Cookies are not sent on normal cross-site subrequests, but
40
+	 * are sent when a user is navigating to the origin site.
41
+	 *
42
+	 * This is the default cookie value if SameSite has not been
43
+	 * explicitly specified in recent browser versions..
44
+	 *
45
+	 * @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite#lax
46
+	 *
47
+	 * @var string
48
+	 */
49
+	public const SAME_SITE_LAX = 'Lax';
50
+
51
+	/**
52
+	 * Cookies will only be sent in a first-party context and not
53
+	 * be sent along with requests initiated by third party websites.
54
+	 *
55
+	 * @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite#strict
56
+	 *
57
+	 * @var string
58
+	 */
59
+	public const SAME_SITE_STRICT = 'Strict';
60
+
61
+	/**
62
+	 * Cookies will be sent in all contexts, i.e. in responses to
63
+	 * both first-party and cross-site requests.
64
+	 *
65
+	 * If SameSite=None is set, the cookie Secure attribute must
66
+	 * also be set (or the cookie will be blocked).
67
+	 *
68
+	 * @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite#none
69
+	 *
70
+	 * @var string
71
+	 */
72
+	public const SAME_SITE_NONE = 'None';
73
+
74
+	/**
75
+	 * Cookie option keys
76
+	 *
77
+	 * @var string
78
+	 */
79
+	public const OPTION_KEY_PATH = 'path';
80
+	public const OPTION_KEY_DOMAIN = 'domain';
81
+	public const OPTION_KEY_SECURE = 'secure';
82
+	public const OPTION_KEY_HTTP_ONLY = 'httpOnly';
83
+	public const OPTION_KEY_SAMESITE = 'sameSite';
84
+
85
+	/**
86
+	 * Default cookie options
87
+	 *
88
+	 * @var array{
89
+	 *        path?: ?string,
90
+	 *        domain?: ?string,
91
+	 *        secure?: ?bool,
92
+	 *        httpOnly?: ?bool,
93
+	 *        sameSite?: ?string
94
+	 *      }
95
+	 */
96
+	protected static array $defaultOptions = [
97
+		self::OPTION_KEY_PATH      => '/',
98
+		self::OPTION_KEY_DOMAIN    => null,
99
+		self::OPTION_KEY_SECURE    => null,
100
+		self::OPTION_KEY_HTTP_ONLY => true,
101
+		self::OPTION_KEY_SAMESITE  => self::SAME_SITE_LAX,
102
+	];
103
+
104
+	/**
105
+	 * The cookie name
106
+	 *
107
+	 * @var string
108
+	 */
109
+	private string $name;
110
+
111
+	/**
112
+	 * The cookie value
113
+	 *
114
+	 * @var string
115
+	 */
116
+	private string $value;
117
+
118
+	/**
119
+	 * The cookie expiration date
120
+	 *
121
+	 * @var DateTimeInterface|null
122
+	 */
123
+	private ?DateTimeInterface $expires;
124
+
125
+	/**
126
+	 * The cookie options
127
+	 *
128
+	 * @var array{
129
+	 *        path?: ?string,
130
+	 *        domain?: ?string,
131
+	 *        secure?: ?bool,
132
+	 *        httpOnly?: ?bool,
133
+	 *        sameSite?: ?string
134
+	 *      }
135
+	 */
136
+	private array $options;
137
+
138
+	/**
139
+	 * Constructor of the class
140
+	 *
141
+	 * @param string $name
142
+	 * @param string $value
143
+	 * @param DateTimeInterface|null $expires
144
+	 * @param array{path?: ?string, domain?: ?string, secure?: ?bool, httpOnly?: ?bool, sameSite?: ?string} $options
145
+	 *
146
+	 * @throws InvalidHeaderValueException
147
+	 *         If one of the parameters isn't valid.
148
+	 */
149
+	public function __construct(string $name, string $value, ?DateTimeInterface $expires = null, array $options = [])
150
+	{
151
+		$this->validateCookieName($name);
152
+
153
+		if (isset($options[self::OPTION_KEY_PATH])) {
154
+			$this->validateCookieOption(self::OPTION_KEY_PATH, $options[self::OPTION_KEY_PATH]);
155
+		}
156
+
157
+		if (isset($options[self::OPTION_KEY_DOMAIN])) {
158
+			$this->validateCookieOption(self::OPTION_KEY_DOMAIN, $options[self::OPTION_KEY_DOMAIN]);
159
+		}
160
+
161
+		if (isset($options[self::OPTION_KEY_SAMESITE])) {
162
+			$this->validateCookieOption(self::OPTION_KEY_SAMESITE, $options[self::OPTION_KEY_SAMESITE]);
163
+		}
164
+
165
+		if ($value === '') {
166
+			$value = 'deleted';
167
+			$expires = new DateTimeImmutable('1 year ago');
168
+		}
169
+
170
+		$options += static::$defaultOptions;
171
+
172
+		$this->name = $name;
173
+		$this->value = $value;
174
+		$this->expires = $expires;
175
+		$this->options = $options;
176
+	}
177
+
178
+	/**
179
+	 * {@inheritdoc}
180
+	 */
181
+	public function getFieldName(): string
182
+	{
183
+		return 'Set-Cookie';
184
+	}
185
+
186
+	/**
187
+	 * {@inheritdoc}
188
+	 */
189
+	public function getFieldValue(): string
190
+	{
191
+		$name = rawurlencode($this->name);
192
+		$value = rawurlencode($this->value);
193
+		$result = sprintf('%s=%s', $name, $value);
194
+
195
+		if (isset($this->expires)) {
196
+			$result .= '; Expires=' . $this->formatDateTime($this->expires);
197
+			$result .= '; Max-Age=' . max($this->expires->getTimestamp() - time(), 0);
198
+		}
199
+
200
+		if (isset($this->options[self::OPTION_KEY_PATH])) {
201
+			$result .= '; Path=' . $this->options[self::OPTION_KEY_PATH];
202
+		}
203
+
204
+		if (isset($this->options[self::OPTION_KEY_DOMAIN])) {
205
+			$result .= '; Domain=' . $this->options[self::OPTION_KEY_DOMAIN];
206
+		}
207
+
208
+		if (isset($this->options[self::OPTION_KEY_SECURE]) && $this->options[self::OPTION_KEY_SECURE]) {
209
+			$result .= '; Secure';
210
+		}
211
+
212
+		if (isset($this->options[self::OPTION_KEY_HTTP_ONLY]) && $this->options[self::OPTION_KEY_HTTP_ONLY]) {
213
+			$result .= '; HttpOnly';
214
+		}
215
+
216
+		if (isset($this->options[self::OPTION_KEY_SAMESITE])) {
217
+			$result .= '; SameSite=' . $this->options[self::OPTION_KEY_SAMESITE];
218
+		}
219
+
220
+		return $result;
221
+	}
222
+
223
+	/**
224
+	 * Validates the given cookie name
225
+	 *
226
+	 * @param string $name
227
+	 *
228
+	 * @return void
229
+	 *
230
+	 * @throws InvalidHeaderValueException
231
+	 *         If the cookie name isn't valid.
232
+	 */
233
+	private function validateCookieName(string $name): void
234
+	{
235
+		if ('' === $name) {
236
+			throw new InvalidHeaderValueException('Cookie name cannot be empty');
237
+		}
238
+
239
+		// https://github.com/php/php-src/blob/02a5335b710aa36cd0c3108bfb9c6f7a57d40000/ext/standard/head.c#L93
240
+		if (strpbrk($name, "=,; \t\r\n\013\014") !== false) {
241
+			throw new InvalidHeaderValueException(sprintf(
242
+				'The cookie name "%s" contains prohibited characters',
243
+				$name
244
+			));
245
+		}
246
+	}
247
+
248
+	/**
249
+	 * Validates the given cookie option
250
+	 *
251
+	 * @param string $validKey
252
+	 * @param mixed $value
253
+	 *
254
+	 * @return void
255
+	 *
256
+	 * @throws InvalidHeaderValueException
257
+	 *         If the cookie option isn't valid.
258
+	 */
259
+	private function validateCookieOption(string $validKey, $value): void
260
+	{
261
+		if (!is_string($value)) {
262
+			throw new InvalidHeaderValueException(sprintf(
263
+				'The cookie option "%s" must be a string',
264
+				$validKey
265
+			));
266
+		}
267
+
268
+		// https://github.com/php/php-src/blob/02a5335b710aa36cd0c3108bfb9c6f7a57d40000/ext/standard/head.c#L103
269
+		// https://github.com/php/php-src/blob/02a5335b710aa36cd0c3108bfb9c6f7a57d40000/ext/standard/head.c#L108
270
+		if (strpbrk($value, ",; \t\r\n\013\014") !== false) {
271
+			throw new InvalidHeaderValueException(sprintf(
272
+				'The cookie option "%s" contains prohibited characters',
273
+				$validKey
274
+			));
275
+		}
276
+	}
277 277
 }
Please login to merge, or discard this patch.
src/Header/ClearSiteDataHeader.php 1 patch
Indentation   +36 added lines, -36 removed lines patch added patch discarded remove patch
@@ -29,46 +29,46 @@
 block discarded – undo
29 29
 class ClearSiteDataHeader extends Header
30 30
 {
31 31
 
32
-    /**
33
-     * @var list<string>
34
-     */
35
-    private array $directives;
32
+	/**
33
+	 * @var list<string>
34
+	 */
35
+	private array $directives;
36 36
 
37
-    /**
38
-     * Constructor of the class
39
-     *
40
-     * @param string ...$directives
41
-     *
42
-     * @throws InvalidHeaderValueException
43
-     *         If one of the directives isn't valid.
44
-     */
45
-    public function __construct(string ...$directives)
46
-    {
47
-        /** @var list<string> $directives */
37
+	/**
38
+	 * Constructor of the class
39
+	 *
40
+	 * @param string ...$directives
41
+	 *
42
+	 * @throws InvalidHeaderValueException
43
+	 *         If one of the directives isn't valid.
44
+	 */
45
+	public function __construct(string ...$directives)
46
+	{
47
+		/** @var list<string> $directives */
48 48
 
49
-        $this->validateQuotedString(...$directives);
49
+		$this->validateQuotedString(...$directives);
50 50
 
51
-        $this->directives = $directives;
52
-    }
51
+		$this->directives = $directives;
52
+	}
53 53
 
54
-    /**
55
-     * {@inheritdoc}
56
-     */
57
-    public function getFieldName(): string
58
-    {
59
-        return 'Clear-Site-Data';
60
-    }
54
+	/**
55
+	 * {@inheritdoc}
56
+	 */
57
+	public function getFieldName(): string
58
+	{
59
+		return 'Clear-Site-Data';
60
+	}
61 61
 
62
-    /**
63
-     * {@inheritdoc}
64
-     */
65
-    public function getFieldValue(): string
66
-    {
67
-        $segments = [];
68
-        foreach ($this->directives as $directive) {
69
-            $segments[] = sprintf('"%s"', $directive);
70
-        }
62
+	/**
63
+	 * {@inheritdoc}
64
+	 */
65
+	public function getFieldValue(): string
66
+	{
67
+		$segments = [];
68
+		foreach ($this->directives as $directive) {
69
+			$segments[] = sprintf('"%s"', $directive);
70
+		}
71 71
 
72
-        return implode(', ', $segments);
73
-    }
72
+		return implode(', ', $segments);
73
+	}
74 74
 }
Please login to merge, or discard this patch.
src/Header/KeepAliveHeader.php 1 patch
Indentation   +41 added lines, -41 removed lines patch added patch discarded remove patch
@@ -29,52 +29,52 @@
 block discarded – undo
29 29
 class KeepAliveHeader extends Header
30 30
 {
31 31
 
32
-    /**
33
-     * @var array<string, string>
34
-     */
35
-    private array $parameters;
32
+	/**
33
+	 * @var array<string, string>
34
+	 */
35
+	private array $parameters;
36 36
 
37
-    /**
38
-     * Constructor of the class
39
-     *
40
-     * @param array<array-key, mixed> $parameters
41
-     *
42
-     * @throws InvalidHeaderValueParameterException
43
-     *         If the parameters aren't valid.
44
-     */
45
-    public function __construct(array $parameters = [])
46
-    {
47
-        $parameters = $this->validateParameters($parameters);
37
+	/**
38
+	 * Constructor of the class
39
+	 *
40
+	 * @param array<array-key, mixed> $parameters
41
+	 *
42
+	 * @throws InvalidHeaderValueParameterException
43
+	 *         If the parameters aren't valid.
44
+	 */
45
+	public function __construct(array $parameters = [])
46
+	{
47
+		$parameters = $this->validateParameters($parameters);
48 48
 
49
-        $this->parameters = $parameters;
50
-    }
49
+		$this->parameters = $parameters;
50
+	}
51 51
 
52
-    /**
53
-     * {@inheritdoc}
54
-     */
55
-    public function getFieldName(): string
56
-    {
57
-        return 'Keep-Alive';
58
-    }
52
+	/**
53
+	 * {@inheritdoc}
54
+	 */
55
+	public function getFieldName(): string
56
+	{
57
+		return 'Keep-Alive';
58
+	}
59 59
 
60
-    /**
61
-     * {@inheritdoc}
62
-     */
63
-    public function getFieldValue(): string
64
-    {
65
-        $segments = [];
66
-        foreach ($this->parameters as $name => $value) {
67
-            // the construction <foo=> isn't valid...
68
-            if ($value === '') {
69
-                $segments[] = $name;
70
-                continue;
71
-            }
60
+	/**
61
+	 * {@inheritdoc}
62
+	 */
63
+	public function getFieldValue(): string
64
+	{
65
+		$segments = [];
66
+		foreach ($this->parameters as $name => $value) {
67
+			// the construction <foo=> isn't valid...
68
+			if ($value === '') {
69
+				$segments[] = $name;
70
+				continue;
71
+			}
72 72
 
73
-            $format = $this->isToken($value) ? '%s=%s' : '%s="%s"';
73
+			$format = $this->isToken($value) ? '%s=%s' : '%s="%s"';
74 74
 
75
-            $segments[] = sprintf($format, $name, $value);
76
-        }
75
+			$segments[] = sprintf($format, $name, $value);
76
+		}
77 77
 
78
-        return implode(', ', $segments);
79
-    }
78
+		return implode(', ', $segments);
79
+	}
80 80
 }
Please login to merge, or discard this patch.
src/Header/EtagHeader.php 1 patch
Indentation   +31 added lines, -31 removed lines patch added patch discarded remove patch
@@ -28,39 +28,39 @@
 block discarded – undo
28 28
 class EtagHeader extends Header
29 29
 {
30 30
 
31
-    /**
32
-     * @var string
33
-     */
34
-    private string $value;
31
+	/**
32
+	 * @var string
33
+	 */
34
+	private string $value;
35 35
 
36
-    /**
37
-     * Constructor of the class
38
-     *
39
-     * @param string $value
40
-     *
41
-     * @throws InvalidHeaderValueException
42
-     *         If the value isn't valid.
43
-     */
44
-    public function __construct(string $value)
45
-    {
46
-        $this->validateQuotedString($value);
36
+	/**
37
+	 * Constructor of the class
38
+	 *
39
+	 * @param string $value
40
+	 *
41
+	 * @throws InvalidHeaderValueException
42
+	 *         If the value isn't valid.
43
+	 */
44
+	public function __construct(string $value)
45
+	{
46
+		$this->validateQuotedString($value);
47 47
 
48
-        $this->value = $value;
49
-    }
48
+		$this->value = $value;
49
+	}
50 50
 
51
-    /**
52
-     * {@inheritdoc}
53
-     */
54
-    public function getFieldName(): string
55
-    {
56
-        return 'ETag';
57
-    }
51
+	/**
52
+	 * {@inheritdoc}
53
+	 */
54
+	public function getFieldName(): string
55
+	{
56
+		return 'ETag';
57
+	}
58 58
 
59
-    /**
60
-     * {@inheritdoc}
61
-     */
62
-    public function getFieldValue(): string
63
-    {
64
-        return sprintf('"%s"', $this->value);
65
-    }
59
+	/**
60
+	 * {@inheritdoc}
61
+	 */
62
+	public function getFieldValue(): string
63
+	{
64
+		return sprintf('"%s"', $this->value);
65
+	}
66 66
 }
Please login to merge, or discard this patch.
src/Header/AllowHeader.php 1 patch
Indentation   +35 added lines, -35 removed lines patch added patch discarded remove patch
@@ -29,44 +29,44 @@
 block discarded – undo
29 29
 class AllowHeader extends Header
30 30
 {
31 31
 
32
-    /**
33
-     * @var list<string>
34
-     */
35
-    private array $methods = [];
32
+	/**
33
+	 * @var list<string>
34
+	 */
35
+	private array $methods = [];
36 36
 
37
-    /**
38
-     * Constructor of the class
39
-     *
40
-     * @param string ...$methods
41
-     *
42
-     * @throws InvalidHeaderValueException
43
-     *         If one of the methods isn't valid.
44
-     */
45
-    public function __construct(string ...$methods)
46
-    {
47
-        /** @var list<string> $methods */
37
+	/**
38
+	 * Constructor of the class
39
+	 *
40
+	 * @param string ...$methods
41
+	 *
42
+	 * @throws InvalidHeaderValueException
43
+	 *         If one of the methods isn't valid.
44
+	 */
45
+	public function __construct(string ...$methods)
46
+	{
47
+		/** @var list<string> $methods */
48 48
 
49
-        $this->validateToken(...$methods);
49
+		$this->validateToken(...$methods);
50 50
 
51
-        // normalize the list of methods...
52
-        foreach ($methods as $method) {
53
-            $this->methods[] = strtoupper($method);
54
-        }
55
-    }
51
+		// normalize the list of methods...
52
+		foreach ($methods as $method) {
53
+			$this->methods[] = strtoupper($method);
54
+		}
55
+	}
56 56
 
57
-    /**
58
-     * {@inheritdoc}
59
-     */
60
-    public function getFieldName(): string
61
-    {
62
-        return 'Allow';
63
-    }
57
+	/**
58
+	 * {@inheritdoc}
59
+	 */
60
+	public function getFieldName(): string
61
+	{
62
+		return 'Allow';
63
+	}
64 64
 
65
-    /**
66
-     * {@inheritdoc}
67
-     */
68
-    public function getFieldValue(): string
69
-    {
70
-        return implode(', ', $this->methods);
71
-    }
65
+	/**
66
+	 * {@inheritdoc}
67
+	 */
68
+	public function getFieldValue(): string
69
+	{
70
+		return implode(', ', $this->methods);
71
+	}
72 72
 }
Please login to merge, or discard this patch.