Test Failed
Push — master ( 18f28d...e07c1c )
by Alexey
03:12
created

Cookie::__construct()   D

Complexity

Conditions 9
Paths 16

Size

Total Lines 36
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 9

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 36
rs 4.909
ccs 20
cts 20
cp 1
cc 9
eloc 26
nc 16
nop 7
crap 9
1
<?php declare(strict_types = 1);
2
3
namespace Venta\Http;
4
5
use Venta\Contracts\Http\Cookie as CookieContract;
6
7
/**
8
 * Class Cookie
9
 *
10
 * @package Venta\Http
11
 */
12
class Cookie implements CookieContract
13
{
14
    protected $domain;
15
16
    protected $expire;
17
18
    protected $httpOnly;
19
20
    protected $name;
21
22
    protected $path;
23
24
    protected $secure;
25
26
    protected $value;
27
28
    /**
29
     * Cookie constructor.
30
     *
31
     * @param        $name
32
     * @param null $value
33
     * @param int $expire
34
     * @param string $path
35
     * @param null $domain
36
     * @param bool $secure
37
     * @param bool $httpOnly
38
     */
39 14
    public function __construct(
40
        $name,
41
        $value = null,
42
        $expire = 0,
43
        $path = '/',
44
        $domain = null,
45
        $secure = false,
46
        $httpOnly = true
47
    ) {
48 14
        if (preg_match("/[=,; \t\r\n\013\014]/", $name)) {
49 1
            throw new \InvalidArgumentException(sprintf('The cookie name "%s" contains invalid characters.', $name));
50
        }
51
52 13
        if (empty($name)) {
53 1
            throw new \InvalidArgumentException('The cookie name cannot be empty.');
54
        }
55
56 12
        $expire = ($expire === "") ? 0 : $expire;
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison === seems to always evaluate to false as the types of $expire (integer) and '' (string) can never be identical. Maybe you want to use a loose comparison == instead?
Loading history...
Coding Style Comprehensibility introduced by
The string literal does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
57 12
        if ($expire instanceof \DateTimeInterface) {
58 1
            $expire = $expire->format('U');
59 11
        } elseif (!is_numeric($expire)) {
60 3
            $expire = strtotime($expire);
61
62 3
            if (false === $expire || -1 === $expire) {
63 1
                throw new \InvalidArgumentException('The cookie expiration time is not valid.');
64
            }
65
        }
66
67 11
        $this->name = $name;
68 11
        $this->value = $value;
69 11
        $this->domain = $domain;
70 11
        $this->expire = $expire;
71 11
        $this->path = empty($path) ? '/' : $path;
72 11
        $this->secure = (bool)$secure;
73 11
        $this->httpOnly = (bool)$httpOnly;
74 11
    }
75
76 2
    public static function createFromString(string $cookie)
77
    {
78 2
        $cookie = str_replace(' ', '', $cookie);
79
        $pattern =
80 2
            '/^(\w+)=(\w+);(?:expires=([^\s|\;]+);)?(?:path=([^\s|\;]+);)?(?:domain=([^\s|\;]+);)?(?:(secure);)?(httponly)?/';
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 126 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
81 2
        preg_match($pattern, $cookie, $result);
82 2
        array_shift($result);
83 2
        $reflected = new \ReflectionClass(self::class);
84
85 2
        return $reflected->newInstanceArgs($result);
86
    }
87
88
    /**
89
     * @param $string
90
     * @return int timestamp
91
     */
92 1
    public static function inDateInterval(string $string)
93
    {
94 1
        return (new \DateTime('now'))->add(new \DateInterval($string))->getTimestamp();
95
    }
96
97
    /**
98
     * @param $days
99
     * @return int timestamp
100
     */
101 2
    public static function inDays($days)
102
    {
103 2
        return (new \DateTime('now'))->add(new \DateInterval('P' . $days . 'D'))->getTimestamp();
104
    }
105
106
    /**
107
     * @param $hours
108
     * @return int timestamp
109
     */
110 1
    public static function inHours($hours)
111
    {
112 1
        return (new \DateTime('now'))->add(new \DateInterval('PT' . $hours . 'H'))->getTimestamp();
113
    }
114
115
    /**
116
     * @param $minutes
117
     * @return int timestamp
118
     */
119 4
    public static function inMinutes($minutes)
120
    {
121 4
        return (new \DateTime('now'))->add(new \DateInterval('PT' . $minutes . 'M'))->getTimestamp();
122
    }
123
124
    /**
125
     * @param $months
126
     * @return int timestamp
127
     */
128 1
    public static function inMonths($months)
129
    {
130 1
        return (new \DateTime('now'))->add(new \DateInterval('P' . $months . 'M'))->getTimestamp();
131
    }
132
133
    /**
134
     * @param $days
135
     * @return int timestamp
136
     */
137 1
    public static function inWeeks($days)
138
    {
139 1
        $weeks = $days * 7;
140
141 1
        return (new \DateTime('now'))->add(new \DateInterval('P' . $weeks . 'D'))->getTimestamp();
142
    }
143
144
    /**
145
     * @return int timestamp
146
     */
147 2
    public static function outdated()
148
    {
149 2
        return (new \DateTime('now'))->sub(new \DateInterval('P12M'))->getTimestamp();
150
    }
151
152
    /**
153
     * @return string
154
     */
155 8
    public function __toString()
156
    {
157 8
        $str = urlencode($this->getName()) . '=';
158
159 8
        if ('' === (string)$this->getValue()) {
160 1
            $str .= 'deleted; expires=' . gmdate('D, d-M-Y H:i:s T', static::outdated());
161
        } else {
162 7
            $str .= urlencode($this->getValue());
163
164 7
            if ($this->getExpireTime() !== 0) {
165 5
                $str .= '; expires=' . gmdate('D, d-M-Y H:i:s T', $this->getExpireTime());
166
            }
167
        }
168
169 8
        if ($this->path) {
170 8
            $str .= '; path=' . $this->path;
171
        }
172
173 8
        if ($this->getDomain()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->getDomain() of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
174 4
            $str .= '; domain=' . $this->getDomain();
175
        }
176
177 8
        if (true === $this->isSecure()) {
178 2
            $str .= '; secure';
179
        }
180
181 8
        if (true === $this->isHttpOnly()) {
182 7
            $str .= '; httponly';
183
        }
184
185 8
        return (string)$str;
186
    }
187
188
    public function asPlainText()
189
    {
190
        return $this->__toString();
191
    }
192
193
    /**
194
     * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be string|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
195
     */
196 8
    public function getDomain()
197
    {
198 8
        return $this->domain;
199
    }
200
201
    /**
202
     * @return int|string timestamp
203
     */
204 9
    public function getExpireTime()
205
    {
206 9
        return $this->expire;
207
    }
208
209
    /**
210
     * @return string
211
     */
212 8
    public function getName()
213
    {
214 8
        return $this->name;
215
    }
216
217
    /**
218
     * @return string|null
219
     */
220 8
    public function getValue()
221
    {
222 8
        return $this->value;
223
    }
224
225
    /**
226
     * @return bool
227
     */
228 8
    public function isHttpOnly()
229
    {
230 8
        return $this->httpOnly;
231
    }
232
233
    /**
234
     * @return bool
235
     */
236 8
    public function isSecure()
237
    {
238 8
        return $this->secure;
239
    }
240
}