Passed
Pull Request — master (#19920)
by Rutger
09:12
created

CookieCollection::removeAll()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 0
dl 0
loc 6
ccs 0
cts 4
cp 0
crap 6
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @link https://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license https://www.yiiframework.com/license/
6
 */
7
8
namespace yii\web;
9
10
use ArrayIterator;
11
use Yii;
12
use yii\base\BaseObject;
13
use yii\base\InvalidCallException;
14
15
/**
16
 * CookieCollection maintains the cookies available in the current request.
17
 *
18
 * For more details and usage information on CookieCollection, see the [guide article on handling cookies](guide:runtime-sessions-cookies).
19
 *
20
 * @property-read int $count The number of cookies in the collection.
21
 *
22
 * @author Qiang Xue <[email protected]>
23
 * @since 2.0
24
 */
25
class CookieCollection extends BaseObject implements \IteratorAggregate, \ArrayAccess, \Countable
26
{
27
    /**
28
     * @var bool whether this collection is read only.
29
     */
30
    public $readOnly = false;
31
32
    /**
33
     * @var Cookie[] the cookies in this collection (indexed by the cookie names)
34
     */
35
    private $_cookies;
36
37
38
    /**
39
     * Constructor.
40
     * @param array $cookies the cookies that this collection initially contains. This should be
41
     * an array of name-value pairs.
42
     * @param array $config name-value pairs that will be used to initialize the object properties
43
     */
44 91
    public function __construct($cookies = [], $config = [])
45
    {
46 91
        $this->_cookies = $cookies;
47 91
        parent::__construct($config);
48 91
    }
49
50
    /**
51
     * Returns an iterator for traversing the cookies in the collection.
52
     * This method is required by the SPL interface [[\IteratorAggregate]].
53
     * It will be implicitly called when you use `foreach` to traverse the collection.
54
     * @return ArrayIterator<string, Cookie> an iterator for traversing the cookies in the collection.
55
     */
56
    #[\ReturnTypeWillChange]
57 7
    public function getIterator()
58
    {
59 7
        return new ArrayIterator($this->_cookies);
60
    }
61
62
    /**
63
     * Returns the number of cookies in the collection.
64
     * This method is required by the SPL `Countable` interface.
65
     * It will be implicitly called when you use `count($collection)`.
66
     * @return int the number of cookies in the collection.
67
     */
68
    #[\ReturnTypeWillChange]
69
    public function count()
70
    {
71
        return $this->getCount();
72
    }
73
74
    /**
75
     * Returns the number of cookies in the collection.
76
     * @return int the number of cookies in the collection.
77
     */
78
    public function getCount()
79
    {
80
        return count($this->_cookies);
81
    }
82
83
    /**
84
     * Returns the cookie with the specified name.
85
     * @param string $name the cookie name
86
     * @return Cookie|null the cookie with the specified name. Null if the named cookie does not exist.
87
     * @see getValue()
88
     */
89
    public function get($name)
90
    {
91
        return isset($this->_cookies[$name]) ? $this->_cookies[$name] : null;
92
    }
93
94
    /**
95
     * Returns the value of the named cookie.
96
     * @param string $name the cookie name
97
     * @param mixed $defaultValue the value that should be returned when the named cookie does not exist.
98
     * @return mixed the value of the named cookie.
99
     * @see get()
100
     */
101 87
    public function getValue($name, $defaultValue = null)
102
    {
103 87
        return isset($this->_cookies[$name]) ? $this->_cookies[$name]->value : $defaultValue;
104
    }
105
106
    /**
107
     * Returns whether there is a cookie with the specified name.
108
     * Note that if a cookie is marked for deletion from browser or its value is an empty string, this method will return false.
109
     * @param string $name the cookie name
110
     * @return bool whether the named cookie exists
111
     * @see remove()
112
     */
113 4
    public function has($name)
114
    {
115 4
        return isset($this->_cookies[$name]) && $this->_cookies[$name]->value !== ''
116 3
            && ($this->_cookies[$name]->expire === null
117 3
                || $this->_cookies[$name]->expire === 0
118
                || (
119 3
                    is_string($this->_cookies[$name]->expire) && strtotime($this->_cookies[$name]->expire) >= time()
0 ignored issues
show
Bug introduced by
It seems like $this->_cookies[$name]->expire can also be of type null; however, parameter $datetime of strtotime() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

119
                    is_string($this->_cookies[$name]->expire) && strtotime(/** @scrutinizer ignore-type */ $this->_cookies[$name]->expire) >= time()
Loading history...
120 4
                    || $this->_cookies[$name]->expire >= time()
121
                )
122
            );
123
    }
124
125
    /**
126
     * Adds a cookie to the collection.
127
     * If there is already a cookie with the same name in the collection, it will be removed first.
128
     * @param Cookie $cookie the cookie to be added
129
     * @throws InvalidCallException if the cookie collection is read only
130
     */
131 91
    public function add($cookie)
132
    {
133 91
        if ($this->readOnly) {
134
            throw new InvalidCallException('The cookie collection is read only.');
135
        }
136 91
        $this->_cookies[$cookie->name] = $cookie;
137 91
    }
138
139
    /**
140
     * Removes a cookie.
141
     * If `$removeFromBrowser` is true, the cookie will be removed from the browser.
142
     * In this case, a cookie with outdated expiry will be added to the collection.
143
     * @param Cookie|string $cookie the cookie object or the name of the cookie to be removed.
144
     * @param bool $removeFromBrowser whether to remove the cookie from browser
145
     * @throws InvalidCallException if the cookie collection is read only
146
     */
147 2
    public function remove($cookie, $removeFromBrowser = true)
148
    {
149 2
        if ($this->readOnly) {
150
            throw new InvalidCallException('The cookie collection is read only.');
151
        }
152 2
        if ($cookie instanceof Cookie) {
153 2
            $cookie->expire = 1;
154 2
            $cookie->value = '';
155
        } else {
156
            $cookie = Yii::createObject([
157
                'class' => 'yii\web\Cookie',
158
                'name' => $cookie,
159
                'expire' => 1,
160
            ]);
161
        }
162 2
        if ($removeFromBrowser) {
163 2
            $this->_cookies[$cookie->name] = $cookie;
164
        } else {
165
            unset($this->_cookies[$cookie->name]);
166
        }
167 2
    }
168
169
    /**
170
     * Removes all cookies.
171
     * @throws InvalidCallException if the cookie collection is read only
172
     */
173
    public function removeAll()
174
    {
175
        if ($this->readOnly) {
176
            throw new InvalidCallException('The cookie collection is read only.');
177
        }
178
        $this->_cookies = [];
179
    }
180
181
    /**
182
     * Returns the collection as a PHP array.
183
     * @return Cookie[] the array representation of the collection.
184
     * The array keys are cookie names, and the array values are the corresponding cookie objects.
185
     */
186 3
    public function toArray()
187
    {
188 3
        return $this->_cookies;
189
    }
190
191
    /**
192
     * Populates the cookie collection from an array.
193
     * @param array $array the cookies to populate from
194
     * @since 2.0.3
195
     */
196 3
    public function fromArray(array $array)
197
    {
198 3
        $this->_cookies = $array;
199 3
    }
200
201
    /**
202
     * Returns whether there is a cookie with the specified name.
203
     * This method is required by the SPL interface [[\ArrayAccess]].
204
     * It is implicitly called when you use something like `isset($collection[$name])`.
205
     * @param string $name the cookie name
206
     * @return bool whether the named cookie exists
207
     */
208
    #[\ReturnTypeWillChange]
209
    public function offsetExists($name)
210
    {
211
        return $this->has($name);
212
    }
213
214
    /**
215
     * Returns the cookie with the specified name.
216
     * This method is required by the SPL interface [[\ArrayAccess]].
217
     * It is implicitly called when you use something like `$cookie = $collection[$name];`.
218
     * This is equivalent to [[get()]].
219
     * @param string $name the cookie name
220
     * @return Cookie|null the cookie with the specified name, null if the named cookie does not exist.
221
     */
222
    #[\ReturnTypeWillChange]
223
    public function offsetGet($name)
224
    {
225
        return $this->get($name);
226
    }
227
228
    /**
229
     * Adds the cookie to the collection.
230
     * This method is required by the SPL interface [[\ArrayAccess]].
231
     * It is implicitly called when you use something like `$collection[$name] = $cookie;`.
232
     * This is equivalent to [[add()]].
233
     * @param string $name the cookie name
234
     * @param Cookie $cookie the cookie to be added
235
     */
236
    #[\ReturnTypeWillChange]
237
    public function offsetSet($name, $cookie)
238
    {
239
        $this->add($cookie);
240
    }
241
242
    /**
243
     * Removes the named cookie.
244
     * This method is required by the SPL interface [[\ArrayAccess]].
245
     * It is implicitly called when you use something like `unset($collection[$name])`.
246
     * This is equivalent to [[remove()]].
247
     * @param string $name the cookie name
248
     */
249
    #[\ReturnTypeWillChange]
250
    public function offsetUnset($name)
251
    {
252
        $this->remove($name);
253
    }
254
}
255