Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
93.94% covered (success)
93.94%
31 / 33
88.89% covered (warning)
88.89%
8 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
Session
93.94% covered (success)
93.94%
31 / 33
88.89% covered (warning)
88.89%
8 / 9
12.03
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 setUser
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 authenticatedUserId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 remember
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 forgetRemembered
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 getAuthToken
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 signalActivity
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 lastActivity
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 rememberCookieOptions
84.62% covered (warning)
84.62%
11 / 13
0.00% covered (danger)
0.00%
0 / 1
3.03
1<?php
2
3declare(strict_types=1);
4
5namespace Cosray;
6
7use Celemas\Session\Session as BaseSession;
8use SessionHandlerInterface;
9
10class Session extends BaseSession
11{
12    protected string $authCookie;
13
14    public function __construct(
15        array $options = [],
16        string $name = '',
17        ?SessionHandlerInterface $handler = null,
18    ) {
19        parent::__construct($options, $name, $handler);
20
21        $this->authCookie = $name ? $name . '_auth' : 'cosray_auth';
22    }
23
24    public function setUser(int $userId): void
25    {
26        $_SESSION['user_id'] = $userId;
27    }
28
29    public function authenticatedUserId(): ?int
30    {
31        return $_SESSION['user_id'] ?? null;
32    }
33
34    public function remember(#[\SensitiveParameter] Token $token, int $expires): void
35    {
36        $value = $token->get();
37        $_COOKIE[$this->authCookie] = $value;
38
39        setcookie(
40            $this->authCookie,
41            $value,
42            $this->rememberCookieOptions($expires),
43        );
44    }
45
46    public function forgetRemembered(): void
47    {
48        unset($_COOKIE[$this->authCookie]);
49
50        setcookie(
51            $this->authCookie,
52            '',
53            $this->rememberCookieOptions(time() - (60 * 60 * 24)),
54        );
55    }
56
57    public function getAuthToken(): ?string
58    {
59        return $_COOKIE[$this->authCookie] ?? null;
60    }
61
62    public function signalActivity(): void
63    {
64        $_SESSION['last_activity'] = time();
65    }
66
67    public function lastActivity(): ?int
68    {
69        return $_SESSION['last_activity'] ?? null;
70    }
71
72    /** @return array{expires: int, path: string, domain?: string, secure: bool, httponly: bool, samesite: string, partitioned?: bool} */
73    private function rememberCookieOptions(int $expires): array
74    {
75        $options = [
76            'expires' => $expires,
77            'path' => (string) ($this->options['cookie_path'] ?? '/'),
78            'secure' => (bool) ($this->options['cookie_secure'] ?? true),
79            'httponly' => (bool) ($this->options['cookie_httponly'] ?? true),
80            'samesite' => (string) ($this->options['cookie_samesite'] ?? 'Lax'),
81        ];
82
83        $domain = (string) ($this->options['cookie_domain'] ?? '');
84        if ($domain !== '') {
85            $options['domain'] = $domain;
86        }
87
88        if (isset($this->options['cookie_partitioned'])) {
89            $options['partitioned'] = (bool) $this->options['cookie_partitioned'];
90        }
91
92        return $options;
93    }
94}