RememberMeDetails::expires()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
/**
4
 * This file is part of web-stack
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
declare(strict_types=1);
11
12
namespace Slick\WebStack\Domain\Security\Http\RememberMe;
13
14
use Slick\WebStack\Domain\Security\Exception\AuthenticationException;
15
use Stringable;
16
17
/**
18
 * RememberMeDetails
19
 *
20
 * @package Slick\WebStack\Domain\Security\Http\RememberMe
21
 */
22
final class RememberMeDetails implements Stringable
23
{
24
    public const COOKIE_DELIMITER = ':';
25
26
    public function __construct(
27
        private readonly string $userFqcn,
28
        private readonly string $userIdentifier,
29
        private readonly int|string $expires,
30
        private string $value
31
    ) {
32
    }
33
34
    public static function fromRawCookie(string $rawCookie): RememberMeDetails
35
    {
36
        if (!str_contains($rawCookie, self::COOKIE_DELIMITER)) {
37
            $rawCookie = base64_decode($rawCookie);
38
        }
39
40
        $cookieParts = explode(self::COOKIE_DELIMITER, $rawCookie, 4);
41
        if (4 !== count($cookieParts)) {
42
            throw new AuthenticationException('The cookie contains invalid data.');
43
        }
44
45
        if (false === $cookieParts[1] = base64_decode(strtr($cookieParts[1], '-_~', '+/='), true)) {
46
            throw new AuthenticationException(
47
                'The user identifier contains a character from outside the base64 alphabet.'
48
            );
49
        }
50
51
        $params = [
52
            'userFqcn' => strtr((string) $cookieParts[0], '.', '\\'),
53
            'userIdentifier' => $cookieParts[1],
54
            'expires' => (int) $cookieParts[2],
55
            'value' => (string) $cookieParts[3],
56
        ];
57
58
        return new RememberMeDetails(...$params);
59
    }
60
61
    /**
62
     * RememberMeDetails userFqcn
63
     *
64
     * @return string
65
     */
66
    public function userFqcn(): string
67
    {
68
        return $this->userFqcn;
69
    }
70
71
    /**
72
     * RememberMeDetails userIdentifier
73
     *
74
     * @return string
75
     */
76
    public function userIdentifier(): string
77
    {
78
        return $this->userIdentifier;
79
    }
80
81
    /**
82
     * RememberMeDetails expires
83
     *
84
     * @return int
85
     */
86
    public function expires(): int
87
    {
88
        return (int) $this->expires;
89
    }
90
91
    /**
92
     * RememberMeDetails value
93
     *
94
     * @return string
95
     */
96
    public function value(): string
97
    {
98
        return $this->value;
99
    }
100
101
    /**
102
     * Clones the object and sets the value property with the provided value.
103
     *
104
     * @param string $value The value to set on the cloned object.
105
     *
106
     * @return RememberMeDetails The cloned object with the updated value.
107
     */
108
    public function withValue(string $value): RememberMeDetails
109
    {
110
        $details = clone $this;
111
        $details->value = $value;
112
113
        return $details;
114
    }
115
116
    /**
117
     * @inheritDoc
118
     */
119
    public function __toString(): string
120
    {
121
        return implode(
122
            self::COOKIE_DELIMITER,
123
            [
124
                strtr($this->userFqcn, '\\', '.'),
125
                strtr(base64_encode($this->userIdentifier), '+/=', '-_~'),
126
                $this->expires,
127
                $this->value
128
            ]
129
        );
130
    }
131
}
132