Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
98.68% covered (success)
98.68%
75 / 76
96.43% covered (success)
96.43%
27 / 28
CRAP
0.00% covered (danger)
0.00%
0 / 1
User
98.68% covered (success)
98.68%
75 / 76
96.43% covered (success)
96.43%
27 / 28
43
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 __toString
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 __serialize
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 __unserialize
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 eraseCredentials
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRoles
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 getRole
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setRole
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getParams
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getParam
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 getUserParams
95.00% covered (success)
95.00%
19 / 20
0.00% covered (danger)
0.00%
0 / 1
8
 setParams
100.00% covered (success)
100.00%
2 / 2
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
 getIdentifier
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getUserIdentifier
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 setIdentifier
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getPassword
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getGoogleId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setGoogleId
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getGitHubId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setGitHubId
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getMaxfields
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addMaxfield
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 removeMaxfield
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 getFavourites
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addFavourite
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 removeFavourite
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 toggleFavourite
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3declare(strict_types=1);
4
5namespace App\Entity;
6
7use App\Enum\MapBoxProfilesEnum;
8use App\Enum\MapBoxStylesEnum;
9use App\Enum\MapProvidersEnum;
10use App\Enum\MaxfieldEngineEnum;
11use App\Enum\UserRole;
12use App\Repository\UserRepository;
13use App\Settings\UserSettings;
14use Doctrine\Common\Collections\ArrayCollection;
15use Doctrine\Common\Collections\Collection;
16use Doctrine\DBAL\Types\Types;
17use Doctrine\ORM\Mapping\Column;
18use Doctrine\ORM\Mapping\Entity;
19use Doctrine\ORM\Mapping\GeneratedValue;
20use Doctrine\ORM\Mapping\Id;
21use Doctrine\ORM\Mapping\ManyToMany;
22use Doctrine\ORM\Mapping\OneToMany;
23use Doctrine\ORM\Mapping\Table;
24use Stringable;
25use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
26use Symfony\Component\Security\Core\User\UserInterface;
27use Symfony\Component\Validator\Constraints as Assert;
28use Symfony\Component\Validator\Constraints\NotBlank;
29
30#[Entity(repositoryClass: UserRepository::class)]
31#[Table(name: 'system_user')]
32#[UniqueEntity(fields: 'identifier', message: 'This identifier is already in use')]
33class User implements UserInterface, Stringable
34{
35    #[Column, Id, GeneratedValue(strategy: 'SEQUENCE')]
36    private ?int $id = null;
37
38    #[Column(unique: true), NotBlank]
39    private string $identifier = '*';
40
41    #[Column(type: Types::STRING, length: 50, enumType: UserRole::class)]
42    #[Assert\NotNull]
43    #[Assert\Type(type: UserRole::class, message: 'The role must be a valid user role.')]
44    private UserRole $role = UserRole::USER;
45
46    /**
47     * @var array<string>
48     */
49    #[Column(type: Types::JSON, nullable: false, options: ['default' => '[]'])]
50    private array $params = [];
51
52    #[Column(length: 100, nullable: true)]
53    private ?string $googleId = null;
54
55    #[Column(nullable: true)]
56    private ?int $gitHubId = null;
57
58    /**
59     * @var Collection<int, Maxfield>
60     */
61    #[OneToMany(targetEntity: Maxfield::class, mappedBy: 'owner')]
62    private Collection $maxfields;
63
64    /**
65     * @var Collection<int, Maxfield>
66     */
67    #[ManyToMany(targetEntity: Maxfield::class)]
68    private Collection $favourites;
69
70    public function __construct()
71    {
72        $this->maxfields = new ArrayCollection();
73        $this->favourites = new ArrayCollection();
74    }
75
76    public function __toString(): string
77    {
78        return $this->identifier;
79    }
80
81    /**
82     * @return array{
83     *     id: integer|null,
84     *     identifier: string|null
85     * }
86     */
87    public function __serialize(): array
88    {
89        return [
90            'id' => $this->id,
91            'identifier' => $this->identifier,
92        ];
93    }
94
95    /**
96     * @param array{
97     *     id: int|null,
98     *     identifier: string|null
99     * } $data
100     */
101    public function __unserialize(array $data): void
102    {
103        $this->id = $data['id'] ?? null;
104        $this->identifier = (string)($data['identifier'] ?? null);
105        $this->params = [];
106        $this->maxfields = new ArrayCollection();
107        $this->favourites = new ArrayCollection();
108    }
109
110    public function eraseCredentials(): void {}
111
112    public function getRoles(): array
113    {
114        $roles = [$this->role->value];
115
116        // guarantee every user at least has ROLE_USER
117        $roles[] = UserRole::USER->value;
118
119        return \array_unique($roles);
120    }
121
122    public function getRole(): UserRole
123    {
124        return $this->role;
125    }
126
127    public function setRole(UserRole $role): User
128
129    {
130        $this->role = $role;
131
132        return $this;
133    }
134
135    /**
136     * @return array<string>
137     */
138    public function getParams(): array
139    {
140        return $this->params;
141    }
142
143    public function getParam(string $name): string
144    {
145        return array_key_exists($name, $this->params)
146            ? (string) ($this->params[$name] ?: '')
147            : '';
148    }
149
150    public function getUserParams(): UserSettings
151    {
152        $settings = new UserSettings();
153
154        $settings->agentName = $this->getParam('agentName');
155        $settings->lat = (float)$this->getParam('lat');
156        $settings->lon = (float)$this->getParam('lon');
157        $settings->zoom = (int)$this->getParam('zoom');
158        $settings->mapboxApiKey = $this->getParam('mapboxApiKey');
159        $settings->defaultStyle = $this->getParam('defaultStyle') !== '' && $this->getParam('defaultStyle') !== '0'
160            ? (MapBoxStylesEnum::tryFrom($this->getParam('defaultStyle')) ?? MapBoxStylesEnum::Standard)
161            : MapBoxStylesEnum::Standard;
162        $settings->defaultProfile = $this->getParam('defaultProfile') !== '' && $this->getParam('defaultProfile') !== '0'
163            ? (MapBoxProfilesEnum::tryFrom($this->getParam('defaultProfile')) ?? MapBoxProfilesEnum::Driving)
164            : MapBoxProfilesEnum::Driving;
165        $settings->mapProvider = $this->getParam('mapProvider') !== '' && $this->getParam('mapProvider') !== '0'
166            ? (MapProvidersEnum::tryFrom($this->getParam('mapProvider')) ?? MapProvidersEnum::leaflet)
167            : MapProvidersEnum::leaflet;
168        $settings->maxfieldEngine = $this->getParam('maxfieldEngine') !== ''
169            ? (MaxfieldEngineEnum::tryFrom($this->getParam('maxfieldEngine')) ?? MaxfieldEngineEnum::php)
170            : MaxfieldEngineEnum::php;
171        $settings->dockerContainer = $this->getParam('dockerContainer');
172
173        return $settings;
174    }
175
176    /**
177     * @param array<string> $params
178     */
179    public function setParams(array $params): self
180    {
181        $this->params = $params;
182
183        return $this;
184    }
185
186    public function getId(): ?int
187    {
188        return $this->id;
189    }
190
191    public function getIdentifier(): string
192    {
193        return $this->identifier;
194    }
195
196    /** @return non-empty-string */
197    public function getUserIdentifier(): string
198    {
199        return $this->identifier ?: '*';
200    }
201
202    public function setIdentifier(string $identifier): self
203    {
204        $this->identifier = $identifier;
205
206        return $this;
207    }
208
209    /**
210     * @todo this method is required by the the rememberMe functionality :(
211     */
212    public function getPassword(): ?string
213    {
214        return null;
215    }
216
217    public function getGoogleId(): ?string
218    {
219        return $this->googleId;
220    }
221
222    public function setGoogleId(?string $googleId): self
223    {
224        $this->googleId = $googleId;
225
226        return $this;
227    }
228
229    public function getGitHubId(): ?int
230    {
231        return $this->gitHubId;
232    }
233
234    public function setGitHubId(?int $gitHubId): self
235    {
236        $this->gitHubId = $gitHubId;
237
238        return $this;
239    }
240
241    /**
242     * @return Collection<int, Maxfield>
243     */
244    public function getMaxfields(): Collection
245    {
246        return $this->maxfields;
247    }
248
249    public function addMaxfield(Maxfield $maxfield): self
250    {
251        if (!$this->maxfields->contains($maxfield)) {
252            $this->maxfields->add($maxfield);
253            $maxfield->setOwner($this);
254        }
255
256        return $this;
257    }
258
259    public function removeMaxfield(Maxfield $maxfield): self
260    {
261        // set the owning side to null (unless already changed)
262        if ($this->maxfields->removeElement($maxfield) && $maxfield->getOwner() === $this) {
263            $maxfield->setOwner(null);
264        }
265
266        return $this;
267    }
268
269    /**
270     * @return Collection<int, Maxfield>
271     */
272    public function getFavourites(): Collection
273    {
274        return $this->favourites;
275    }
276
277    public function addFavourite(Maxfield $favourite): self
278    {
279        if (!$this->favourites->contains($favourite)) {
280            $this->favourites->add($favourite);
281        }
282
283        return $this;
284    }
285
286    public function removeFavourite(Maxfield $favourite): self
287    {
288        $this->favourites->removeElement($favourite);
289
290        return $this;
291    }
292
293    /**
294     * @return bool the new state
295     */
296    public function toggleFavourite(Maxfield $favourite): bool
297    {
298        if ($this->favourites->contains($favourite)) {
299            $this->favourites->removeElement($favourite);
300
301            return false;
302        }
303
304        $this->favourites->add($favourite);
305
306        return true;
307    }
308}