Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
95.00% covered (success)
95.00%
19 / 20
94.12% covered (success)
94.12%
16 / 17
CRAP
0.00% covered (danger)
0.00%
0 / 1
User
94.74% covered (success)
94.74%
18 / 19
94.12% covered (success)
94.12%
16 / 17
20.06
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getUsername
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getEmail
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPasswordHash
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getLocale
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setLocale
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 verifyPassword
66.67% covered (warning)
66.67%
2 / 3
0.00% covered (danger)
0.00%
0 / 1
2.15
 isActive
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
3
 getStatus
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getSpecialAccess
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isSuperuser
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isMfaEnabled
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCreatedAt
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getUpdatedAt
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCreatedBy
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getOwner
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5/** @license For full copyright and license information, please see the LICENSE.md file. */
6
7namespace App\Modules\User\Domain\Model;
8
9defined('AMMONLY_APP') || exit('Direct script access is forbidden.');
10
11use DateTimeImmutable;
12
13/**
14 * User Entity in Domain Layer (DDD).
15 *
16 * Pure PHP entity completely decoupled from framework and database details.
17 *
18 * @package App\Modules\User\Domain\Model
19 */
20final class User
21{
22    /**
23     * User Entity constructor.
24     *
25     * @param int|null $id Unique user identifier.
26     * @param string $username Unique username.
27     * @param string $email Unique email address.
28     * @param string $passwordHash Hashed password.
29     * @param bool $isActive Account active flag.
30     * @param bool $isSuperuser Whether user has full superuser privileges.
31     * @param DateTimeImmutable|null $createdAt Creation timestamp.
32     * @param DateTimeImmutable|null $updatedAt Modification timestamp.
33     * @param int $createdBy Creator user ID.
34     * @param int $owner Record owner user ID.
35     */
36    public function __construct(
37        private ?int $id,
38        private string $username,
39        private string $email,
40        private string $passwordHash,
41        private bool $isActive = true,
42        private bool $isSuperuser = false,
43        private string $locale = 'en',
44        private ?DateTimeImmutable $createdAt = null,
45        private ?DateTimeImmutable $updatedAt = null,
46        private int $createdBy = 1,
47        private int $owner = 1,
48        private bool $isMfaEnabled = false,
49        private string $status = 'active',
50        private int $specialAccess = 1
51    ) {
52    }
53
54    public function getId(): ?int
55    {
56        return $this->id;
57    }
58
59    public function getUsername(): string
60    {
61        return $this->username;
62    }
63
64    public function getEmail(): string
65    {
66        return $this->email;
67    }
68
69    public function getPasswordHash(): string
70    {
71        return $this->passwordHash;
72    }
73
74    public function getLocale(): string
75    {
76        return $this->locale;
77    }
78
79    public function setLocale(string $locale): void
80    {
81        $this->locale = $locale;
82    }
83
84    /**
85     * Verifies plain text password against stored hash with optional Yii3 PasswordHasher.
86     *
87     * @param string $plainPassword Password to verify.
88     * @param \Yiisoft\Security\PasswordHasher|null $hasher Optional PasswordHasher instance.
89     * @return bool True if password matches hash.
90     */
91    public function verifyPassword(
92        string $plainPassword,
93        ?\Yiisoft\Security\PasswordHasher $hasher = null
94    ): bool {
95        if ($hasher !== null) {
96            return $hasher->validate($plainPassword, $this->passwordHash);
97        }
98
99        return password_verify($plainPassword, $this->passwordHash);
100    }
101
102    public function isActive(): bool
103    {
104        return $this->isActive && $this->status === 'active' && $this->specialAccess === 1;
105    }
106
107    public function getStatus(): string
108    {
109        return $this->status;
110    }
111
112    public function getSpecialAccess(): int
113    {
114        return $this->specialAccess;
115    }
116
117    /**
118     * Returns whether the user has superuser privileges.
119     *
120     * @return bool True if user is a superuser.
121     */
122    public function isSuperuser(): bool
123    {
124        return $this->isSuperuser;
125    }
126
127    /**
128     * Returns whether multi-factor authentication (2FA/MFA) is active on this account.
129     *
130     * @return bool True if MFA protection is enabled.
131     */
132    public function isMfaEnabled(): bool
133    {
134        return $this->isMfaEnabled;
135    }
136
137    public function getCreatedAt(): ?DateTimeImmutable
138    {
139        return $this->createdAt;
140    }
141
142    public function getUpdatedAt(): ?DateTimeImmutable
143    {
144        return $this->updatedAt;
145    }
146
147    public function getCreatedBy(): int
148    {
149        return $this->createdBy;
150    }
151
152    public function getOwner(): int
153    {
154        return $this->owner;
155    }
156}