Passed
Push — master ( fca16e...a09e23 )
by Alexander
04:10
created

ResponseHeaders::getCookies()   A

Complexity

Conditions 6
Paths 6

Size

Total Lines 23
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 11
nc 6
nop 1
dl 0
loc 23
rs 9.2222
c 1
b 0
f 0
1
<?php
2
3
/**
4
 * Lenevor Framework
5
 *
6
 * LICENSE
7
 *
8
 * This source file is subject to the new BSD license that is bundled
9
 * with this package in the file license.md.
10
 * It is also available through the world-wide-web at this URL:
11
 * https://lenevor.com/license
12
 * If you did not receive a copy of the license and are unable to
13
 * obtain it through the world-wide-web, please send an email
14
 * to [email protected] so we can send you a copy immediately.
15
 *
16
 * @package     Lenevor
17
 * @subpackage  Base
18
 * @link        https://lenevor.com
19
 * @copyright   Copyright (c) 2019 - 2023 Alexander Campo <[email protected]>
20
 * @license     https://opensource.org/licenses/BSD-3-Clause New BSD license or see https://lenevor.com/license or see /license.md
21
 */
22
23
namespace Syscodes\Components\Http;
24
25
use InvalidArgumentException;
26
use Syscodes\Components\Http\Loaders\Headers;
27
28
/**
29
 * ResponseHeaders is a container for Response HTTP headers.
30
 */
31
class ResponseHeaders extends Headers
32
{
33
	const COOKIE_FLAT = 'flat';
34
	const COOKIE_ARRAY = 'array';
35
	
36
	/**
37
	 * The list of cookies.
38
	 * 
39
	 * @var array $cookies
40
	 */
41
	protected $cookies = [];
42
43
    /**
44
     * The header names.
45
	 * 
46
	 * @var array $headerNames 
47
     */
48
	protected $headerNames = [];
49
50
	/**
51
	 * Constructor. Create a new ResponseHeaders class instance.
52
	 * 
53
	 * @param  array  $headers
54
	 * 
55
	 * @return void 
56
	 */
57
	public function __construct(array $headers = [])
58
	{
59
		parent::__construct($headers);
60
		
61
		if ( ! isset($this->headers['cache-control'])) {
62
			$this->set('Cache-Control', '');
63
		}
64
65
		if ( ! isset($this->headers['date'])) {
66
			$this->initDate();
67
		}
68
	}
69
70
	/**
71
	 * Returns the headers, without cookies.
72
	 * 
73
	 * @return mixed
74
	 */
75
	public function allPreserveCaseWithoutCookies()
76
	{
77
		$headers = $this->allPreserveCase();
78
		
79
		if (isset($this->headerNames['set-cookie'])) {
80
			unset($headers[$this->headerNames['set-cookie']]);
81
		}
82
		
83
		return $headers;
84
	}
85
86
    /**
87
	 * Returns the headers, with original capitalizations.
88
	 * 
89
	 * @return array An array of headers
90
	 */
91
	public function allPreserveCase(): array
92
	{
93
		$headers = [];
94
		
95
		foreach ($this->all() as $name => $value) {
96
			$headers[$this->headerNames[$name] ?? $name] = $value;
97
		}
98
		
99
		return $headers;
100
	}
101
	
102
	/**
103
	 * Returns all the headers.
104
	 * 
105
	 * @param  string|null  $key  The name of the headers
106
	 * 
107
	 * @return array
108
	 */
109
	public function all(string $key = null): array
110
	{
111
		$headers = parent::all();
112
		
113
		if (null !== $key) {
114
			$key = strtr($key, self::STRING_UPPER, self::STRING_LOWER);
115
			
116
			return 'set-cookie' !== $key ? $headers[$key] ?? [] : array_map('strval', $this->getCookies());
117
		}
118
		
119
		foreach ($this->getCookies() as $cookie) {
120
			$headers['set-cookie'][] = (string) $cookie;
121
		}
122
		
123
		return $headers;
124
	}
125
126
	/**
127
	 * Replaces the current HTTP headers by a new set.
128
	 * 
129
	 * @param  array  $headers
130
	 * 
131
	 * @return void
132
	 */
133
	public function replace(array $headers = []): void
134
	{
135
		$this->headerNames = [];
136
137
		parent::replace($headers);
138
139
		if ( ! isset($this->headers['cache-control'])) {
140
			$this->set('Cache-Control', '');
141
		}
142
		
143
		if ( ! isset($this->headers['date'])) {
144
			$this->initDate();
145
		}
146
	}
147
148
	/**
149
	 * Sets a header by name.
150
	 * 
151
	 * @param  string  $key  The header name
152
	 * @param  string|string[]|null  $values  The value or an array of values
153
	 * @param  bool  $replace  If you want to replace the value exists by the header, 
154
	 * 					       it is not overwritten / overwritten when it is false
155
	 *
156
	 * @return void
157
	 */
158
	public function set(string $key, $values, bool $replace = true): void
159
	{
160
		$unique = strtr($key, self::STRING_UPPER, self::STRING_LOWER); 
161
		
162
		if ('set-cookie' === $unique) {
163
			if ($replace) {
164
				$this->cookies = [];
165
			}
166
			
167
			foreach ((array) $values as $cookie) {
168
				$this->setCookie($cookie);
0 ignored issues
show
Bug introduced by
$cookie of type string is incompatible with the type Syscodes\Components\Http\Cookie expected by parameter $cookie of Syscodes\Components\Http...nseHeaders::setCookie(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

168
				$this->setCookie(/** @scrutinizer ignore-type */ $cookie);
Loading history...
169
			}
170
			
171
			$this->headerNames[$unique] = $key;
172
173
			return;
174
		}
175
		
176
		$this->headerNames[$unique] = $key;
177
		
178
		parent::set($key, $values, $replace);
179
	}
180
	
181
	/**
182
	 * Gets an array with all cookies.
183
	 * 
184
	 * @param  string  $format
185
	 * 
186
	 * @return Cookie[]
187
	 * 
188
	 * @throws \InvalidArgumentException
189
	 */
190
	public function getCookies(string $format = self::COOKIE_FLAT): array
191
	{
192
		if ( ! in_array($format, [self::COOKIE_FLAT, self::COOKIE_ARRAY])) {
193
			throw new InvalidArgumentException(
194
				sprintf('Format "%s" invalid (%s)', $format, implode(', ', [self::COOKIE_FLAT, self::COOKIE_ARRAY])
195
			));
196
		}
197
		
198
		if (self::COOKIE_ARRAY === $format) {
199
			return $this->cookies;
200
		}
201
		
202
		$stringCookies = [];
203
204
		foreach ($this->cookies as $path) {
205
			foreach ($path as $cookies) {
206
				foreach ($cookies as $cookie) {
207
					$stringCookies[] = $cookie;
208
				}
209
			}
210
		}
211
		
212
		return $stringCookies;
213
    }
214
215
	/**
216
	 * Sets the cookie.
217
	 * 
218
	 * @param  \Syscodes\Components\Http\Cookie  $cookie
219
	 * 
220
	 * @return static
221
	 */
222
	public function setCookie(Cookie $cookie): static
223
	{
224
		$this->cookies[$cookie->getDomain()][$cookie->getPath()][$cookie->getName()] = $cookie;
225
		$this->headerNames['set-cookie'] = 'Set-Cookie';
226
227
		return $this;
228
	}
229
230
	/**
231
	 * Initialize the date.
232
	 * 
233
	 * @return void
234
	 */
235
	private function initDate(): void
236
	{
237
		$this->set('Date', gmdate('D, d M Y H:i:s').' GMT');
238
	}
239
}