Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
42 / 42
100.00% covered (success)
100.00%
11 / 11
CRAP
100.00% covered (success)
100.00%
1 / 1
Day
100.00% covered (success)
100.00%
42 / 42
100.00% covered (success)
100.00%
11 / 11
20
100.00% covered (success)
100.00%
1 / 1
 getDefaults
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
 __toString
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 setDateTime
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 toDateTime
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 hasAppointmentsByType
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 isBookable
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hasAppointments
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 getWithStatus
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
6
 withAddedDay
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 getDayHash
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCalculatedDayHash
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace BO\Zmsentities;
4
5class Day extends Schema\Entity
6{
7    public const PRIMARY = 'day';
8
9    public const FULL = 'full';
10
11    public const BOOKABLE = 'bookable';
12
13    public const NOTBOOKABLE = 'notBookable';
14
15    public const RESTRICTED = 'restricted';
16
17    public const DETAIL = 'detail';
18
19    public static $schema = "day.json";
20
21    #[\Override]
22    public function getDefaults()
23    {
24        return [
25            'year' => '',
26            'month' => '',
27            'day' => '',
28            'status' => self::NOTBOOKABLE,
29            'freeAppointments' => new Slot(),
30            'allAppointments' => new Slot()
31        ];
32    }
33
34    //@todo freeAppointments could be an array, should be slot entity
35    public function __toString()
36    {
37        $this->freeAppointments = new Slot($this->freeAppointments);
38        return "Day {$this->status}@{$this->year}-{$this->month}-{$this->day} with " . $this->freeAppointments;
39    }
40
41    public function setDateTime(\DateTimeInterface $dateTime)
42    {
43        $this['year'] = $dateTime->format('Y');
44        $this['month'] = $dateTime->format('m');
45        $this['day'] = $dateTime->format('d');
46        return $this;
47    }
48
49    public function toDateTime()
50    {
51        $date = Helper\DateTime::createFromFormat('Y-m-d', $this['year'] . '-' . $this['month'] . '-' . $this['day']);
52        return Helper\DateTime::create($date);
53    }
54
55    /**
56     * @return bool TRUE or FALSE if one or more appointments, if no appointments for $slotType were defined, than NULL
57     */
58    public function hasAppointmentsByType($slotType)
59    {
60        $freeAppointmentCount = $this->toProperty()->freeAppointments->{$slotType}->get();
61        $allAppointmentCount = $this->toProperty()->allAppointments->{$slotType}->get();
62        if (null !== $allAppointmentCount && $allAppointmentCount <= 0) {
63            return null;
64        }
65        return (0 < $freeAppointmentCount);
66    }
67
68    public function isBookable()
69    {
70        return ($this->status == self::BOOKABLE);
71    }
72
73    public function hasAppointments()
74    {
75        return ($this->status == self::BOOKABLE || $this->status == self::FULL);
76    }
77
78    /**
79     * Check if day is bookable
80     * The return self or status
81     *
82     * @return \ArrayObject or String
83     */
84    public function getWithStatus($slotType, \DateTimeInterface $now)
85    {
86        $hasAppointments = $this->hasAppointmentsByType($slotType);
87        if ($this->status != self::RESTRICTED && $hasAppointments !== null) {
88            $this->status = ($hasAppointments) ? self::BOOKABLE : self::FULL;
89        } elseif (null === $hasAppointments) {
90            $this->status = self::NOTBOOKABLE;
91        }
92        // if dayend < todays time + half an hour, it is restricted
93        if ($this->toDateTime()->getTimestamp() + 86400 <= $now->getTimestamp() + 1800) {
94            $this->status =  self::RESTRICTED;
95        }
96        return $this;
97    }
98
99    public function withAddedDay(Day $day)
100    {
101        $merged = clone $this;
102        if (!$merged->freeAppointments instanceof Slot) {
103            $merged->freeAppointments = new Slot($merged->freeAppointments);
104        }
105        $merged->freeAppointments = $merged->freeAppointments->withAddedSlot($day->freeAppointments);
106        return $merged;
107    }
108
109    /**
110     * Returns an unique string hash per day optimized for b-trees
111     */
112    public function getDayHash()
113    {
114        return $this::getCalculatedDayHash($this->day, $this->month, $this->year);
115    }
116
117    public static function getCalculatedDayHash($dayNumber, $month, $year)
118    {
119        $dateHash = str_pad($dayNumber, 2, '0', STR_PAD_LEFT)
120            . "-"
121            . str_pad($month, 2, '0', STR_PAD_LEFT)
122            . "-$year";
123        return $dateHash;
124    }
125}