Completed
Push — master ( 1cdf46...d8c9d1 )
by Adrien
07:48
created

Bookable::bookableTagRemoved()   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
ccs 0
cts 2
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\DBAL\Types\BookableStateType;
8
use Application\DBAL\Types\BookingTypeType;
9
use Application\Repository\BookableTagRepository;
10
use Application\Traits\HasCode;
11
use Application\Traits\HasDescription;
12
use Application\Traits\HasName;
13
use Application\Traits\HasRemarks;
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
use Money\Money;
20
21
/**
22
 * An item that can be booked by a user
23
 *
24
 * @ORM\Entity(repositoryClass="Application\Repository\BookableRepository")
25
 */
26
class Bookable extends AbstractModel
27
{
28
    use HasName;
29
    use HasDescription;
30
    use HasCode;
31
    use HasRemarks;
32
33
    /**
34
     * @var Money
35
     *
36
     * @ORM\Column(type="Money", options={"default" = 0})
37
     */
38
    private $initialPrice;
39
40
    /**
41
     * @var Money
42
     *
43
     * @ORM\Column(type="Money", options={"default" = 0})
44
     */
45
    private $periodicPrice;
46
47
    /**
48
     * @var Money
49
     *
50
     * @ORM\Column(type="Money",  options={"default" = 0, "unsigned" = true})
51
     */
52
    private $purchasePrice;
53
54
    /**
55
     * @var int
56
     *
57
     * @ORM\Column(type="smallint", options={"default" = "-1"})
58
     */
59
    private $simultaneousBookingMaximum = 1;
60
61
    /**
62
     * @var string
63
     *
64
     * @ORM\Column(type="BookingType", length=10, options={"default" = BookingTypeType::SELF_APPROVED})
65
     */
66
    private $bookingType = BookingTypeType::SELF_APPROVED;
67
68
    /**
69
     * @var bool
70
     *
71
     * @ORM\Column(type="boolean", options={"default" = 1})
72
     */
73
    private $isActive = true;
74
75
    /**
76
     * @var string
77
     *
78
     * @ORM\Column(type="BookableState", length=10, options={"default" = BookableStateType::GOOD})
79
     */
80
    private $state = BookableStateType::GOOD;
81
82
    /**
83
     * @var null|Date
84
     * @ORM\Column(type="date", nullable=true)
85
     */
86
    private $verificationDate;
87
88
    /**
89
     * @var BookableTag
90
     *
91
     * @ORM\ManyToMany(targetEntity="BookableTag", mappedBy="bookables")
92
     */
93
    private $bookableTags;
94
95
    /**
96
     * @var Collection
97
     * @ORM\OneToMany(targetEntity="Booking", mappedBy="bookable")
98
     */
99
    private $bookings;
100
101
    /**
102
     * @var Collection
103
     * @ORM\ManyToMany(targetEntity="License", mappedBy="bookables")
104
     */
105
    private $licenses;
106
107
    /**
108
     * @var null|Image
109
     * @ORM\OneToOne(targetEntity="Image", orphanRemoval=true)
110
     * @ORM\JoinColumn(name="image_id", referencedColumnName="id")
111
     */
112
    private $image;
113
114
    /**
115
     * @var null|Account
116
     *
117
     * @ORM\ManyToOne(targetEntity="Account")
118
     * @ORM\JoinColumns({
119
     *     @ORM\JoinColumn(nullable=true, onDelete="CASCADE")
120
     * })
121
     */
122
    private $creditAccount;
123
124
    /**
125
     * Constructor
126
     */
127 15
    public function __construct()
128
    {
129 15
        $this->initialPrice = Money::CHF(0);
130 15
        $this->periodicPrice = Money::CHF(0);
131 15
        $this->purchasePrice = Money::CHF(0);
132
133 15
        $this->bookings = new ArrayCollection();
134 15
        $this->licenses = new ArrayCollection();
135 15
        $this->bookableTags = new ArrayCollection();
0 ignored issues
show
Documentation Bug introduced by
It seems like new Doctrine\Common\Collections\ArrayCollection() of type Doctrine\Common\Collections\ArrayCollection is incompatible with the declared type Application\Model\BookableTag of property $bookableTags.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
136 15
    }
137
138
    /**
139
     * @return Collection
140
     */
141 2
    public function getBookings(): Collection
142
    {
143 2
        return $this->bookings;
144
    }
145
146
    /**
147
     * Notify the bookable that it has a new booking.
148
     * This should only be called by Booking::addBookable()
149
     *
150
     * @param Booking $booking
151
     */
152 11
    public function bookingAdded(Booking $booking): void
153
    {
154 11
        $this->bookings->add($booking);
155 11
    }
156
157
    /**
158
     * Notify the bookable that it a booking was removed.
159
     * This should only be called by Booking::removeBookable()
160
     *
161
     * @param Booking $booking
162
     */
163 1
    public function bookingRemoved(Booking $booking): void
164
    {
165 1
        $this->bookings->removeElement($booking);
166 1
    }
167
168
    /**
169
     * @return Collection
170
     */
171 3
    public function getLicenses(): Collection
172
    {
173 3
        return $this->licenses;
174
    }
175
176
    /**
177
     * Notify the bookable that it has a new license.
178
     * This should only be called by License::addBookable()
179
     *
180
     * @param License $license
181
     */
182 1
    public function licenseAdded(License $license): void
183
    {
184 1
        $this->licenses->add($license);
185 1
    }
186
187
    /**
188
     * Notify the bookable that it a license was removed.
189
     * This should only be called by License::removeBookable()
190
     *
191
     * @param License $license
192
     */
193 1
    public function licenseRemoved(License $license): void
194
    {
195 1
        $this->licenses->removeElement($license);
196 1
    }
197
198
    /**
199
     * @return Money
200
     */
201 7
    public function getInitialPrice(): Money
202
    {
203 7
        return $this->initialPrice;
204
    }
205
206
    /**
207
     * @param Money $initialPrice
208
     */
209 6
    public function setInitialPrice(Money $initialPrice): void
210
    {
211 6
        $this->initialPrice = $initialPrice;
212 6
    }
213
214
    /**
215
     * @return Money
216
     */
217 11
    public function getPeriodicPrice(): Money
218
    {
219 11
        return $this->periodicPrice;
220
    }
221
222
    /**
223
     * @param Money $periodicPrice
224
     */
225 8
    public function setPeriodicPrice(Money $periodicPrice): void
226
    {
227 8
        $this->periodicPrice = $periodicPrice;
228 8
    }
229
230
    /**
231
     * @return Money
232
     */
233
    public function getPurchasePrice(): Money
234
    {
235
        return $this->purchasePrice;
236
    }
237
238
    /**
239
     * @param Money $purchasePrice
240
     */
241
    public function setPurchasePrice(Money $purchasePrice): void
242
    {
243
        $this->purchasePrice = $purchasePrice;
244
    }
245
246
    /**
247
     * @return int
248
     */
249 1
    public function getSimultaneousBookingMaximum(): int
250
    {
251 1
        return $this->simultaneousBookingMaximum;
252
    }
253
254
    /**
255
     * @param int $simultaneousBookingMaximum
256
     */
257
    public function setSimultaneousBookingMaximum(int $simultaneousBookingMaximum): void
258
    {
259
        $this->simultaneousBookingMaximum = $simultaneousBookingMaximum;
260
    }
261
262
    /**
263
     * @API\Field(type="BookingType")
264
     *
265
     * @return string
266
     */
267 7
    public function getBookingType(): string
268
    {
269 7
        return $this->bookingType;
270
    }
271
272
    /**
273
     * Whether this bookable can be booked
274
     *
275
     * @return bool
276
     */
277 2
    public function isActive(): bool
278
    {
279 2
        return $this->isActive;
280
    }
281
282
    /**
283
     * Whether this bookable can be booked
284
     *
285
     * @param bool $isActive
286
     */
287
    public function setIsActive(bool $isActive): void
288
    {
289
        $this->isActive = $isActive;
290
    }
291
292
    /**
293
     * @API\Input(type="BookingType")
294
     *
295
     * @param string $state
296
     */
297 1
    public function setBookingType(string $state): void
298
    {
299 1
        $this->bookingType = $state;
300 1
    }
301
302
    /**
303
     * State of the bookable
304
     *
305
     * @API\Field(type="BookableState")
306
     *
307
     * @return string
308
     */
309
    public function getState(): string
310
    {
311
        return $this->state;
312
    }
313
314
    /**
315
     * State of the bookable
316
     *
317
     * @API\Input(type="BookableState")
318
     *
319
     * @param string $state
320
     */
321
    public function setState(string $state): void
322
    {
323
        $this->state = $state;
324
    }
325
326
    /**
327
     * The date then the bookable was last checked
328
     *
329
     * @return null|Date
330
     */
331
    public function getVerificationDate(): ?Date
332
    {
333
        return $this->verificationDate;
334
    }
335
336
    /**
337
     * The date then the bookable was last checked
338
     *
339
     * @param null|Date $verificationDate
340
     */
341
    public function setVerificationDate(?Date $verificationDate): void
342
    {
343
        $this->verificationDate = $verificationDate;
344
    }
345
346
    /**
347
     * @return Collection
348
     */
349 7
    public function getBookableTags(): Collection
350
    {
351 7
        return $this->bookableTags;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->bookableTags returns the type Application\Model\BookableTag which is incompatible with the type-hinted return Doctrine\Common\Collections\Collection.
Loading history...
352
    }
353
354
    /**
355
     * Notify the user that it has a new bookableTag.
356
     * This should only be called by BookableTag::addUser()
357
     *
358
     * @param BookableTag $bookableTag
359
     */
360 1
    public function bookableTagAdded(BookableTag $bookableTag): void
361
    {
362 1
        $this->bookableTags->add($bookableTag);
0 ignored issues
show
Bug introduced by
The method add() does not exist on Application\Model\BookableTag. ( Ignorable by Annotation )

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

362
        $this->bookableTags->/** @scrutinizer ignore-call */ 
363
                             add($bookableTag);

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...
363 1
    }
364
365
    /**
366
     * Notify the user that it a bookableTag was removed.
367
     * This should only be called by BookableTag::removeUser()
368
     *
369
     * @param BookableTag $bookableTag
370
     */
371
    public function bookableTagRemoved(BookableTag $bookableTag): void
372
    {
373
        $this->bookableTags->removeElement($bookableTag);
0 ignored issues
show
Bug introduced by
The method removeElement() does not exist on Application\Model\BookableTag. ( Ignorable by Annotation )

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

373
        $this->bookableTags->/** @scrutinizer ignore-call */ 
374
                             removeElement($bookableTag);

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...
374
    }
375
376
    /**
377
     * @return null|Image
378
     */
379 1
    public function getImage(): ?Image
380
    {
381 1
        return $this->image;
382
    }
383
384
    /**
385
     * @param null|Image $image
386
     */
387 1
    public function setImage(?Image $image): void
388
    {
389
        // We must trigger lazy loading, otherwise Doctrine will seriously
390
        // mess up lifecycle callbacks and delete unrelated image on disk
391 1
        if ($this->image) {
392 1
            $this->image->getFilename();
393
        }
394
395 1
        $this->image = $image;
396 1
    }
397
398
    /**
399
     * The account to credit when booking this bookable
400
     *
401
     * @return null|Account
402
     */
403 6
    public function getCreditAccount(): ?Account
404
    {
405 6
        return $this->creditAccount;
406
    }
407
408
    /**
409
     * The account to credit when booking this bookable
410
     *
411
     * @param null|Account $creditAccount
412
     */
413 5
    public function setCreditAccount(?Account $creditAccount): void
414
    {
415 5
        $this->creditAccount = $creditAccount;
416 5
    }
417
418
    /**
419
     * Return a list of effective active bookings including sharing conditions.
420
     *
421
     * Only "admin-only" + storage tags are sharable bookables. In this case, a list of bookings is returned.
422
     *
423
     * For other bookable types, returns null
424
     *
425
     * @return Booking[]
426
     */
427 7
    public function getSharedBookings(): array
428
    {
429 7
        $isAdminOnly = $this->getBookingType() === \Application\DBAL\Types\BookingTypeType::ADMIN_ONLY;
430
431 7
        $isStorage = false;
432 7
        foreach ($this->getBookableTags() as $tag) {
433 3
            if ($tag->getId() === BookableTagRepository::STORAGE_ID) {
434 1
                $isStorage = true;
435
436 1
                break;
437
            }
438
        }
439
440 7
        if (!$isAdminOnly || !$isStorage) {
441 7
            return [];
442
        }
443
444
        $bookings = $this->getBookings()->filter(function (Booking $booking): bool {
445 1
            return !$booking->getEndDate();
446 1
        })->toArray();
447
448 1
        return $bookings;
449
    }
450
}
451