Passed
Pull Request — master (#244)
by
unknown
02:57
created

CookieCollection::getCookies()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 1
eloc 1
c 1
b 1
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Web;
6
7
use ArrayAccess;
8
use ArrayIterator;
9
use Closure;
10
use Countable;
11
use DateTimeImmutable;
12
use InvalidArgumentException;
13
use IteratorAggregate;
14
use Psr\Http\Message\ResponseInterface;
15
use Psr\Http\Message\ServerRequestInterface;
16
17
use function array_keys;
18
use function array_values;
19
use function count;
20
use function in_array;
21
22
/**
23
 * A CookieCollection is a collection implementation to wrap an array of Cookie class instances
24
 */
25
final class CookieCollection implements IteratorAggregate, ArrayAccess, Countable
26
{
27
    /**
28
     * @var Cookie[] the cookies in this collection (indexed by the cookie name)
29
     */
30
    private array $cookies = [];
31
32
    /**
33
     * CookieCollection constructor.
34
     * @param array $cookies the cookies that this collection initially contains.
35
     */
36
    public function __construct(array $cookies = [])
37
    {
38
        foreach ($cookies as $cookie) {
39
            if (!($cookie instanceof Cookie)) {
40
                throw new InvalidArgumentException('CookieCollection can contain only Cookie instances.');
41
            }
42
43
            $this->cookies[$cookie->getName()] = $cookie;
44
        }
45
    }
46
47
    /**
48
     * Returns the collection as a PHP array.
49
     * The array keys are cookie names, and the array values are the corresponding cookie objects.
50
     */
51
    public function toArray(): array
52
    {
53
        return $this->cookies;
54
    }
55
56
    /**
57
     * Returns an iterator for traversing the cookies in the collection.
58
     * This method is required by the SPL interface [[\IteratorAggregate]].
59
     * It will be implicitly called when you use `foreach` to traverse the collection.
60
     */
61
    public function getIterator(): \Traversable
62
    {
63
        return new ArrayIterator($this->cookies);
64
    }
65
66
    /**
67
     * Returns whether there is a cookie with the specified name.
68
     * This method is required by the SPL interface [[\ArrayAccess]].
69
     * It is implicitly called when you use something like `isset($collection[$name])`.
70
     * This is equivalent to [[has()]].
71
     * @param string $name the cookie name
72
     * @return bool whether the named cookie exists
73
     */
74
    public function offsetExists($name): bool
75
    {
76
        return $this->has($name);
77
    }
78
79
    /**
80
     * Returns the cookie with the specified name.
81
     * This method is required by the SPL interface [[\ArrayAccess]].
82
     * It is implicitly called when you use something like `$cookie = $collection[$name];`.
83
     * This is equivalent to [[get()]].
84
     * @param string $name the cookie name
85
     * @return Cookie the cookie with the specified name, null if the named cookie does not exist.
86
     */
87
    public function offsetGet($name): Cookie
88
    {
89
        return $this->get($name);
90
    }
91
92
    /**
93
     * Adds the cookie to the collection.
94
     * This method is required by the SPL interface [[\ArrayAccess]].
95
     * It is implicitly called when you use something like `$collection[$name] = $cookie;`.
96
     * This is equivalent to [[add()]].
97
     * @param string $name the cookie name
98
     * @param Cookie $cookie the cookie to be added
99
     */
100
    public function offsetSet($name, $cookie): void
101
    {
102
        $this->add($cookie);
103
    }
104
105
    /**
106
     * Removes the named cookie.
107
     * This method is required by the SPL interface [[\ArrayAccess]].
108
     * It is implicitly called when you use something like `unset($collection[$name])`.
109
     * This is equivalent to [[remove()]].
110
     * @param string $name the cookie name
111
     */
112
    public function offsetUnset($name): void
113
    {
114
        $this->remove($name);
115
    }
116
117
    /**
118
     * Returns the number of cookies in the collection.
119
     * This method is required by the SPL `Countable` interface.
120
     * It will be implicitly called when you use `count($collection)`.
121
     * @return int the number of cookies in the collection.
122
     */
123
    public function count(): int
124
    {
125
        return count($this->cookies);
126
    }
127
128
    /**
129
     * Returns the cookie with the specified name.
130
     * @param string $name the cookie name
131
     * @return Cookie the cookie with the specified name. Null if the named cookie does not exist.
132
     * @see getValue()
133
     */
134
    public function get(string $name): Cookie
135
    {
136
        return $this->cookies[$name];
137
    }
138
139
    /**
140
     * Returns the value of the named cookie.
141
     * @param string $name the cookie name
142
     * @param mixed $defaultValue the value that should be returned when the named cookie does not exist.
143
     * @return mixed the value of the named cookie.
144
     * @see get()
145
     */
146
    public function getValue(string $name, $defaultValue = null): ?string
147
    {
148
        return isset($this->cookies[$name]) ? $this->cookies[$name]->getValue() : $defaultValue;
149
    }
150
151
    /**
152
     * Adds a cookie to the collection.
153
     * If there is already a cookie with the same name in the collection, it will be removed first.
154
     * @param Cookie $cookie the cookie to be added
155
     */
156
    public function add(Cookie $cookie): void
157
    {
158
        $this->cookies[$cookie->getName()] = $cookie;
159
    }
160
161
    /**
162
     * Returns whether there is a cookie with the specified name.
163
     * @param string $name the cookie name
164
     * @return bool whether the named cookie exists
165
     * @see remove()
166
     */
167
    public function has(string $name): bool
168
    {
169
        return isset($this->cookies[$name]);
170
    }
171
172
    /**
173
     * Removes a cookie.
174
     * @param string $name the name of the cookie to be removed.
175
     * @return Cookie|null cookie that is removed
176
     */
177
    public function remove(string $name): ?Cookie
178
    {
179
        if (!isset($this->cookies[$name])) {
180
            return null;
181
        }
182
183
        $removed = $this->cookies[$name];
184
        unset($this->cookies[$name]);
185
186
        return $removed;
187
    }
188
189
    /**
190
     * Set cookie expire date to outdated to further remove it from browser.
191
     * @param string $name the name of the cookie to expire.
192
     */
193
    public function expire(string $name): void
194
    {
195
        if (!isset($this->cookies[$name])) {
196
            return;
197
        }
198
199
        $this->cookies[$name] = $this->cookies[$name]->expire();
200
    }
201
202
    /**
203
     * Removes all cookies.
204
     */
205
    public function clear(): void
206
    {
207
        $this->cookies = [];
208
    }
209
210
    /**
211
     * Returns whether the collection already contains the cookie.
212
     * @param Cookie $cookie the cookie to check for
213
     * @return bool whether cookie exists
214
     * @see has()
215
     */
216
    public function contains(Cookie $cookie): bool
217
    {
218
        return in_array($cookie, $this->cookies, true);
219
    }
220
221
    /**
222
     * Tests for the existence of the cookie that satisfies the given predicate.
223
     * @param Closure $p The predicate.
224
     * @return bool whether the predicate is true for at least on cookie.
225
     */
226
    public function exists(Closure $p): bool
227
    {
228
        foreach ($this->cookies as $name => $cookie) {
229
            if ($p($name, $cookie)) {
230
                return true;
231
            }
232
        }
233
234
        return false;
235
    }
236
237
    /**
238
     * Gets all names/indices of the collection.
239
     * @return array<int, string> The names/indices of the collection.
240
     */
241
    public function getNames(): array
242
    {
243
        return array_keys($this->cookies);
244
    }
245
246
    /**
247
     * Gets all cookies of the collection as an indexed array.
248
     * @return array The cookie in the collection, in the order they appear in the collection.
249
     */
250
    public function getCookies(): array
251
    {
252
        return array_values($this->cookies);
253
    }
254
255
    /**
256
     * Checks whether the collection is empty (contains no cookies).
257
     * @return bool whether the collection is empty.
258
     */
259
    public function isEmpty(): bool
260
    {
261
        return empty($this->cookies);
262
    }
263
264
    /**
265
     * Populates the cookie collection from an array of 'name' => 'value' pairs.
266
     * @param array $array the cookies to populate from
267
     * @return self collection created from array
268
     */
269
    public static function fromArray(array $array): self
270
    {
271
        // check if associative array with 'name' => 'value' pairs is passed
272
        if (count(array_filter(array_keys($array), 'is_string')) === 0) {
273
            throw new InvalidArgumentException('Array in wrong format is passed.');
274
        }
275
276
        $elements = [];
277
        foreach ($array as $name => $value) {
278
            $elements[$name] = new Cookie($name, $value);
279
        }
280
281
        return new self($elements);
282
    }
283
284
    /**
285
     * Populates the cookie collection from a ResponseInterface.
286
     * @param ResponseInterface $response the response object to populate from
287
     * @return self collection created from response
288
     */
289
    public static function fromResponse(ResponseInterface $response): self
290
    {
291
        $collection = new self();
292
        foreach ($response->getHeader('Set-Cookie') as $setCookieString) {
293
            $cookie = Cookie::fromSetCookieString($setCookieString);
294
            $collection->add($cookie);
295
        }
296
        return $collection;
297
    }
298
}
299