User::setAvatar()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ProjetNormandie\UserBundle\Entity;
6
7
use ApiPlatform\Metadata\ApiResource;
8
use ApiPlatform\Metadata\Get;
9
use ApiPlatform\Metadata\GetCollection;
10
use ApiPlatform\Metadata\Post;
11
use ApiPlatform\Metadata\ApiFilter;
12
use ApiPlatform\Doctrine\Orm\Filter\SearchFilter;
13
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
14
use ApiPlatform\Metadata\Put;
15
use ApiPlatform\OpenApi\Model;
16
use DateTime;
17
use Doctrine\Common\Collections\ArrayCollection;
18
use Doctrine\Common\Collections\Collection;
19
use Doctrine\ORM\Mapping as ORM;
20
use Gedmo\Timestampable\Traits\TimestampableEntity;
21
use Gedmo\Mapping\Annotation as Gedmo;
22
use ProjetNormandie\UserBundle\Controller\User\Autocomplete;
23
use ProjetNormandie\UserBundle\Controller\User\GetMe;
24
use ProjetNormandie\UserBundle\Repository\UserRepository;
25
use Symfony\Bridge\Doctrine\Validator\Constraints as DoctrineAssert;
26
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
27
use Symfony\Component\Security\Core\User\UserInterface;
28
use Symfony\Component\Serializer\Annotation\Groups;
29
use Symfony\Component\Validator\Constraints as Assert;
30
31
#[ORM\Table(name:'pnu_user')]
32
#[ORM\Entity(repositoryClass: UserRepository::class)]
33
#[ORM\EntityListeners(["ProjetNormandie\UserBundle\EventListener\Entity\UserListener"])]
34
#[DoctrineAssert\UniqueEntity(["email"])]
35
#[DoctrineAssert\UniqueEntity(["username"])]
36
#[ApiResource(
37
    operations: [
38
        new GetCollection(),
39
        new GetCollection(
40
            uriTemplate: '/users/autocomplete',
41
            controller: Autocomplete::class,
42
            openapi: new Model\Operation(
43
                responses: [
44
                    '200' => new Model\Response(description: 'Users retrieved successfully')
45
                ],
46
                summary: 'Retrieves users by autocompletion',
47
                description: 'Retrieves users by autocompletion',
48
                parameters: [
49
                    new Model\Parameter(
50
                        name: 'query',
51
                        in: 'query',
52
                        required: true,
53
                        schema: [
54
                            'type' => 'string'
55
                        ]
56
                    )
57
                ],
58
                security: [],
59
            ),
60
            normalizationContext: ['groups' => [
61
                'user:read']
62
            ],
63
        ),
64
        new Post(
65
            denormalizationContext: ['groups' => ['user:create']],
66
            validationContext: ['groups' => ['Default', 'user:create']],
67
        ),
68
        new Put(
69
            denormalizationContext: ['groups' => ['user:update']],
70
            security: 'is_granted("ROLE_USER") and (object == user)',
71
            validationContext: ['groups' => ['Default', 'user:update']]
72
        ),
73
        new Get(
74
            uriTemplate: '/users/me',
75
            controller: GetMe::class,
76
            openapi: new Model\Operation(
77
                responses: [
78
                    '200' => new Model\Response(description: 'Current user retrieved successfully')
79
                ],
80
                summary: 'Get current user',
81
                description: 'Get current authenticated user data',
82
                security: [['bearerAuth' => []]],
83
            ),
84
            normalizationContext: ['groups' => ['user:read', 'user:read:email']],
85
            read: false,
86
        ),
87
        new Get(),
88
    ],
89
    normalizationContext: ['groups' => ['user:read']]
90
)]
91
#[ApiFilter(SearchFilter::class, properties: ['id' => 'exact', 'username' => 'partial'])]
92
#[ApiFilter(OrderFilter::class, properties: ['id', 'username'], arguments: ['orderParameterName' => 'order'])]
93
class User implements UserInterface, PasswordAuthenticatedUserInterface
94
{
95
    use TimestampableEntity;
96
97
    #[Groups(['user:read', 'user:read:minimal'])]
98
    #[ORM\Id, ORM\Column, ORM\GeneratedValue]
99
    protected ?int $id = null;
100
101
102
    #[Groups(['user:read', 'user:read:minimal', 'user:create', 'user:update'])]
103
    #[ORM\Column(length: 100, unique: true, nullable: false)]
104
    protected string $username = '';
105
106
    #[Groups(['user:read:email', 'user:create', 'user:update'])]
107
    #[ORM\Column(length: 180, unique: true, nullable: false)]
108
    private string $email = '';
109
110
111
    #[ORM\Column(nullable: false, options: ['default' => true])]
112
    protected bool $enabled = true;
113
114
    /**
115
     * @var array<string>
116
     */
117
    #[ORM\Column(type: 'array', nullable: false)]
118
    private array $roles = [];
119
120
    #[ORM\Column(length: 255)]
121
    private ?string $password;
122
123
    /**
124
     * Plain password. Used for model validation. Must not be persisted.
125
     */
126
    #[Assert\NotBlank(groups: ['user:create'])]
127
    #[Groups(['user:create'])]
128
    protected ?string $plainPassword = null;
129
130
    #[Groups(['user:read'])]
131
    #[ORM\Column(type: 'datetime', nullable: true)]
132
    protected ?DateTime $lastLogin = null;
133
134
    #[ORM\Column(length: 255, unique: true, nullable: true)]
135
    protected ?string $confirmationToken = null;
136
137
    #[ORM\Column(type: 'datetime', nullable: true)]
138
    protected ?DateTime $passwordRequestedAt = null;
139
140
    #[Groups(['user:read'])]
141
    #[ORM\Column(nullable: false, options: ['default' => 0])]
142
    protected int $nbConnexion = 0;
143
144
    /**
145
     * Extra data for extensions and additional bundles.
146
     * @var array<string, mixed>
147
     */
148
    #[Groups(['user:read', 'user:read:minimal'])]
149
    #[ORM\Column(type: 'json', nullable: true)]
150
    protected array $extraData = [];
151
152
    #[ORM\Column(length: 255, nullable: false, options: ['default' => 'default.png'])]
153
    protected string $avatar = 'default.png';
154
155
    #[ORM\Column(length: 1000, nullable: true)]
156
    protected ?string $comment = null;
157
158
    #[Groups(['user:read', 'user:update'])]
159
    #[ORM\Column(length: 2, nullable: false, options: ['default' => 'en'])]
160
    protected string $language = 'en';
161
162
    #[Groups(['user:read', 'user:read:minimal'])]
163
    #[ORM\Column(length: 128)]
164
    #[Gedmo\Slug(fields: ['username'])]
165
    protected string $slug;
166
167
    #[ORM\JoinTable(name: 'pnu_user_group')]
168
    #[ORM\JoinColumn(name: 'user_id', referencedColumnName: 'id')]
169
    #[ORM\InverseJoinColumn(name: 'group_id', referencedColumnName: 'id')]
170
    #[ORM\ManyToMany(targetEntity: Group::class)]
171
    protected Collection $groups;
172
173
    public function __construct()
174
    {
175
        $this->groups = new ArrayCollection();
176
    }
177
178
    public function getId(): ?int
179
    {
180
        return $this->id;
181
    }
182
183
    public function setId(?int $id): void
184
    {
185
        $this->id = $id;
186
    }
187
188
    public function getUsername(): string
189
    {
190
        return $this->username;
191
    }
192
193
    public function setUsername($username): void
194
    {
195
        $this->username = $username;
196
    }
197
198
    public function getEmail(): ?string
199
    {
200
        return $this->email;
201
    }
202
203
    public function setEmail(string $email): void
204
    {
205
        $this->email = $email;
206
    }
207
208
    public function setEnabled($boolean): void
209
    {
210
        $this->enabled = (bool) $boolean;
211
    }
212
213
    public function isEnabled(): bool
214
    {
215
        return $this->enabled;
216
    }
217
218
    public function getRoles(): array
219
    {
220
        $roles = $this->roles;
221
222
        foreach ($this->getGroups() as $group) {
223
            $roles = array_merge($roles, $group->getRoles());
224
        }
225
226
        // we need to make sure to have at least one role
227
        $roles[] = 'ROLE_USER';
228
229
        return array_values(array_unique($roles));
230
    }
231
232
    public function setRoles(array $roles): void
233
    {
234
        $this->roles = $roles;
235
    }
236
237
    public function getPassword(): ?string
238
    {
239
        return $this->password;
240
    }
241
242
    public function setPassword(string $password): void
243
    {
244
        $this->password = $password;
245
    }
246
247
    /**
248
     * Returning a salt is only needed, if you are not using a modern
249
     * hashing algorithm (e.g. bcrypt or sodium) in your security.yaml.
250
     */
251
    public function getSalt(): ?string
252
    {
253
        return null;
254
    }
255
256
    public function getPlainPassword(): ?string
257
    {
258
        return $this->plainPassword;
259
    }
260
261
    public function hasRole($role): bool
262
    {
263
        return in_array(strtoupper($role), $this->getRoles(), true);
264
    }
265
266
    public function eraseCredentials(): void
267
    {
268
        // If you store any temporary, sensitive data on the user, clear it here
269
        // $this->plainPassword = null;
270
    }
271
272
    public function getLastLogin(): ?DateTime
273
    {
274
        return $this->lastLogin;
275
    }
276
277
    public function setLastLogin(?DateTime $time = null): void
278
    {
279
        if ($time === null) {
280
            $time = new \DateTime();
281
        }
282
283
        $lastLogin = $this->getLastLogin();
284
285
        if ($lastLogin === null || $lastLogin->format('Y-m-d') !== $time->format('Y-m-d')) {
286
            ++$this->nbConnexion;
287
        }
288
289
        $this->lastLogin = $time;
290
    }
291
292
    public function updateLastLoginOnly(?\DateTime $time = null): void
293
    {
294
        if ($time === null) {
295
            $time = new \DateTime();
296
        }
297
298
        $this->lastLogin = $time;
299
    }
300
301
    public function setConfirmationToken($confirmationToken): void
302
    {
303
        $this->confirmationToken = $confirmationToken;
304
    }
305
306
    public function getConfirmationToken(): ?string
307
    {
308
        return $this->confirmationToken;
309
    }
310
311
    public function setPasswordRequestedAt(?DateTime $date = null): void
312
    {
313
        $this->passwordRequestedAt = $date;
314
    }
315
316
    public function getPasswordRequestedAt(): ?DateTime
317
    {
318
        return $this->passwordRequestedAt;
319
    }
320
321
    public function isPasswordRequestExpired($ttl): bool
322
    {
323
        return $this->getPasswordRequestedAt() instanceof DateTime &&
324
               $this->getPasswordRequestedAt()->getTimestamp() + $ttl < time();
325
    }
326
327
    public function getLanguage(): string
328
    {
329
        return $this->language;
330
    }
331
332
    public function setLanguage(string $language): void
333
    {
334
        $this->language = $language;
335
    }
336
337
    public function getSlug(): string
338
    {
339
        return $this->slug;
340
    }
341
342
    public function getNbConnexion(): int
343
    {
344
        return $this->nbConnexion;
345
    }
346
347
    public function setNbConnexion(int $nbConnexion): void
348
    {
349
        $this->nbConnexion = $nbConnexion;
350
    }
351
352
    /**
353
     * Get extra data by key or all extra data if no key provided.
354
     *
355
     * @param string|null $key The key to retrieve
356
     * @return mixed The value or all extraData if no key provided
357
     */
358
    public function getExtraData(?string $key = null): mixed
359
    {
360
        if ($key === null) {
361
            return $this->extraData;
362
        }
363
364
        return $this->extraData[$key] ?? null;
365
    }
366
367
    /**
368
     * Set extra data with a given key.
369
     *
370
     * @param string $key The key to set
371
     * @param mixed $value The value to set
372
     */
373
    public function setExtraData(string $key, mixed $value): void
374
    {
375
        $this->extraData[$key] = $value;
376
    }
377
378
    /**
379
     * Check if extra data with given key exists.
380
     *
381
     * @param string $key The key to check
382
     * @return bool True if the key exists
383
     */
384
    public function hasExtraData(string $key): bool
385
    {
386
        return array_key_exists($key, $this->extraData);
387
    }
388
389
    /**
390
     * Remove extra data with given key.
391
     *
392
     * @param string $key The key to remove
393
     */
394
    public function removeExtraData(string $key): void
395
    {
396
        if ($this->hasExtraData($key)) {
397
            unset($this->extraData[$key]);
398
        }
399
    }
400
401
    public function getAvatar(): string
402
    {
403
        return $this->avatar;
404
    }
405
406
    public function setAvatar(string $avatar): void
407
    {
408
        $this->avatar = $avatar;
409
    }
410
411
    public function getComment(): ?string
412
    {
413
        return $this->comment;
414
    }
415
416
    public function setComment(?string $comment = null): void
417
    {
418
        $this->comment = $comment;
419
    }
420
421
    public function setGroups($groups): void
422
    {
423
        $this->groups = $groups;
424
    }
425
426
    public function getGroups(): Collection
427
    {
428
        return $this->groups;
429
    }
430
431
    public function setPlainPassword($password): void
432
    {
433
        $this->plainPassword = $password;
434
    }
435
436
    public function addGroup($group): void
437
    {
438
        $this->groups[] = $group;
439
    }
440
441
    public function removeGroup(Group $group): void
442
    {
443
        $this->groups->removeElement($group);
444
    }
445
446
    public function __toString()
447
    {
448
        return sprintf('%s [%d]', $this->getUsername(), $this->getId());
449
    }
450
451
    public function addRole($role): void
452
    {
453
        $role = strtoupper($role);
454
        if (!in_array($role, $this->roles, true)) {
455
            $this->roles[] = $role;
456
        }
457
    }
458
459
    public function removeRole($role): void
460
    {
461
        if (false !== $key = array_search(strtoupper($role), $this->roles, true)) {
462
            unset($this->roles[$key]);
463
            $this->roles = array_values($this->roles);
464
        }
465
    }
466
467
    public function getUserIdentifier(): string
468
    {
469
        return $this->email;
470
    }
471
}
472