Issues (10)

src/Entity/User.php (1 issue)

Labels
Severity
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\Repository\UserRepository;
24
use Symfony\Bridge\Doctrine\Validator\Constraints as DoctrineAssert;
25
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
26
use Symfony\Component\Security\Core\User\UserInterface;
27
use Symfony\Component\Serializer\Annotation\Groups;
28
use Symfony\Component\Validator\Constraints as Assert;
29
30
#[ORM\Table(name:'pnu_user')]
31
#[ORM\Entity(repositoryClass: UserRepository::class)]
32
#[ORM\EntityListeners(["ProjetNormandie\UserBundle\EventListener\Entity\UserListener"])]
33
#[DoctrineAssert\UniqueEntity(["email"])]
34
#[DoctrineAssert\UniqueEntity(["username"])]
35
#[ApiResource(
36
    operations: [
37
        new GetCollection(),
38
        new GetCollection(
39
            uriTemplate: '/users/autocomplete',
40
            controller: Autocomplete::class,
41
            openapi: new Model\Operation(
42
                responses: [
43
                    '200' => new Model\Response(description: 'Users retrieved successfully')
44
                ],
45
                summary: 'Retrieves users by autocompletion',
46
                description: 'Retrieves users by autocompletion',
47
                parameters: [
48
                    new Model\Parameter(
49
                        name: 'query',
50
                        in: 'query',
51
                        required: true,
52
                        schema: [
53
                            'type' => 'string'
54
                        ]
55
                    )
56
                ],
57
                security: [],
58
            ),
59
            normalizationContext: ['groups' => [
60
                'user:read']
61
            ],
62
        ),
63
        new Post(
64
            denormalizationContext: ['groups' => ['user:create']],
65
            validationContext: ['groups' => ['Default', 'user:create']],
66
        ),
67
        new Put(
68
            denormalizationContext: ['groups' => ['user:update']],
69
            validationContext: ['groups' => ['Default', 'user:update']],
70
        ),
71
        new Get(),
72
    ],
73
    normalizationContext: ['groups' => ['user:read']]
74
)]
75
#[ApiFilter(SearchFilter::class, properties: ['id' => 'exact', 'username' => 'partial'])]
76
#[ApiFilter(OrderFilter::class, properties: ['id', 'username'], arguments: ['orderParameterName' => 'order'])]
77
class User implements UserInterface, PasswordAuthenticatedUserInterface
78
{
79
    use TimestampableEntity;
80
81
    #[Groups(['user:read'])]
82
    #[ORM\Id, ORM\Column, ORM\GeneratedValue]
83
    protected ?int $id = null;
84
85
86
    #[Groups(['user:read', 'user:create', 'user:update'])]
87
    #[ORM\Column(length: 100, unique: true, nullable: false)]
88
    protected string $username = '';
89
90
    #[Groups(['user:read', 'user:create', 'user:update'])]
91
    #[ORM\Column(length: 180, unique: true, nullable: false)]
92
    private string $email = '';
93
94
95
    #[ORM\Column(nullable: false, options: ['default' => true])]
96
    protected bool $enabled = true;
97
98
    /**
99
     * @var array<string>
100
     */
101
    #[ORM\Column(type: 'array', nullable: false)]
102
    private array $roles = [];
103
104
    #[ORM\Column(length: 255)]
105
    private ?string $password;
106
107
    /**
108
     * Plain password. Used for model validation. Must not be persisted.
109
     */
110
    #[Assert\NotBlank(groups: ['user:create'])]
111
    #[Groups(['user:create'])]
112
    protected ?string $plainPassword = null;
113
114
    #[Groups(['user:read'])]
115
    #[ORM\Column(type: 'datetime', nullable: true)]
116
    protected ?DateTime $lastLogin = null;
117
118
    #[ORM\Column(length: 255, unique: true, nullable: true)]
119
    protected ?string $confirmationToken = null;
120
121
    #[ORM\Column(type: 'datetime', nullable: true)]
122
    protected ?DateTime $passwordRequestedAt = null;
123
124
    #[Groups(['user:read'])]
125
    #[ORM\Column(nullable: false, options: ['default' => 0])]
126
    protected int $nbConnexion = 0;
127
128
    /**
129
     * Extra data for extensions and additional bundles.
130
     * @var array<string, mixed>
131
     */
132
    #[Groups(['user:read'])]
133
    #[ORM\Column(type: 'json', nullable: true)]
134
    protected array $extraData = [];
135
136
    #[ORM\Column(length: 255, nullable: false, options: ['default' => 'default.png'])]
137
    protected string $avatar = 'default.png';
138
139
    #[ORM\Column(length: 1000, nullable: true)]
140
    protected ?string $comment = null;
141
142
    #[Groups(['user:read', 'user:update'])]
143
    #[ORM\Column(length: 2, nullable: false, options: ['default' => 'en'])]
144
    protected string $language = 'en';
145
146
    #[ORM\Column(length: 128)]
147
    #[Gedmo\Slug(fields: ['username'])]
148
    protected string $slug;
149
150
    #[ORM\JoinTable(name: 'pnu_user_group')]
151
    #[ORM\JoinColumn(name: 'user_id', referencedColumnName: 'id')]
152
    #[ORM\InverseJoinColumn(name: 'group_id', referencedColumnName: 'id')]
153
    #[ORM\ManyToMany(targetEntity: Group::class)]
154
    protected Collection $groups;
155
156
    public function __construct()
157
    {
158
        $this->groups = new ArrayCollection();
159
    }
160
161
    public function getId(): ?int
162
    {
163
        return $this->id;
164
    }
165
166
    public function setId(?int $id): void
167
    {
168
        $this->id = $id;
169
    }
170
171
    public function getUsername(): string
172
    {
173
        return $this->username;
174
    }
175
176
    public function setUsername($username): void
177
    {
178
        $this->username = $username;
179
    }
180
181
    public function getEmail(): ?string
182
    {
183
        return $this->email;
184
    }
185
186
    public function setEmail(string $email): void
187
    {
188
        $this->email = $email;
189
    }
190
191
    public function setEnabled($boolean): void
192
    {
193
        $this->enabled = (bool) $boolean;
194
    }
195
196
    public function isEnabled(): bool
197
    {
198
        return $this->enabled;
199
    }
200
201
    public function getRoles(): array
202
    {
203
        $roles = $this->roles;
204
205
        foreach ($this->getGroups() as $group) {
206
            $roles = array_merge($roles, $group->getRoles());
207
        }
208
209
        // we need to make sure to have at least one role
210
        $roles[] = 'ROLE_USER';
211
212
        return array_values(array_unique($roles));
213
    }
214
215
    public function setRoles(array $roles): void
216
    {
217
        $this->roles = $roles;
218
    }
219
220
    public function getPassword(): ?string
221
    {
222
        return $this->password;
223
    }
224
225
    public function setPassword(string $password): void
226
    {
227
        $this->password = $password;
228
    }
229
230
    /**
231
     * Returning a salt is only needed, if you are not using a modern
232
     * hashing algorithm (e.g. bcrypt or sodium) in your security.yaml.
233
     */
234
    public function getSalt(): ?string
235
    {
236
        return null;
237
    }
238
239
    public function getPlainPassword(): ?string
240
    {
241
        return $this->plainPassword;
242
    }
243
244
    public function hasRole($role): bool
245
    {
246
        return in_array(strtoupper($role), $this->getRoles(), true);
247
    }
248
249
    public function eraseCredentials(): void
250
    {
251
        // If you store any temporary, sensitive data on the user, clear it here
252
        // $this->plainPassword = null;
253
    }
254
255
    public function getLastLogin(): ?DateTime
256
    {
257
        return $this->lastLogin;
258
    }
259
260
    public function setLastLogin(?DateTime $time = null): void
261
    {
262
        $lastLogin = $this->getLastLogin();
263
        if (($lastLogin === null) || ($lastLogin->format('Y-m-d') != $time->format('Y-m-d'))) {
0 ignored issues
show
The method format() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

263
        if (($lastLogin === null) || ($lastLogin->format('Y-m-d') != $time->/** @scrutinizer ignore-call */ format('Y-m-d'))) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
264
            ++$this->nbConnexion;
265
        }
266
        $this->lastLogin = $time;
267
    }
268
269
    public function setConfirmationToken($confirmationToken): void
270
    {
271
        $this->confirmationToken = $confirmationToken;
272
    }
273
274
    public function getConfirmationToken(): ?string
275
    {
276
        return $this->confirmationToken;
277
    }
278
279
    public function setPasswordRequestedAt(?DateTime $date = null): void
280
    {
281
        $this->passwordRequestedAt = $date;
282
    }
283
284
    public function getPasswordRequestedAt(): ?DateTime
285
    {
286
        return $this->passwordRequestedAt;
287
    }
288
289
    public function isPasswordRequestExpired($ttl): bool
290
    {
291
        return $this->getPasswordRequestedAt() instanceof DateTime &&
292
               $this->getPasswordRequestedAt()->getTimestamp() + $ttl < time();
293
    }
294
295
    public function getLanguage(): string
296
    {
297
        return $this->language;
298
    }
299
300
    public function setLanguage(string $language): void
301
    {
302
        $this->language = $language;
303
    }
304
305
    public function getSlug(): string
306
    {
307
        return $this->slug;
308
    }
309
310
    public function getNbConnexion(): int
311
    {
312
        return $this->nbConnexion;
313
    }
314
315
    public function setNbConnexion(int $nbConnexion): void
316
    {
317
        $this->nbConnexion = $nbConnexion;
318
    }
319
320
    /**
321
     * Get extra data by key or all extra data if no key provided.
322
     *
323
     * @param string|null $key The key to retrieve
324
     * @return mixed The value or all extraData if no key provided
325
     */
326
    public function getExtraData(?string $key = null): mixed
327
    {
328
        if ($key === null) {
329
            return $this->extraData;
330
        }
331
332
        return $this->extraData[$key] ?? null;
333
    }
334
335
    /**
336
     * Set extra data with a given key.
337
     *
338
     * @param string $key The key to set
339
     * @param mixed $value The value to set
340
     */
341
    public function setExtraData(string $key, mixed $value): void
342
    {
343
        $this->extraData[$key] = $value;
344
    }
345
346
    /**
347
     * Check if extra data with given key exists.
348
     *
349
     * @param string $key The key to check
350
     * @return bool True if the key exists
351
     */
352
    public function hasExtraData(string $key): bool
353
    {
354
        return array_key_exists($key, $this->extraData);
355
    }
356
357
    /**
358
     * Remove extra data with given key.
359
     *
360
     * @param string $key The key to remove
361
     */
362
    public function removeExtraData(string $key): void
363
    {
364
        if ($this->hasExtraData($key)) {
365
            unset($this->extraData[$key]);
366
        }
367
    }
368
369
    public function getAvatar(): string
370
    {
371
        return $this->avatar;
372
    }
373
374
    public function setAvatar(string $avatar): void
375
    {
376
        $this->avatar = $avatar;
377
    }
378
379
    public function getComment(): ?string
380
    {
381
        return $this->comment;
382
    }
383
384
    public function setComment(?string $comment = null): void
385
    {
386
        $this->comment = $comment;
387
    }
388
389
    public function setGroups($groups): void
390
    {
391
        $this->groups = $groups;
392
    }
393
394
    public function getGroups(): Collection
395
    {
396
        return $this->groups;
397
    }
398
399
    public function setPlainPassword($password): void
400
    {
401
        $this->plainPassword = $password;
402
    }
403
404
    public function addGroup($group): void
405
    {
406
        $this->groups[] = $group;
407
    }
408
409
    public function removeGroup(Group $group): void
410
    {
411
        $this->groups->removeElement($group);
412
    }
413
414
    public function __toString()
415
    {
416
        return sprintf('%s [%d]', $this->getUsername(), $this->getId());
417
    }
418
419
    public function addRole($role): void
420
    {
421
        $role = strtoupper($role);
422
        if (!in_array($role, $this->roles, true)) {
423
            $this->roles[] = $role;
424
        }
425
    }
426
427
    public function removeRole($role): void
428
    {
429
        if (false !== $key = array_search(strtoupper($role), $this->roles, true)) {
430
            unset($this->roles[$key]);
431
            $this->roles = array_values($this->roles);
432
        }
433
    }
434
435
    public function getUserIdentifier(): string
436
    {
437
        return $this->email;
438
    }
439
}
440