Passed
Pull Request — master (#24)
by Alexander
02:57
created

CurrentIdentityService::afterLogout()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\User\CurrentIdentity;
6
7
use Psr\EventDispatcher\EventDispatcherInterface;
8
use Yiisoft\Auth\IdentityInterface;
9
use Yiisoft\Auth\IdentityRepositoryInterface;
10
use Yiisoft\User\CurrentIdentity\Storage\CurrentIdentityStorageInterface;
11
use Yiisoft\User\CurrentIdentity\Event\AfterLogout;
12
use Yiisoft\User\CurrentIdentity\Event\AfterLogin;
13
use Yiisoft\User\CurrentIdentity\Event\BeforeLogout;
14
use Yiisoft\User\CurrentIdentity\Event\BeforeLogin;
15
use Yiisoft\User\GuestIdentity;
16
17
final class CurrentIdentityService
18
{
19
    private CurrentIdentityStorageInterface $currentIdentityStorage;
20
    private IdentityRepositoryInterface $identityRepository;
21
    private EventDispatcherInterface $eventDispatcher;
22
23
    private ?IdentityInterface $identity = null;
24
    private ?IdentityInterface $temporarilyIdentity = null;
25
26 20
    public function __construct(
27
        CurrentIdentityStorageInterface $currentIdentityStorage,
28
        IdentityRepositoryInterface $identityRepository,
29
        EventDispatcherInterface $eventDispatcher
30
    ) {
31 20
        $this->currentIdentityStorage = $currentIdentityStorage;
32 20
        $this->identityRepository = $identityRepository;
33 20
        $this->eventDispatcher = $eventDispatcher;
34 20
    }
35
36
    /**
37
     * Returns the identity object associated with the currently logged-in user.
38
     */
39 16
    public function get(): IdentityInterface
40
    {
41 16
        $identity = $this->temporarilyIdentity ?? $this->identity;
42
43 16
        if ($identity === null) {
44 11
            $identity = $this->determineIdentity();
45 11
            $this->identity = $identity;
46
        }
47
48 16
        return $identity;
49
    }
50
51 11
    private function determineIdentity(): IdentityInterface
52
    {
53 11
        $identity = null;
54
55 11
        $id = $this->currentIdentityStorage->get();
56 11
        if ($id !== null) {
57
            $identity = $this->identityRepository->findIdentity($id);
58
        }
59
60 11
        return $identity ?? new GuestIdentity();
61
    }
62
63
    /**
64
     * Returns a value indicating whether the user is a guest (not authenticated).
65
     *
66
     * @see get()
67
     *
68
     * @return bool Whether the current user is a guest.
69
     */
70 15
    public function isGuest(): bool
71
    {
72 15
        return $this->get() instanceof GuestIdentity;
73
    }
74
75
    /**
76
     * Logs in a user.
77
     *
78
     * @param IdentityInterface $identity The user identity (which should already be authenticated).
79
     *
80
     * @return bool Whether the user is logged in.
81
     */
82 8
    public function login(IdentityInterface $identity): bool
83
    {
84 8
        if ($this->beforeLogin($identity)) {
85 8
            $this->switchIdentity($identity);
86 8
            $this->afterLogin($identity);
87
        }
88 8
        return !$this->isGuest();
89
    }
90
91
    /**
92
     * This method is called before logging in a user.
93
     * The default implementation will trigger the {@see BeforeLogin} event.
94
     *
95
     * @param IdentityInterface $identity The user identity information.
96
     *
97
     * @return bool Whether the user should continue to be logged in.
98
     */
99 8
    private function beforeLogin(IdentityInterface $identity): bool
100
    {
101 8
        $event = new BeforeLogin($identity);
102 8
        $this->eventDispatcher->dispatch($event);
103 8
        return $event->isValid();
104
    }
105
106
    /**
107
     * This method is called after the user is successfully logged in.
108
     *
109
     * @param IdentityInterface $identity The user identity information.
110
     */
111 8
    private function afterLogin(IdentityInterface $identity): void
112
    {
113 8
        $this->eventDispatcher->dispatch(new AfterLogin($identity));
114 8
    }
115
116
    /**
117
     * Logs out the current user.
118
     *
119
     * @return bool Whether the user is logged out.
120
     */
121 3
    public function logout(): bool
122
    {
123 3
        if ($this->isGuest()) {
124 1
            return false;
125
        }
126
127 2
        $identity = $this->get();
128 2
        if ($this->beforeLogout($identity)) {
129 2
            $this->switchIdentity(new GuestIdentity());
130 2
            $this->afterLogout($identity);
131
        }
132
133 2
        return $this->isGuest();
134
    }
135
136
    /**
137
     * This method is invoked when calling {@see logout()} to log out a user.
138
     *
139
     * @param IdentityInterface $identity The user identity information.
140
     *
141
     * @return bool Whether the user should continue to be logged out.
142
     */
143 2
    private function beforeLogout(IdentityInterface $identity): bool
144
    {
145 2
        $event = new BeforeLogout($identity);
146 2
        $this->eventDispatcher->dispatch($event);
147 2
        return $event->isValid();
148
    }
149
150
    /**
151
     * This method is invoked right after a user is logged out via {@see logout()}.
152
     *
153
     * @param IdentityInterface $identity The user identity information.
154
     */
155 2
    private function afterLogout(IdentityInterface $identity): void
156
    {
157 2
        $this->eventDispatcher->dispatch(new AfterLogout($identity));
158 2
    }
159
160
    public function setTemporarilyIdentity(IdentityInterface $identity): void
161
    {
162
        $this->temporarilyIdentity = $identity;
163
    }
164
165
    public function clearTemporarilyIdentity(): void
166
    {
167
        $this->temporarilyIdentity = null;
168
    }
169
170
    /**
171
     * Switches to a new identity for the current user.
172
     *
173
     * This method is called by {@see login()} and {@see logout()}
174
     * when the current user needs to be associated with the corresponding identity information.
175
     *
176
     * @param IdentityInterface $identity The identity information to be associated with the current user.
177
     * In order to indicate that the user is guest, use {@see GuestIdentity}.
178
     */
179 8
    private function switchIdentity(IdentityInterface $identity): void
180
    {
181 8
        $this->identity = $identity;
182
183 8
        $id = $identity->getId();
184 8
        if ($id === null) {
185 2
            $this->currentIdentityStorage->clear();
186
        } else {
187 8
            $this->currentIdentityStorage->set($id);
188
        }
189 8
    }
190
}
191