PluginProbe ʕ •ᴥ•ʔ
VikAppointments Services Booking Calendar / 1.2.21
VikAppointments Services Booking Calendar v1.2.21
1.2.21 1.2.20 trunk 1.2.17 1.2.18 1.2.19
vikappointments / site / helpers / libraries / availability / timeline / parser / service.php
vikappointments / site / helpers / libraries / availability / timeline / parser Last commit date
allemployees.php 5 days ago employee.php 5 days ago group.php 5 days ago groupext.php 5 days ago index.html 5 days ago service.php 5 days ago
service.php
230 lines
1 <?php
2 /**
3 * @package VikAppointments
4 * @subpackage core
5 * @author E4J s.r.l.
6 * @copyright Copyright (C) 2021 E4J s.r.l. All Rights Reserved.
7 * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
8 * @link https://vikwp.com
9 */
10
11 // No direct access
12 defined('ABSPATH') or die('No script kiddies please!');
13
14 VAPLoader::import('libraries.availability.timeline.parser');
15
16 /**
17 * Service timeline parser (missing employee selection).
18 *
19 * @since 1.7
20 */
21 class VAPAvailabilityTimelineParserService extends VAPAvailabilityTimelineParser
22 {
23 /**
24 * Internal method used by children classes to implement their own logic
25 * to fetch the availability timeline.
26 *
27 * @param string $date The UTC date in military format.
28 * @param integer $people The number of participants.
29 * @param integer $id The selected appointment ID.
30 *
31 * @return mixed The resulting timeline on success, false otherwise.
32 */
33 protected function buildTimeline($date, $people = 1, $id = 0)
34 {
35 $id_service = (int) $this->search->get('id_service');
36
37 // get service details
38 $service = JModelVAP::getInstance('serempassoc')->getOverrides($id_service);
39
40 // load all supported employees
41 $employees = JModelVAP::getInstance('service')->getEmployees($id_service);
42
43 $timelines = array();
44
45 // iterate employees
46 foreach ($employees as $employee)
47 {
48 // temporarily set the employee
49 $this->search->set('id_employee', (int) $employee->id);
50
51 // get proper parser with updated searcher
52 $parser = VAPAvailabilityTimelineFactory::getParser($this->search);
53
54 // obtain timeline from parent
55 $tmp = $parser->getTimeline($date, $people, $id);
56
57 if ($tmp)
58 {
59 // register timeline only if existing
60 $timelines[] = $tmp;
61 }
62 }
63
64 // reset employee from search
65 $this->search->set('id_employee', 0);
66
67 // merge all the timelines found into a single one
68 $arr = $this->mergeTimelines($timelines);
69
70 // create timeline
71 $timeline = new VAPAvailabilityTimeline($date, $this->search);
72
73 foreach ($arr as $k => $block)
74 {
75 // create check-in date time
76 $checkin = JFactory::getDate($date);
77 $checkin->modify(JHtml::fetch('vikappointments.min2time', $k, $string = true, $format = 'H:i:s'));
78
79 // check whether the time is in the past (preserve them in case of admin)
80 if ($arr[$k] && $this->search->isPastTime($checkin))
81 {
82 // unset block if it is in the past
83 unset($arr[$k]);
84 }
85 else if ($k >= 1440)
86 {
87 /**
88 * Unset the time slots that exceed the midnight.
89 *
90 * @since 1.6
91 */
92 if (!$service->checkout_selection)
93 {
94 /**
95 * Time-slots that exceed the midnight are mandatory for
96 * the checkout selection. Unset them only whether the
97 * "checkout_selection" parameter is turned off.
98 *
99 * @since 1.6.2
100 */
101 unset($arr[$k]);
102 }
103 }
104
105 if (isset($arr[$k]))
106 {
107 $trace = array();
108
109 // add time
110 $timeBlock = $timeline->addTime($k, $arr[$k]['status'], $service->duration);
111
112 // calculate rate for the current time block
113 $price = VAPSpecialRates::getRate($id_service, 0, $timeBlock->checkin(), $people, $trace);
114
115 // multiply by the number of guests (if enabled)
116 if ($service->priceperpeople)
117 {
118 $price *= $people;
119 }
120
121 // set time block price
122 $timeBlock->setPrice($price);
123
124 if ($trace && !empty($trace['rates']))
125 {
126 // register rate trace
127 $timeBlock->setRatesTrace($trace['rates']);
128 }
129
130 // set overall occupancy
131 $timeBlock->setOccupancy(array($block['occupancy'], $block['capacity']));
132 }
133 }
134
135 // make sure all the times are not in the past
136 if (!$timeline->hasTimes())
137 {
138 // all times are in the past
139 $this->setError(JText::translate('VAPFINDRESNOLONGERAVAILABLE'));
140
141 return false;
142 }
143
144 return $timeline;
145 }
146
147 /**
148 * Parses the timelines in the array to fetch a single timeline.
149 *
150 * @param array $timelines The fetched timelines.
151 *
152 * @return array The resulting timeline.
153 */
154 protected function mergeTimelines($timelines)
155 {
156 // convert timelines into array for a better ease of use
157 foreach ($timelines as $i => $timeline)
158 {
159 // convert the timeline into an array by keeping all the time details
160 $timelines[$i] = $timeline->toArray($flatten = true, $statusOnly = false);
161 }
162
163 $arr = array();
164
165 foreach ($timelines as $timeline)
166 {
167 foreach ($timeline as $time => $block)
168 {
169 // get time slot status
170 $res = $block['status'];
171
172 $is_pending = false;
173
174 for ($i = 0; $i < count($timelines) && $res != 1; $i++)
175 {
176 $res = (!empty($timelines[$i][$time])) ? $timelines[$i][$time]['status'] : 0;
177
178 if ($res == 2)
179 {
180 $is_pending = true;
181 }
182 }
183
184 if ($res == 0 && $is_pending)
185 {
186 $res = 2;
187 }
188
189 // refresh status
190 $block['status'] = $res;
191
192 if (!isset($arr[$time]))
193 {
194 $arr[$time] = $block;
195 }
196 else
197 {
198 /**
199 * The timeline now sums the total occupancy and capacity of
200 * 2+ matching time slots.
201 *
202 * NOTE: it is definitely incorrect to have a service able
203 * to host multiple guests that it is also assigned to multiple
204 * employees (with selection turned off). This because, even if
205 * the total capacity is correct, the available times might be
206 * split. Lets take as example 2 employees with capacity 4 and
207 * both them own a reservation for 2 guests. The real remaining
208 * availability should be 2 for the first service, 2 for the
209 * second one. However, with the summed capacity, the resulting
210 * availability will be equal to 4.
211 *
212 * @since 1.7
213 */
214 $arr[$time]['occupancy'] += $block['occupancy'];
215 $arr[$time]['capacity'] += $block['capacity'];
216 }
217 }
218 }
219
220 /**
221 * Sort employees working days to be listed in ascending ordering.
222 *
223 * @since 1.6.1
224 */
225 ksort($arr);
226
227 return $arr;
228 }
229 }
230