Failed Conditions
Push — master ( 7f8dd2...bf3bcd )
by Sylvain
07:42
created

Bookable::getCreditAccount()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
ccs 2
cts 2
cp 1
crap 1
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
20
/**
21
 * An item that can be booked by a user
22
 *
23
 * @ORM\Entity(repositoryClass="Application\Repository\BookableRepository")
24
 */
25
class Bookable extends AbstractModel
26
{
27
    use HasName;
28
    use HasDescription;
29
    use HasCode;
30
    use HasRemarks;
31
32
    /**
33
     * @var string
34
     *
35
     * @ORM\Column(type="decimal", precision=10, scale=2, options={"default" = "0.00"})
36
     */
37
    private $initialPrice = '0';
38
39
    /**
40
     * @var string
41
     *
42
     * @ORM\Column(type="decimal", precision=10, scale=2, options={"default" = "0.00"})
43
     */
44
    private $periodicPrice = '0';
45
46
    /**
47
     * @var string
48
     *
49
     * @ORM\Column(type="decimal", precision=10, scale=2, options={"default" = "0.00", "unsigned" = true})
50
     */
51
    private $purchasePrice = '0';
52
53
    /**
54
     * @var int
55
     *
56
     * @ORM\Column(type="smallint", options={"default" = "-1"})
57
     */
58
    private $simultaneousBookingMaximum = 1;
59
60
    /**
61
     * @var string
62
     *
63
     * @ORM\Column(type="BookingType", length=10, options={"default" = BookingTypeType::SELF_APPROVED})
64
     */
65
    private $bookingType = BookingTypeType::SELF_APPROVED;
66
67
    /**
68
     * @var bool
69
     *
70
     * @ORM\Column(type="boolean", options={"default" = 1})
71
     */
72
    private $isActive = true;
73
74
    /**
75
     * @var string
76
     *
77
     * @ORM\Column(type="BookableState", length=10, options={"default" = BookableStateType::GOOD})
78
     */
79
    private $state = BookableStateType::GOOD;
80
81
    /**
82
     * @var null|Date
83
     * @ORM\Column(type="date", nullable=true)
84
     */
85
    private $verificationDate;
86
87
    /**
88
     * @var BookableTag
89
     *
90
     * @ORM\ManyToMany(targetEntity="BookableTag", mappedBy="bookables")
91
     */
92
    private $bookableTags;
93
94
    /**
95
     * @var Collection
96
     * @ORM\OneToMany(targetEntity="Booking", mappedBy="bookable")
97
     */
98
    private $bookings;
99
100
    /**
101
     * @var Collection
102
     * @ORM\ManyToMany(targetEntity="License", mappedBy="bookables")
103
     */
104
    private $licenses;
105
106
    /**
107
     * @var null|Image
108
     * @ORM\OneToOne(targetEntity="Image", orphanRemoval=true)
109
     * @ORM\JoinColumn(name="image_id", referencedColumnName="id")
110
     */
111
    private $image;
112
113
    /**
114
     * @var null|Account
115
     *
116
     * @ORM\ManyToOne(targetEntity="Account")
117
     * @ORM\JoinColumns({
118
     *     @ORM\JoinColumn(nullable=true, onDelete="CASCADE")
119
     * })
120
     */
121
    private $creditAccount;
122
123
    /**
124
     * Constructor
125
     */
126 13
    public function __construct()
127
    {
128 13
        $this->bookings = new ArrayCollection();
129 13
        $this->licenses = new ArrayCollection();
130 13
        $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...
131 13
    }
132
133
    /**
134
     * @return Collection
135
     */
136 1
    public function getBookings(): Collection
137
    {
138 1
        return $this->bookings;
139
    }
140
141
    /**
142
     * Notify the bookable that it has a new booking.
143
     * This should only be called by Booking::addBookable()
144
     *
145
     * @param Booking $booking
146
     */
147 9
    public function bookingAdded(Booking $booking): void
148
    {
149 9
        $this->bookings->add($booking);
150 9
    }
151
152
    /**
153
     * Notify the bookable that it a booking was removed.
154
     * This should only be called by Booking::removeBookable()
155
     *
156
     * @param Booking $booking
157
     */
158 1
    public function bookingRemoved(Booking $booking): void
159
    {
160 1
        $this->bookings->removeElement($booking);
161 1
    }
162
163
    /**
164
     * @return Collection
165
     */
166 2
    public function getLicenses(): Collection
167
    {
168 2
        return $this->licenses;
169
    }
170
171
    /**
172
     * Notify the bookable that it has a new license.
173
     * This should only be called by License::addBookable()
174
     *
175
     * @param License $license
176
     */
177 1
    public function licenseAdded(License $license): void
178
    {
179 1
        $this->licenses->add($license);
180 1
    }
181
182
    /**
183
     * Notify the bookable that it a license was removed.
184
     * This should only be called by License::removeBookable()
185
     *
186
     * @param License $license
187
     */
188 1
    public function licenseRemoved(License $license): void
189
    {
190 1
        $this->licenses->removeElement($license);
191 1
    }
192
193
    /**
194
     * @return string
195
     */
196 6
    public function getInitialPrice(): string
197
    {
198 6
        return $this->initialPrice;
199
    }
200
201
    /**
202
     * @param string $initialPrice
203
     */
204 6
    public function setInitialPrice(string $initialPrice): void
205
    {
206 6
        $this->initialPrice = $initialPrice;
207 6
    }
208
209
    /**
210
     * @return string
211
     */
212 10
    public function getPeriodicPrice(): string
213
    {
214 10
        return $this->periodicPrice;
215
    }
216
217
    /**
218
     * @param string $periodicPrice
219
     */
220 8
    public function setPeriodicPrice(string $periodicPrice): void
221
    {
222 8
        $this->periodicPrice = $periodicPrice;
223 8
    }
224
225
    /**
226
     * @return string
227
     */
228
    public function getPurchasePrice(): string
229
    {
230
        return $this->purchasePrice;
231
    }
232
233
    /**
234
     * @param string $purchasePrice
235
     */
236
    public function setPurchasePrice(string $purchasePrice): void
237
    {
238
        $this->purchasePrice = $purchasePrice;
239
    }
240
241
    /**
242
     * @return int
243
     */
244
    public function getSimultaneousBookingMaximum(): int
245
    {
246
        return $this->simultaneousBookingMaximum;
247
    }
248
249
    /**
250
     * @param int $simultaneousBookingMaximum
251
     */
252
    public function setSimultaneousBookingMaximum(int $simultaneousBookingMaximum): void
253
    {
254
        $this->simultaneousBookingMaximum = $simultaneousBookingMaximum;
255
    }
256
257
    /**
258
     * @API\Field(type="BookingType")
259
     *
260
     * @return string
261
     */
262 6
    public function getBookingType(): string
263
    {
264 6
        return $this->bookingType;
265
    }
266
267
    /**
268
     * Whether this bookable can be booked
269
     *
270
     * @return bool
271
     */
272 1
    public function isActive(): bool
273
    {
274 1
        return $this->isActive;
275
    }
276
277
    /**
278
     * Whether this bookable can be booked
279
     *
280
     * @param bool $isActive
281
     */
282
    public function setIsActive(bool $isActive): void
283
    {
284
        $this->isActive = $isActive;
285
    }
286
287
    /**
288
     * @API\Input(type="BookingType")
289
     *
290
     * @param string $state
291
     */
292
    public function setBookingType(string $state): void
293
    {
294
        $this->bookingType = $state;
295
    }
296
297
    /**
298
     * State of the bookable
299
     *
300
     * @API\Field(type="BookableState")
301
     *
302
     * @return string
303
     */
304
    public function getState(): string
305
    {
306
        return $this->state;
307
    }
308
309
    /**
310
     * State of the bookable
311
     *
312
     * @API\Input(type="BookableState")
313
     *
314
     * @param string $state
315
     */
316
    public function setState(string $state): void
317
    {
318
        $this->state = $state;
319
    }
320
321
    /**
322
     * The date then the bookable was last checked
323
     *
324
     * @return null|Date
325
     */
326
    public function getVerificationDate(): ?Date
327
    {
328
        return $this->verificationDate;
329
    }
330
331
    /**
332
     * The date then the bookable was last checked
333
     *
334
     * @param null|Date $verificationDate
335
     */
336
    public function setVerificationDate(?Date $verificationDate): void
337
    {
338
        $this->verificationDate = $verificationDate;
339
    }
340
341
    /**
342
     * @return Collection
343
     */
344 6
    public function getBookableTags(): Collection
345
    {
346 6
        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...
347
    }
348
349
    /**
350
     * Notify the user that it has a new bookableTag.
351
     * This should only be called by BookableTag::addUser()
352
     *
353
     * @param BookableTag $bookableTag
354
     */
355
    public function bookableTagAdded(BookableTag $bookableTag): void
356
    {
357
        $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

357
        $this->bookableTags->/** @scrutinizer ignore-call */ 
358
                             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...
358
    }
359
360
    /**
361
     * Notify the user that it a bookableTag was removed.
362
     * This should only be called by BookableTag::removeUser()
363
     *
364
     * @param BookableTag $bookableTag
365
     */
366
    public function bookableTagRemoved(BookableTag $bookableTag): void
367
    {
368
        $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

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