Completed
Branch 2.x (03096d)
by Julián
08:36
created

Session   B

Complexity

Total Complexity 38

Size/Duplication

Total Lines 350
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
wmc 38
lcom 1
cbo 4
dl 0
loc 350
rs 8.3999
c 0
b 0
f 0

20 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A getManager() 0 4 1
A start() 0 18 3
A regenerateId() 0 12 2
A close() 0 12 2
A destroy() 0 14 2
A isActive() 0 4 1
A isDestroyed() 0 4 1
A getId() 0 4 1
A setId() 0 4 1
A has() 0 4 1
A get() 0 4 2
A set() 0 8 1
A verifyScalarValue() 0 12 4
A remove() 0 8 2
A clear() 0 11 2
A manageTimeout() 0 15 3
A getCookieString() 0 16 2
B getCookieParameters() 0 30 5
A getConfiguration() 0 4 1
1
<?php
2
3
/*
4
 * sessionware (https://github.com/juliangut/sessionware).
5
 * PSR7 session management middleware.
6
 *
7
 * @license BSD-3-Clause
8
 * @link https://github.com/juliangut/sessionware
9
 * @author Julián Gutiérrez <[email protected]>
10
 */
11
12
declare(strict_types=1);
13
14
namespace Jgut\Sessionware;
15
16
use Jgut\Sessionware\Manager\Manager;
17
use League\Event\EmitterAwareInterface;
18
use League\Event\EmitterTrait;
19
use League\Event\Event;
20
21
/**
22
 * Session helper.
23
 */
24
class Session implements EmitterAwareInterface
25
{
26
    use EmitterTrait;
27
28
    /**
29
     * Session manager.
30
     *
31
     * @var Manager
32
     */
33
    protected $sessionManager;
34
35
    /**
36
     * Session data.
37
     *
38
     * @var array
39
     */
40
    protected $data = [];
41
42
    /**
43
     * Session constructor.
44
     *
45
     * @param Manager $sessionManager
46
     */
47
    public function __construct(Manager $sessionManager)
48
    {
49
        $this->sessionManager = $sessionManager;
50
    }
51
52
    /**
53
     * Get session manager.
54
     *
55
     * @return Manager
56
     */
57
    public function getManager()
58
    {
59
        return $this->sessionManager;
60
    }
61
62
    /**
63
     * Start session.
64
     *
65
     * @throws \RuntimeException
66
     */
67
    public function start()
68
    {
69
        if ($this->isActive()) {
70
            return;
71
        }
72
73
        $this->emit(Event::named('pre.session_start'), $this);
74
75
        $this->data = $this->sessionManager->sessionStart();
76
77
        if ($this->sessionManager->shouldRegenerateId()) {
78
            $this->regenerateId();
79
        }
80
81
        $this->emit(Event::named('post.session_start'), $this);
82
83
        $this->manageTimeout();
84
    }
85
86
    /**
87
     * Regenerate session identifier keeping parameters.
88
     *
89
     * @throws \RuntimeException
90
     *
91
     * @SuppressWarnings(PMD.Superglobals)
92
     */
93
    public function regenerateId()
94
    {
95
        if (!$this->isActive()) {
96
            throw new \RuntimeException('Cannot regenerate a not started session');
97
        }
98
99
        $this->emit(Event::named('pre.session_regenerate_id'), $this);
100
101
        $this->sessionManager->sessionRegenerateId();
102
103
        $this->emit(Event::named('pre.session_regenerate_id'), $this);
104
    }
105
106
    /**
107
     * Close session.
108
     *
109
     * @SuppressWarnings(PMD.Superglobals)
110
     */
111
    public function close()
112
    {
113
        if (!$this->isActive()) {
114
            return;
115
        }
116
117
        $this->emit(Event::named('pre.session_close'), $this);
118
119
        $this->sessionManager->sessionEnd($this->data);
120
121
        $this->emit(Event::named('pre.session_close'), $this);
122
    }
123
124
    /**
125
     * Destroy session.
126
     *
127
     * @throws \RuntimeException
128
     */
129
    public function destroy()
130
    {
131
        if (!$this->isActive()) {
132
            throw new \RuntimeException('Cannot destroy a not started session');
133
        }
134
135
        $this->emit(Event::named('pre.session_destroy'), $this);
136
137
        $this->sessionManager->sessionDestroy();
138
139
        $this->emit(Event::named('pre.session_destroy'), $this);
140
141
        $this->data = [];
142
    }
143
144
    /**
145
     * Is there an active session.
146
     *
147
     * @return bool
148
     */
149
    public function isActive() : bool
150
    {
151
        return $this->sessionManager->isSessionStarted();
152
    }
153
154
    /**
155
     * Has session been destroyed.
156
     *
157
     * @return bool
158
     */
159
    public function isDestroyed() : bool
160
    {
161
        return $this->sessionManager->isSessionDestroyed();
162
    }
163
164
    /**
165
     * Get session identifier.
166
     *
167
     * @return string
168
     */
169
    public function getId() : string
170
    {
171
        return $this->sessionManager->getSessionId();
172
    }
173
174
    /**
175
     * Set session identifier.
176
     *
177
     * @param string $sessionId
178
     *
179
     * @throws \RuntimeException
180
     */
181
    public function setId(string $sessionId)
182
    {
183
        $this->sessionManager->setSessionId($sessionId);
184
    }
185
186
    /**
187
     * Session parameter existence.
188
     *
189
     * @param string $key
190
     *
191
     * @return bool
192
     */
193
    public function has(string $key) : bool
194
    {
195
        return array_key_exists($key, $this->data);
196
    }
197
198
    /**
199
     * Retrieve session parameter.
200
     *
201
     * @param string     $key
202
     * @param mixed|null $default
203
     *
204
     * @return mixed
205
     */
206
    public function get(string $key, $default = null)
207
    {
208
        return array_key_exists($key, $this->data) ? $this->data[$key] : $default;
209
    }
210
211
    /**
212
     * Set session parameter.
213
     *
214
     * @param string $key
215
     * @param mixed  $value
216
     *
217
     * @throws \InvalidArgumentException
218
     *
219
     * @return static
220
     */
221
    public function set(string $key, $value) : self
222
    {
223
        $this->verifyScalarValue($value);
224
225
        $this->data[$key] = $value;
226
227
        return $this;
228
    }
229
230
    /**
231
     * Verify only scalar values allowed.
232
     *
233
     * @param string|int|float|bool|array $value
234
     *
235
     * @throws \InvalidArgumentException
236
     */
237
    final protected function verifyScalarValue($value)
238
    {
239
        if (is_array($value)) {
240
            foreach ($value as $val) {
241
                $this->verifyScalarValue($val);
242
            }
243
        }
244
245
        if (!is_scalar($value)) {
246
            throw new \InvalidArgumentException(sprintf('Session values must be scalars, %s given', gettype($value)));
247
        }
248
    }
249
250
    /**
251
     * Remove session parameter.
252
     *
253
     * @param string $key
254
     *
255
     * @return static
256
     */
257
    public function remove(string $key) : self
258
    {
259
        if (array_key_exists($key, $this->data)) {
260
            unset($this->data[$key]);
261
        }
262
263
        return $this;
264
    }
265
266
    /**
267
     * Remove all session parameters.
268
     *
269
     * @return static
270
     */
271
    public function clear() : self
272
    {
273
        $timeoutKey = $this->getConfiguration()->getTimeoutKey();
274
        $sessionTimeout = array_key_exists($timeoutKey, $this->data)
275
            ? $this->data[$timeoutKey]
276
            : time() + $this->getConfiguration()->getLifetime();
277
278
        $this->data = [$timeoutKey => $sessionTimeout];
279
280
        return $this;
281
    }
282
283
    /**
284
     * Manage session timeout.
285
     *
286
     * @throws \RuntimeException
287
     */
288
    protected function manageTimeout()
289
    {
290
        $configuration = $this->getConfiguration();
291
        $timeoutKey = $configuration->getTimeoutKey();
292
293
        if (array_key_exists($timeoutKey, $this->data) && $this->data[$timeoutKey] < time()) {
294
            $this->emit(Event::named('pre.session_timeout'), $this);
295
296
            $this->sessionManager->sessionRegenerateId();
297
298
            $this->emit(Event::named('post.session_timeout'), $this);
299
        }
300
301
        $this->data[$timeoutKey] = time() + $configuration->getLifetime();
302
    }
303
304
    /**
305
     * Get cookie header content.
306
     *
307
     * @return string
308
     */
309
    public function getCookieString() : string
310
    {
311
        $configuration = $this->getConfiguration();
312
313
        $timeoutKey = $configuration->getTimeoutKey();
314
        $expireTime = array_key_exists($timeoutKey, $this->data)
315
            ? $this->data[$timeoutKey]
316
            : time() + $configuration->getLifetime();
317
318
        return sprintf(
319
            '%s=%s; %s',
320
            urlencode($configuration->getName()),
321
            urlencode($this->getId()),
322
            $this->getCookieParameters($expireTime)
323
        );
324
    }
325
326
    /**
327
     * Get session cookie parameters.
328
     *
329
     * @param int $expireTime
330
     *
331
     * @return string
332
     */
333
    protected function getCookieParameters(int $expireTime) : string
334
    {
335
        $configuration = $this->getConfiguration();
336
337
        $cookieParams = [
338
            sprintf(
339
                'expires=%s; max-age=%s',
340
                gmdate('D, d M Y H:i:s T', $expireTime),
341
                $configuration->getLifetime()
342
            ),
343
        ];
344
345
        if (!empty($configuration->getCookiePath())) {
346
            $cookieParams[] = 'path=' . $configuration->getCookiePath();
347
        }
348
349
        if (!empty($configuration->getCookieDomain())) {
350
            $cookieParams[] = 'domain=' . $configuration->getCookieDomain();
351
        }
352
353
        if ($configuration->isCookieSecure()) {
354
            $cookieParams[] = 'secure';
355
        }
356
357
        if ($configuration->isCookieHttpOnly()) {
358
            $cookieParams[] = 'httponly';
359
        }
360
361
        return implode('; ', $cookieParams);
362
    }
363
364
    /**
365
     * Get session configuration.
366
     *
367
     * @return Configuration
368
     */
369
    protected function getConfiguration() : Configuration
370
    {
371
        return $this->sessionManager->getConfiguration();
372
    }
373
}
374