Passed
Push — master ( 4959cd...65a92c )
by Marcel
17:47
created

User   B

Complexity

Total Complexity 46

Size/Duplication

Total Lines 290
Duplicated Lines 0 %

Test Coverage

Coverage 89.23%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 106
c 2
b 0
f 0
dl 0
loc 290
ccs 58
cts 65
cp 0.8923
rs 8.72
wmc 46

45 Methods

Rating   Name   Duplication   Size   Complexity  
A setIsSubstitutionNotificationsEnabled() 0 3 1
A getIdpId() 0 2 1
A setUserType() 0 3 1
A addStudent() 0 2 1
A getPassword() 0 2 1
A isStudentOrParent() 0 2 2
A getFirstname() 0 2 1
A eraseCredentials() 0 1 1
A __toString() 0 2 1
A __construct() 0 5 1
A __serialize() 0 4 1
A setIsMessageNotificationsEnabled() 0 3 1
A getDismissedMessages() 0 2 1
A removeDismissedMessage() 0 2 1
A getLastname() 0 2 1
A isMessageNotificationsEnabled() 0 2 1
A setRoles() 0 2 1
A setIsEmailNotificationsEnabled() 0 3 1
A getUsername() 0 2 1
A setFirstname() 0 3 1
A __unserialize() 0 3 1
A getSalt() 0 2 1
A setUsername() 0 3 1
A removeStudent() 0 2 1
A addDismissedMessage() 0 2 1
A getRoles() 0 2 1
A getData() 0 2 1
A getEmail() 0 2 1
A getUserIdentifier() 0 2 1
A isTeacher() 0 2 1
A setData() 0 2 1
A getUserType() 0 2 1
A isEmailNotificationsEnabled() 0 2 1
A isSubstitutionNotificationsEnabled() 0 2 1
A getId() 0 2 1
A getStudents() 0 2 1
A isParent() 0 2 1
A setTeacher() 0 3 1
A setIdpId() 0 3 1
A setLastname() 0 3 1
A isExamNotificationsEnabled() 0 2 1
A setIsExamNotificationsEnabled() 0 3 1
A getTeacher() 0 2 1
A setEmail() 0 3 1
A isStudent() 0 2 1

How to fix   Complexity   

Complex Class

Complex classes like User often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use User, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace App\Entity;
4
5
use Doctrine\Common\Collections\ArrayCollection;
6
use Doctrine\Common\Collections\Collection;
7
use Doctrine\ORM\Mapping as ORM;
8
use Ramsey\Uuid\Uuid;
9
use Ramsey\Uuid\UuidInterface;
10
use Stringable;
11
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
12
use Symfony\Component\Security\Core\User\UserInterface;
13
use Symfony\Component\Validator\Constraints as Assert;
14
15
#[UniqueEntity(fields: ['username'])]
16
#[ORM\Entity]
17
class User implements UserInterface, Stringable {
18
19
    use IdTrait;
20
    use UuidTrait;
21
22
    #[ORM\Column(type: 'uuid')]
23
    private ?UuidInterface $idpId = null;
24
25
    #[ORM\Column(type: 'string', unique: true)]
26
    private ?string $username = null;
27
28
    #[Assert\NotBlank(allowNull: true)]
29
    #[ORM\Column(type: 'string', nullable: true)]
30
    private ?string $firstname = null;
31
32
    #[Assert\NotBlank(allowNull: true)]
33
    #[ORM\Column(type: 'string', nullable: true)]
34
    private ?string $lastname = null;
35
36
    #[Assert\Email]
37
    #[Assert\NotBlank(allowNull: true)]
38
    #[ORM\Column(type: 'string', nullable: true)]
39
    private ?string $email = null;
40
41
    #[ORM\ManyToOne(targetEntity: Teacher::class)]
42
    #[ORM\JoinColumn(onDelete: 'SET NULL')]
43
    private ?Teacher $teacher = null;
44
45
    /**
46
     * @var Collection<Student>
47
     */
48
    #[ORM\JoinTable(name: 'user_students')]
49
    #[ORM\JoinColumn(onDelete: 'CASCADE')]
50
    #[ORM\InverseJoinColumn(onDelete: 'CASCADE')]
51
    #[ORM\ManyToMany(targetEntity: Student::class)]
52
    private $students;
53
54
    /**
55
     * @var string[]
56
     */
57
    #[ORM\Column(type: 'json')]
58
    private array $roles = ['ROLE_USER'];
59
60
    #[ORM\Column(type: 'string', enumType: UserType::class)]
61
    private ?UserType $userType = null;
62
63
    /**
64
     * @var ArrayCollection<Message>
65
     */
66
    #[ORM\JoinTable(name: 'user_dismissed_messages')]
67
    #[ORM\JoinColumn(onDelete: 'CASCADE')]
68
    #[ORM\InverseJoinColumn(onDelete: 'CASCADE')]
69
    #[ORM\ManyToMany(targetEntity: Message::class)]
70
    private $dismissedMessages;
71
72
    #[ORM\Column(type: 'boolean')]
73
    private bool $isSubstitutionNotificationsEnabled = false;
74
75
    #[ORM\Column(type: 'boolean')]
76
    private bool $isExamNotificationsEnabled = false;
77
78
    #[ORM\Column(type: 'boolean')]
79
    private bool $isMessageNotificationsEnabled = false;
80
81
    #[ORM\Column(type: 'boolean')]
82
    private bool $isEmailNotificationsEnabled = false;
83
84
    /**
85
     * @var string[]
86
     */
87
    #[ORM\Column(type: 'json')]
88
    private array $data = [ ];
89
90
    public function __construct() {
91
        $this->uuid = Uuid::uuid4();
92
93
        $this->students = new ArrayCollection();
94
        $this->dismissedMessages = new ArrayCollection();
95
    }
96
97
    public function getIdpId(): ?UuidInterface {
98
        return $this->idpId;
99
    }
100
101
    public function setIdpId(UuidInterface $uuid): User {
102
        $this->idpId = $uuid;
103
        return $this;
104
    }
105
106
    public function getId(): ?int {
107
        return $this->id;
108
    }
109
110
    public function getFirstname(): ?string {
111
        return $this->firstname;
112
    }
113
114
    public function setFirstname(?string $firstname): User {
115
        $this->firstname = $firstname;
116
        return $this;
117
    }
118
119
    public function getLastname(): ?string {
120
        return $this->lastname;
121
    }
122
123
    public function setLastname(?string $lastname): User {
124
        $this->lastname = $lastname;
125
        return $this;
126 28
    }
127 28
128
    public function getEmail(): ?string {
129 28
        return $this->email;
130 28
    }
131 28
132
    public function setEmail(?string $email): User {
133
        $this->email = $email;
134
        return $this;
135
    }
136
137
    public function getTeacher(): ?Teacher {
138
        return $this->teacher;
139
    }
140
141
    public function setTeacher(?Teacher $teacher): User {
142
        $this->teacher = $teacher;
143
        return $this;
144 10
    }
145 10
146 10
    public function getUserType(): UserType {
147
        return $this->userType;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->userType could return the type null which is incompatible with the type-hinted return App\Entity\UserType. Consider adding an additional type-check to rule them out.
Loading history...
148
    }
149
150
    public function setUserType(UserType $userType): User {
151
        $this->userType = $userType;
152 12
        return $this;
153 12
    }
154
155
    /**
156
     * @param string[] $roles
157
     */
158
    public function setRoles(array $roles) {
159 7
        $this->roles = $roles;
160 7
    }
161
162
    /**
163
     * @return string[]
164
     */
165
    public function getRoles(): array {
166
        return $this->roles;
167 7
    }
168 7
169 7
    public function setUsername(string $username): User {
170
        $this->username = $username;
171
        return $this;
172
    }
173
174
    public function getUsername(): string {
175 7
        return $this->username;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->username could return the type null which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
176 7
    }
177
178
    public function addDismissedMessage(Message $message) {
179
        $this->dismissedMessages->add($message);
180
    }
181
182
    public function removeDismissedMessage(Message $message) {
183 7
        $this->dismissedMessages->removeElement($message);
184 7
    }
185 7
186
    /**
187
     * @return Collection<Message>
188
     */
189
    public function getDismissedMessages(): Collection {
190
        return $this->dismissedMessages;
191 9
    }
192 9
193
    public function addStudent(Student $student) {
194
        $this->students->add($student);
195
    }
196
197
    public function removeStudent(Student $student) {
198
        $this->students->removeElement($student);
199 19
    }
200 19
201 19
    /**
202
     * @return Collection<Student>
203
     */
204
    public function getStudents(): Collection {
205
        return $this->students;
206
    }
207 9
208 9
    public function isSubstitutionNotificationsEnabled(): bool {
209
        return $this->isSubstitutionNotificationsEnabled;
210
    }
211
212
    public function setIsSubstitutionNotificationsEnabled(bool $isSubstitutionNotificationsEnabled): User {
213
        $this->isSubstitutionNotificationsEnabled = $isSubstitutionNotificationsEnabled;
214
        return $this;
215 4
    }
216 4
217 4
    public function isExamNotificationsEnabled(): bool {
218
        return $this->isExamNotificationsEnabled;
219
    }
220
221
    public function setIsExamNotificationsEnabled(bool $isExamNotificationsEnabled): User {
222
        $this->isExamNotificationsEnabled = $isExamNotificationsEnabled;
223 21
        return $this;
224 21
    }
225
226
    public function isMessageNotificationsEnabled(): bool {
227
        return $this->isMessageNotificationsEnabled;
228
    }
229
230
    public function setIsMessageNotificationsEnabled(bool $isMessageNotificationsEnabled): User {
231 27
        $this->isMessageNotificationsEnabled = $isMessageNotificationsEnabled;
232 27
        return $this;
233 27
    }
234
235
    public function isEmailNotificationsEnabled(): bool {
236
        return $this->isEmailNotificationsEnabled;
237
    }
238
239 16
    public function setIsEmailNotificationsEnabled(bool $isEmailNotificationsEnabled): User {
240 16
        $this->isEmailNotificationsEnabled = $isEmailNotificationsEnabled;
241 16
        return $this;
242
    }
243
244
    public function getData(string $key, $default = null) {
245
        return $this->data[$key] ?? $default;
246 16
    }
247 16
248
    public function setData(string $key, $data): void {
249
        $this->data[$key] = $data;
250
    }
251
252
    /**
253
     * @inheritDoc
254 16
     */
255 16
    public function getPassword(): ?string {
256 16
        return '';
257
    }
258
259
    /**
260
     * @inheritDoc
261
     */
262 17
    public function getSalt(): ?string {
263 17
        return null;
264
    }
265
266 1
    /**
267 1
     * @inheritDoc
268 1
     */
269
    public function eraseCredentials() { }
270 1
271 1
    public function getUserIdentifier(): string {
272 1
        return $this->getUsername();
273
    }
274
275
    public function __serialize(): array {
276
        return [
277 1
            'id' => $this->getId(),
278 1
            'username' => $this->getUsername()
279
        ];
280
    }
281 16
282 16
    public function __unserialize(array $serialized) {
283 16
        $this->id = $serialized['id'];
284
        $this->username = $serialized['username'];
285
    }
286
287
    public function __toString(): string {
288
        return sprintf('%s, %s (%s)', $this->getLastname(), $this->getFirstname(), $this->getUsername());
289
    }
290
291
    public function isStudent(): bool {
292 15
        return $this->getUserType() === UserType::Student;
293 15
    }
294
295
    public function isParent(): bool {
296
        return $this->getUserType() === UserType::Parent;
297
    }
298
299
    public function isStudentOrParent(): bool {
300
        return $this->isStudent() || $this->isParent();
301
    }
302
303
    public function isTeacher(): bool {
304
        return $this->getUserType() === UserType::Teacher;
305
    }
306
}