Failed Conditions
Push — master ( 356b1f...e74f9e )
by Adrien
10:44
created

User::setBirthday()   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 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
ccs 0
cts 0
cp 0
crap 2
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 24
     * Set currently logged in user
41
     * WARNING: this method should only be called from \Application\Authentication\AuthenticationListener
42 24
     *
43
     * @param \Application\Model\User $user
44
     */
45 24
    public static function setCurrent(?self $user): void
46 24
    {
47
        self::$currentUser = $user;
48
49
        // Initalize ACL filter with current user if a logged in one exists
50
        _em()->getFilters()->getFilter(AclFilter::class)->setUser($user);
51
    }
52
53 19
    /**
54
     * Returns currently logged user or null
55 19
     *
56
     * @return null|self
57
     */
58
    public static function getCurrent(): ?self
59
    {
60
        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 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 17
    /**
102
     * @var null|Date
103 17
     * @ORM\Column(type="date", nullable=true)
104 17
     */
105
    private $birthday;
106
107
    /**
108
     * @var Collection
109
     * @ORM\OneToMany(targetEntity="Booking", mappedBy="responsible")
110
     */
111
    private $bookings;
112
113
    /**
114
     * Constructor
115
     *
116
     * @param string $role role for new user
117
     */
118
    public function __construct(string $role = self::ROLE_MEMBER)
119
    {
120
        $this->role = $role;
121
        $this->bookings = new ArrayCollection();
122
    }
123
124
    /**
125 1
     * Set login (eg: johndoe)
126
     *
127 1
     * @API\Input(type="Application\Api\Scalar\LoginType")
128
     *
129
     * @param string $login
130
     */
131
    public function setLogin(string $login): void
132
    {
133
        $this->login = $login;
134
    }
135 3
136
    /**
137
     * Get login (eg: johndoe)
138
     *
139 3
     * @API\Field(type="Application\Api\Scalar\LoginType")
140 1
     *
141
     * @return string
142
     */
143 3
    public function getLogin(): string
144 3
    {
145
        return $this->login;
146
    }
147
148
    /**
149
     * Encrypt and change the user password
150
     *
151
     * @param string $password
152
     */
153 3
    public function setPassword(string $password): void
154
    {
155 3
        // Ignore empty password that could be sent "by mistake" by the client
156
        // when agreeing to terms
157
        if ($password === '') {
158
            return;
159
        }
160
161
        $this->password = password_hash($password, PASSWORD_DEFAULT);
162
    }
163 1
164
    /**
165 1
     * Returns the hashed password
166 1
     *
167
     * @API\Exclude
168
     *
169
     * @return string
170
     */
171
    public function getPassword(): string
172
    {
173
        return $this->password;
174
    }
175 1
176
    /**
177 1
     * Set email
178
     *
179
     * @param string $email
180
     */
181
    public function setEmail(string $email): void
182
    {
183
        $this->email = $email;
184
    }
185 14
186
    /**
187 14
     * Get email
188
     *
189
     * @API\Field(type="Email")
190
     *
191
     * @return string
192
     */
193
    public function getEmail(): string
194
    {
195
        return $this->email;
196
    }
197
198
    /**
199
     * Returns whether the user is administrator and thus have can do anything.
200
     *
201 7
     * @API\Field(type="Application\Api\Enum\UserRoleType")
202
     */
203 7
    public function getRole(): string
204 2
    {
205
        return $this->role;
206
    }
207 5
208
    /**
209 5
     * Sets the user role
210 5
     *
211 5
     * The current user is allowed to promote another user up to the same role as himself. So
212
     * a Senior can promote a Student to Senior. Or an Admin can promote a Junior to Admin.
213
     *
214 5
     * But the current user is **not** allowed to demote a user who has a higher role than himself.
215 5
     * That means that a Senior cannot demote an Admin to Student.
216 5
     *
217 5
     * @param string $role
218 3
     */
219
    public function setRole(string $role): void
220 5
    {
221 2
        if ($role === $this->role) {
222
            return;
223
        }
224 5
225 5
        $currentRole = self::getCurrent() ? self::getCurrent()->getRole() : self::ROLE_ANONYMOUS;
226
        $orderedRoles = [
227
            self::ROLE_ANONYMOUS,
228
            self::ROLE_MEMBER,
229 5
            self::ROLE_ADMINISTRATOR,
230 3
        ];
231
232
        $newFound = false;
233 2
        $oldFound = false;
234 2
        foreach ($orderedRoles as $r) {
235
            if ($r === $this->role) {
236
                $oldFound = true;
237
            }
238
            if ($r === $role) {
239
                $newFound = true;
240
            }
241 5
242
            if ($r === $currentRole) {
243 5
                break;
244
            }
245
        }
246
247
        if (!$newFound || !$oldFound) {
248
            throw new Exception($currentRole . ' is not allowed to change role to ' . $role);
249
        }
250
251 2
        $this->role = $role;
252
    }
253 2
254 2
    /**
255
     * The date until the user is active. Or `null` if there is not limit in time
256
     *
257
     * @return null|Chronos
258
     */
259
    public function getActiveUntil(): ?Chronos
260
    {
261
        return $this->activeUntil;
262
    }
263 3
264
    /**
265 3
     * The date until the user is active. Or `null` if there is not limit in time
266
     *
267 3
     * @param null|Chronos $activeUntil
268
     */
269
    public function setActiveUntil(?Chronos $activeUntil): void
270
    {
271
        $this->activeUntil = $activeUntil;
272 3
    }
273 3
274
    /**
275 3
     * Get a list of global permissions for this user
276 3
     *
277 3
     * @API\Field(type="GlobalPermissionsList")
278 3
     *
279 3
     * @return array
280 3
     */
281
    public function getGlobalPermissions(): array
282 3
    {
283 3
        $acl = new Acl();
284
        $types = [
285
            Country::class,
286
            Tag::class,
287 3
            self::class,
288
        ];
289 3
290
        $permissions = ['create'];
291
        $result = [];
292
293
        $previousUser = self::getCurrent();
294
        self::setCurrent($this);
295
        foreach ($types as $type) {
296
            $instance = new $type();
297
            $sh = lcfirst(Utility::getShortClassName($instance));
298
            $result[$sh] = [];
299
300
            foreach ($permissions as $p) {
301
                $result[$sh][$p] = $acl->isCurrentUserAllowed($instance, $p);
302
            }
303
        }
304
305
        self::setCurrent($previousUser);
306
307
        return $result;
308
    }
309
310
    /**
311
     * @return string
312
     */
313
    public function getPhone(): string
314
    {
315
        return $this->phone;
316
    }
317
318
    /**
319
     * @param string $phone
320
     */
321
    public function setPhone(string $phone): void
322
    {
323
        $this->phone = $phone;
324
    }
325
326
    /**
327
     * @return null|Date
328
     */
329
    public function getBirthday(): ?Date
330
    {
331
        return $this->birthday;
332
    }
333
334
    /**
335
     * @param null|Date $birthday
336
     */
337
    public function setBirthday(?Date $birthday): void
338
    {
339
        $this->birthday = $birthday;
340
    }
341
342
    /**
343
     * Get bookings
344
     *
345
     * @return Collection
346
     */
347
    public function getBookings(): Collection
348
    {
349
        return $this->bookings;
350
    }
351
352
    /**
353
     * Notify the user that it has a new booking.
354
     * This should only be called by Booking::setResponsible()
355
     *
356
     * @param Booking $booking
357
     */
358
    public function bookingAdded(Booking $booking): void
359
    {
360
        $this->bookings->add($booking);
361
    }
362
}
363