Completed
Pull Request — master (#31)
by Marco
05:52
created

SetCookie::__toString()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 16
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 16
ccs 11
cts 11
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 11
nc 1
nop 0
crap 1
1
<?php
2
3
namespace Dflydev\FigCookies;
4
5
use DateTime;
6
use DateTimeInterface;
7
use Dflydev\FigCookies\Modifier\SameSite;
8
9
class SetCookie
10
{
11
    private $name;
12
    private $value;
13
    private $expires = 0;
14
    private $maxAge = 0;
15
    private $path;
16
    private $domain;
17
    private $secure = false;
18
    private $httpOnly = false;
19
    /** @var SameSite|null */
20
    private $sameSite;
21
22 34
    private function __construct($name, $value = null)
23
    {
24 34
        $this->name = $name;
25 34
        $this->value = $value;
26 34
    }
27
28 19
    public function getName()
29
    {
30 19
        return $this->name;
31
    }
32
33 3
    public function getValue()
34
    {
35 3
        return $this->value;
36
    }
37
38 2
    public function getExpires()
39
    {
40 2
        return $this->expires;
41
    }
42
43
    public function getMaxAge()
44
    {
45
        return $this->maxAge;
46
    }
47
48
    public function getPath()
49
    {
50
        return $this->path;
51
    }
52
53
    public function getDomain()
54
    {
55
        return $this->domain;
56
    }
57
58
    public function getSecure()
59
    {
60
        return $this->secure;
61
    }
62
63
    public function getHttpOnly()
64
    {
65
        return $this->httpOnly;
66
    }
67
68
    /** @return SameSite|null */
69 1
    public function getSameSite()
70
    {
71 1
        return $this->sameSite;
72
    }
73
74 31
    public function withValue($value = null)
75
    {
76 31
        $clone = clone($this);
77
78 31
        $clone->value = $value;
79
80 31
        return $clone;
81
    }
82
83 15
    private function resolveExpires($expires = null)
84
    {
85 15
        if (is_null($expires)) {
86
            return null;
87
        }
88
89 15
        if ($expires instanceof DateTime || $expires instanceof DateTimeInterface) {
90 2
            return $expires->getTimestamp();
91
        }
92
93 13
        if (is_numeric($expires)) {
94
            return $expires;
95
        }
96
97 13
        return strtotime($expires);
98
    }
99
100 15
    public function withExpires($expires = null)
101
    {
102 15
        $expires = $this->resolveExpires($expires);
103
104 15
        $clone = clone($this);
105
106 15
        $clone->expires = $expires;
107
108 15
        return $clone;
109
    }
110
111 1
    public function rememberForever()
112
    {
113 1
        return $this->withExpires(new DateTime('+5 years'));
114
    }
115
116 1
    public function expire()
117
    {
118 1
        return $this->withExpires(new DateTime('-5 years'));
119
    }
120
121 6
    public function withMaxAge($maxAge = null)
122
    {
123 6
        $clone = clone($this);
124
125 6
        $clone->maxAge = $maxAge;
126
127 6
        return $clone;
128
    }
129
130 14
    public function withPath($path = null)
131
    {
132 14
        $clone = clone($this);
133
134 14
        $clone->path = $path;
135
136 14
        return $clone;
137
    }
138
139 9
    public function withDomain($domain = null)
140
    {
141 9
        $clone = clone($this);
142
143 9
        $clone->domain = $domain;
144
145 9
        return $clone;
146
    }
147
148 12
    public function withSecure($secure = null)
149
    {
150 12
        $clone = clone($this);
151
152 12
        $clone->secure = $secure;
153
154 12
        return $clone;
155
    }
156
157 14
    public function withHttpOnly($httpOnly = null)
158
    {
159 14
        $clone = clone($this);
160
161 14
        $clone->httpOnly = $httpOnly;
162
163 14
        return $clone;
164
    }
165
166 2
    public function withSameSite(SameSite $sameSite)
167
    {
168 2
        $clone = clone($this);
169
170 2
        $clone->sameSite = $sameSite;
171
172 2
        return $clone;
173
    }
174
175
    public function withoutSameSite()
176
    {
177
        $clone = clone($this);
178
179
        $clone->sameSite = null;
180
181
        return $clone;
182
    }
183
184 20
    public function __toString()
185
    {
186
        $cookieStringParts = [
187 20
            urlencode($this->name).'='.urlencode($this->value),
188 20
        ];
189
190 20
        $cookieStringParts = $this->appendFormattedDomainPartIfSet($cookieStringParts);
191 20
        $cookieStringParts = $this->appendFormattedPathPartIfSet($cookieStringParts);
192 20
        $cookieStringParts = $this->appendFormattedExpiresPartIfSet($cookieStringParts);
193 20
        $cookieStringParts = $this->appendFormattedMaxAgePartIfSet($cookieStringParts);
194 20
        $cookieStringParts = $this->appendFormattedSecurePartIfSet($cookieStringParts);
195 20
        $cookieStringParts = $this->appendFormattedHttpOnlyPartIfSet($cookieStringParts);
196 20
        $cookieStringParts = $this->appendFormattedSameSitePartIfSet($cookieStringParts);
197
198 20
        return implode('; ', $cookieStringParts);
199
    }
200
201 9
    public static function create($name, $value = null)
202
    {
203 9
        return new static($name, $value);
204
    }
205
206 1
    public static function createRememberedForever($name, $value = null)
207
    {
208 1
        return static::create($name, $value)->rememberForever();
209
    }
210
211 1
    public static function createExpired($name)
212
    {
213 1
        return static::create($name)->expire();
214
    }
215
216 31
    public static function fromSetCookieString($string)
217
    {
218 31
        $rawAttributes = StringUtil::splitOnAttributeDelimiter($string);
219
220 31
        list ($cookieName, $cookieValue) = StringUtil::splitCookiePair(array_shift($rawAttributes));
221
222
        /** @var SetCookie $setCookie */
223 31
        $setCookie = new static($cookieName);
224
225 31
        if (! is_null($cookieValue)) {
226 31
            $setCookie = $setCookie->withValue($cookieValue);
227 31
        }
228
229 31
        while ($rawAttribute = array_shift($rawAttributes)) {
230 14
            $rawAttributePair = explode('=', $rawAttribute, 2);
231
232 14
            $attributeKey = $rawAttributePair[0];
233 14
            $attributeValue = count($rawAttributePair) > 1 ? $rawAttributePair[1] : null;
234
235 14
            $attributeKey = strtolower($attributeKey);
236
237
            switch ($attributeKey) {
238 14
                case 'expires':
239 13
                    $setCookie = $setCookie->withExpires($attributeValue);
240 13
                    break;
241 14
                case 'max-age':
242 6
                    $setCookie = $setCookie->withMaxAge($attributeValue);
243 6
                    break;
244 14
                case 'domain':
245 9
                    $setCookie = $setCookie->withDomain($attributeValue);
246 9
                    break;
247 14
                case 'path':
248 14
                    $setCookie = $setCookie->withPath($attributeValue);
249 14
                    break;
250 14
                case 'secure':
251 12
                    $setCookie = $setCookie->withSecure(true);
252 12
                    break;
253 14
                case 'httponly':
254 14
                    $setCookie = $setCookie->withHttpOnly(true);
255 14
                    break;
256 2
                case 'samesite':
257 2
                    $setCookie = $setCookie->withSameSite(SameSite::fromString($attributeValue));
258 2
                    break;
259
            }
260
261 14
        }
262
263 31
        return $setCookie;
264
    }
265 20
    private function appendFormattedDomainPartIfSet(array $cookieStringParts)
266
    {
267 20
        if ($this->domain) {
268 9
            $cookieStringParts[] = sprintf("Domain=%s", $this->domain);
269 9
        }
270
271 20
        return $cookieStringParts;
272
    }
273
274 20
    private function appendFormattedPathPartIfSet(array $cookieStringParts)
275
    {
276 20
        if ($this->path) {
277 10
            $cookieStringParts[] = sprintf("Path=%s", $this->path);
278 10
        }
279
280 20
        return $cookieStringParts;
281
    }
282
283 20
    private function appendFormattedExpiresPartIfSet(array $cookieStringParts)
284
    {
285 20
        if ($this->expires) {
286 9
            $cookieStringParts[] = sprintf("Expires=%s", gmdate('D, d M Y H:i:s T', $this->expires));
287 9
        }
288
289 20
        return $cookieStringParts;
290
    }
291
292 20
    private function appendFormattedMaxAgePartIfSet(array $cookieStringParts)
293
    {
294 20
        if ($this->maxAge) {
295 6
            $cookieStringParts[] = sprintf("Max-Age=%s", $this->maxAge);
296 6
        }
297
298 20
        return $cookieStringParts;
299
    }
300
301 20
    private function appendFormattedSecurePartIfSet(array $cookieStringParts)
302
    {
303 20
        if ($this->secure) {
304 8
            $cookieStringParts[] = 'Secure';
305 8
        }
306
307 20
        return $cookieStringParts;
308
    }
309
310 20
    private function appendFormattedHttpOnlyPartIfSet(array $cookieStringParts)
311
    {
312 20
        if ($this->httpOnly) {
313 10
            $cookieStringParts[] = 'HttpOnly';
314 10
        }
315
316 20
        return $cookieStringParts;
317
    }
318
319
    /**
320
     * @param string[] $cookieStringParts
321
     *
322
     * @return string[]
323
     */
324 20
    private function appendFormattedSameSitePartIfSet(array $cookieStringParts)
325
    {
326 20
        if (null === $this->sameSite) {
327 18
            return $cookieStringParts;
328
        }
329
330 2
        $cookieStringParts[] = $this->sameSite->asString();
331
332 2
        return $cookieStringParts;
333
    }
334
}
335