Completed
Push — master ( 334f6b...01d482 )
by Adrien
11:34
created

User::getLicenses()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 0
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Application\Model;
6
7
use Application\Acl\Acl;
8
use Application\Api\Exception;
9
use Application\ORM\Query\Filter\AclFilter;
10
use Application\Traits\HasName;
11
use Application\Traits\HasResponsible;
12
use Application\Utility;
13
use Cake\Chronos\Chronos;
14
use Cake\Chronos\Date;
15
use Doctrine\Common\Collections\ArrayCollection;
16
use Doctrine\Common\Collections\Collection;
17
use Doctrine\ORM\Mapping as ORM;
18
use GraphQL\Doctrine\Annotation as API;
19
20
/**
21
 * User
22
 *
23
 * @ORM\Entity(repositoryClass="Application\Repository\UserRepository")
24
 */
25
class User extends AbstractModel
26
{
27
    const ROLE_ANONYMOUS = 'anonymous';
28
    const ROLE_MEMBER = 'member';
29
    const ROLE_ADMINISTRATOR = 'administrator';
30
31
    use HasName;
32
    use HasResponsible;
33
34
    /**
35
     * @var User
36
     */
37
    private static $currentUser;
38
39
    /**
40
     * Set currently logged in user
41
     * WARNING: this method should only be called from \Application\Authentication\AuthenticationListener
42
     *
43
     * @param \Application\Model\User $user
44
     */
45 24
    public static function setCurrent(?self $user): void
46
    {
47 24
        self::$currentUser = $user;
48
49
        // Initalize ACL filter with current user if a logged in one exists
50 24
        _em()->getFilters()->getFilter(AclFilter::class)->setUser($user);
51 24
    }
52
53
    /**
54
     * Returns currently logged user or null
55
     *
56
     * @return null|self
57
     */
58 19
    public static function getCurrent(): ?self
59
    {
60 19
        return self::$currentUser;
61
    }
62
63
    /**
64
     * @var string
65
     *
66
     * @ORM\Column(type="string", length=50, unique=true)
67
     */
68
    private $login;
69
70
    /**
71
     * @var null|string
72
     *
73
     * @ORM\Column(type="string", length=255)
74
     */
75
    private $password;
76
77
    /**
78
     * @var string
79
     * @ORM\Column(type="string", length=191)
80
     */
81
    private $email;
82
83
    /**
84
     * @var string
85
     * @ORM\Column(type="UserRole", options={"default" = User::ROLE_MEMBER})
86
     */
87
    private $role = self::ROLE_MEMBER;
88
89
    /**
90
     * @var Chronos
91
     * @ORM\Column(type="datetime", nullable=true)
92
     */
93
    private $activeUntil;
94
95
    /**
96
     * @var string
97
     * @ORM\Column(type="string", length=25, options={"default" = ""})
98
     */
99
    private $phone = '';
100
101
    /**
102
     * @var null|Date
103
     * @ORM\Column(type="date", nullable=true)
104
     */
105
    private $birthday;
106
107
    /**
108
     * @var Collection
109
     * @ORM\OneToMany(targetEntity="Booking", mappedBy="responsible")
110
     */
111
    private $bookings;
112
113
    /**
114
     * @var Collection
115
     * @ORM\ManyToMany(targetEntity="License", mappedBy="users")
116
     */
117
    private $licenses;
118
119
    /**
120
     * @var Collection
121
     * @ORM\ManyToMany(targetEntity="UserTag", mappedBy="users")
122
     */
123
    private $tags;
124 17
125
    /**
126 17
     * Constructor
127 17
     *
128 17
     * @param string $role role for new user
129 17
     */
130
    public function __construct(string $role = self::ROLE_MEMBER)
131
    {
132
        $this->role = $role;
133
        $this->bookings = new ArrayCollection();
134
        $this->licenses = new ArrayCollection();
135
        $this->tags = new ArrayCollection();
136
    }
137
138
    /**
139
     * Set login (eg: johndoe)
140
     *
141
     * @API\Input(type="Application\Api\Scalar\LoginType")
142
     *
143
     * @param string $login
144
     */
145
    public function setLogin(string $login): void
146
    {
147
        $this->login = $login;
148
    }
149
150 1
    /**
151
     * Get login (eg: johndoe)
152 1
     *
153
     * @API\Field(type="Application\Api\Scalar\LoginType")
154
     *
155
     * @return string
156
     */
157
    public function getLogin(): string
158
    {
159
        return $this->login;
160 3
    }
161
162
    /**
163
     * Encrypt and change the user password
164 3
     *
165 1
     * @param string $password
166
     */
167
    public function setPassword(string $password): void
168 3
    {
169 3
        // Ignore empty password that could be sent "by mistake" by the client
170
        // when agreeing to terms
171
        if ($password === '') {
172
            return;
173
        }
174
175
        $this->password = password_hash($password, PASSWORD_DEFAULT);
176
    }
177
178 3
    /**
179
     * Returns the hashed password
180 3
     *
181
     * @API\Exclude
182
     *
183
     * @return null|string
184
     */
185
    public function getPassword(): ?string
186
    {
187
        return $this->password;
188
    }
189
190 1
    /**
191
     * Set email
192 1
     *
193 1
     * @API\Input(type="Email")
194
     *
195
     * @param string $email
196
     */
197
    public function setEmail(string $email): void
198
    {
199
        $this->email = $email;
200
    }
201
202 1
    /**
203
     * Get email
204 1
     *
205
     * @API\Field(type="Email")
206
     *
207
     * @return string
208
     */
209
    public function getEmail(): string
210
    {
211
        return $this->email;
212 14
    }
213
214 14
    /**
215
     * Returns whether the user is administrator and thus have can do anything.
216
     *
217
     * @API\Field(type="Application\Api\Enum\UserRoleType")
218
     */
219
    public function getRole(): string
220
    {
221
        return $this->role;
222
    }
223
224
    /**
225
     * Sets the user role
226
     *
227
     * The current user is allowed to promote another user up to the same role as himself. So
228 7
     * a Senior can promote a Student to Senior. Or an Admin can promote a Junior to Admin.
229
     *
230 7
     * But the current user is **not** allowed to demote a user who has a higher role than himself.
231 2
     * That means that a Senior cannot demote an Admin to Student.
232
     *
233
     * @param string $role
234 5
     */
235
    public function setRole(string $role): void
236 5
    {
237 5
        if ($role === $this->role) {
238 5
            return;
239
        }
240
241 5
        $currentRole = self::getCurrent() ? self::getCurrent()->getRole() : self::ROLE_ANONYMOUS;
242 5
        $orderedRoles = [
243 5
            self::ROLE_ANONYMOUS,
244 5
            self::ROLE_MEMBER,
245 3
            self::ROLE_ADMINISTRATOR,
246
        ];
247 5
248 2
        $newFound = false;
249
        $oldFound = false;
250
        foreach ($orderedRoles as $r) {
251 5
            if ($r === $this->role) {
252 5
                $oldFound = true;
253
            }
254
            if ($r === $role) {
255
                $newFound = true;
256 5
            }
257 3
258
            if ($r === $currentRole) {
259
                break;
260 2
            }
261 2
        }
262
263
        if (!$newFound || !$oldFound) {
264
            throw new Exception($currentRole . ' is not allowed to change role to ' . $role);
265
        }
266
267
        $this->role = $role;
268 5
    }
269
270 5
    /**
271
     * The date until the user is active. Or `null` if there is not limit in time
272
     *
273
     * @return null|Chronos
274
     */
275
    public function getActiveUntil(): ?Chronos
276
    {
277
        return $this->activeUntil;
278 2
    }
279
280 2
    /**
281 2
     * The date until the user is active. Or `null` if there is not limit in time
282
     *
283
     * @param null|Chronos $activeUntil
284
     */
285
    public function setActiveUntil(?Chronos $activeUntil): void
286
    {
287
        $this->activeUntil = $activeUntil;
288
    }
289
290 3
    /**
291
     * Get a list of global permissions for this user
292 3
     *
293
     * @API\Field(type="GlobalPermissionsList")
294 3
     *
295
     * @return array
296
     */
297
    public function getGlobalPermissions(): array
298
    {
299 3
        $acl = new Acl();
300 3
        $types = [
301
            Country::class,
302 3
            License::class,
303 3
            self::class,
304 3
        ];
305 3
306 3
        $permissions = ['create'];
307 3
        $result = [];
308
309 3
        $previousUser = self::getCurrent();
310 3
        self::setCurrent($this);
311
        foreach ($types as $type) {
312
            $instance = new $type();
313
            $sh = lcfirst(Utility::getShortClassName($instance));
314 3
            $result[$sh] = [];
315
316 3
            foreach ($permissions as $p) {
317
                $result[$sh][$p] = $acl->isCurrentUserAllowed($instance, $p);
318
            }
319
        }
320
321
        self::setCurrent($previousUser);
322
323
        return $result;
324
    }
325
326
    /**
327
     * @return string
328
     */
329
    public function getPhone(): string
330
    {
331
        return $this->phone;
332
    }
333
334
    /**
335
     * @param string $phone
336
     */
337
    public function setPhone(string $phone): void
338
    {
339
        $this->phone = $phone;
340
    }
341
342
    /**
343
     * @return null|Date
344
     */
345
    public function getBirthday(): ?Date
346
    {
347
        return $this->birthday;
348
    }
349
350
    /**
351
     * @param null|Date $birthday
352
     */
353
    public function setBirthday(?Date $birthday): void
354
    {
355
        $this->birthday = $birthday;
356
    }
357
358
    /**
359
     * Get bookings
360
     *
361
     * @return Collection
362
     */
363
    public function getBookings(): Collection
364
    {
365
        return $this->bookings;
366
    }
367
368
    /**
369
     * Notify the user that it has a new booking.
370
     * This should only be called by Booking::setResponsible()
371
     *
372
     * @param Booking $booking
373
     */
374
    public function bookingAdded(Booking $booking): void
375
    {
376
        $this->bookings->add($booking);
377
    }
378
379
    /**
380
     * @return Collection
381
     */
382
    public function getLicenses(): Collection
383
    {
384
        return $this->licenses;
385
    }
386
387
    /**
388
     * @return Collection
389
     */
390
    public function getTags(): Collection
391
    {
392
        return $this->tags;
393
    }
394
}
395