Completed
Push — master ( 863689...e44ba2 )
by Gabriel
03:17
created

UserEntityTrait::hasPasswordResetTokenExpired()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace Sinergi\Users\User;
4
5
use DateTime;
6
use Sinergi\Users\Group\GroupEntityInterface;
7
use Sinergi\Users\Group\GroupRepositoryInterface;
8
use Sinergi\Users\Session\SessionEntityInterface;
9
use Sinergi\Users\Session\SessionRepositoryInterface;
10
use Sinergi\Users\Utils\Token;
11
use DateInterval;
12
13
trait UserEntityTrait
14
{
15
    protected $id;
16
    protected $groupId;
17
    /** @var GroupEntityInterface */
18
    protected $group;
19
    /** @var SessionEntityInterface[] */
20
    protected $sessions;
21
    protected $status;
22
    protected $isAdmin;
23
    protected $email = null;
24
    protected $pendingEmail = null;
25
    protected $deletedEmail = null;
26
    protected $isEmailConfirmed = false;
27
    protected $emailConfirmationToken;
28
    protected $emailConfirmationTokenAttempts;
29
    protected $emailConfirmationTokenExpirationDatetime;
30
    protected $lastEmailTokenGeneratedDatetime;
31
    protected $password;
32
    protected $passwordResetToken;
33
    protected $passwordResetTokenExpirationDatetime;
34
    protected $lastPasswordResetTokenGeneratedDatetime;
35
    protected $creationDatetime;
36
    protected $modificationDatetime;
37
    /** @var GroupRepositoryInterface */
38
    protected $groupRepository;
39
    /** @var SessionRepositoryInterface */
40
    protected $sessionRepository;
41
42
    public function __construct(
43
        GroupRepositoryInterface $groupRepository = null,
44
        SessionRepositoryInterface $sessionRepository = null
45
    ) {
46
        $this->groupRepository = $groupRepository;
47
        $this->sessionRepository = $sessionRepository;
48
        $this->setStatus(UserEntityInterface::STATUS_ACTIVE);
49
        $this->setCreationDatetime(new DateTime());
50
        $this->setModificationDatetime(new DateTime());
51
    }
52
53
    /** @return int */
54
    public function getId()
55
    {
56
        return $this->id;
57
    }
58
59
    public function setId(int $id): UserEntityInterface
60
    {
61
        $this->id = $id;
62
        return $this;
63
    }
64
65
    /** @return int|null */
66
    public function getGroupId()
67
    {
68
        return $this->groupId;
69
    }
70
71
    public function setGroupId(int $groupId = null): UserEntityInterface
72
    {
73
        $this->groupId = $groupId;
74
        return $this;
75
    }
76
77
    /** @return GroupEntityInterface|null */
78
    public function getGroup()
79
    {
80
        if ($this->group && $this->group->getId() === $this->groupId) {
81
            return $this->group;
82
        } elseif (!$this->groupRepository) {
83
            throw new \Exception('Cannot fetch group without group repository');
84
        }
85
        return $this->group = $this->groupRepository->findById($this->getGroupId());
86
    }
87
88
    public function setGroup(GroupEntityInterface $group = null): UserEntityInterface
89
    {
90
        $this->setGroupId($group->getId());
0 ignored issues
show
Bug introduced by
It seems like $group is not always an object, but can also be of type null. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
91
        $this->group = $group;
92
        return $this;
93
    }
94
95
    /** @return SessionEntityInterface[] */
96
    public function getSessions()
97
    {
98
        if (is_array($this->sessions)) {
99
            return $this->sessions;
100
        } elseif (!$this->sessionRepository) {
101
            throw new \Exception('Cannot fetch sessions without session repository');
102
        }
103
        return $this->sessions = $this->sessionRepository->findByUserId($this->getId());
104
    }
105
106
    /** @return string|null */
107
    public function getStatus()
108
    {
109
        return $this->status;
110
    }
111
112
    public function setStatus(string $status): UserEntityInterface
113
    {
114
        $this->status = $status;
115
        return $this;
116
    }
117
118
    public function isAdmin(): bool
119
    {
120
        return $this->isAdmin;
121
    }
122
123
    public function setIsAdmin(bool $isAdmin): UserEntityInterface
124
    {
125
        $this->isAdmin = $isAdmin;
126
        return $this;
127
    }
128
129
    public function isActive(): bool
130
    {
131
        return $this->getStatus() === UserEntityInterface::STATUS_ACTIVE;
132
    }
133
134
    public function getEmail(): string
135
    {
136
        return $this->email ?: '';
137
    }
138
139
    public function setEmail(string $email): UserEntityInterface
140
    {
141
        $this->email = $email;
142
        return $this;
143
    }
144
145
    /** @return string */
146
    public function getPendingEmail()
147
    {
148
        return $this->pendingEmail;
149
    }
150
151
    public function setPendingEmail(string $pendingEmail): UserEntityInterface
152
    {
153
        $this->pendingEmail = $pendingEmail;
154
        return $this;
155
    }
156
157
    public function isEmailConfirmed(): bool
158
    {
159
        return $this->isEmailConfirmed;
160
    }
161
162
    public function setIsEmailConfirmed(bool $isEmailConfirmed): UserEntityInterface
163
    {
164
        $this->isEmailConfirmed = $isEmailConfirmed;
165
        return $this;
166
    }
167
168
    /** @return string */
169
    public function getEmailConfirmationToken()
170
    {
171
        return $this->emailConfirmationToken;
172
    }
173
174
    public function setEmailConfirmationToken(string $emailConfirmationToken = null): UserEntityInterface
175
    {
176
        $this->emailConfirmationToken = $emailConfirmationToken;
177
        return $this;
178
    }
179
180
    /** @return int */
181
    public function getEmailConfirmationTokenAttempts()
182
    {
183
        return $this->emailConfirmationTokenAttempts;
184
    }
185
186
    public function setEmailConfirmationTokenAttempts(int $emailConfirmationTokenAttempts = 0): UserEntityInterface
187
    {
188
        $this->emailConfirmationTokenAttempts = $emailConfirmationTokenAttempts;
189
        return $this;
190
    }
191
192
    /** @return DateTime */
193
    public function getEmailConfirmationTokenExpirationDatetime()
194
    {
195
        return $this->emailConfirmationTokenExpirationDatetime;
196
    }
197
198
    public function setEmailConfirmationTokenExpirationDatetime(
199
        DateTime $emailConfirmationTokenExpirationDatetime = null
200
    ): UserEntityInterface {
201
        $this->emailConfirmationTokenExpirationDatetime = $emailConfirmationTokenExpirationDatetime;
202
        return $this;
203
    }
204
205
    /** @return DateTime */
206
    public function getLastEmailTokenGeneratedDatetime()
207
    {
208
        return $this->lastEmailTokenGeneratedDatetime;
209
    }
210
211
    public function setLastEmailTokenGeneratedDatetime(
212
        DateTime $lastEmailTokenGeneratedDatetime
213
    ): UserEntityInterface {
214
        $this->lastEmailTokenGeneratedDatetime = $lastEmailTokenGeneratedDatetime;
215
        return $this;
216
    }
217
218
    public function hasEmailConfirmationTokenCooldownExpired(): bool
219
    {
220
        return (new DateTime())->getTimestamp() - $this->getLastEmailTokenGeneratedDatetime()->getTimestamp() >
221
            UserEntityInterface::EMAIL_COOLDOWN;
222
    }
223
224
    public function hasEmailConfirmationTokenExpired(): bool
225
    {
226
        return ($this->getEmailConfirmationTokenExpirationDatetime() <= new DateTime());
227
    }
228
229
    public function hasTooManyEmailConfirmationTokenAttempts(): bool
230
    {
231
        return $this->getEmailConfirmationTokenAttempts() > 5;
232
    }
233
234 View Code Duplication
    public function generateEmailConfirmationToken($token = null, DateInterval $expiration = null): UserEntityInterface
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
235
    {
236
        if (null === $expiration) {
237
            $expiration = new DateInterval('P1D');
238
        }
239
        $this->setEmailConfirmationTokenAttempts(0);
240
        $this->setEmailConfirmationToken(null === $token ? Token::generate(40) : $token);
241
        $this->setEmailConfirmationTokenExpirationDatetime((new DateTime())->add($expiration));
242
        $this->setLastEmailTokenGeneratedDatetime(new DateTime());
243
        return $this;
244
    }
245
246
    /** @return string */
247
    public function getDeletedEmail()
248
    {
249
        return $this->deletedEmail;
250
    }
251
252
    public function setDeletedEmail(string $deletedEmail): UserEntityInterface
253
    {
254
        $this->deletedEmail = $deletedEmail;
255
        return $this;
256
    }
257
258
    /** @return string */
259
    public function getPassword()
260
    {
261
        return $this->password;
262
    }
263
264
    public function setPassword(string $password): UserEntityInterface
265
    {
266
        $this->password = $password;
267
        $this->hashPassword();
268
        return $this;
269
    }
270
271
    /** @return string */
272
    public function getPasswordResetToken()
273
    {
274
        return $this->passwordResetToken;
275
    }
276
277
    public function setPasswordResetToken(string $passwordResetToken = null): UserEntityInterface
278
    {
279
        $this->passwordResetToken = $passwordResetToken;
280
        return $this;
281
    }
282
283
    /** @return DateTime */
284
    public function getPasswordResetTokenExpirationDatetime()
285
    {
286
        return $this->passwordResetTokenExpirationDatetime;
287
    }
288
289
    public function setPasswordResetTokenExpirationDatetime(
290
        DateTime $passwordResetTokenExpirationDatetime = null
291
    ): UserEntityInterface {
292
        $this->passwordResetTokenExpirationDatetime = $passwordResetTokenExpirationDatetime;
293
        return $this;
294
    }
295
296
    /** @return DateTime */
297
    public function getLastPasswordResetTokenGeneratedDatetime()
298
    {
299
        return $this->lastPasswordResetTokenGeneratedDatetime;
300
    }
301
302
    public function setLastPasswordResetTokenGeneratedDatetime(
303
        DateTime $lastPasswordResetTokenGeneratedDatetime
304
    ): UserEntityInterface {
305
        $this->lastPasswordResetTokenGeneratedDatetime = $lastPasswordResetTokenGeneratedDatetime;
306
        return $this;
307
    }
308
309
    public function hasPasswordResetTokenExpired(): bool
310
    {
311
        return ($this->getPasswordResetTokenExpirationDatetime() <= new DateTime());
312
    }
313
314
    public function hasPasswordResetTokenCooldownExpired(): bool
315
    {
316
        return (new DateTime())->getTimestamp() - $this->getLastPasswordResetTokenGeneratedDatetime()->getTimestamp() >
317
            UserEntityInterface::EMAIL_COOLDOWN;
318
    }
319
320 View Code Duplication
    public function generatePasswordResetToken($token = null, DateInterval $expiration = null): UserEntityInterface
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
321
    {
322
        if (null === $expiration) {
323
            $expiration = new DateInterval('P1D');
324
        }
325
326
        $this->setPasswordResetToken(null === $token ? Token::generate(40) : $token);
327
        $this->setPasswordResetTokenExpirationDatetime((new DateTime())->add($expiration));
328
        $this->setLastPasswordResetTokenGeneratedDatetime(new DateTime());
329
        return $this;
330
    }
331
332
    protected function hashPassword(): UserEntityInterface
333
    {
334
        $this->password = password_hash(
335
            (string) $this->password,
336
            PASSWORD_DEFAULT
337
        );
338
        return $this;
339
    }
340
341
    public function testPassword(string $password): bool
342
    {
343
        return password_verify($password, $this->password);
344
    }
345
346
    public function getCreationDatetime(): DateTime
347
    {
348
        return $this->creationDatetime;
349
    }
350
351
    public function setCreationDatetime(DateTime $creationDatetime): UserEntityInterface
352
    {
353
        $this->creationDatetime = $creationDatetime;
354
        return $this;
355
    }
356
357
    public function getModificationDatetime(): DateTime
358
    {
359
        return $this->modificationDatetime;
360
    }
361
362
    public function setModificationDatetime(DateTime $modificationDatetime): UserEntityInterface
363
    {
364
        $this->modificationDatetime = $modificationDatetime;
365
        return $this;
366
    }
367
368
    public function setGroupRepository(GroupRepositoryInterface $groupRepository): UserEntityInterface
369
    {
370
        $this->groupRepository = $groupRepository;
371
        return $this;
372
    }
373
374
    public function setSessionRepository(SessionRepositoryInterface $sessionRepository): UserEntityInterface
375
    {
376
        $this->sessionRepository = $sessionRepository;
377
        return $this;
378
    }
379
380
    public function toArray(): array
381
    {
382
        return [
383
            'id' => $this->getId(),
384
            'groupId' => $this->getGroupId(),
385
            'status' => $this->getStatus(),
386
            'isAdmin' => $this->isAdmin(),
387
            'email' => $this->getEmail(),
388
            'pendingEmail' => $this->getPendingEmail(),
389
            'deletedEmail' => $this->getDeletedEmail(),
390
            'isEmailConfirmed' => $this->isEmailConfirmed(),
391
            'emailConfirmationToken' => $this->getEmailConfirmationToken(),
392
            'emailConfirmationTokenExpirationDatetime' => $this->getEmailConfirmationTokenExpirationDatetime() ?
393
                $this->getEmailConfirmationTokenExpirationDatetime()->format('Y-m-d H:i:s') : null,
394
            'lastEmailTokenGeneratedDatetime' => $this->getLastEmailTokenGeneratedDatetime() ?
395
                $this->getLastEmailTokenGeneratedDatetime()->format('Y-m-d H:i:s') : null,
396
            'password' => $this->getPassword(),
397
            'passwordResetToken' => $this->getPasswordResetToken(),
398
            'passwordResetTokenExpirationDatetime' => $this->getPasswordResetTokenExpirationDatetime() ?
399
                $this->getPasswordResetTokenExpirationDatetime()->format('Y-m-d H:i:s') : null,
400
            'lastPasswordResetTokenGeneratedDatetime' => $this->getLastPasswordResetTokenGeneratedDatetime() ?
401
                $this->getLastPasswordResetTokenGeneratedDatetime()->format('Y-m-d H:i:s') : null,
402
            'creationDatetime' => $this->getCreationDatetime()->format('Y-m-d H:i:s'),
403
            'modificationDatetime' => $this->getModificationDatetime()->format('Y-m-d H:i:s'),
404
        ];
405
    }
406
407
    public function jsonSerialize()
408
    {
409
        return array_intersect_key(
410
            $this->toArray(),
411
            [
412
                'id' => null,
413
                'groupId' => null,
414
                'status' => null,
415
                'isAdmin' => null,
416
                'email' => null,
417
                'isEmailConfirmed' => null,
418
                'creationDatetime' => null,
419
                'modificationDatetime' => null,
420
            ]
421
        );
422
    }
423
}
424