Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 156
0.00% covered (danger)
0.00%
0 / 92
CRAP
0.00% covered (danger)
0.00%
0 / 1
User
0.00% covered (danger)
0.00%
0 / 156
0.00% covered (danger)
0.00%
0 / 92
10506
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getId
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setId
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getUsername
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setUsername
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getOldUsername
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setOldUsername
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getPasswordHash
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setPasswordHash
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getEmail
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setEmail
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 isEmailVerified
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setEmailIsVerified
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getEmailVerificationToken
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setEmailVerificationToken
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getFirstName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setFirstName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getLastName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setLastName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getFullName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getGender
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setGender
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getStreet
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setStreet
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getPostalCode
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setPostalCode
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getCity
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setCity
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getRegion
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setRegion
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getCountryCode
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setCountryCode
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getBirthdate
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setBirthdate
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getPhone
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setPhone
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getPermissions
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setPermissions
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getPermissionMap
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
20
 setPermissionMap
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 hasPermission
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 addPermission
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 removePermission
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 getRoot
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setRoot
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getParentUserId
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setParentUserId
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getMemberType
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setMemberType
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getMemberLastPaid
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setMemberLastPaid
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getWantsPostalMail
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setWantsPostalMail
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getPostalTitle
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setPostalTitle
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getPostalName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setPostalName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getJoinedOn
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setJoinedOn
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getJoinedReason
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setJoinedReason
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getLeftOn
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setLeftOn
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getLeftReason
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setLeftReason
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getSolvNumber
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setSolvNumber
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getSiCardNumber
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setSiCardNumber
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getAhvNumber
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setAhvNumber
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getDressSize
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setDressSize
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getAvatarImageId
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setAvatarImageId
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getNotes
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setNotes
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getLastLoginAt
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setLastLoginAt
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getRoles
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 addRole
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 removeRole
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 __toString
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 pretty
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
30
 softDelete
0.00% covered (danger)
0.00%
0 / 26
0.00% covered (danger)
0.00%
0 / 1
2
 getEntityNameForStorage
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getEntityIdForStorage
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getIdFieldNameForSearch
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getIdForSearch
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getTitleForSearch
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getCriteriaForFilter
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getCriteriaForQuery
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace Olz\Entity\Users;
4
5use Doctrine\Common\Collections\ArrayCollection;
6use Doctrine\Common\Collections\Collection;
7use Doctrine\Common\Collections\Criteria;
8use Doctrine\Common\Collections\Expr\Expression;
9use Doctrine\ORM\Mapping as ORM;
10use Olz\Entity\Common\DataStorageInterface;
11use Olz\Entity\Common\DataStorageTrait;
12use Olz\Entity\Common\OlzEntity;
13use Olz\Entity\Common\SearchableInterface;
14use Olz\Entity\Roles\Role;
15use Olz\Repository\Users\UserRepository;
16
17#[ORM\Table(name: 'users')]
18#[ORM\Index(name: 'username_index', columns: ['username'])]
19#[ORM\Entity(repositoryClass: UserRepository::class)]
20class User extends OlzEntity implements DataStorageInterface, SearchableInterface {
21    use DataStorageTrait;
22
23    #[ORM\Id]
24    #[ORM\Column(type: 'integer', nullable: false)]
25    #[ORM\GeneratedValue]
26    public int $id;
27
28    #[ORM\Column(type: 'integer', nullable: true)]
29    public ?int $parent_user;
30
31    #[ORM\Column(type: 'string', nullable: false)]
32    public string $username;
33
34    #[ORM\Column(type: 'string', nullable: true)]
35    public ?string $old_username;
36
37    #[ORM\Column(type: 'text', nullable: true)]
38    public ?string $password;
39
40    #[ORM\Column(type: 'text', nullable: true)]
41    public ?string $email;
42
43    #[ORM\Column(type: 'boolean', nullable: false)]
44    public bool $email_is_verified;
45
46    #[ORM\Column(type: 'text', nullable: true)]
47    public ?string $email_verification_token;
48
49    #[ORM\Column(type: 'text', nullable: false)]
50    public string $first_name;
51
52    #[ORM\Column(type: 'text', nullable: false)]
53    public string $last_name;
54
55    #[ORM\Column(type: 'string', length: 2, nullable: true, options: ['comment' => 'M(ale), F(emale), or O(ther)'])]
56    public ?string $gender;
57
58    #[ORM\Column(type: 'text', nullable: true)]
59    public ?string $street;
60
61    #[ORM\Column(type: 'text', nullable: true)]
62    public ?string $postal_code;
63
64    #[ORM\Column(type: 'text', nullable: true)]
65    public ?string $city;
66
67    #[ORM\Column(type: 'text', nullable: true)]
68    public ?string $region;
69
70    #[ORM\Column(type: 'string', length: 3, nullable: true, options: ['comment' => 'two-letter code (ISO-3166-alpha-2)'])]
71    public ?string $country_code;
72
73    #[ORM\Column(type: 'date', nullable: true)]
74    public ?\DateTime $birthdate;
75
76    #[ORM\Column(type: 'text', nullable: true)]
77    public ?string $phone;
78
79    #[ORM\Column(type: 'text', nullable: true)]
80    public ?string $avatar_image_id;
81
82    #[ORM\Column(type: 'text', nullable: false)]
83    public string $permissions;
84
85    #[ORM\Column(type: 'text', nullable: true)]
86    public ?string $root;
87
88    #[ORM\Column(type: 'string', length: 3, nullable: true, options: ['comment' => 'Aktiv, Ehrenmitglied, Verein, Sponsor'])]
89    public ?string $member_type;
90
91    #[ORM\Column(type: 'date', nullable: true)]
92    public ?\DateTime $member_last_paid;
93
94    #[ORM\Column(type: 'boolean', nullable: false, options: ['default' => 0])]
95    public bool $wants_postal_mail;
96
97    #[ORM\Column(type: 'text', nullable: true, options: ['comment' => 'if not {m: Herr, f: Frau, o: }'])]
98    public ?string $postal_title;
99
100    #[ORM\Column(type: 'text', nullable: true, options: ['comment' => "if not 'First Last'"])]
101    public ?string $postal_name;
102
103    #[ORM\Column(type: 'date', nullable: true)]
104    public ?\DateTime $joined_on;
105
106    #[ORM\Column(type: 'text', nullable: true)]
107    public ?string $joined_reason;
108
109    #[ORM\Column(type: 'date', nullable: true)]
110    public ?\DateTime $left_on;
111
112    #[ORM\Column(type: 'text', nullable: true)]
113    public ?string $left_reason;
114
115    #[ORM\Column(type: 'text', nullable: true)]
116    public ?string $solv_number;
117
118    #[ORM\Column(type: 'text', nullable: true)]
119    public ?string $si_card_number;
120
121    #[ORM\Column(type: 'string', length: 17, nullable: true)]
122    public ?string $ahv_number;
123
124    #[ORM\Column(type: 'string', length: 4, nullable: true, options: ['comment' => '3XS, XXS, XS, S, M, L, XL, XXL, 3XL'])]
125    public ?string $dress_size;
126
127    #[ORM\Column(type: 'text', nullable: false, options: ['default' => ''])]
128    public string $notes;
129
130    /** @var Collection<int|string, Role>&iterable<Role> */
131    #[ORM\JoinTable(name: 'users_roles')]
132    #[ORM\ManyToMany(targetEntity: Role::class, inversedBy: 'users')]
133    private Collection $roles;
134
135    #[ORM\Column(type: 'datetime', nullable: true)]
136    private ?\DateTime $last_login_at;
137
138    public function __construct() {
139        $this->roles = new ArrayCollection();
140    }
141
142    public function getId(): ?int {
143        return $this->id ?? null;
144    }
145
146    public function setId(int $new_value): void {
147        $this->id = $new_value;
148    }
149
150    public function getUsername(): string {
151        return $this->username;
152    }
153
154    public function setUsername(string $new_value): void {
155        $this->username = $new_value;
156    }
157
158    public function getOldUsername(): ?string {
159        return $this->old_username;
160    }
161
162    public function setOldUsername(?string $new_value): void {
163        $this->old_username = $new_value;
164    }
165
166    public function getPasswordHash(): ?string {
167        return $this->password;
168    }
169
170    public function setPasswordHash(?string $new_value): void {
171        $this->password = $new_value;
172    }
173
174    public function getEmail(): ?string {
175        return $this->email;
176    }
177
178    public function setEmail(?string $new_value): void {
179        $this->email = $new_value;
180    }
181
182    public function isEmailVerified(): bool {
183        return $this->email_is_verified;
184    }
185
186    public function setEmailIsVerified(bool $new_value): void {
187        $this->email_is_verified = $new_value;
188    }
189
190    public function getEmailVerificationToken(): ?string {
191        return $this->email_verification_token;
192    }
193
194    public function setEmailVerificationToken(?string $new_value): void {
195        $this->email_verification_token = $new_value;
196    }
197
198    public function getFirstName(): string {
199        return $this->first_name;
200    }
201
202    public function setFirstName(string $new_value): void {
203        $this->first_name = $new_value;
204    }
205
206    public function getLastName(): string {
207        return $this->last_name;
208    }
209
210    public function setLastName(string $new_value): void {
211        $this->last_name = $new_value;
212    }
213
214    public function getFullName(): string {
215        return "{$this->getFirstName()} {$this->getLastName()}";
216    }
217
218    public function getGender(): ?string {
219        return $this->gender;
220    }
221
222    public function setGender(?string $new_value): void {
223        $this->gender = $new_value;
224    }
225
226    public function getStreet(): ?string {
227        return $this->street;
228    }
229
230    public function setStreet(?string $new_value): void {
231        $this->street = $new_value;
232    }
233
234    public function getPostalCode(): ?string {
235        return $this->postal_code;
236    }
237
238    public function setPostalCode(?string $new_value): void {
239        $this->postal_code = $new_value;
240    }
241
242    public function getCity(): ?string {
243        return $this->city;
244    }
245
246    public function setCity(?string $new_value): void {
247        $this->city = $new_value;
248    }
249
250    public function getRegion(): ?string {
251        return $this->region;
252    }
253
254    public function setRegion(?string $new_value): void {
255        $this->region = $new_value;
256    }
257
258    public function getCountryCode(): ?string {
259        return $this->country_code;
260    }
261
262    public function setCountryCode(?string $new_value): void {
263        $this->country_code = $new_value;
264    }
265
266    public function getBirthdate(): ?\DateTime {
267        return $this->birthdate;
268    }
269
270    public function setBirthdate(?\DateTime $new_value): void {
271        $this->birthdate = $new_value;
272    }
273
274    public function getPhone(): ?string {
275        return $this->phone;
276    }
277
278    public function setPhone(?string $new_value): void {
279        $this->phone = $new_value;
280    }
281
282    public function getPermissions(): string {
283        return $this->permissions;
284    }
285
286    public function setPermissions(string $new_value): void {
287        $this->permissions = $new_value;
288    }
289
290    /** @return array<string, true> */
291    public function getPermissionMap(): array {
292        $permission_list = preg_split('/[ ]+/', $this->permissions ?? '');
293        if (!is_array($permission_list)) {
294            return [];
295        }
296        $permission_map = [];
297        foreach ($permission_list as $permission) {
298            if (strlen($permission) > 0) {
299                $permission_map[$permission] = true;
300            }
301        }
302        return $permission_map;
303    }
304
305    /** @param array<string, bool> $new_value */
306    public function setPermissionMap(array $new_value): void {
307        $permission_list = [];
308        foreach ($new_value as $key => $value) {
309            if ($value) {
310                $permission_list[] = $key;
311            }
312        }
313        $this->permissions = ' '.implode(' ', $permission_list).' ';
314    }
315
316    public function hasPermission(string $has_permission): bool {
317        $permission_map = $this->getPermissionMap();
318        return $permission_map[$has_permission] ?? false;
319    }
320
321    public function addPermission(string $add_permission): void {
322        $permission_map = $this->getPermissionMap();
323        $permission_map[$add_permission] = true;
324        $this->setPermissionMap($permission_map);
325    }
326
327    public function removePermission(string $remove_permission): void {
328        $permission_map = $this->getPermissionMap();
329        $permission_map[$remove_permission] = false;
330        $this->setPermissionMap($permission_map);
331    }
332
333    public function getRoot(): ?string {
334        return $this->root;
335    }
336
337    public function setRoot(?string $new_value): void {
338        $this->root = $new_value;
339    }
340
341    public function getParentUserId(): ?int {
342        return $this->parent_user;
343    }
344
345    public function setParentUserId(?int $new_value): void {
346        $this->parent_user = $new_value;
347    }
348
349    public function getMemberType(): ?string {
350        return $this->member_type;
351    }
352
353    public function setMemberType(?string $new_value): void {
354        $this->member_type = $new_value;
355    }
356
357    public function getMemberLastPaid(): ?\DateTime {
358        return $this->member_last_paid;
359    }
360
361    public function setMemberLastPaid(?\DateTime $new_value): void {
362        $this->member_last_paid = $new_value;
363    }
364
365    public function getWantsPostalMail(): bool {
366        return $this->wants_postal_mail;
367    }
368
369    public function setWantsPostalMail(bool $new_value): void {
370        $this->wants_postal_mail = $new_value;
371    }
372
373    public function getPostalTitle(): ?string {
374        return $this->postal_title;
375    }
376
377    public function setPostalTitle(?string $new_value): void {
378        $this->postal_title = $new_value;
379    }
380
381    public function getPostalName(): ?string {
382        return $this->postal_name;
383    }
384
385    public function setPostalName(?string $new_value): void {
386        $this->postal_name = $new_value;
387    }
388
389    public function getJoinedOn(): ?\DateTime {
390        return $this->joined_on;
391    }
392
393    public function setJoinedOn(?\DateTime $new_value): void {
394        $this->joined_on = $new_value;
395    }
396
397    public function getJoinedReason(): ?string {
398        return $this->joined_reason;
399    }
400
401    public function setJoinedReason(?string $new_value): void {
402        $this->joined_reason = $new_value;
403    }
404
405    public function getLeftOn(): ?\DateTime {
406        return $this->left_on;
407    }
408
409    public function setLeftOn(?\DateTime $new_value): void {
410        $this->left_on = $new_value;
411    }
412
413    public function getLeftReason(): ?string {
414        return $this->left_reason;
415    }
416
417    public function setLeftReason(?string $new_value): void {
418        $this->left_reason = $new_value;
419    }
420
421    public function getSolvNumber(): ?string {
422        return $this->solv_number;
423    }
424
425    public function setSolvNumber(?string $new_value): void {
426        $this->solv_number = $new_value;
427    }
428
429    public function getSiCardNumber(): ?string {
430        return $this->si_card_number;
431    }
432
433    public function setSiCardNumber(?string $new_value): void {
434        $this->si_card_number = $new_value;
435    }
436
437    public function getAhvNumber(): ?string {
438        return $this->ahv_number;
439    }
440
441    public function setAhvNumber(?string $new_value): void {
442        $this->ahv_number = $new_value;
443    }
444
445    public function getDressSize(): ?string {
446        return $this->dress_size;
447    }
448
449    public function setDressSize(?string $new_value): void {
450        $this->dress_size = $new_value;
451    }
452
453    public function getAvatarImageId(): ?string {
454        return $this->avatar_image_id;
455    }
456
457    public function setAvatarImageId(?string $new_value): void {
458        $this->avatar_image_id = $new_value;
459    }
460
461    public function getNotes(): string {
462        return $this->notes;
463    }
464
465    public function setNotes(string $new_value): void {
466        $this->notes = $new_value;
467    }
468
469    public function getLastLoginAt(): ?\DateTime {
470        return $this->last_login_at;
471    }
472
473    public function setLastLoginAt(?\DateTime $new_value): void {
474        $this->last_login_at = $new_value;
475    }
476
477    /** @return Collection<int|string, Role>&iterable<Role> */
478    public function getRoles(): Collection {
479        return $this->roles;
480    }
481
482    public function addRole(Role $role): void {
483        if (!$this->roles->contains($role)) {
484            $this->roles->add($role);
485        }
486    }
487
488    public function removeRole(Role $role): void {
489        $this->roles->removeElement($role);
490    }
491
492    // ---
493
494    public function __toString(): string {
495        $username = $this->getUsername();
496        $id = $this->getId();
497        return "{$username} (User ID: {$id})";
498    }
499
500    public function pretty(): string {
501        $is_verified = $this->isEmailVerified() ? '✅ verified' : '❌ not verified';
502        $has_permission = $this->hasPermission('verified_email') ? '✅ permission' : '❌ no permission';
503        $roles = implode(', ', array_map(
504            fn ($role): string => $role->getUsername(),
505            [...$this->roles],
506        ));
507        $has_password = $this->getPasswordHash() ? '✅ password' : '❌ no password';
508        $is_child = $this->getParentUserId() ? "🚸 child of {$this->getParentUserId()}" : '✅ parent';
509        return <<<ZZZZZZZZZZ
510            Name: {$this->getFullName()}
511            Username: {$this->getUsername()} (old: {$this->getOldUsername()})
512            E-Mail: {$this->getEmail()} ({$is_verified} / {$has_permission})
513            Password: {$has_password} / {$is_child}
514            Permissions: {$this->getPermissions()}
515            Roles ({$this->roles->count()}): {$roles}
516            ZZZZZZZZZZ;
517    }
518
519    public function softDelete(): void {
520        $this->entityUtils()->updateOlzEntity($this, ['onOff' => false]);
521        $this->setEmail('');
522        $this->setPasswordHash('');
523        $this->setPhone('');
524        $this->setGender(null);
525        $this->setBirthdate(null);
526        $this->setStreet(null);
527        $this->setPostalCode(null);
528        $this->setCity(null);
529        $this->setRegion(null);
530        $this->setCountryCode(null);
531        $this->setPermissions('');
532        $this->setRoot(null);
533        $this->setMemberType(null);
534        $this->setMemberLastPaid(null);
535        $this->setWantsPostalMail(false);
536        $this->setPostalTitle(null);
537        $this->setPostalName(null);
538        $this->setJoinedOn(null);
539        $this->setJoinedReason(null);
540        $this->setLeftOn(null);
541        $this->setLeftReason(null);
542        $this->setSolvNumber(null);
543        $this->setSiCardNumber(null);
544        $this->setNotes('');
545        $this->roles->clear();
546    }
547
548    // ---
549
550    public static function getEntityNameForStorage(): string {
551        return 'users';
552    }
553
554    public function getEntityIdForStorage(): string {
555        return "{$this->getId()}";
556    }
557
558    public static function getIdFieldNameForSearch(): string {
559        return 'id';
560    }
561
562    public function getIdForSearch(): int {
563        return $this->getId() ?? 0;
564    }
565
566    public function getTitleForSearch(): string {
567        return $this->getFullName();
568    }
569
570    public static function getCriteriaForFilter(string $key, string $value): Expression {
571        throw new \Exception("No such User filter: {$key}");
572    }
573
574    public static function getCriteriaForQuery(string $query): Expression {
575        return Criteria::expr()->orX(
576            Criteria::expr()->contains('first_name', $query),
577            Criteria::expr()->contains('last_name', $query),
578            Criteria::expr()->contains('username', $query),
579            Criteria::expr()->contains('email', $query),
580        );
581    }
582}