PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.8.16
VikBooking Hotel Booking Engine & PMS v1.8.16
1.8.16 1.8.15 1.8.14 1.8.13 1.8.12 1.8.11 1.8.10 1.8.9 1.8.6 1.8.7 1.8.8 trunk 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 All 37 releases
← All changes | site/views/search/view.html.php +1406 -1280 1.7.1 → 1.8.16 View file →
@@ -15,1379 +15,1505 @@
15 15 class VikbookingViewSearch extends JViewVikBooking
16 16 {
17 17 public function display($tpl = null)
18 18 {
19 + if (!VikBooking::allowBooking()) {
20 + echo VikBooking::getDisabledBookingMsg();
21 + return;
22 + }
23 +
24 + $app = JFactory::getApplication();
19 25 $dbo = JFactory::getDbo();
20 - if (VikBooking::allowBooking()) {
21 - $session = JFactory::getSession();
22 - $mainframe = JFactory::getApplication();
23 - $vbo_tn = VikBooking::getTranslator();
24 - $pcheckindate = VikRequest::getString('checkindate', '', 'request');
25 - $pcheckinm = VikRequest::getString('checkinm', '', 'request');
26 - $pcheckinh = VikRequest::getString('checkinh', '', 'request');
27 - $pcheckoutdate = VikRequest::getString('checkoutdate', '', 'request');
28 - $pcheckoutm = VikRequest::getString('checkoutm', '', 'request');
29 - $pcheckouth = VikRequest::getString('checkouth', '', 'request');
30 - $pcategories = VikRequest::getString('categories', '', 'request');
31 - $proomsnum = VikRequest::getInt('roomsnum', '', 'request');
32 - $proomsnum = $proomsnum < 1 ? 1 : $proomsnum;
33 - $showchildren = VikBooking::showChildrenFront();
34 - $padults = VikRequest::getVar('adults', array());
35 - $pchildren = VikRequest::getVar('children', array());
36 - $ppkg_id = VikRequest::getInt('pkg_id', '', 'request');
37 - $pcategory_ids = VikRequest::getVar('category_ids', array());
38 - $nowdf = VikBooking::getDateFormat();
39 - if ($nowdf == "%d/%m/%Y") {
40 - $df = 'd/m/Y';
41 - } elseif ($nowdf == "%m/%d/%Y") {
42 - $df = 'm/d/Y';
43 - } else {
44 - $df = 'Y/m/d';
26 + $session = JFactory::getSession();
27 + $vbo_tn = VikBooking::getTranslator();
28 +
29 + $pcheckindate = VikRequest::getString('checkindate', '', 'request');
30 + $pcheckinm = VikRequest::getString('checkinm', '', 'request');
31 + $pcheckinh = VikRequest::getString('checkinh', '', 'request');
32 + $pcheckoutdate = VikRequest::getString('checkoutdate', '', 'request');
33 + $pcheckoutm = VikRequest::getString('checkoutm', '', 'request');
34 + $pcheckouth = VikRequest::getString('checkouth', '', 'request');
35 + $pcategories = VikRequest::getString('categories', '', 'request');
36 + $proomsnum = VikRequest::getInt('roomsnum', '', 'request');
37 + $proomsnum = $proomsnum < 1 ? 1 : $proomsnum;
38 + $showchildren = VikBooking::showChildrenFront();
39 + $padults = (array) VikRequest::getVar('adults', []);
40 + $pchildren = (array) VikRequest::getVar('children', []);
41 + $ppkg_id = VikRequest::getInt('pkg_id', '', 'request');
42 + $pcategory_ids = (array) VikRequest::getVar('category_ids', []);
43 +
44 + $nowdf = VikBooking::getDateFormat();
45 + if ($nowdf == "%d/%m/%Y") {
46 + $df = 'd/m/Y';
47 + } elseif ($nowdf == "%m/%d/%Y") {
48 + $df = 'm/d/Y';
49 + } else {
50 + $df = 'Y/m/d';
51 + }
52 +
53 + $timeopst = VikBooking::getTimeOpenStore();
54 + if (!(strlen($pcheckinh) > 0) && !(strlen($pcheckouth) > 0) && is_array($timeopst)) {
55 + $opent = VikBooking::getHoursMinutes($timeopst[0]);
56 + $closet = VikBooking::getHoursMinutes($timeopst[1]);
57 + $pcheckinh = $opent[0];
58 + $pcheckinm = $opent[1];
59 + $pcheckouth = $closet[0];
60 + $pcheckoutm = $closet[1];
61 + }
62 +
63 + // channel manager
64 + $ch_start_date = VikRequest::getString('start_date', '', 'request');
65 + $ch_end_date = VikRequest::getString('end_date', '', 'request');
66 + $ch_num_adults = VikRequest::getInt('num_adults', '', 'request');
67 + $ch_num_children = VikRequest::getInt('num_children', '', 'request');
68 + if (!empty($ch_start_date) && !empty($ch_end_date)) {
69 + if (!empty($ch_num_adults) && $ch_num_adults > 0) {
70 + $padults = [$ch_num_adults];
45 71 }
46 - $timeopst = VikBooking::getTimeOpenStore();
47 - if (!(strlen($pcheckinh) > 0) && !(strlen($pcheckouth) > 0) && is_array($timeopst)) {
48 - $opent = VikBooking::getHoursMinutes($timeopst[0]);
49 - $closet = VikBooking::getHoursMinutes($timeopst[1]);
50 - $pcheckinh = $opent[0];
51 - $pcheckinm = $opent[1];
52 - $pcheckouth = $closet[0];
53 - $pcheckoutm = $closet[1];
72 + if (!empty($ch_num_children) && $ch_num_children > 0) {
73 + $pchildren = [$ch_num_children];
54 74 }
55 - //vikbooking 1.5 channel manager
56 - $ch_start_date = VikRequest::getString('start_date', '', 'request');
57 - $ch_end_date = VikRequest::getString('end_date', '', 'request');
58 - $ch_num_adults = VikRequest::getInt('num_adults', '', 'request');
59 - $ch_num_children = VikRequest::getInt('num_children', '', 'request');
60 - if (!empty($ch_start_date) && !empty($ch_end_date)) {
61 - if (!empty($ch_num_adults) && $ch_num_adults > 0) {
62 - $padults = array(0 => $ch_num_adults);
63 - }
64 - if (!empty($ch_num_children) && $ch_num_children > 0) {
65 - $pchildren = array(0 => $ch_num_children);
66 - }
67 - if ($ch_start_date_ts = strtotime($ch_start_date)) {
68 - if ($ch_end_date_ts = strtotime($ch_end_date)) {
69 - $pcheckindate = date($df, $ch_start_date_ts);
70 - $pcheckoutdate = date($df, $ch_end_date_ts);
71 - if (is_array($timeopst)) {
72 - $opent = VikBooking::getHoursMinutes($timeopst[0]);
73 - $closet = VikBooking::getHoursMinutes($timeopst[1]);
74 - $pcheckinh = $opent[0];
75 - $pcheckinm = $opent[1];
76 - $pcheckouth = $closet[0];
77 - $pcheckoutm = $closet[1];
78 - } else {
79 - $pcheckinh = 0;
80 - $pcheckinm = 0;
81 - $pcheckouth = 0;
82 - $pcheckoutm = 0;
83 - }
75 + if ($ch_start_date_ts = strtotime($ch_start_date)) {
76 + if ($ch_end_date_ts = strtotime($ch_end_date)) {
77 + $pcheckindate = date($df, $ch_start_date_ts);
78 + $pcheckoutdate = date($df, $ch_end_date_ts);
79 + if (is_array($timeopst)) {
80 + $opent = VikBooking::getHoursMinutes($timeopst[0]);
81 + $closet = VikBooking::getHoursMinutes($timeopst[1]);
82 + $pcheckinh = $opent[0];
83 + $pcheckinm = $opent[1];
84 + $pcheckouth = $closet[0];
85 + $pcheckoutm = $closet[1];
86 + } else {
87 + $pcheckinh = 0;
88 + $pcheckinm = 0;
89 + $pcheckouth = 0;
90 + $pcheckoutm = 0;
84 91 }
85 92 }
86 93 }
87 - //
94 + }
88 95
89 - /**
90 - * To facilitate the search suggestions to drive more bookings in case of low
91 - * availability on the requested dates, we grab all rooms by ignoring their
92 - * minimum needed occupancy, and by considering only their maximum capacity.
93 - * This can make sense because "solo-rates" (for single-occupancy) are, most
94 - * of the times, forced by most OTAs. If the "search suggestions" are enabled
95 - * then the minimum occupancy of the rooms will be ignored to guarantee the
96 - * completion of a reservation by the guest, which would be booking a greater
97 - * room. In terms of pricing and availability nothing changes of course.
98 - *
99 - * @since 1.14.3 (J) - 1.4.3 (WP)
100 - */
101 - $booking_suggestion = VikRequest::getInt('suggestion', 0, 'request');
102 - //
96 + /**
97 + * To facilitate the search suggestions to drive more bookings in case of low
98 + * availability on the requested dates, we grab all rooms by ignoring their
99 + * minimum needed occupancy, and by considering only their maximum capacity.
100 + * This can make sense because "solo-rates" (for single-occupancy) are, most
101 + * of the times, forced by most OTAs. If the "search suggestions" are enabled
102 + * then the minimum occupancy of the rooms will be ignored to guarantee the
103 + * completion of a reservation by the guest, which would be booking a greater
104 + * room. In terms of pricing and availability nothing changes of course.
105 + *
106 + * @since 1.14.3 (J) - 1.4.3 (WP)
107 + */
108 + $booking_suggestion = VikRequest::getInt('suggestion', 0, 'request');
103 109
104 - $arradultsrooms = array();
105 - $arradultsclause = array();
106 - $arrpeople = array();
107 - if (count($padults) > 0) {
108 - foreach ($padults as $kad => $adu) {
109 - $roomnumb = $kad + 1;
110 - if (strlen($adu)) {
111 - $numadults = intval($adu);
112 - if ($numadults >= 0) {
113 - $arradultsrooms[$roomnumb] = $numadults;
114 - $arrpeople[$roomnumb]['adults'] = $numadults;
115 - // build capacity requirement clauses
116 - $room_requirements = array();
110 + /**
111 + * It is possible to display some listings as unavailable in case they are fully booked.
112 + * If enabled, the unavailable listings will be displayed as long as some are available.
113 + *
114 + * @since 1.17.2 (J) - 1.7.2 (WP)
115 + */
116 + $unavailable_listings = [];
117 +
118 + $arradultsrooms = [];
119 + $arradultsclause = [];
120 + $arrpeople = [];
121 + if ($padults) {
122 + foreach ($padults as $kad => $adu) {
123 + $roomnumb = $kad + 1;
124 + if (strlen($adu)) {
125 + $numadults = intval($adu);
126 + if ($numadults >= 0) {
127 + $arradultsrooms[$roomnumb] = $numadults;
128 + $arrpeople[$roomnumb]['adults'] = $numadults;
129 + // build capacity requirement clauses
130 + $room_requirements = [];
131 + if (!$booking_suggestion) {
132 + array_push($room_requirements, "`r`.`fromadult`<=" . $numadults);
133 + }
134 + array_push($room_requirements, "`r`.`toadult`>=" . $numadults);
135 + if ($showchildren && !empty($pchildren[$kad]) && intval($pchildren[$kad]) > 0) {
136 + $numchildren = intval($pchildren[$kad]);
137 + $arrpeople[$roomnumb]['children'] = $numchildren;
117 138 if (!$booking_suggestion) {
118 - array_push($room_requirements, "`r`.`fromadult`<=" . $numadults);
139 + array_push($room_requirements, "`r`.`fromchild`<=" . $numchildren);
119 140 }
120 - array_push($room_requirements, "`r`.`toadult`>=" . $numadults);
121 - if ($showchildren && !empty($pchildren[$kad]) && intval($pchildren[$kad]) > 0) {
122 - $numchildren = intval($pchildren[$kad]);
123 - $arrpeople[$roomnumb]['children'] = $numchildren;
124 - if (!$booking_suggestion) {
125 - array_push($room_requirements, "`r`.`fromchild`<=" . $numchildren);
126 - }
127 - array_push($room_requirements, "`r`.`tochild`>=" . $numchildren);
128 - } else {
129 - $arrpeople[$roomnumb]['children'] = 0;
130 - //VikBooking 1.4 May Patch: if no children then the room must accept no children
131 - if ($showchildren && intval($pchildren[$kad]) == 0) {
132 - array_push($room_requirements, "`r`.`fromchild` = 0");
133 - }
134 - //
141 + array_push($room_requirements, "`r`.`tochild`>=" . $numchildren);
142 + } else {
143 + $arrpeople[$roomnumb]['children'] = 0;
144 + // if no children then the room must accept no children
145 + if ($showchildren && intval($pchildren[$kad]) == 0) {
146 + array_push($room_requirements, "`r`.`fromchild` = 0");
135 147 }
136 - array_push($room_requirements, "`r`.`totpeople` >= " . ($arrpeople[$roomnumb]['adults'] + $arrpeople[$roomnumb]['children']));
137 - if (!$booking_suggestion) {
138 - array_push($room_requirements, "`r`.`mintotpeople` <= " . ($arrpeople[$roomnumb]['adults'] + $arrpeople[$roomnumb]['children']));
139 - }
140 - $strclause = '(' . implode(' AND ', $room_requirements) . ')';
141 - $arradultsclause[] = $strclause;
142 148 }
149 + array_push($room_requirements, "`r`.`totpeople` >= " . ($arrpeople[$roomnumb]['adults'] + $arrpeople[$roomnumb]['children']));
150 + if (!$booking_suggestion) {
151 + array_push($room_requirements, "`r`.`mintotpeople` <= " . ($arrpeople[$roomnumb]['adults'] + $arrpeople[$roomnumb]['children']));
152 + }
153 + $strclause = '(' . implode(' AND ', $room_requirements) . ')';
154 + $arradultsclause[] = $strclause;
143 155 }
144 156 }
145 157 }
158 + }
146 159
147 - //VBO 1.10 - Modify booking
148 - $mod_booking = array();
149 - $skip_busy_ids = array();
150 - $cur_mod = $session->get('vboModBooking', '');
151 - if (is_array($cur_mod) && count($cur_mod)) {
152 - $mod_booking = $cur_mod;
153 - $skip_busy_ids = VikBooking::loadBookingBusyIds($mod_booking['id']);
160 + // Modify booking
161 + $mod_booking = [];
162 + $skip_busy_ids = [];
163 + $cur_mod = $session->get('vboModBooking', '');
164 + if (is_array($cur_mod) && $cur_mod) {
165 + $mod_booking = $cur_mod;
166 + $skip_busy_ids = VikBooking::loadBookingBusyIds($mod_booking['id']);
167 + }
168 +
169 + // Session values
170 + $session->set('vbroomsnum', $proomsnum);
171 + $session->set('vbarrpeople', $arrpeople);
172 +
173 + if (empty($pcheckindate) || empty($pcheckoutdate) || $proomsnum <= 0 || count($arradultsrooms) != $proomsnum) {
174 + $this->setVboError(JText::translate('VBSELPRDATE'));
175 + return;
176 + }
177 +
178 + if (!VikBooking::dateIsValid($pcheckindate) || !VikBooking::dateIsValid($pcheckoutdate)) {
179 + $this->setVboError(JText::translate('VBWRONGDF') . ": " . VikBooking::sayDateFormat());
180 + return;
181 + }
182 +
183 + $first = VikBooking::getDateTimestamp($pcheckindate, $pcheckinh, $pcheckinm);
184 + $second = VikBooking::getDateTimestamp($pcheckoutdate, $pcheckouth, $pcheckoutm);
185 + $actnow = time();
186 + $today_bookings = VikBooking::todayBookings();
187 + if ($today_bookings) {
188 + $actnow = mktime(0, 0, 0, date('n'), date('j'), date('Y'));
189 + }
190 +
191 + if ($second <= $first || $first < $actnow) {
192 + $session->set('vbcheckin', '');
193 + $session->set('vbcheckout', '');
194 + if ($first <= $actnow) {
195 + if (date('d/m/Y', $first) == date('d/m/Y', $actnow)) {
196 + $emess = JText::translate('VBSRCHERRCHKINPASSED');
197 + } else {
198 + $emess = JText::translate('VBSRCHERRCHKINPAST');
199 + }
200 + } else {
201 + $emess = JText::translate('VBPICKBRET');
154 202 }
155 - //
156 - $session->set('vbroomsnum', $proomsnum);
157 - $session->set('vbarrpeople', $arrpeople);
158 - if (!empty($pcheckindate) && !empty($pcheckoutdate) && $proomsnum > 0 && count($arradultsrooms) == $proomsnum) {
159 - if (VikBooking::dateIsValid($pcheckindate) && VikBooking::dateIsValid($pcheckoutdate)) {
160 - $first = VikBooking::getDateTimestamp($pcheckindate, $pcheckinh, $pcheckinm);
161 - $second = VikBooking::getDateTimestamp($pcheckoutdate, $pcheckouth, $pcheckoutm);
162 - $actnow = time();
163 - $today_bookings = VikBooking::todayBookings();
164 - if ($today_bookings) {
165 - $actnow = mktime(0, 0, 0, date('n'), date('j'), date('Y'));
203 + $this->setVboError($emess);
204 + return;
205 + }
206 +
207 + // set stay dates and number of nights
208 + $session->set('vbcheckin', $first);
209 + $session->set('vbcheckout', $second);
210 + $secdiff = $second - $first;
211 + $daysdiff = $secdiff / 86400;
212 + if (is_int($daysdiff)) {
213 + if ($daysdiff < 1) {
214 + $daysdiff = 1;
215 + }
216 + } else {
217 + if ($daysdiff < 1) {
218 + $daysdiff = 1;
219 + } else {
220 + $sum = floor($daysdiff) * 86400;
221 + $newdiff = $secdiff - $sum;
222 + $maxhmore = VikBooking::getHoursMoreRb() * 3600;
223 + if ($maxhmore >= $newdiff) {
224 + $daysdiff = floor($daysdiff);
225 + } else {
226 + $daysdiff = ceil($daysdiff);
227 + }
228 + }
229 + }
230 +
231 + // push data to tracker
232 + VikBooking::getTracker()->pushDates($first, $second, $daysdiff)->pushParty($arrpeople);
233 +
234 + // restrictions
235 + $allrestrictions = VikBooking::loadRestrictions(false);
236 + $restrictions = VikBooking::globalRestrictions($allrestrictions);
237 + $restrcheckin = getdate($first);
238 + $restrcheckout = getdate($second);
239 + $restrictionsvalid = true;
240 + $restrictions_affcount = 0;
241 + $restrictionerrmsg = '';
242 + if ($restrictions) {
243 + if (array_key_exists($restrcheckin['mon'], $restrictions)) {
244 + // restriction found for this month, checking:
245 + $restrictions_affcount++;
246 + if (strlen((string)$restrictions[$restrcheckin['mon']]['wday'])) {
247 + $rvalidwdays = [$restrictions[$restrcheckin['mon']]['wday']];
248 + if (strlen((string)$restrictions[$restrcheckin['mon']]['wdaytwo'])) {
249 + $rvalidwdays[] = $restrictions[$restrcheckin['mon']]['wdaytwo'];
166 250 }
167 - if ($second > $first && $first >= $actnow) {
168 - $session->set('vbcheckin', $first);
169 - $session->set('vbcheckout', $second);
170 - $secdiff = $second - $first;
171 - $daysdiff = $secdiff / 86400;
172 - if (is_int($daysdiff)) {
173 - if ($daysdiff < 1) {
174 - $daysdiff = 1;
251 + if (!in_array($restrcheckin['wday'], $rvalidwdays)) {
252 + $restrictionsvalid = false;
253 + $restrictionerrmsg = JText::sprintf('VBRESTRERRWDAYARRIVAL', VikBooking::sayMonth($restrcheckin['mon']), VikBooking::sayWeekDay($restrictions[$restrcheckin['mon']]['wday']).(strlen($restrictions[$restrcheckin['mon']]['wdaytwo']) > 0 ? '/'.VikBooking::sayWeekDay($restrictions[$restrcheckin['mon']]['wdaytwo']) : ''));
254 + } elseif ($restrictions[$restrcheckin['mon']]['multiplyminlos'] == 1) {
255 + if (($daysdiff % $restrictions[$restrcheckin['mon']]['minlos']) != 0) {
256 + $restrictionsvalid = false;
257 + $restrictionerrmsg = JText::sprintf('VBRESTRERRMULTIPLYMINLOS', VikBooking::sayMonth($restrcheckin['mon']), $restrictions[$restrcheckin['mon']]['minlos']);
258 + }
259 + }
260 + $comborestr = VikBooking::parseJsDrangeWdayCombo($restrictions[$restrcheckin['mon']]);
261 + if ($comborestr) {
262 + if (array_key_exists($restrcheckin['wday'], $comborestr)) {
263 + if (!in_array($restrcheckout['wday'], $comborestr[$restrcheckin['wday']])) {
264 + $restrictionsvalid = false;
265 + $restrictionerrmsg = JText::sprintf('VBRESTRERRWDAYCOMBO', VikBooking::sayMonth($restrcheckin['mon']), VikBooking::sayWeekDay($comborestr[$restrcheckin['wday']][0]).(count($comborestr[$restrcheckin['wday']]) == 2 ? '/'.VikBooking::sayWeekDay($comborestr[$restrcheckin['wday']][1]) : ''), VikBooking::sayWeekDay($restrcheckin['wday']));
175 266 }
176 - } else {
177 - if ($daysdiff < 1) {
178 - $daysdiff = 1;
179 - } else {
180 - $sum = floor($daysdiff) * 86400;
181 - $newdiff = $secdiff - $sum;
182 - $maxhmore = VikBooking::getHoursMoreRb() * 3600;
183 - if ($maxhmore >= $newdiff) {
184 - $daysdiff = floor($daysdiff);
185 - } else {
186 - $daysdiff = ceil($daysdiff);
267 + }
268 + }
269 + } elseif (!empty($restrictions[$restrcheckin['mon']]['ctad']) || !empty($restrictions[$restrcheckin['mon']]['ctdd'])) {
270 + if (!empty($restrictions[$restrcheckin['mon']]['ctad'])) {
271 + $ctarestrictions = explode(',', $restrictions[$restrcheckin['mon']]['ctad']);
272 + if (in_array('-'.$restrcheckin['wday'].'-', $ctarestrictions)) {
273 + $restrictionsvalid = false;
274 + $restrictionerrmsg = JText::sprintf('VBRESTRERRWDAYCTAMONTH', VikBooking::sayWeekDay($restrcheckin['wday']), VikBooking::sayMonth($restrcheckin['mon']));
275 + }
276 + }
277 + if (!empty($restrictions[$restrcheckin['mon']]['ctdd'])) {
278 + $ctdrestrictions = explode(',', $restrictions[$restrcheckin['mon']]['ctdd']);
279 + if (in_array('-'.$restrcheckout['wday'].'-', $ctdrestrictions)) {
280 + $restrictionsvalid = false;
281 + $restrictionerrmsg = JText::sprintf('VBRESTRERRWDAYCTDMONTH', VikBooking::sayWeekDay($restrcheckout['wday']), VikBooking::sayMonth($restrcheckin['mon']));
282 + }
283 + }
284 + }
285 + if (!empty($restrictions[$restrcheckin['mon']]['maxlos']) && $restrictions[$restrcheckin['mon']]['maxlos'] > 0 && $restrictions[$restrcheckin['mon']]['maxlos'] > $restrictions[$restrcheckin['mon']]['minlos']) {
286 + if ($daysdiff > $restrictions[$restrcheckin['mon']]['maxlos']) {
287 + $restrictionsvalid = false;
288 + $restrictionerrmsg = JText::sprintf('VBRESTRERRMAXLOSEXCEEDED', VikBooking::sayMonth($restrcheckin['mon']), $restrictions[$restrcheckin['mon']]['maxlos']);
289 + }
290 + }
291 + if ($daysdiff < $restrictions[$restrcheckin['mon']]['minlos']) {
292 + $restrictionsvalid = false;
293 + $restrictionerrmsg = JText::sprintf('VBRESTRERRMINLOSEXCEEDED', VikBooking::sayMonth($restrcheckin['mon']), $restrictions[$restrcheckin['mon']]['minlos']);
294 + }
295 + } elseif (array_key_exists('range', $restrictions)) {
296 + /**
297 + * We use this map to know which restriction IDs are okay or not okay with the Min LOS.
298 + * The most recent restrictions will have a higher priority over the oldest ones.
299 + *
300 + * @since 1.13.5 (J) - 1.3.6 (WP)
301 + */
302 + $minlos_priority = [
303 + 'ok' => [],
304 + 'nok' => [],
305 + ];
306 + //
307 + foreach ($restrictions['range'] as $restr) {
308 + /**
309 + * We should not always add 82799 seconds to the end date of the restriction
310 + * because if they only last for one day (like a Saturday), then $restr['dto']
311 + * will be already set to the time 23:59:59.
312 + *
313 + * @since 1.13 (J) - 1.3.0 (WP)
314 + * @since 1.18.3 (J) - 1.8.3 (WP) timestamps ending with 9 for a range greater than 1 day indicate that the restriction end time
315 + * is already set to 23:59:59 (VCM Connector may be responsible), so no seconds should be added or the restriction end date
316 + * will be the day after, and if after the check-in time, it may be included.
317 + */
318 + $end_operator = date('Y-m-d', $restr['dfrom']) != date('Y-m-d', $restr['dto']) && substr((string) $restr['dto'], -1, 1) != 9 ? 82799 : 0;
319 +
320 + /**
321 + * Adjust at runtime the restriction end date in case we have records written by third-party
322 + * dynamic pricing systems that last for one day, where the date-from and date-to are identical.
323 + *
324 + * @since 1.18.16 (J) - 1.8.16 (WP)
325 + */
326 + if ($restr['dfrom'] == $restr['dto'] && !$end_operator) {
327 + $end_operator = 82799;
328 + }
329 +
330 + if ($restr['dfrom'] <= $restrcheckin[0] && ($restr['dto'] + $end_operator) >= $restrcheckin[0]) {
331 + // restriction found for this date range based on arrival date, check if compliant
332 + $restrictions_affcount++;
333 + if (strlen((string)$restr['wday'])) {
334 + $rvalidwdays = [$restr['wday']];
335 + if (strlen((string)$restr['wdaytwo'])) {
336 + $rvalidwdays[] = $restr['wdaytwo'];
337 + }
338 + if (!in_array($restrcheckin['wday'], $rvalidwdays)) {
339 + $restrictionsvalid = false;
340 + $restrictionerrmsg = JText::sprintf('VBRESTRERRWDAYARRIVALRANGE', VikBooking::sayWeekDay($restr['wday']).(strlen((string)$restr['wdaytwo']) ? '/'.VikBooking::sayWeekDay($restr['wdaytwo']) : ''));
341 + } elseif ($restr['multiplyminlos'] == 1) {
342 + if (($daysdiff % $restr['minlos']) != 0) {
343 + $restrictionsvalid = false;
344 + $restrictionerrmsg = JText::sprintf('VBRESTRERRMULTIPLYMINLOSRANGE', $restr['minlos']);
187 345 }
188 346 }
189 - }
190 - // VBO 1.11 - push data to tracker
191 - VikBooking::getTracker()->pushDates($first, $second, $daysdiff)->pushParty($arrpeople);
192 - //
193 - //Restrictions
194 - $allrestrictions = VikBooking::loadRestrictions(false);
195 - $restrictions = VikBooking::globalRestrictions($allrestrictions);
196 - $restrcheckin = getdate($first);
197 - $restrcheckout = getdate($second);
198 - $restrictionsvalid = true;
199 - $restrictions_affcount = 0;
200 - $restrictionerrmsg = '';
201 - if (count($restrictions) > 0) {
202 - if (array_key_exists($restrcheckin['mon'], $restrictions)) {
203 - //restriction found for this month, checking:
204 - $restrictions_affcount++;
205 - if (strlen((string)$restrictions[$restrcheckin['mon']]['wday'])) {
206 - $rvalidwdays = array($restrictions[$restrcheckin['mon']]['wday']);
207 - if (strlen((string)$restrictions[$restrcheckin['mon']]['wdaytwo'])) {
208 - $rvalidwdays[] = $restrictions[$restrcheckin['mon']]['wdaytwo'];
209 - }
210 - if (!in_array($restrcheckin['wday'], $rvalidwdays)) {
347 + $comborestr = VikBooking::parseJsDrangeWdayCombo($restr);
348 + if ($comborestr) {
349 + if (array_key_exists($restrcheckin['wday'], $comborestr)) {
350 + if (!in_array($restrcheckout['wday'], $comborestr[$restrcheckin['wday']])) {
211 351 $restrictionsvalid = false;
212 - $restrictionerrmsg = JText::sprintf('VBRESTRERRWDAYARRIVAL', VikBooking::sayMonth($restrcheckin['mon']), VikBooking::sayWeekDay($restrictions[$restrcheckin['mon']]['wday']).(strlen($restrictions[$restrcheckin['mon']]['wdaytwo']) > 0 ? '/'.VikBooking::sayWeekDay($restrictions[$restrcheckin['mon']]['wdaytwo']) : ''));
213 - } elseif ($restrictions[$restrcheckin['mon']]['multiplyminlos'] == 1) {
214 - if (($daysdiff % $restrictions[$restrcheckin['mon']]['minlos']) != 0) {
215 - $restrictionsvalid = false;
216 - $restrictionerrmsg = JText::sprintf('VBRESTRERRMULTIPLYMINLOS', VikBooking::sayMonth($restrcheckin['mon']), $restrictions[$restrcheckin['mon']]['minlos']);
217 - }
352 + $restrictionerrmsg = JText::sprintf('VBRESTRERRWDAYCOMBORANGE', VikBooking::sayWeekDay($comborestr[$restrcheckin['wday']][0]).(count($comborestr[$restrcheckin['wday']]) == 2 ? '/'.VikBooking::sayWeekDay($comborestr[$restrcheckin['wday']][1]) : ''), VikBooking::sayWeekDay($restrcheckin['wday']));
218 353 }
219 - $comborestr = VikBooking::parseJsDrangeWdayCombo($restrictions[$restrcheckin['mon']]);
220 - if (count($comborestr) > 0) {
221 - if (array_key_exists($restrcheckin['wday'], $comborestr)) {
222 - if (!in_array($restrcheckout['wday'], $comborestr[$restrcheckin['wday']])) {
223 - $restrictionsvalid = false;
224 - $restrictionerrmsg = JText::sprintf('VBRESTRERRWDAYCOMBO', VikBooking::sayMonth($restrcheckin['mon']), VikBooking::sayWeekDay($comborestr[$restrcheckin['wday']][0]).(count($comborestr[$restrcheckin['wday']]) == 2 ? '/'.VikBooking::sayWeekDay($comborestr[$restrcheckin['wday']][1]) : ''), VikBooking::sayWeekDay($restrcheckin['wday']));
225 - }
226 - }
227 - }
228 - } elseif (!empty($restrictions[$restrcheckin['mon']]['ctad']) || !empty($restrictions[$restrcheckin['mon']]['ctdd'])) {
229 - if (!empty($restrictions[$restrcheckin['mon']]['ctad'])) {
230 - $ctarestrictions = explode(',', $restrictions[$restrcheckin['mon']]['ctad']);
231 - if (in_array('-'.$restrcheckin['wday'].'-', $ctarestrictions)) {
232 - $restrictionsvalid = false;
233 - $restrictionerrmsg = JText::sprintf('VBRESTRERRWDAYCTAMONTH', VikBooking::sayWeekDay($restrcheckin['wday']), VikBooking::sayMonth($restrcheckin['mon']));
234 - }
235 - }
236 - if (!empty($restrictions[$restrcheckin['mon']]['ctdd'])) {
237 - $ctdrestrictions = explode(',', $restrictions[$restrcheckin['mon']]['ctdd']);
238 - if (in_array('-'.$restrcheckout['wday'].'-', $ctdrestrictions)) {
239 - $restrictionsvalid = false;
240 - $restrictionerrmsg = JText::sprintf('VBRESTRERRWDAYCTDMONTH', VikBooking::sayWeekDay($restrcheckout['wday']), VikBooking::sayMonth($restrcheckin['mon']));
241 - }
242 - }
243 354 }
244 - if (!empty($restrictions[$restrcheckin['mon']]['maxlos']) && $restrictions[$restrcheckin['mon']]['maxlos'] > 0 && $restrictions[$restrcheckin['mon']]['maxlos'] > $restrictions[$restrcheckin['mon']]['minlos']) {
245 - if ($daysdiff > $restrictions[$restrcheckin['mon']]['maxlos']) {
246 - $restrictionsvalid = false;
247 - $restrictionerrmsg = JText::sprintf('VBRESTRERRMAXLOSEXCEEDED', VikBooking::sayMonth($restrcheckin['mon']), $restrictions[$restrcheckin['mon']]['maxlos']);
248 - }
355 + }
356 + } elseif (!empty($restr['ctad']) || !empty($restr['ctdd'])) {
357 + if (!empty($restr['ctad'])) {
358 + $ctarestrictions = explode(',', $restr['ctad']);
359 + if (in_array('-'.$restrcheckin['wday'].'-', $ctarestrictions)) {
360 + $restrictionsvalid = false;
361 + $restrictionerrmsg = JText::sprintf('VBRESTRERRWDAYCTARANGE', VikBooking::sayWeekDay($restrcheckin['wday']));
249 362 }
250 - if ($daysdiff < $restrictions[$restrcheckin['mon']]['minlos']) {
363 + }
364 + if (!empty($restr['ctdd'])) {
365 + $ctdrestrictions = explode(',', $restr['ctdd']);
366 + if (in_array('-'.$restrcheckout['wday'].'-', $ctdrestrictions) && $restrcheckout[0] <= ($restr['dto'] + $end_operator)) {
251 367 $restrictionsvalid = false;
252 - $restrictionerrmsg = JText::sprintf('VBRESTRERRMINLOSEXCEEDED', VikBooking::sayMonth($restrcheckin['mon']), $restrictions[$restrcheckin['mon']]['minlos']);
368 + $restrictionerrmsg = JText::sprintf('VBRESTRERRWDAYCTDRANGE', VikBooking::sayWeekDay($restrcheckout['wday']));
253 369 }
254 - } elseif (array_key_exists('range', $restrictions)) {
255 - /**
256 - * We use this map to know which restriction IDs are okay or not okay with the Min LOS.
257 - * The most recent restrictions will have a higher priority over the oldest ones.
258 - *
259 - * @since 1.13.5 (J) - 1.3.6 (WP)
260 - */
261 - $minlos_priority = array(
262 - 'ok' => array(),
263 - 'nok' => array()
264 - );
265 - //
266 - foreach ($restrictions['range'] as $restr) {
267 - /**
268 - * We should not always add 82799 seconds to the end date of the restriction
269 - * because if they only last for one day (like a Saturday), then $restr['dto']
270 - * will be already set to the time 23:59:59.
271 - *
272 - * @since 1.13 (J) - 1.3.0 (WP)
273 - */
274 - $end_operator = date('Y-m-d', $restr['dfrom']) != date('Y-m-d', $restr['dto']) ? 82799 : 0;
275 - //
276 - if ($restr['dfrom'] <= $restrcheckin[0] && ($restr['dto'] + $end_operator) >= $restrcheckin[0]) {
277 - // restriction found for this date range based on arrival date, check if compliant
278 - $restrictions_affcount++;
279 - if (strlen((string)$restr['wday'])) {
280 - $rvalidwdays = array($restr['wday']);
281 - if (strlen((string)$restr['wdaytwo'])) {
282 - $rvalidwdays[] = $restr['wdaytwo'];
283 - }
284 - if (!in_array($restrcheckin['wday'], $rvalidwdays)) {
285 - $restrictionsvalid = false;
286 - $restrictionerrmsg = JText::sprintf('VBRESTRERRWDAYARRIVALRANGE', VikBooking::sayWeekDay($restr['wday']).(strlen((string)$restr['wdaytwo']) ? '/'.VikBooking::sayWeekDay($restr['wdaytwo']) : ''));
287 - } elseif ($restr['multiplyminlos'] == 1) {
288 - if (($daysdiff % $restr['minlos']) != 0) {
289 - $restrictionsvalid = false;
290 - $restrictionerrmsg = JText::sprintf('VBRESTRERRMULTIPLYMINLOSRANGE', $restr['minlos']);
291 - }
292 - }
293 - $comborestr = VikBooking::parseJsDrangeWdayCombo($restr);
294 - if ($comborestr) {
295 - if (array_key_exists($restrcheckin['wday'], $comborestr)) {
296 - if (!in_array($restrcheckout['wday'], $comborestr[$restrcheckin['wday']])) {
297 - $restrictionsvalid = false;
298 - $restrictionerrmsg = JText::sprintf('VBRESTRERRWDAYCOMBORANGE', VikBooking::sayWeekDay($comborestr[$restrcheckin['wday']][0]).(count($comborestr[$restrcheckin['wday']]) == 2 ? '/'.VikBooking::sayWeekDay($comborestr[$restrcheckin['wday']][1]) : ''), VikBooking::sayWeekDay($restrcheckin['wday']));
299 - }
300 - }
301 - }
302 - } elseif (!empty($restr['ctad']) || !empty($restr['ctdd'])) {
303 - if (!empty($restr['ctad'])) {
304 - $ctarestrictions = explode(',', $restr['ctad']);
305 - if (in_array('-'.$restrcheckin['wday'].'-', $ctarestrictions)) {
306 - $restrictionsvalid = false;
307 - $restrictionerrmsg = JText::sprintf('VBRESTRERRWDAYCTARANGE', VikBooking::sayWeekDay($restrcheckin['wday']));
308 - }
309 - }
310 - if (!empty($restr['ctdd'])) {
311 - $ctdrestrictions = explode(',', $restr['ctdd']);
312 - if (in_array('-'.$restrcheckout['wday'].'-', $ctdrestrictions) && $restrcheckout[0] <= ($restr['dto'] + $end_operator)) {
313 - $restrictionsvalid = false;
314 - $restrictionerrmsg = JText::sprintf('VBRESTRERRWDAYCTDRANGE', VikBooking::sayWeekDay($restrcheckout['wday']));
315 - }
316 - }
317 - }
318 - if (!empty($restr['maxlos']) && $restr['maxlos'] > 0 && $restr['maxlos'] > $restr['minlos']) {
319 - if ($daysdiff > $restr['maxlos']) {
320 - $restrictionsvalid = false;
321 - $restrictionerrmsg = JText::sprintf('VBRESTRERRMAXLOSEXCEEDEDRANGE', $restr['maxlos']);
322 - }
323 - }
324 - if ($daysdiff < $restr['minlos']) {
325 - $restrictionsvalid = false;
326 - $restrictionerrmsg = JText::sprintf('VBRESTRERRMINLOSEXCEEDEDRANGE', $restr['minlos']);
327 - array_push($minlos_priority['nok'], (int)$restr['id']);
328 - } else {
329 - array_push($minlos_priority['ok'], (int)$restr['id']);
330 - }
331 - } elseif ($restr['dfrom'] <= $restrcheckout[0] && ($restr['dto'] + $end_operator) >= $restrcheckout[0] && !empty($restr['ctdd'])) {
332 - /**
333 - * We validate the CTD restrictions depending on the check-out date.
334 - *
335 - * @since 1.16.3 (J) - 1.6.3 (WP)
336 - */
337 - $ctdrestrictions = explode(',', $restr['ctdd']);
338 - if (in_array('-'.$restrcheckout['wday'].'-', $ctdrestrictions)) {
339 - $restrictions_affcount++;
340 - $restrictionsvalid = false;
341 - $restrictionerrmsg = JText::sprintf('VBRESTRERRWDAYCTDRANGE', VikBooking::sayWeekDay($restrcheckout['wday']));
342 - }
343 - }
344 - }
345 - /**
346 - * We give priority to more recent restrictions to override MinLOS.
347 - *
348 - * @since 1.13.5 (J) - 1.3.6 (WP)
349 - */
350 - if (!$restrictionsvalid && count($minlos_priority['ok']) && count($minlos_priority['nok']) && max($minlos_priority['ok']) > max($minlos_priority['nok'])) {
351 - // we unset the error message and we reset the validity because a more recent restriction is allowing this MinLOS
352 - $restrictionsvalid = true;
353 - $restrictionerrmsg = '';
354 - }
355 - //
356 370 }
357 371 }
372 + if (!empty($restr['maxlos']) && $restr['maxlos'] > 0 && $restr['maxlos'] >= $restr['minlos']) {
373 + if ($daysdiff > $restr['maxlos']) {
374 + $restrictionsvalid = false;
375 + $restrictionerrmsg = JText::sprintf('VBRESTRERRMAXLOSEXCEEDEDRANGE', $restr['maxlos']);
376 + }
377 + }
378 + if ($daysdiff < $restr['minlos']) {
379 + $restrictionsvalid = false;
380 + $restrictionerrmsg = JText::sprintf('VBRESTRERRMINLOSEXCEEDEDRANGE', $restr['minlos']);
381 + array_push($minlos_priority['nok'], (int)$restr['id']);
382 + } else {
383 + array_push($minlos_priority['ok'], (int)$restr['id']);
384 + }
385 + } elseif ($restr['dfrom'] <= $restrcheckout[0] && ($restr['dto'] + $end_operator) >= $restrcheckout[0] && !empty($restr['ctdd'])) {
358 386 /**
359 - * We are no longer counting the "global restriction records" applied to all rooms, but
360 - * we are rather counting all restriction records, global and for individual rooms. This
361 - * way we apply the default Min LOS only when there are no restrictions at all. We are
362 - * also ignoring if some restrictions were applied. This is the previous IF statement:
387 + * We validate the CTD restrictions depending on the check-out date.
363 388 *
364 - * if (!count($restrictions) || $restrictions_affcount <= 0) {
365 - *
366 - * @since 1.15.0 (J) - 1.5.0 (WP)
389 + * @since 1.16.3 (J) - 1.6.3 (WP)
367 390 */
368 - if (!count($allrestrictions)) {
369 - // check global MinLOS (only in case there are no restrictions affecting these dates or no restrictions at all)
370 - $globminlos = VikBooking::getDefaultNightsCalendar();
371 - if ($globminlos > 1 && $daysdiff < $globminlos) {
372 - $restrictionsvalid = false;
373 - $restrictionerrmsg = JText::sprintf('VBRESTRERRMINLOSEXCEEDEDRANGE', $globminlos);
391 + $ctdrestrictions = explode(',', $restr['ctdd']);
392 + if (in_array('-'.$restrcheckout['wday'].'-', $ctdrestrictions)) {
393 + $restrictions_affcount++;
394 + $restrictionsvalid = false;
395 + $restrictionerrmsg = JText::sprintf('VBRESTRERRWDAYCTDRANGE', VikBooking::sayWeekDay($restrcheckout['wday']));
396 + }
397 + }
398 + }
399 + /**
400 + * We give priority to more recent restrictions to override MinLOS.
401 + *
402 + * @since 1.13.5 (J) - 1.3.6 (WP)
403 + */
404 + if (!$restrictionsvalid && $minlos_priority['ok'] && $minlos_priority['nok'] && max($minlos_priority['ok']) > max($minlos_priority['nok'])) {
405 + // we unset the error message and we reset the validity because a more recent restriction is allowing this MinLOS
406 + $restrictionsvalid = true;
407 + $restrictionerrmsg = '';
408 + }
409 + //
410 + }
411 + }
412 + /**
413 + * We are no longer counting the "global restriction records" applied to all rooms, but
414 + * we are rather counting all restriction records, global and for individual rooms. This
415 + * way we apply the default Min LOS only when there are no restrictions at all. We are
416 + * also ignoring if some restrictions were applied. This is the previous IF statement:
417 + *
418 + * if (!$restrictions || $restrictions_affcount <= 0) {
419 + *
420 + * @since 1.15.0 (J) - 1.5.0 (WP)
421 + */
422 + if (!$allrestrictions) {
423 + // check global MinLOS (only in case there are no restrictions affecting these dates or no restrictions at all)
424 + $globminlos = VikBooking::getDefaultNightsCalendar();
425 + if ($globminlos > 1 && $daysdiff < $globminlos) {
426 + $restrictionsvalid = false;
427 + $restrictionerrmsg = JText::sprintf('VBRESTRERRMINLOSEXCEEDEDRANGE', $globminlos);
428 + }
429 + }
430 +
431 + // check if we are coming from a package to not consider the global restrictions for the standard booking procedure
432 + if (!empty($ppkg_id)) {
433 + $pkg = VikBooking::getPackage($ppkg_id);
434 + if ($pkg) {
435 + //the package exists so we let the next view perform the validation of the package criteria (MinLOS, MaxLOS etc..).
436 + $restrictionsvalid = true;
437 + $restrictionerrmsg = '';
438 + }
439 + }
440 +
441 + // closing dates
442 + $err_closingdates = VikBooking::validateClosingDates($first, $second, $df);
443 + if (!empty($err_closingdates)) {
444 + $restrictionsvalid = false;
445 + $restrictionerrmsg = JText::sprintf('VBERRDATESCLOSED', $err_closingdates);
446 + }
447 +
448 + // maximum date in the future for bookings
449 + $err_maxdatefuture = VikBooking::validateMaxDateBookings($first);
450 + if (!empty($err_maxdatefuture)) {
451 + $restrictionsvalid = false;
452 + $restrictionerrmsg = JText::sprintf('VBOERRMAXDATEBOOKINGS', $err_maxdatefuture);
453 + }
454 +
455 + // minimum days in advance for bookings
456 + $err_mindaysadv = VikBooking::validateMinDaysAdvance($first);
457 + if (!empty($err_mindaysadv)) {
458 + $restrictionsvalid = false;
459 + $restrictionerrmsg = JText::sprintf('VBOERRMINDAYSADV', $err_mindaysadv);
460 + }
461 +
462 + if ($restrictionsvalid !== true) {
463 + $this->setVboError($restrictionerrmsg);
464 + return;
465 + }
466 +
467 + $hoursdiff = VikBooking::countHoursToArrival($first);
468 + $q = "SELECT `p`.*,`r`.`id` AS `r_reference_id`,`r`.`name`,`r`.`img`,`r`.`idcat`,`r`.`idcarat`,`r`.`units`,`r`.`moreimgs`,`r`.`fromadult`,`r`.`toadult`,`r`.`fromchild`,`r`.`tochild`,`r`.`smalldesc`,`r`.`totpeople`,`r`.`params`,`r`.`imgcaptions`,`rp`.`name` AS `rpname`,`rp`.`minlos`,`rp`.`minhadv` FROM `#__vikbooking_dispcost` AS `p`, `#__vikbooking_rooms` AS `r`, `#__vikbooking_prices` AS `rp` WHERE `p`.`days`=".(int)$daysdiff." AND `p`.`idroom`=`r`.`id` AND `p`.`idprice`=`rp`.`id` AND `r`.`avail`='1' AND (".implode(" OR ", $arradultsclause).") ORDER BY `p`.`cost` ASC, `p`.`idprice` DESC, `p`.`idroom` ASC;";
469 + $dbo->setQuery($q);
470 + $tars = $dbo->loadAssocList();
471 +
472 + if (!$tars) {
473 + $sayerr = JText::translate('VBNOROOMAVFOR') . " " . $daysdiff . " " . ($daysdiff > 1 ? JText::translate('VBDAYS') : JText::translate('VBDAY'));
474 + if (count($padults) === 1) {
475 + $sayerr .= ", ".$arrpeople[1]['adults']." ".($arrpeople[1]['adults'] > 1 ? JText::translate('VBSEARCHRESADULTS') : JText::translate('VBSEARCHRESADULT'));
476 + if ($arrpeople[1]['children'] > 0) {
477 + $sayerr .= ", ".$arrpeople[1]['children']." ".($arrpeople[1]['children'] > 1 ? JText::translate('VBSEARCHRESCHILDREN') : JText::translate('VBSEARCHRESCHILD'));
478 + }
479 + }
480 + $err_code_info = [
481 + 'code' => 2,
482 + 'fromts' => $first,
483 + 'tots' => $second,
484 + 'party' => $arrpeople
485 + ];
486 +
487 + // push data to tracker and close
488 + VikBooking::getTracker()->pushMessage($sayerr, 'error')->closeTrack();
489 +
490 + $this->setVboError($sayerr, $err_code_info);
491 + return;
492 + }
493 +
494 + $vbo_tn->translateContents($tars, '#__vikbooking_rooms', ['id' => 'r_reference_id']);
495 + $arrtar = [];
496 + foreach ($tars as $tar) {
497 + $arrtar[$tar['idroom']][] = $tar;
498 + }
499 +
500 + // rate plans closed on these dates
501 + $roomrpclosed = VikBooking::getRoomRplansClosedInDates(array_keys($arrtar), $first, $daysdiff);
502 + if ($roomrpclosed) {
503 + foreach ($arrtar as $kk => $tt) {
504 + if (array_key_exists($kk, $roomrpclosed)) {
505 + foreach ($tt as $tk => $tv) {
506 + if (array_key_exists($tv['idprice'], $roomrpclosed[$kk])) {
507 + unset($arrtar[$kk][$tk]);
508 + }
509 + }
510 + if (!$arrtar[$kk]) {
511 + unset($arrtar[$kk]);
512 + } else {
513 + $arrtar[$kk] = array_values($arrtar[$kk]);
514 + }
515 + }
516 + }
517 + }
518 +
519 + // rate plans with a minlos, or with a min hours in advance
520 + foreach ($arrtar as $kk => $tt) {
521 + foreach ($tt as $tk => $tv) {
522 + if (!empty($tv['minlos']) && $tv['minlos'] > $daysdiff) {
523 + unset($arrtar[$kk][$tk]);
524 + } elseif ($hoursdiff < $tv['minhadv']) {
525 + unset($arrtar[$kk][$tk]);
526 + }
527 + }
528 + if (!$arrtar[$kk]) {
529 + unset($arrtar[$kk]);
530 + } else {
531 + $arrtar[$kk] = array_values($arrtar[$kk]);
532 + }
533 + }
534 +
535 + /**
536 + * Search results filtering options.
537 + *
538 + * @since 1.18.3 (J) - 1.8.3 (WP)
539 + */
540 + $resultFilters = (array) $app->input->get('filters', [], 'array');
541 + $filterAmenityIds = array_values(array_filter(array_map('intval', (array) ($resultFilters['amenity'] ?? null))));
542 + if (is_array($resultFilters['category'] ?? null)) {
543 + // sanitize category filtering options
544 + $resultFilters['category'] = array_values(array_filter(array_map('intval', $resultFilters['category'])));
545 + if ($resultFilters['category']) {
546 + // replace native category filter
547 + $pcategory_ids = $resultFilters['category'];
548 + }
549 + }
550 +
551 + // native search filtering and available records
552 + $filtercat = (!empty($pcategories) && $pcategories != "all");
553 + $filtermulticat = (is_array($pcategory_ids) && $pcategory_ids);
554 + $groupdays = VikBooking::getGroupDays($first, $second, $daysdiff);
555 + $morehst = VikBooking::getHoursRoomAvail() * 3600;
556 + $allbusy = VikBooking::loadBusyRecords(array_keys($arrtar), $first, $second);
557 + $all_locked = VikBooking::loadLockedRecords(array_keys($arrtar), $actnow);
558 + foreach ($arrtar as $kk => $tt) {
559 + $cats = explode(';', (string) $tt[0]['idcat']);
560 + if ($filtercat) {
561 + if (!in_array($pcategories, $cats)) {
562 + unset($arrtar[$kk]);
563 + continue;
564 + }
565 + }
566 + if ($filtermulticat) {
567 + /**
568 + * Added support for multiple category IDs as filter
569 + *
570 + * @since 1.13
571 + */
572 + $multicat_found = false;
573 + foreach ($pcategory_ids as $fcatid) {
574 + if (!empty($fcatid) && in_array($fcatid, $cats)) {
575 + $multicat_found = true;
576 + break;
577 + }
578 + }
579 + if (!$multicat_found) {
580 + unset($arrtar[$kk]);
581 + continue;
582 + }
583 + }
584 +
585 + if ($filterAmenityIds) {
586 + // filter listings by amenities (all the selected ones must be supported by the listing)
587 + $carats = array_values(array_filter(array_map('intval', explode(';', (string) $tt[0]['idcarat']))));
588 + if (array_diff($filterAmenityIds, $carats)) {
589 + // some amenities are not available with this listing
590 + unset($arrtar[$kk]);
591 + continue;
592 + }
593 + }
594 +
595 + /**
596 + * Trigger event to allow third party plugins to validate custom search results filtering.
597 + *
598 + * @since 1.18.3 (J) - 1.8.3 (WP)
599 + */
600 + $customFiltering = VBOFactory::getPlatform()->getDispatcher()->filter('onApplySearchResultsFiltering', [$tt[0], $resultFilters]);
601 + if (in_array(false, $customFiltering, true)) {
602 + // listing was requested to be unset
603 + unset($arrtar[$kk]);
604 + continue;
605 + }
606 +
607 + // availability controls
608 + $arrtar[$kk][0]['unitsavail'] = $tt[0]['units'];
609 + if ($allbusy && isset($allbusy[$kk]) && $allbusy[$kk]) {
610 + $units_booked = [];
611 + $check_locked = (bool)($all_locked && isset($all_locked[$kk]) && $all_locked[$kk]);
612 + foreach ($groupdays as $gday) {
613 + $bfound = 0;
614 + foreach ($allbusy[$kk] as $bu) {
615 + if (in_array($bu['id'], $skip_busy_ids)) {
616 + // Booking modification
617 + continue;
618 + }
619 + if ($gday >= $bu['checkin'] && $gday <= ($morehst + $bu['checkout'])) {
620 + $bfound++;
621 + }
622 + }
623 + if ($bfound >= $tt[0]['units']) {
624 + // listing is fully booked
625 + $unavailable_listings[] = $kk;
626 + unset($arrtar[$kk]);
627 + break;
628 + } else {
629 + $units_booked[] = $bfound;
630 + if ($check_locked === true) {
631 + foreach ($all_locked[$kk] as $bu) {
632 + if ($gday >= $bu['checkin'] && $gday <= $bu['realback']) {
633 + $bfound++;
634 + }
374 635 }
636 + if ($bfound >= $tt[0]['units']) {
637 + unset($arrtar[$kk]);
638 + break;
639 + } else {
640 + // push peak to properly calculate the units left by considering the locked records
641 + $units_booked[] = $bfound;
642 + }
375 643 }
376 - //VBO 1.9 - check if we are coming from a package to not consider the global restrictions for the standard booking procedure
644 + }
645 + }
646 + if (isset($arrtar[$kk]) && $units_booked) {
647 + $tot_u_booked = max($units_booked);
648 + $tot_u_left = ($tt[0]['units'] - $tot_u_booked);
649 + $arrtar[$kk][0]['unitsavail'] = $tot_u_left >= 0 ? $tot_u_left : 0;
650 + }
651 + } elseif (!VikBooking::roomNotLocked($kk, $tt[0]['units'], $first, $second)) {
652 + // room is fully locked
653 + unset($arrtar[$kk]);
654 + } elseif ($all_locked && isset($all_locked[$kk]) && $all_locked[$kk]) {
655 + // update number of units left by counting the units temporary locked
656 + $units_booked = [];
657 + foreach ($groupdays as $gday) {
658 + $bfound = 0;
659 + foreach ($all_locked[$kk] as $bu) {
660 + if ($gday >= $bu['checkin'] && $gday <= $bu['realback']) {
661 + $bfound++;
662 + }
663 + }
664 + // push peak to properly calculate the units left
665 + $units_booked[] = $bfound;
666 + }
667 + if (isset($arrtar[$kk]) && $units_booked) {
668 + $tot_u_booked = max($units_booked);
669 + $tot_u_left = ($tt[0]['units'] - $tot_u_booked);
670 + $arrtar[$kk][0]['unitsavail'] = $tot_u_left >= 0 ? $tot_u_left : 0;
671 + }
672 + }
673 +
674 + // single room restrictions
675 + if (isset($arrtar[$kk]) && $allrestrictions) {
676 + $roomrestr = VikBooking::roomRestrictions($kk, $allrestrictions);
677 + if ($roomrestr) {
678 + $restrictionerrmsg = VikBooking::validateRoomRestriction($roomrestr, $restrcheckin, $restrcheckout, $daysdiff);
679 + if (strlen($restrictionerrmsg) > 0) {
680 + // check if we are coming from a package to not consider the restrictions for the standard booking procedure
681 + $canunset = true;
377 682 if (!empty($ppkg_id)) {
378 683 $pkg = VikBooking::getPackage($ppkg_id);
379 - if (count($pkg)) {
380 - //the package exists so we let the next view perform the validation of the package criteria (MinLOS, MaxLOS etc..).
381 - $restrictionsvalid = true;
382 - $restrictionerrmsg = '';
684 + if ($pkg) {
685 + // the package exists so we let the next view perform the validation of the package criterai (MinLOS, MaxLOS etc..).
686 + $canunset = false;
383 687 }
384 688 }
385 - //
386 - //Closing Dates
387 - $err_closingdates = VikBooking::validateClosingDates($first, $second, $df);
388 - if (!empty($err_closingdates)) {
389 - $restrictionsvalid = false;
390 - $restrictionerrmsg = JText::sprintf('VBERRDATESCLOSED', $err_closingdates);
689 + if ($canunset === true) {
690 + unset($arrtar[$kk]);
691 + } else {
692 + $restrictionerrmsg = '';
391 693 }
392 - //
393 - //Maximum date in the future for bookings
394 - $err_maxdatefuture = VikBooking::validateMaxDateBookings($first);
395 - if (!empty($err_maxdatefuture)) {
396 - $restrictionsvalid = false;
397 - $restrictionerrmsg = JText::sprintf('VBOERRMAXDATEBOOKINGS', $err_maxdatefuture);
694 + }
695 + }
696 + }
697 +
698 + /**
699 + * Room-level maximum advance booking notice validation.
700 + *
701 + * @since 1.16.3 (J) - 1.6.3 (WP)
702 + */
703 + $err_maxdatefuture_room = VikBooking::validateMaxDateBookings($first, $kk);
704 + if (!empty($err_maxdatefuture_room)) {
705 + // unset non-compliant room and register last error
706 + unset($arrtar[$kk]);
707 + $restrictionerrmsg = JText::sprintf('VBOERRMAXDATEBOOKINGS', $err_maxdatefuture_room);
708 + }
709 +
710 + /**
711 + * Room-level minimum advance booking notice validation.
712 + *
713 + * @since 1.18.3 (J) - 1.8.3 (WP)
714 + */
715 + $err_mindaysadv_room = VikBooking::validateMinDaysAdvance($first, $kk);
716 + if (!empty($err_mindaysadv_room)) {
717 + // unset non-compliant room and register last error
718 + unset($arrtar[$kk]);
719 + if (is_float($err_mindaysadv_room)) {
720 + // number of minimum hours in advance not met
721 + $restrictionerrmsg = JText::sprintf('VBOERRMINBOOKNOTICE', JText::sprintf('VBO_N_HOURS', intval($err_mindaysadv_room * 24)));
722 + } else {
723 + // integer expected
724 + $restrictionerrmsg = JText::sprintf('VBOERRMINDAYSADV', $err_mindaysadv_room);
725 + }
726 + }
727 + }
728 +
729 + if (!is_array($arrtar) || !$arrtar) {
730 + $err_code_info = [];
731 + if (strlen($restrictionerrmsg)) {
732 + VikError::raiseWarning('', $restrictionerrmsg);
733 + } else {
734 + $err_code_info = [
735 + 'code' => 1,
736 + 'fromts' => $first,
737 + 'tots' => $second,
738 + 'party' => $arrpeople
739 + ];
740 + }
741 + $msg = JText::translate('VBNOROOMSINDATE');
742 +
743 + // push data to tracker and close
744 + VikBooking::getTracker()->pushMessage($msg, 'error')->closeTrack();
745 +
746 + $this->setVboError($msg, $err_code_info);
747 + return;
748 + }
749 +
750 + /**
751 + * Despite of the higher resources needed, we parse all rate plans for all rooms.
752 + *
753 + * @since 1.13 (J) - 1.3.0 (WP)
754 + */
755 + $arrtar = VikBooking::applySeasonalPrices($arrtar, $first, $second);
756 + $multi_rates = 1;
757 + foreach ($arrtar as $idr => $tars) {
758 + $multi_rates = count($tars) > $multi_rates ? count($tars) : $multi_rates;
759 + }
760 + if ($multi_rates > 1) {
761 + for ($r = 1; $r < $multi_rates; $r++) {
762 + $deeper_rates = [];
763 + foreach ($arrtar as $idr => $tars) {
764 + foreach ($tars as $tk => $tar) {
765 + if ($tk == $r) {
766 + $deeper_rates[$idr][0] = $tar;
767 + break;
398 768 }
399 - //
400 - //Minimum days in advance for bookings
401 - $err_mindaysadv = VikBooking::validateMinDaysAdvance($first);
402 - if (!empty($err_mindaysadv)) {
403 - $restrictionsvalid = false;
404 - $restrictionerrmsg = JText::sprintf('VBOERRMINDAYSADV', $err_mindaysadv);
405 - }
406 - //
407 - if ($restrictionsvalid === true) {
408 - $hoursdiff = VikBooking::countHoursToArrival($first);
409 - $q = "SELECT `p`.*,`r`.`id` AS `r_reference_id`,`r`.`name`,`r`.`img`,`r`.`idcat`,`r`.`idcarat`,`r`.`units`,`r`.`moreimgs`,`r`.`fromadult`,`r`.`toadult`,`r`.`fromchild`,`r`.`tochild`,`r`.`smalldesc`,`r`.`totpeople`,`r`.`params`,`r`.`imgcaptions`,`rp`.`name` AS `rpname`,`rp`.`minlos`,`rp`.`minhadv` FROM `#__vikbooking_dispcost` AS `p`, `#__vikbooking_rooms` AS `r`, `#__vikbooking_prices` AS `rp` WHERE `p`.`days`=".(int)$daysdiff." AND `p`.`idroom`=`r`.`id` AND `p`.`idprice`=`rp`.`id` AND `r`.`avail`='1' AND (".implode(" OR ", $arradultsclause).") ORDER BY `p`.`cost` ASC, `p`.`idprice` DESC, `p`.`idroom` ASC;";
410 - $dbo->setQuery($q);
411 - $tars = $dbo->loadAssocList();
412 - if ($tars) {
413 - $vbo_tn->translateContents($tars, '#__vikbooking_rooms', array('id' => 'r_reference_id'));
414 - $arrtar = array();
415 - foreach ($tars as $tar) {
416 - $arrtar[$tar['idroom']][] = $tar;
417 - }
418 - //Closed rate plans on these dates
419 - $roomrpclosed = VikBooking::getRoomRplansClosedInDates(array_keys($arrtar), $first, $daysdiff);
420 - if (count($roomrpclosed) > 0) {
421 - foreach ($arrtar as $kk => $tt) {
422 - if (array_key_exists($kk, $roomrpclosed)) {
423 - foreach ($tt as $tk => $tv) {
424 - if (array_key_exists($tv['idprice'], $roomrpclosed[$kk])) {
425 - unset($arrtar[$kk][$tk]);
426 - }
427 - }
428 - if (!(count($arrtar[$kk]) > 0)) {
429 - unset($arrtar[$kk]);
430 - } else {
431 - $arrtar[$kk] = array_values($arrtar[$kk]);
432 - }
769 + }
770 + }
771 + if (!$deeper_rates) {
772 + continue;
773 + }
774 + $deeper_rates = VikBooking::applySeasonalPrices($deeper_rates, $first, $second);
775 + foreach ($deeper_rates as $idr => $dtars) {
776 + foreach ($dtars as $dtk => $dtar) {
777 + $arrtar[$idr][$r] = $dtar;
778 + }
779 + }
780 + }
781 + }
782 + $arrtar = VikBooking::sortResults($arrtar);
783 +
784 + // separate results per number of rooms with $results
785 + $tmparrtar = $arrtar;
786 + $results = [];
787 + $multiroomcount = [];
788 + foreach ($arrpeople as $numroom => $aduchild) {
789 + $arrtar = $tmparrtar;
790 + $diffusage = [];
791 + $aduchild['children'] = !array_key_exists('children', $aduchild) ? 0 : $aduchild['children'];
792 + $nowtotpeople = $aduchild['adults'] + $aduchild['children'];
793 + foreach ($arrtar as $kk => $tt) {
794 + $validchildren = true;
795 + if ($showchildren) {
796 + if (!($tt[0]['fromchild'] <= $aduchild['children'] && $tt[0]['tochild'] >= $aduchild['children']) && $aduchild['children'] > 0) {
797 + $validchildren = false;
798 + }
799 + }
800 + $validtotpeople = true;
801 + if ($nowtotpeople > $tt[0]['totpeople']) {
802 + $errmess = JText::sprintf('VBERRPEOPLEPERROOM', $nowtotpeople, $aduchild['adults'], $aduchild['children']);
803 + $validtotpeople = false;
804 + }
805 + if ($validchildren && $validtotpeople) {
806 + if ($tt[0]['toadult'] == $aduchild['adults']) {
807 + //clean the diffusage from best usage in case it exists from before
808 + foreach ($arrtar[$kk] as $kpr => $vpr) {
809 + if (array_key_exists('diffusage', $arrtar[$kk][$kpr])) {
810 + unset($arrtar[$kk][$kpr]['diffusage']);
811 + }
812 + if (array_key_exists('diffusagecost', $arrtar[$kk][$kpr])) {
813 + //restore original price
814 + $operator = substr($arrtar[$kk][$kpr]['diffusagecost'], 0, 1);
815 + $valpcent = substr($arrtar[$kk][$kpr]['diffusagecost'], -1);
816 + if ($operator == "+") {
817 + if ($valpcent == "%") {
818 + $diffvalue = substr($arrtar[$kk][$kpr]['diffusagecost'], 1, (strlen($arrtar[$kk][$kpr]['diffusagecost']) - 1));
819 + if (array_key_exists('diffusagecostpernight', $arrtar[$kk][$kpr]) && $arrtar[$kk][$kpr]['diffusagecostpernight'] > 0) {
820 + $arrtar[$kk][$kpr]['cost'] = $arrtar[$kk][$kpr]['diffusagecostpernight'];
821 + } else {
822 + $arrtar[$kk][$kpr]['cost'] = round(($vpr['cost'] * (100 - $diffvalue) / 100), 2);
433 823 }
824 + } else {
825 + $diffvalue = substr($arrtar[$kk][$kpr]['diffusagecost'], 1);
826 + $arrtar[$kk][$kpr]['cost'] = $vpr['cost'] - $diffvalue;
434 827 }
435 - }
436 - //
437 - //VBO 1.10 - rate plans with a minlos, or with a min hours in advance
438 - foreach ($arrtar as $kk => $tt) {
439 - foreach ($tt as $tk => $tv) {
440 - if (!empty($tv['minlos']) && $tv['minlos'] > $daysdiff) {
441 - unset($arrtar[$kk][$tk]);
442 - } elseif ($hoursdiff < $tv['minhadv']) {
443 - unset($arrtar[$kk][$tk]);
828 + } elseif ($operator == "-") {
829 + if ($valpcent == "%") {
830 + $diffvalue = substr($arrtar[$kk][$kpr]['diffusagecost'], 1, (strlen($arrtar[$kk][$kpr]['diffusagecost']) - 1));
831 + if (array_key_exists('diffusagecostpernight', $arrtar[$kk][$kpr]) && $arrtar[$kk][$kpr]['diffusagecostpernight'] > 0) {
832 + $arrtar[$kk][$kpr]['cost'] = $arrtar[$kk][$kpr]['diffusagecostpernight'];
833 + } else {
834 + $arrtar[$kk][$kpr]['cost'] = round(($vpr['cost'] * (100 + $diffvalue) / 100), 2);
444 835 }
445 - }
446 - if (!(count($arrtar[$kk]) > 0)) {
447 - unset($arrtar[$kk]);
448 836 } else {
449 - $arrtar[$kk] = array_values($arrtar[$kk]);
837 + $diffvalue = substr($arrtar[$kk][$kpr]['diffusagecost'], 1);
838 + $arrtar[$kk][$kpr]['cost'] = $vpr['cost'] + $diffvalue;
450 839 }
451 840 }
452 841 //
453 - $filtercat = (!empty($pcategories) && $pcategories != "all");
454 - $filtermulticat = (is_array($pcategory_ids) && count($pcategory_ids));
455 - //vikbooking 1.1
456 - $groupdays = VikBooking::getGroupDays($first, $second, $daysdiff);
457 - $morehst = VikBooking::getHoursRoomAvail() * 3600;
458 - //
459 - $allbusy = VikBooking::loadBusyRecords(array_keys($arrtar), $first, $second);
460 - $all_locked = VikBooking::loadLockedRecords(array_keys($arrtar), $actnow);
461 - foreach ($arrtar as $kk => $tt) {
462 - $cats = explode(";", $tt[0]['idcat']);
463 - if ($filtercat) {
464 - if (!in_array($pcategories, $cats)) {
465 - unset($arrtar[$kk]);
466 - continue;
467 - }
842 + unset($arrtar[$kk][$kpr]['diffusagecost']);
843 + unset($arrtar[$kk][$kpr]['diffusagecostpernight']);
844 + }
845 + }
846 +
847 + // Maximum Occupancy Charges/Discounts
848 + $diffusageprice = VikBooking::loadAdultsDiff($kk, $aduchild['adults']);
849 + // Occupancy Override
850 + if (array_key_exists('occupancy_ovr', $tt[0]) && array_key_exists($aduchild['adults'], $tt[0]['occupancy_ovr']) && strlen($tt[0]['occupancy_ovr'][$aduchild['adults']]['value'])) {
851 + $diffusageprice = $tt[0]['occupancy_ovr'][$aduchild['adults']];
852 + }
853 +
854 + if (is_array($diffusageprice)) {
855 + // set a charge or discount to the price(s) for the different usage of the room
856 + foreach ($arrtar[$kk] as $kpr => $vpr) {
857 + $arrtar[$kk][$kpr]['diffusage'] = $aduchild['adults'];
858 + if ($diffusageprice['chdisc'] == 1) {
859 + // charge
860 + if ($diffusageprice['valpcent'] == 1) {
861 + // fixed value
862 + $arrtar[$kk][$kpr]['diffusagecostpernight'] = $diffusageprice['pernight'] == 1 ? 1 : 0;
863 + $aduseval = $diffusageprice['pernight'] == 1 ? $diffusageprice['value'] * $arrtar[$kk][$kpr]['days'] : $diffusageprice['value'];
864 + $arrtar[$kk][$kpr]['diffusagecost'] = "+".$aduseval;
865 + $arrtar[$kk][$kpr]['cost'] = $vpr['cost'] + $aduseval;
866 + } else {
867 + // percentage value
868 + $arrtar[$kk][$kpr]['diffusagecostpernight'] = $diffusageprice['pernight'] == 1 ? $vpr['cost'] : 0;
869 + $aduseval = $diffusageprice['pernight'] == 1 ? round(($vpr['cost'] * $diffusageprice['value'] / 100) * $arrtar[$kk][$kpr]['days'] + $vpr['cost'], 2) : round(($vpr['cost'] * (100 + $diffusageprice['value']) / 100), 2);
870 + $arrtar[$kk][$kpr]['diffusagecost'] = "+".$diffusageprice['value']."%";
871 + $arrtar[$kk][$kpr]['cost'] = $aduseval;
468 872 }
469 - if ($filtermulticat) {
470 - /**
471 - * Added support for multiple category IDs as filter
472 - *
473 - * @since 1.13
474 - */
475 - $multicat_found = false;
476 - foreach ($pcategory_ids as $fcatid) {
477 - if (!empty($fcatid) && in_array($fcatid, $cats)) {
478 - $multicat_found = true;
479 - break;
480 - }
481 - }
482 - if (!$multicat_found) {
483 - unset($arrtar[$kk]);
484 - continue;
485 - }
873 + } else {
874 + // discount
875 + if ($diffusageprice['valpcent'] == 1) {
876 + // fixed value
877 + $arrtar[$kk][$kpr]['diffusagecostpernight'] = $diffusageprice['pernight'] == 1 ? 1 : 0;
878 + $aduseval = $diffusageprice['pernight'] == 1 ? $diffusageprice['value'] * $arrtar[$kk][$kpr]['days'] : $diffusageprice['value'];
879 + $arrtar[$kk][$kpr]['diffusagecost'] = "-".$aduseval;
880 + $arrtar[$kk][$kpr]['cost'] = $vpr['cost'] - $aduseval;
881 + } else {
882 + // percentage value
883 + $arrtar[$kk][$kpr]['diffusagecostpernight'] = $diffusageprice['pernight'] == 1 ? $vpr['cost'] : 0;
884 + $aduseval = $diffusageprice['pernight'] == 1 ? round($vpr['cost'] - ((($vpr['cost'] / $arrtar[$kk][$kpr]['days']) * $diffusageprice['value'] / 100) * $arrtar[$kk][$kpr]['days']), 2) : round(($vpr['cost'] * (100 - $diffusageprice['value']) / 100), 2);
885 + $arrtar[$kk][$kpr]['diffusagecost'] = "-".$diffusageprice['value']."%";
886 + $arrtar[$kk][$kpr]['cost'] = $aduseval;
486 887 }
487 - $arrtar[$kk][0]['unitsavail'] = $tt[0]['units'];
488 - if ($allbusy && isset($allbusy[$kk]) && $allbusy[$kk]) {
489 - $units_booked = [];
490 - $check_locked = (bool)($all_locked && isset($all_locked[$kk]) && $all_locked[$kk]);
491 - foreach ($groupdays as $gday) {
492 - $bfound = 0;
493 - foreach ($allbusy[$kk] as $bu) {
494 - if (in_array($bu['id'], $skip_busy_ids)) {
495 - //VBO 1.10 - Booking modification
496 - continue;
497 - }
498 - if ($gday >= $bu['checkin'] && $gday <= ($morehst + $bu['checkout'])) {
499 - $bfound++;
500 - }
501 - }
502 - if ($bfound >= $tt[0]['units']) {
503 - unset($arrtar[$kk]);
504 - break;
505 - } else {
506 - $units_booked[] = $bfound;
507 - if ($check_locked === true) {
508 - foreach ($all_locked[$kk] as $bu) {
509 - if ($gday >= $bu['checkin'] && $gday <= $bu['realback']) {
510 - $bfound++;
511 - }
512 - }
513 - if ($bfound >= $tt[0]['units']) {
514 - unset($arrtar[$kk]);
515 - break;
516 - } else {
517 - // push peak to properly calculate the units left by considering the locked records
518 - $units_booked[] = $bfound;
519 - }
520 - }
521 - }
522 - }
523 - if (isset($arrtar[$kk]) && $units_booked) {
524 - $tot_u_booked = max($units_booked);
525 - $tot_u_left = ($tt[0]['units'] - $tot_u_booked);
526 - $arrtar[$kk][0]['unitsavail'] = $tot_u_left >= 0 ? $tot_u_left : 0;
527 - }
528 - } elseif (!VikBooking::roomNotLocked($kk, $tt[0]['units'], $first, $second)) {
529 - // room is fully locked
530 - unset($arrtar[$kk]);
531 - } elseif ($all_locked && isset($all_locked[$kk]) && $all_locked[$kk]) {
532 - // update number of units left by counting the units temporary locked
533 - $units_booked = [];
534 - foreach ($groupdays as $gday) {
535 - $bfound = 0;
536 - foreach ($all_locked[$kk] as $bu) {
537 - if ($gday >= $bu['checkin'] && $gday <= $bu['realback']) {
538 - $bfound++;
539 - }
540 - }
541 - // push peak to properly calculate the units left
542 - $units_booked[] = $bfound;
543 - }
544 - if (isset($arrtar[$kk]) && $units_booked) {
545 - $tot_u_booked = max($units_booked);
546 - $tot_u_left = ($tt[0]['units'] - $tot_u_booked);
547 - $arrtar[$kk][0]['unitsavail'] = $tot_u_left >= 0 ? $tot_u_left : 0;
548 - }
888 + }
889 + }
890 + }
891 + // Maximum Occupancy Charges/Discounts
892 + // best usage
893 + $results[$numroom][] = $arrtar[$kk];
894 + if (!isset($multiroomcount[$arrtar[$kk][0]['idroom']])) {
895 + $multiroomcount[$arrtar[$kk][0]['idroom']] = ['count' => 0];
896 + }
897 + $multiroomcount[$arrtar[$kk][0]['idroom']]['count'] += 1;
898 + $multiroomcount[$arrtar[$kk][0]['idroom']]['unitsavail'] = (int)$arrtar[$kk][0]['unitsavail'];
899 + $multiroomcount[$arrtar[$kk][0]['idroom']]['diffusage_r'.$numroom] = 0;
900 + } elseif (($tt[0]['fromadult'] <= $aduchild['adults'] || $booking_suggestion) && $tt[0]['toadult'] > $aduchild['adults']) {
901 + // different usage
902 + $diffusageprice = VikBooking::loadAdultsDiff($kk, $aduchild['adults']);
903 + // Occupancy Override
904 + if (array_key_exists('occupancy_ovr', $tt[0]) && array_key_exists($aduchild['adults'], $tt[0]['occupancy_ovr']) && strlen($tt[0]['occupancy_ovr'][$aduchild['adults']]['value'])) {
905 + $diffusageprice = $tt[0]['occupancy_ovr'][$aduchild['adults']];
906 + }
907 +
908 + if (is_array($diffusageprice)) {
909 + // set a charge or discount to the price(s) for the different usage of the room
910 + foreach ($arrtar[$kk] as $kpr => $vpr) {
911 + $arrtar[$kk][$kpr]['diffusage'] = $aduchild['adults'];
912 + if ($diffusageprice['chdisc'] == 1) {
913 + // charge
914 + if ($diffusageprice['valpcent'] == 1) {
915 + // fixed value
916 + $arrtar[$kk][$kpr]['diffusagecostpernight'] = $diffusageprice['pernight'] == 1 ? 1 : 0;
917 + $aduseval = $diffusageprice['pernight'] == 1 ? $diffusageprice['value'] * $arrtar[$kk][$kpr]['days'] : $diffusageprice['value'];
918 + $arrtar[$kk][$kpr]['diffusagecost'] = "+".$aduseval;
919 + $arrtar[$kk][$kpr]['cost'] = $vpr['cost'] + $aduseval;
920 + } else {
921 + // percentage value
922 + $arrtar[$kk][$kpr]['diffusagecostpernight'] = $diffusageprice['pernight'] == 1 ? $vpr['cost'] : 0;
923 + $aduseval = $diffusageprice['pernight'] == 1 ? round(($vpr['cost'] * $diffusageprice['value'] / 100) * $arrtar[$kk][$kpr]['days'] + $vpr['cost'], 2) : round(($vpr['cost'] * (100 + $diffusageprice['value']) / 100), 2);
924 + $arrtar[$kk][$kpr]['diffusagecost'] = "+".$diffusageprice['value']."%";
925 + $arrtar[$kk][$kpr]['cost'] = $aduseval;
549 926 }
550 - // single room restrictions
551 - if (isset($arrtar[$kk]) && $allrestrictions) {
552 - $roomrestr = VikBooking::roomRestrictions($kk, $allrestrictions);
553 - if (count($roomrestr) > 0) {
554 - $restrictionerrmsg = VikBooking::validateRoomRestriction($roomrestr, $restrcheckin, $restrcheckout, $daysdiff);
555 - if (strlen($restrictionerrmsg) > 0) {
556 - //VBO 1.9 - check if we are coming from a package to not consider the restrictions for the standard booking procedure
557 - $canunset = true;
558 - if (!empty($ppkg_id)) {
559 - $pkg = VikBooking::getPackage($ppkg_id);
560 - if (count($pkg)) {
561 - //the package exists so we let the next view perform the validation of the package criterai (MinLOS, MaxLOS etc..).
562 - $canunset = false;
563 - }
564 - }
565 - if ($canunset === true) {
566 - unset($arrtar[$kk]);
567 - } else {
568 - $restrictionerrmsg = '';
569 - }
570 - //
571 - }
572 - }
927 + } else {
928 + // discount
929 + if ($diffusageprice['valpcent'] == 1) {
930 + // fixed value
931 + $arrtar[$kk][$kpr]['diffusagecostpernight'] = $diffusageprice['pernight'] == 1 ? 1 : 0;
932 + $aduseval = $diffusageprice['pernight'] == 1 ? $diffusageprice['value'] * $arrtar[$kk][$kpr]['days'] : $diffusageprice['value'];
933 + $arrtar[$kk][$kpr]['diffusagecost'] = "-".$aduseval;
934 + $arrtar[$kk][$kpr]['cost'] = $vpr['cost'] - $aduseval;
935 + } else {
936 + // percentage value
937 + $arrtar[$kk][$kpr]['diffusagecostpernight'] = $diffusageprice['pernight'] == 1 ? $vpr['cost'] : 0;
938 + $aduseval = $diffusageprice['pernight'] == 1 ? round($vpr['cost'] - ((($vpr['cost'] / $arrtar[$kk][$kpr]['days']) * $diffusageprice['value'] / 100) * $arrtar[$kk][$kpr]['days']), 2) : round(($vpr['cost'] * (100 - $diffusageprice['value']) / 100), 2);
939 + $arrtar[$kk][$kpr]['diffusagecost'] = "-".$diffusageprice['value']."%";
940 + $arrtar[$kk][$kpr]['cost'] = $aduseval;
573 941 }
574 - //end single room restrictions
942 + }
943 + }
944 + } else {
945 + $arrtar[$kk][0]['diffusage'] = $aduchild['adults'];
946 + }
947 + $diffusage[$numroom][] = $arrtar[$kk];
948 + if (!isset($multiroomcount[$arrtar[$kk][0]['idroom']])) {
949 + $multiroomcount[$arrtar[$kk][0]['idroom']] = ['count' => 0];
950 + }
951 + $multiroomcount[$arrtar[$kk][0]['idroom']]['count'] += 1;
952 + $multiroomcount[$arrtar[$kk][0]['idroom']]['unitsavail'] = (int)$arrtar[$kk][0]['unitsavail'];
953 + $multiroomcount[$arrtar[$kk][0]['idroom']]['diffusage_r'.$numroom] = 1;
954 + }
955 + }
956 + }
957 + // merge $diffusage rooms with and after best usage rooms in $results
958 + if ($diffusage) {
959 + foreach ($diffusage as $nr => $du) {
960 + foreach ($du as $duroom) {
961 + $results[$nr][]=$duroom;
962 + }
963 + }
964 + }
965 + }
575 966
967 + // check if rooms repeated passed the availability
968 + $limitpassed = false;
969 + $search_type = VikBooking::getSmartSearchType();
970 + $js_search = $search_type == 'dynamic' ? true : false;
971 + // dynamic smart search via PHP
972 + $js_overcounter = [];
973 + if ($js_search && $proomsnum > 1 && $multiroomcount) {
974 + $tot_avail = 0;
975 + foreach ($multiroomcount as $idroom => $info) {
976 + $tot_avail += $info['unitsavail'];
977 + }
978 + if ($tot_avail >= $proomsnum) {
979 + $gen_avail = $results;
980 + foreach ($multiroomcount as $idroom => $info) {
981 + $multiroomcount[$idroom]['used'] = 0;
982 + if ($info['count'] > $info['unitsavail']) {
983 + $excessnum = $info['count'] - $info['unitsavail'];
984 + if ($excessnum > 0) {
985 + for ($z = $proomsnum; $z >= 1; $z--) {
986 + if ($excessnum > 0) {
576 987 /**
577 - * Room-level maximum advance booking notice validation.
578 - *
579 - * @since 1.16.3 (J) - 1.6.3 (WP)
988 + * @see comments below
580 989 */
581 - $err_maxdatefuture_room = VikBooking::validateMaxDateBookings($first, $kk);
582 - if (!empty($err_maxdatefuture_room)) {
583 - // unset non-compliant room and register last error
584 - unset($arrtar[$kk]);
585 - $restrictionerrmsg = JText::sprintf('VBOERRMAXDATEBOOKINGS', $err_maxdatefuture_room);
586 - }
587 - }
588 - if (is_array($arrtar) && $arrtar) {
589 - /**
590 - * Despite of the higher resources needed, we parse all rate plans for all rooms.
591 - *
592 - * @since 1.13 (J) - 1.3.0 (WP)
593 - */
594 - $arrtar = VikBooking::applySeasonalPrices($arrtar, $first, $second);
595 - $multi_rates = 1;
596 - foreach ($arrtar as $idr => $tars) {
597 - $multi_rates = count($tars) > $multi_rates ? count($tars) : $multi_rates;
598 - }
599 - if ($multi_rates > 1) {
600 - for ($r = 1; $r < $multi_rates; $r++) {
601 - $deeper_rates = array();
602 - foreach ($arrtar as $idr => $tars) {
603 - foreach ($tars as $tk => $tar) {
604 - if ($tk == $r) {
605 - $deeper_rates[$idr][0] = $tar;
606 - break;
607 - }
608 - }
609 - }
610 - if (!$deeper_rates) {
611 - continue;
612 - }
613 - $deeper_rates = VikBooking::applySeasonalPrices($deeper_rates, $first, $second);
614 - foreach ($deeper_rates as $idr => $dtars) {
615 - foreach ($dtars as $dtk => $dtar) {
616 - $arrtar[$idr][$r] = $dtar;
617 - }
618 - }
619 - }
620 - }
621 - $arrtar = VikBooking::sortResults($arrtar);
990 + $excessproc = false;
622 991 //
623 -
624 - // separate results per number of rooms with $results
625 - $tmparrtar = $arrtar;
626 - $results = array();
627 - $multiroomcount = array();
628 - foreach ($arrpeople as $numroom => $aduchild) {
629 - $arrtar = $tmparrtar;
630 - $diffusage = array();
631 - $aduchild['children'] = !array_key_exists('children', $aduchild) ? 0 : $aduchild['children'];
632 - $nowtotpeople = $aduchild['adults'] + $aduchild['children'];
633 - foreach ($arrtar as $kk => $tt) {
634 - $validchildren = true;
635 - if ($showchildren) {
636 - if (!($tt[0]['fromchild'] <= $aduchild['children'] && $tt[0]['tochild'] >= $aduchild['children']) && $aduchild['children'] > 0) {
637 - $validchildren = false;
638 - }
639 - }
640 - $validtotpeople = true;
641 - if ($nowtotpeople > $tt[0]['totpeople']) {
642 - $errmess = JText::sprintf('VBERRPEOPLEPERROOM', $nowtotpeople, $aduchild['adults'], $aduchild['children']);
643 - $validtotpeople = false;
644 - }
645 - if ($validchildren && $validtotpeople) {
646 - if ($tt[0]['toadult'] == $aduchild['adults']) {
647 - //clean the diffusage from best usage in case it exists from before
648 - foreach ($arrtar[$kk] as $kpr => $vpr) {
649 - if (array_key_exists('diffusage', $arrtar[$kk][$kpr])) {
650 - unset($arrtar[$kk][$kpr]['diffusage']);
651 - }
652 - if (array_key_exists('diffusagecost', $arrtar[$kk][$kpr])) {
653 - //restore original price
654 - $operator = substr($arrtar[$kk][$kpr]['diffusagecost'], 0, 1);
655 - $valpcent = substr($arrtar[$kk][$kpr]['diffusagecost'], -1);
656 - if ($operator == "+") {
657 - if ($valpcent == "%") {
658 - $diffvalue = substr($arrtar[$kk][$kpr]['diffusagecost'], 1, (strlen($arrtar[$kk][$kpr]['diffusagecost']) - 1));
659 - if (array_key_exists('diffusagecostpernight', $arrtar[$kk][$kpr]) && $arrtar[$kk][$kpr]['diffusagecostpernight'] > 0) {
660 - $arrtar[$kk][$kpr]['cost'] = $arrtar[$kk][$kpr]['diffusagecostpernight'];
661 - } else {
662 - $arrtar[$kk][$kpr]['cost'] = round(($vpr['cost'] * (100 - $diffvalue) / 100), 2);
663 - }
664 - } else {
665 - $diffvalue = substr($arrtar[$kk][$kpr]['diffusagecost'], 1);
666 - $arrtar[$kk][$kpr]['cost'] = $vpr['cost'] - $diffvalue;
667 - }
668 - } elseif ($operator == "-") {
669 - if ($valpcent == "%") {
670 - $diffvalue = substr($arrtar[$kk][$kpr]['diffusagecost'], 1, (strlen($arrtar[$kk][$kpr]['diffusagecost']) - 1));
671 - if (array_key_exists('diffusagecostpernight', $arrtar[$kk][$kpr]) && $arrtar[$kk][$kpr]['diffusagecostpernight'] > 0) {
672 - $arrtar[$kk][$kpr]['cost'] = $arrtar[$kk][$kpr]['diffusagecostpernight'];
673 - } else {
674 - $arrtar[$kk][$kpr]['cost'] = round(($vpr['cost'] * (100 + $diffvalue) / 100), 2);
675 - }
676 - } else {
677 - $diffvalue = substr($arrtar[$kk][$kpr]['diffusagecost'], 1);
678 - $arrtar[$kk][$kpr]['cost'] = $vpr['cost'] + $diffvalue;
679 - }
680 - }
681 - //
682 - unset($arrtar[$kk][$kpr]['diffusagecost']);
683 - unset($arrtar[$kk][$kpr]['diffusagecostpernight']);
684 - }
685 - }
686 - //
687 - //VikBooking 1.3 - Maximum Occupancy Charges/Discounts
688 - $diffusageprice = VikBooking::loadAdultsDiff($kk, $aduchild['adults']);
689 - //Occupancy Override
690 - if (array_key_exists('occupancy_ovr', $tt[0]) && array_key_exists($aduchild['adults'], $tt[0]['occupancy_ovr']) && strlen($tt[0]['occupancy_ovr'][$aduchild['adults']]['value'])) {
691 - $diffusageprice = $tt[0]['occupancy_ovr'][$aduchild['adults']];
692 - }
693 - //
694 - if (is_array($diffusageprice)) {
695 - //set a charge or discount to the price(s) for the different usage of the room
696 - foreach ($arrtar[$kk] as $kpr => $vpr) {
697 - $arrtar[$kk][$kpr]['diffusage'] = $aduchild['adults'];
698 - if ($diffusageprice['chdisc'] == 1) {
699 - //charge
700 - if ($diffusageprice['valpcent'] == 1) {
701 - //fixed value
702 - $arrtar[$kk][$kpr]['diffusagecostpernight'] = $diffusageprice['pernight'] == 1 ? 1 : 0;
703 - $aduseval = $diffusageprice['pernight'] == 1 ? $diffusageprice['value'] * $arrtar[$kk][$kpr]['days'] : $diffusageprice['value'];
704 - $arrtar[$kk][$kpr]['diffusagecost'] = "+".$aduseval;
705 - $arrtar[$kk][$kpr]['cost'] = $vpr['cost'] + $aduseval;
706 - } else {
707 - //percentage value
708 - $arrtar[$kk][$kpr]['diffusagecostpernight'] = $diffusageprice['pernight'] == 1 ? $vpr['cost'] : 0;
709 - $aduseval = $diffusageprice['pernight'] == 1 ? round(($vpr['cost'] * $diffusageprice['value'] / 100) * $arrtar[$kk][$kpr]['days'] + $vpr['cost'], 2) : round(($vpr['cost'] * (100 + $diffusageprice['value']) / 100), 2);
710 - $arrtar[$kk][$kpr]['diffusagecost'] = "+".$diffusageprice['value']."%";
711 - $arrtar[$kk][$kpr]['cost'] = $aduseval;
712 - }
713 - } else {
714 - //discount
715 - if ($diffusageprice['valpcent'] == 1) {
716 - //fixed value
717 - $arrtar[$kk][$kpr]['diffusagecostpernight'] = $diffusageprice['pernight'] == 1 ? 1 : 0;
718 - $aduseval = $diffusageprice['pernight'] == 1 ? $diffusageprice['value'] * $arrtar[$kk][$kpr]['days'] : $diffusageprice['value'];
719 - $arrtar[$kk][$kpr]['diffusagecost'] = "-".$aduseval;
720 - $arrtar[$kk][$kpr]['cost'] = $vpr['cost'] - $aduseval;
721 - } else {
722 - //percentage value
723 - $arrtar[$kk][$kpr]['diffusagecostpernight'] = $diffusageprice['pernight'] == 1 ? $vpr['cost'] : 0;
724 - $aduseval = $diffusageprice['pernight'] == 1 ? round($vpr['cost'] - ((($vpr['cost'] / $arrtar[$kk][$kpr]['days']) * $diffusageprice['value'] / 100) * $arrtar[$kk][$kpr]['days']), 2) : round(($vpr['cost'] * (100 - $diffusageprice['value']) / 100), 2);
725 - $arrtar[$kk][$kpr]['diffusagecost'] = "-".$diffusageprice['value']."%";
726 - $arrtar[$kk][$kpr]['cost'] = $aduseval;
727 - }
728 - }
729 - }
730 - }
731 - //VikBooking 1.3 - Maximum Occupancy Charges/Discounts
732 - //best usage
733 - $results[$numroom][] = $arrtar[$kk];
734 - if (!isset($multiroomcount[$arrtar[$kk][0]['idroom']])) {
735 - $multiroomcount[$arrtar[$kk][0]['idroom']] = array('count' => 0);
736 - }
737 - $multiroomcount[$arrtar[$kk][0]['idroom']]['count'] += 1;
738 - $multiroomcount[$arrtar[$kk][0]['idroom']]['unitsavail'] = (int)$arrtar[$kk][0]['unitsavail'];
739 - $multiroomcount[$arrtar[$kk][0]['idroom']]['diffusage_r'.$numroom] = 0;
740 - } elseif (($tt[0]['fromadult'] <= $aduchild['adults'] || $booking_suggestion) && $tt[0]['toadult'] > $aduchild['adults']) {
741 - //different usage
742 - $diffusageprice = VikBooking::loadAdultsDiff($kk, $aduchild['adults']);
743 - //Occupancy Override
744 - if (array_key_exists('occupancy_ovr', $tt[0]) && array_key_exists($aduchild['adults'], $tt[0]['occupancy_ovr']) && strlen($tt[0]['occupancy_ovr'][$aduchild['adults']]['value'])) {
745 - $diffusageprice = $tt[0]['occupancy_ovr'][$aduchild['adults']];
746 - }
747 - //
748 - if (is_array($diffusageprice)) {
749 - //set a charge or discount to the price(s) for the different usage of the room
750 - foreach ($arrtar[$kk] as $kpr => $vpr) {
751 - $arrtar[$kk][$kpr]['diffusage'] = $aduchild['adults'];
752 - if ($diffusageprice['chdisc'] == 1) {
753 - //charge
754 - if ($diffusageprice['valpcent'] == 1) {
755 - //fixed value
756 - $arrtar[$kk][$kpr]['diffusagecostpernight'] = $diffusageprice['pernight'] == 1 ? 1 : 0;
757 - $aduseval = $diffusageprice['pernight'] == 1 ? $diffusageprice['value'] * $arrtar[$kk][$kpr]['days'] : $diffusageprice['value'];
758 - $arrtar[$kk][$kpr]['diffusagecost'] = "+".$aduseval;
759 - $arrtar[$kk][$kpr]['cost'] = $vpr['cost'] + $aduseval;
760 - } else {
761 - //percentage value
762 - $arrtar[$kk][$kpr]['diffusagecostpernight'] = $diffusageprice['pernight'] == 1 ? $vpr['cost'] : 0;
763 - $aduseval = $diffusageprice['pernight'] == 1 ? round(($vpr['cost'] * $diffusageprice['value'] / 100) * $arrtar[$kk][$kpr]['days'] + $vpr['cost'], 2) : round(($vpr['cost'] * (100 + $diffusageprice['value']) / 100), 2);
764 - $arrtar[$kk][$kpr]['diffusagecost'] = "+".$diffusageprice['value']."%";
765 - $arrtar[$kk][$kpr]['cost'] = $aduseval;
766 - }
767 - } else {
768 - //discount
769 - if ($diffusageprice['valpcent'] == 1) {
770 - //fixed value
771 - $arrtar[$kk][$kpr]['diffusagecostpernight'] = $diffusageprice['pernight'] == 1 ? 1 : 0;
772 - $aduseval = $diffusageprice['pernight'] == 1 ? $diffusageprice['value'] * $arrtar[$kk][$kpr]['days'] : $diffusageprice['value'];
773 - $arrtar[$kk][$kpr]['diffusagecost'] = "-".$aduseval;
774 - $arrtar[$kk][$kpr]['cost'] = $vpr['cost'] - $aduseval;
775 - } else {
776 - //percentage value
777 - $arrtar[$kk][$kpr]['diffusagecostpernight'] = $diffusageprice['pernight'] == 1 ? $vpr['cost'] : 0;
778 - $aduseval = $diffusageprice['pernight'] == 1 ? round($vpr['cost'] - ((($vpr['cost'] / $arrtar[$kk][$kpr]['days']) * $diffusageprice['value'] / 100) * $arrtar[$kk][$kpr]['days']), 2) : round(($vpr['cost'] * (100 - $diffusageprice['value']) / 100), 2);
779 - $arrtar[$kk][$kpr]['diffusagecost'] = "-".$diffusageprice['value']."%";
780 - $arrtar[$kk][$kpr]['cost'] = $aduseval;
781 - }
782 - }
783 - }
784 - } else {
785 - $arrtar[$kk][0]['diffusage'] = $aduchild['adults'];
786 - }
787 - $diffusage[$numroom][] = $arrtar[$kk];
788 - if (!isset($multiroomcount[$arrtar[$kk][0]['idroom']])) {
789 - $multiroomcount[$arrtar[$kk][0]['idroom']] = array('count' => 0);
790 - }
791 - $multiroomcount[$arrtar[$kk][0]['idroom']]['count'] += 1;
792 - $multiroomcount[$arrtar[$kk][0]['idroom']]['unitsavail'] = (int)$arrtar[$kk][0]['unitsavail'];
793 - $multiroomcount[$arrtar[$kk][0]['idroom']]['diffusage_r'.$numroom] = 1;
794 - }
795 - }
796 - }
797 - //merge $diffusage rooms with and after best usage rooms in $results
798 - if (count($diffusage) > 0) {
799 - foreach ($diffusage as $nr => $du) {
800 - foreach ($du as $duroom) {
801 - $results[$nr][]=$duroom;
802 - }
803 - }
804 - }
805 - //
806 - }
807 - //
808 - //check if rooms repeated passed the availability
809 - $limitpassed = false;
810 - $search_type = VikBooking::getSmartSearchType();
811 - $js_search = $search_type == 'dynamic' ? true : false;
812 - //dynamic smart search via PHP
813 - $js_overcounter = array();
814 - if ($js_search && $proomsnum > 1 && count($multiroomcount) > 0) {
815 - $tot_avail = 0;
816 - foreach ($multiroomcount as $idroom => $info) {
817 - $tot_avail += $info['unitsavail'];
818 - }
819 - if ($tot_avail >= $proomsnum) {
820 - $gen_avail = $results;
821 - foreach ($multiroomcount as $idroom => $info) {
822 - $multiroomcount[$idroom]['used'] = 0;
823 - if ($info['count'] > $info['unitsavail']) {
824 - $excessnum = $info['count'] - $info['unitsavail'];
825 - if ($excessnum > 0) {
826 - for ($z = $proomsnum; $z >= 1; $z--) {
827 - if ($excessnum > 0) {
828 - /**
829 - * VBO 1.10 Patch May 2018
830 - * @see comments below
831 - */
832 - $excessproc = false;
833 - //
834 - foreach ($results[$z] as $kres => $res) {
835 - if ($res[0]['idroom'] == $idroom) {
836 - /**
837 - * We do not need to unset the rooms as we risk to produce no results.
838 - * We skip this control if the "search type" setting is set to "dynamic".
839 - *
840 - * @since 1.12 Patch October 2nd 2019
841 - */
842 - if (!$js_search) {
843 - unset($gen_avail[$z][$kres]);
844 - }
845 - $excessproc = true;
846 - }
847 - }
848 - if ($excessproc) {
849 - /**
850 - * VBO 1.10 Patch May 2018
851 - * @see comments below
852 - */
853 - $excessnum--;
854 - }
855 - }
856 - }
857 - }
858 - }
859 - }
992 + foreach ($results[$z] as $kres => $res) {
993 + if ($res[0]['idroom'] == $idroom) {
860 994 /**
861 995 * We do not need to unset the rooms as we risk to produce no results.
862 996 * We skip this control if the "search type" setting is set to "dynamic".
863 997 *
864 - * @since 1.12 Patch October 2nd 2019
998 + * @since 1.12
865 999 */
866 1000 if (!$js_search) {
867 - for ($z = $proomsnum; $z >= 1; $z--) {
868 - if (!isset($gen_avail[$z]) || !count($gen_avail[$z])) {
869 - foreach ($gen_avail as $oknroom => $res) {
870 - if (count($gen_avail[$oknroom]) > 1) {
871 - $searchfrom = min(array_keys($res));
872 - foreach ($res as $kr => $rr) {
873 - if (intval($kr) > intval($searchfrom)) {
874 - //check if the second, third.. cheapest room(s) is compatible
875 - if ($rr[0]['fromadult'] <= $arrpeople[$z]['adults'] && $rr[0]['toadult'] >= $arrpeople[$z]['adults'] && $rr[0]['fromchild'] <= $arrpeople[$z]['children'] && $rr[0]['tochild'] >= $arrpeople[$z]['children']) {
876 - $gen_avail[$z][] = $gen_avail[$oknroom][$kr];
877 - unset($gen_avail[$oknroom][$kr]);
878 - break 2;
879 - }
880 - }
881 - }
882 - }
883 - }
884 - }
885 - }
1001 + unset($gen_avail[$z][$kres]);
886 1002 }
887 - /**
888 - * VBO 1.10 Patch May 2018
889 - *
890 - * Scenario: One room with 3 units in total, 2 units booked and 1 free on certain dates, for 6 adults.
891 - * Another room with 5 units available on these dates, for 2 adults. Dynamic search enabled.
892 - *
893 - * Reservation: 3 room types, 6 adults 1st room, 6 adults 2nd room, 2 adults 3rd room.
894 - *
895 - * Results: the 6-adult room is displayed for the 1st and 2nd rooms requested, the 2-adult room for the 3rd.
896 - * With the Dynamic search enabled, by selecting the 6-adult room once, it gets removed from the other combo.
897 - * This leaves one room-party empty, with no results, but no errors are displayed for the search suggestions,
898 - * the search results page just gets stuck in there because for a party there are no rooms that can be chosen.
899 - *
900 - * Solution: if one room-party has no more rooms, unset it so that $js_overcounter won't be set, and the
901 - * "automatic smart search via PHP" statement will be processed below. This will raise the error "not enough rooms",
902 - * and the Search Suggestions will correctly calculate the availability.
903 - *
904 - */
905 - foreach ($gen_avail as $oknroom => $res) {
906 - if (!count($gen_avail[$oknroom])) {
907 - unset($gen_avail[$oknroom]);
908 - }
909 - }
910 - //
911 - if (count($gen_avail) == $proomsnum) {
912 - $js_overcounter = $multiroomcount;
913 - unset($gen_avail);
914 - }
1003 + $excessproc = true;
915 1004 }
916 1005 }
917 - //
918 - //automatic smart search via PHP
919 - if ($proomsnum > 1 && count($multiroomcount) > 0) {
920 - foreach ($multiroomcount as $idroom => $info) {
921 - if ($info['count'] > $info['unitsavail']) {
922 - $excessnum = $info['count'] - $info['unitsavail'];
923 - for ($z = $proomsnum; $z >= 1; $z--) {
924 - /**
925 - * VBO 1.10 Patch June 2018
926 - * the different usage clause below should be ignored, or we risk to keep a room in excess
927 - * for some room parties when there should be actually no availability for booking multiple times.
928 - * This room in excess may be removed only for the parties with different usage, and this is incorrect.
929 - */
930 - if (true || (array_key_exists('diffusage_r'.$z, $info) && $info['diffusage_r'.$z] == 1)) {
931 - //remove repeated room where diffusage and excessnum still exceeds
932 - if ($excessnum > 0 && count($js_overcounter) == 0) {
933 - foreach ($results[$z] as $kres => $res) {
934 - if ($res[0]['idroom'] == $idroom) {
935 - unset($results[$z][$kres]);
936 - $limitpassed = true;
937 - }
938 - }
939 - if ($limitpassed) {
940 - $excessnum--;
941 - }
942 - }
943 - //
944 - }
945 - }
946 - //if excessnum still exceeds, means that the room is not available for the repeated best usages
947 - if ($excessnum > 0) {
948 - for ($z = $proomsnum; $z >= 1; $z--) {
949 - if ($excessnum > 0 && count($js_overcounter) == 0) {
950 - foreach ($results[$z] as $kres => $res) {
951 - if ($res[0]['idroom'] == $idroom) {
952 - unset($results[$z][$kres]);
953 - $limitpassed = true;
954 - }
955 - }
956 - if ($limitpassed) {
957 - $excessnum--;
958 - }
959 - }
960 - }
961 - }
962 - //
1006 + if ($excessproc) {
1007 + /**
1008 + * @see comments below
1009 + */
1010 + $excessnum--;
1011 + }
1012 + }
1013 + }
1014 + }
1015 + }
1016 + }
1017 + /**
1018 + * We do not need to unset the rooms as we risk to produce no results.
1019 + * We skip this control if the "search type" setting is set to "dynamic".
1020 + *
1021 + * @since 1.12 Patch October 2nd 2019
1022 + */
1023 + if (!$js_search) {
1024 + for ($z = $proomsnum; $z >= 1; $z--) {
1025 + if (!isset($gen_avail[$z]) || !$gen_avail[$z]) {
1026 + foreach ($gen_avail as $oknroom => $res) {
1027 + if (count($gen_avail[$oknroom]) > 1) {
1028 + $searchfrom = min(array_keys($res));
1029 + foreach ($res as $kr => $rr) {
1030 + if (intval($kr) > intval($searchfrom)) {
1031 + //check if the second, third.. cheapest room(s) is compatible
1032 + if ($rr[0]['fromadult'] <= $arrpeople[$z]['adults'] && $rr[0]['toadult'] >= $arrpeople[$z]['adults'] && $rr[0]['fromchild'] <= $arrpeople[$z]['children'] && $rr[0]['tochild'] >= $arrpeople[$z]['children']) {
1033 + $gen_avail[$z][] = $gen_avail[$oknroom][$kr];
1034 + unset($gen_avail[$oknroom][$kr]);
1035 + break 2;
963 1036 }
964 1037 }
965 1038 }
966 - //
967 - //if some room was repeated and removed from the multi rooms searched, check if enough results for each room
968 - if ($limitpassed == true) {
969 - $critic = array();
970 - for ($z = $proomsnum; $z >= 1; $z--) {
971 - if (!isset($results[$z]) || !count($results[$z])) {
972 - $critic[] = $z;
973 - unset($results[$z]);
1039 + }
1040 + }
1041 + }
1042 + }
1043 + }
1044 + /**
1045 + * VBO 1.10 May 2018
1046 + *
1047 + * Scenario: One room with 3 units in total, 2 units booked and 1 free on certain dates, for 6 adults.
1048 + * Another room with 5 units available on these dates, for 2 adults. Dynamic search enabled.
1049 + *
1050 + * Reservation: 3 room types, 6 adults 1st room, 6 adults 2nd room, 2 adults 3rd room.
1051 + *
1052 + * Results: the 6-adult room is displayed for the 1st and 2nd rooms requested, the 2-adult room for the 3rd.
1053 + * With the Dynamic search enabled, by selecting the 6-adult room once, it gets removed from the other combo.
1054 + * This leaves one room-party empty, with no results, but no errors are displayed for the search suggestions,
1055 + * the search results page just gets stuck in there because for a party there are no rooms that can be chosen.
1056 + *
1057 + * Solution: if one room-party has no more rooms, unset it so that $js_overcounter won't be set, and the
1058 + * "automatic smart search via PHP" statement will be processed below. This will raise the error "not enough rooms",
1059 + * and the Search Suggestions will correctly calculate the availability.
1060 + *
1061 + */
1062 + foreach ($gen_avail as $oknroom => $res) {
1063 + if (!$gen_avail[$oknroom]) {
1064 + unset($gen_avail[$oknroom]);
1065 + }
1066 + }
1067 + //
1068 + if (count($gen_avail) == $proomsnum) {
1069 + $js_overcounter = $multiroomcount;
1070 + unset($gen_avail);
1071 + }
1072 + }
1073 + }
1074 +
1075 + // automatic smart search via PHP
1076 + if ($proomsnum > 1 && $multiroomcount) {
1077 + foreach ($multiroomcount as $idroom => $info) {
1078 + if ($info['count'] > $info['unitsavail']) {
1079 + $excessnum = $info['count'] - $info['unitsavail'];
1080 + for ($z = $proomsnum; $z >= 1; $z--) {
1081 + /**
1082 + * VBO 1.10 June 2018
1083 + * the different usage clause below should be ignored, or we risk to keep a room in excess
1084 + * for some room parties when there should be actually no availability for booking multiple times.
1085 + * This room in excess may be removed only for the parties with different usage, and this is incorrect.
1086 + */
1087 + if (true || (array_key_exists('diffusage_r'.$z, $info) && $info['diffusage_r'.$z] == 1)) {
1088 + // remove repeated room where diffusage and excessnum still exceeds
1089 + if ($excessnum > 0 && !$js_overcounter) {
1090 + foreach ($results[$z] as $kres => $res) {
1091 + if ($res[0]['idroom'] == $idroom) {
1092 + unset($results[$z][$kres]);
1093 + $limitpassed = true;
1094 + }
1095 + }
1096 + if ($limitpassed) {
1097 + $excessnum--;
1098 + }
1099 + }
1100 + }
1101 + }
1102 + // if excessnum still exceeds, means that the room is not available for the repeated best usages
1103 + if ($excessnum > 0) {
1104 + for ($z = $proomsnum; $z >= 1; $z--) {
1105 + if ($excessnum > 0 && !$js_overcounter) {
1106 + foreach ($results[$z] as $kres => $res) {
1107 + if ($res[0]['idroom'] == $idroom) {
1108 + unset($results[$z][$kres]);
1109 + $limitpassed = true;
1110 + }
1111 + }
1112 + if ($limitpassed) {
1113 + $excessnum--;
1114 + }
1115 + }
1116 + }
1117 + }
1118 + //
1119 + }
1120 + }
1121 + }
1122 + //
1123 + //if some room was repeated and removed from the multi rooms searched, check if enough results for each room
1124 + if ($limitpassed == true) {
1125 + $critic = [];
1126 + for ($z = $proomsnum; $z >= 1; $z--) {
1127 + if (!isset($results[$z]) || !$results[$z]) {
1128 + $critic[] = $z;
1129 + unset($results[$z]);
1130 + }
1131 + }
1132 + if ($critic) {
1133 + //some rooms have 0 results, check if something good for this num of adults can be placed here
1134 + $moved = [];
1135 + foreach ($critic as $kcr => $nroom) {
1136 + foreach ($results as $oknroom => $res) {
1137 + if (count($results[$oknroom]) > 1) {
1138 + $searchfrom = min(array_keys($res));
1139 + foreach ($res as $kr => $rr) {
1140 + if (intval($kr) > intval($searchfrom)) {
1141 + //check if the second, third.. cheapest room(s) is compatible
1142 + if ($rr[0]['fromadult'] <= $arrpeople[$nroom]['adults'] && $rr[0]['toadult'] >= $arrpeople[$nroom]['adults'] && $rr[0]['fromchild'] <= $arrpeople[$nroom]['children'] && $rr[0]['tochild'] >= $arrpeople[$nroom]['children']) {
1143 + $results[$nroom][] = $results[$oknroom][$kr];
1144 + $moved[] = $oknroom.'_'.$nroom;
1145 + unset($results[$oknroom][$kr]);
1146 + unset($critic[$kcr]);
1147 + break 2;
1148 + }
1149 + }
1150 + }
1151 + }
1152 + }
1153 + }
1154 + ksort($results);
1155 + if ($moved) {
1156 + //check if moved rooms had charges/discounts for adults occupancy to update it
1157 + foreach ($moved as $move) {
1158 + $movedata = explode('_', $move);
1159 + if ($arrpeople[$movedata[0]]['adults'] != $arrpeople[$movedata[1]]['adults'] && array_key_exists('diffusagecost', $results[$movedata[1]][0][0])) {
1160 + //reset prices of the room
1161 + foreach ($results[$movedata[1]][0] as $kpr => $vpr) {
1162 + if (array_key_exists('diffusage', $results[$movedata[1]][0][$kpr])) {
1163 + unset($results[$movedata[1]][0][$kpr]['diffusage']);
1164 + }
1165 + if (array_key_exists('diffusagecost', $results[$movedata[1]][0][$kpr])) {
1166 + //restore original price
1167 + $operator = substr($results[$movedata[1]][0][$kpr]['diffusagecost'], 0, 1);
1168 + $valpcent = substr($results[$movedata[1]][0][$kpr]['diffusagecost'], -1);
1169 + if ($operator == "+") {
1170 + if ($valpcent == "%") {
1171 + $diffvalue = substr($results[$movedata[1]][0][$kpr]['diffusagecost'], 1, (strlen($results[$movedata[1]][0][$kpr]['diffusagecost']) - 1));
1172 + if (array_key_exists('diffusagecostpernight', $results[$movedata[1]][0][$kpr]) && $results[$movedata[1]][0][$kpr]['diffusagecostpernight'] > 0) {
1173 + $results[$movedata[1]][0][$kpr]['cost'] = $results[$movedata[1]][0][$kpr]['diffusagecostpernight'];
1174 + } else {
1175 + $results[$movedata[1]][0][$kpr]['cost'] = round(($vpr['cost'] * (100 - $diffvalue) / 100), 2);
974 1176 }
1177 + } else {
1178 + $diffvalue = substr($results[$movedata[1]][0][$kpr]['diffusagecost'], 1);
1179 + $results[$movedata[1]][0][$kpr]['cost'] = $vpr['cost'] - $diffvalue;
975 1180 }
976 - if (count($critic) > 0) {
977 - //some rooms have 0 results, check if something good for this num of adults can be placed here
978 - $moved = array();
979 - foreach ($critic as $kcr => $nroom) {
980 - foreach ($results as $oknroom => $res) {
981 - if (count($results[$oknroom]) > 1) {
982 - $searchfrom = min(array_keys($res));
983 - foreach ($res as $kr => $rr) {
984 - if (intval($kr) > intval($searchfrom)) {
985 - //check if the second, third.. cheapest room(s) is compatible
986 - if ($rr[0]['fromadult'] <= $arrpeople[$nroom]['adults'] && $rr[0]['toadult'] >= $arrpeople[$nroom]['adults'] && $rr[0]['fromchild'] <= $arrpeople[$nroom]['children'] && $rr[0]['tochild'] >= $arrpeople[$nroom]['children']) {
987 - $results[$nroom][] = $results[$oknroom][$kr];
988 - $moved[] = $oknroom.'_'.$nroom;
989 - unset($results[$oknroom][$kr]);
990 - unset($critic[$kcr]);
991 - break 2;
992 - }
993 - }
994 - }
995 - }
996 - }
1181 + } elseif ($operator == "-") {
1182 + if ($valpcent == "%") {
1183 + $diffvalue = substr($results[$movedata[1]][0][$kpr]['diffusagecost'], 1, (strlen($results[$movedata[1]][0][$kpr]['diffusagecost']) - 1));
1184 + if (array_key_exists('diffusagecostpernight', $results[$movedata[1]][0][$kpr]) && $results[$movedata[1]][0][$kpr]['diffusagecostpernight'] > 0) {
1185 + $results[$movedata[1]][0][$kpr]['cost'] = $results[$movedata[1]][0][$kpr]['diffusagecostpernight'];
1186 + } else {
1187 + $results[$movedata[1]][0][$kpr]['cost'] = round(($vpr['cost'] * (100 + $diffvalue) / 100), 2);
997 1188 }
998 - ksort($results);
999 - if (count($moved) > 0) {
1000 - //check if moved rooms had charges/discounts for adults occupancy to update it
1001 - foreach ($moved as $move) {
1002 - $movedata = explode('_', $move);
1003 - if ($arrpeople[$movedata[0]]['adults'] != $arrpeople[$movedata[1]]['adults'] && array_key_exists('diffusagecost', $results[$movedata[1]][0][0])) {
1004 - //reset prices of the room
1005 - foreach ($results[$movedata[1]][0] as $kpr => $vpr) {
1006 - if (array_key_exists('diffusage', $results[$movedata[1]][0][$kpr])) {
1007 - unset($results[$movedata[1]][0][$kpr]['diffusage']);
1008 - }
1009 - if (array_key_exists('diffusagecost', $results[$movedata[1]][0][$kpr])) {
1010 - //restore original price
1011 - $operator = substr($results[$movedata[1]][0][$kpr]['diffusagecost'], 0, 1);
1012 - $valpcent = substr($results[$movedata[1]][0][$kpr]['diffusagecost'], -1);
1013 - if ($operator == "+") {
1014 - if ($valpcent == "%") {
1015 - $diffvalue = substr($results[$movedata[1]][0][$kpr]['diffusagecost'], 1, (strlen($results[$movedata[1]][0][$kpr]['diffusagecost']) - 1));
1016 - if (array_key_exists('diffusagecostpernight', $results[$movedata[1]][0][$kpr]) && $results[$movedata[1]][0][$kpr]['diffusagecostpernight'] > 0) {
1017 - $results[$movedata[1]][0][$kpr]['cost'] = $results[$movedata[1]][0][$kpr]['diffusagecostpernight'];
1018 - } else {
1019 - $results[$movedata[1]][0][$kpr]['cost'] = round(($vpr['cost'] * (100 - $diffvalue) / 100), 2);
1020 - }
1021 - } else {
1022 - $diffvalue = substr($results[$movedata[1]][0][$kpr]['diffusagecost'], 1);
1023 - $results[$movedata[1]][0][$kpr]['cost'] = $vpr['cost'] - $diffvalue;
1024 - }
1025 - } elseif ($operator == "-") {
1026 - if ($valpcent == "%") {
1027 - $diffvalue = substr($results[$movedata[1]][0][$kpr]['diffusagecost'], 1, (strlen($results[$movedata[1]][0][$kpr]['diffusagecost']) - 1));
1028 - if (array_key_exists('diffusagecostpernight', $results[$movedata[1]][0][$kpr]) && $results[$movedata[1]][0][$kpr]['diffusagecostpernight'] > 0) {
1029 - $results[$movedata[1]][0][$kpr]['cost'] = $results[$movedata[1]][0][$kpr]['diffusagecostpernight'];
1030 - } else {
1031 - $results[$movedata[1]][0][$kpr]['cost'] = round(($vpr['cost'] * (100 + $diffvalue) / 100), 2);
1032 - }
1033 - } else {
1034 - $diffvalue = substr($results[$movedata[1]][0][$kpr]['diffusagecost'], 1);
1035 - $results[$movedata[1]][0][$kpr]['cost'] = $vpr['cost'] + $diffvalue;
1036 - }
1037 - }
1038 - //
1039 - unset($results[$movedata[1]][0][$kpr]['diffusagecost']);
1040 - unset($results[$movedata[1]][0][$kpr]['diffusagecostpernight']);
1041 - }
1042 - }
1043 - //end reset prices of the room
1044 - $diffusageprice = VikBooking::loadAdultsDiff($results[$movedata[1]][0][0]['idroom'], $arrpeople[$movedata[1]]['adults']);
1045 - //Occupancy Override - Special Price may be setting a charge/discount for this occupancy while default price had no occupancy pricing
1046 - if (!is_array($diffusageprice)) {
1047 - foreach ($results[$movedata[1]][0] as $kpr => $vpr) {
1048 - if (array_key_exists('occupancy_ovr', $vpr) && array_key_exists($arrpeople[$movedata[1]]['adults'], $vpr['occupancy_ovr']) && strlen($vpr['occupancy_ovr'][$arrpeople[$movedata[1]]['adults']]['value'])) {
1049 - $diffusageprice = $vpr['occupancy_ovr'][$arrpeople[$movedata[1]]['adults']];
1050 - break;
1051 - }
1052 - }
1053 - reset($results[$movedata[1]][0]);
1054 - }
1055 - //
1056 - if (is_array($diffusageprice)) {
1057 - //set a charge or discount to the price(s) for the different usage of the room
1058 - foreach ($results[$movedata[1]][0] as $kpr => $vpr) {
1059 - //Occupancy Override
1060 - if (array_key_exists('occupancy_ovr', $results[$movedata[1]][0][$kpr]) && array_key_exists($arrpeople[$movedata[1]]['adults'], $results[$movedata[1]][0][$kpr]['occupancy_ovr']) && strlen($results[$movedata[1]][0][$kpr]['occupancy_ovr'][$arrpeople[$movedata[1]]['adults']]['value'])) {
1061 - $diffusageprice = $results[$movedata[1]][0][$kpr]['occupancy_ovr'][$arrpeople[$movedata[1]]['adults']];
1062 - }
1063 - //
1064 - $results[$movedata[1]][0][$kpr]['diffusage'] = $arrpeople[$movedata[1]]['adults'];
1065 - if ($diffusageprice['chdisc'] == 1) {
1066 - //charge
1067 - if ($diffusageprice['valpcent'] == 1) {
1068 - //fixed value
1069 - $results[$movedata[1]][0][$kpr]['diffusagecostpernight'] = $diffusageprice['pernight'] == 1 ? 1 : 0;
1070 - $aduseval = $diffusageprice['pernight'] == 1 ? $diffusageprice['value'] * $results[$movedata[1]][0][$kpr]['days'] : $diffusageprice['value'];
1071 - $results[$movedata[1]][0][$kpr]['diffusagecost'] = "+".$aduseval;
1072 - $results[$movedata[1]][0][$kpr]['cost'] = $vpr['cost'] + $aduseval;
1073 - } else {
1074 - //percentage value
1075 - $results[$movedata[1]][0][$kpr]['diffusagecostpernight'] = $diffusageprice['pernight'] == 1 ? $vpr['cost'] : 0;
1076 - $aduseval = $diffusageprice['pernight'] == 1 ? round(($vpr['cost'] * $diffusageprice['value'] / 100) * $results[$movedata[1]][0][$kpr]['days'] + $vpr['cost'], 2) : round(($vpr['cost'] * (100 + $diffusageprice['value']) / 100), 2);
1077 - $results[$movedata[1]][0][$kpr]['diffusagecost'] = "+".$diffusageprice['value']."%";
1078 - $results[$movedata[1]][0][$kpr]['cost'] = $aduseval;
1079 - }
1080 - } else {
1081 - //discount
1082 - if ($diffusageprice['valpcent'] == 1) {
1083 - //fixed value
1084 - $results[$movedata[1]][0][$kpr]['diffusagecostpernight'] = $diffusageprice['pernight'] == 1 ? 1 : 0;
1085 - $aduseval = $diffusageprice['pernight'] == 1 ? $diffusageprice['value'] * $results[$movedata[1]][0][$kpr]['days'] : $diffusageprice['value'];
1086 - $results[$movedata[1]][0][$kpr]['diffusagecost'] = "-".$aduseval;
1087 - $results[$movedata[1]][0][$kpr]['cost'] = $vpr['cost'] - $aduseval;
1088 - } else {
1089 - //percentage value
1090 - $results[$movedata[1]][0][$kpr]['diffusagecostpernight'] = $diffusageprice['pernight'] == 1 ? $vpr['cost'] : 0;
1091 - $aduseval = $diffusageprice['pernight'] == 1 ? round($vpr['cost'] - ((($vpr['cost'] / $results[$movedata[1]][0][$kpr]['days']) * $diffusageprice['value'] / 100) * $results[$movedata[1]][0][$kpr]['days']), 2) : round(($vpr['cost'] * (100 - $diffusageprice['value']) / 100), 2);
1092 - $results[$movedata[1]][0][$kpr]['diffusagecost'] = "-".$diffusageprice['value']."%";
1093 - $results[$movedata[1]][0][$kpr]['cost'] = $aduseval;
1094 - }
1095 - }
1096 - }
1097 - }
1098 - }
1099 - }
1100 - //end check if moved rooms had charges/discounts for adults occupancy to update it
1101 - }
1102 - //
1189 + } else {
1190 + $diffvalue = substr($results[$movedata[1]][0][$kpr]['diffusagecost'], 1);
1191 + $results[$movedata[1]][0][$kpr]['cost'] = $vpr['cost'] + $diffvalue;
1103 1192 }
1104 1193 }
1105 1194 //
1106 - $results = VikBooking::sortMultipleResults($results);
1107 - //save prices in session for the modules
1108 - $sessvals = array();
1109 - $modprices = array();
1110 - $sessvals['roomsnum'] = $proomsnum;
1111 - $sessvals['checkin'] = $first;
1112 - $sessvals['checkout'] = $second;
1113 - for ($i = 1; $i <= $proomsnum; $i++) {
1114 - if (!isset($results[$i])) {
1115 - continue;
1116 - }
1117 - foreach ($results[$i] as $indres => $res) {
1118 - $modprices[$i][] = $res[0]['cost'];
1119 - }
1195 + unset($results[$movedata[1]][0][$kpr]['diffusagecost']);
1196 + unset($results[$movedata[1]][0][$kpr]['diffusagecostpernight']);
1197 + }
1198 + }
1199 + //end reset prices of the room
1200 + $diffusageprice = VikBooking::loadAdultsDiff($results[$movedata[1]][0][0]['idroom'], $arrpeople[$movedata[1]]['adults']);
1201 + //Occupancy Override - Special Price may be setting a charge/discount for this occupancy while default price had no occupancy pricing
1202 + if (!is_array($diffusageprice)) {
1203 + foreach ($results[$movedata[1]][0] as $kpr => $vpr) {
1204 + if (array_key_exists('occupancy_ovr', $vpr) && array_key_exists($arrpeople[$movedata[1]]['adults'], $vpr['occupancy_ovr']) && strlen($vpr['occupancy_ovr'][$arrpeople[$movedata[1]]['adults']]['value'])) {
1205 + $diffusageprice = $vpr['occupancy_ovr'][$arrpeople[$movedata[1]]['adults']];
1206 + break;
1120 1207 }
1121 - for ($i = 1; $i <= $proomsnum; $i++) {
1122 - if (!isset($modprices[$i])) {
1123 - continue;
1124 - }
1125 - $mincost = min($modprices[$i]);
1126 - $maxcost = max($modprices[$i]);
1127 - $sessvals[$i]['min'] = $mincost;
1128 - $sessvals[$i]['max'] = $maxcost;
1129 - $sessvals[$i]['adults'] = $arrpeople[$i]['adults'];
1130 - $sessvals[$i]['children'] = $arrpeople[$i]['children'];
1208 + }
1209 + reset($results[$movedata[1]][0]);
1210 + }
1211 + //
1212 + if (is_array($diffusageprice)) {
1213 + //set a charge or discount to the price(s) for the different usage of the room
1214 + foreach ($results[$movedata[1]][0] as $kpr => $vpr) {
1215 + //Occupancy Override
1216 + if (array_key_exists('occupancy_ovr', $results[$movedata[1]][0][$kpr]) && array_key_exists($arrpeople[$movedata[1]]['adults'], $results[$movedata[1]][0][$kpr]['occupancy_ovr']) && strlen($results[$movedata[1]][0][$kpr]['occupancy_ovr'][$arrpeople[$movedata[1]]['adults']]['value'])) {
1217 + $diffusageprice = $results[$movedata[1]][0][$kpr]['occupancy_ovr'][$arrpeople[$movedata[1]]['adults']];
1131 1218 }
1132 - $session->set('vbsearchdata', $sessvals);
1133 - //end save prices in session for the modules
1134 - //apply price filters
1135 - $ppricefrom = VikRequest::getInt('r1pricefrom', '', 'request');
1136 - $ppriceto = VikRequest::getInt('r1priceto', '', 'request');
1137 - if (!empty($ppricefrom) && !empty($ppriceto)) {
1138 - foreach ($results as $oknroom => $res) {
1139 - $totroomres = count($res);
1140 - foreach ($res as $kr => $rr) {
1141 - if ($oknroom > 1) {
1142 - $ppricefrom = VikRequest::getInt('r'.$oknroom.'pricefrom', '', 'request');
1143 - $ppriceto = VikRequest::getInt('r'.$oknroom.'priceto', '', 'request');
1144 - }
1145 - if (!empty($ppricefrom) && !empty($ppriceto)) {
1146 - if ($rr[0]['cost'] < $ppricefrom || $rr[0]['cost'] > $ppriceto) {
1147 - if ($totroomres > 1) {
1148 - unset($results[$oknroom][$kr]);
1149 - $totroomres--;
1150 - }
1151 - }
1152 - }
1153 - }
1154 - }
1155 - }
1156 - //end apply price filters
1157 - if (count($results) == $proomsnum) {
1158 - // check whether the user is coming from roomdetails
1159 - $proomdetail = VikRequest::getInt('roomdetail', 0, 'request');
1160 - $rate_plan_id = VikRequest::getInt('rate_plan_id', 0, 'request');
1161 - $user_currency = VikRequest::getString('user_currency', '', 'request');
1162 - $children_age = VikRequest::getVar('children_age', array());
1163 - $pitemid = VikRequest::getInt('Itemid', 0, 'request');
1164 - if (!empty($proomdetail) && array_key_exists($proomdetail, $arrtar) && $proomsnum == 1) {
1165 - // VBO 1.11 - push data to tracker and close
1166 - VikBooking::getTracker()->pushRooms($proomdetail)->closeTrack();
1167 - // store in the session that we are coming from the room details page
1168 - $session->set('vboSearchRoomId', $proomdetail);
1169 -
1170 - /**
1171 - * Build redirect URI to the "showprc" View to continue the booking process, and
1172 - * keep some special vars that may serve to reflect the original booking link.
1173 - *
1174 - * @since 1.15.0 (J) - 1.5.0 (WP)
1175 - */
1176 - $url_query_args = [
1177 - 'option' => 'com_vikbooking',
1178 - 'task' => 'showprc',
1179 - 'roomsnum' => '1',
1180 - 'roomopt' => [
1181 - $proomdetail,
1182 - ],
1183 - 'adults' => [
1184 - $arrpeople[1]['adults'],
1185 - ],
1186 - 'children' => [
1187 - $arrpeople[1]['children'],
1188 - ],
1189 - 'days' => $daysdiff,
1190 - 'checkin' => $first,
1191 - 'checkout' => $second,
1192 - ];
1193 - if (!empty($ppkg_id)) {
1194 - $url_query_args['pkg_id'] = $ppkg_id;
1195 - }
1196 - if (!empty($rate_plan_id)) {
1197 - $url_query_args['rate_plan_id'] = $rate_plan_id;
1198 - }
1199 - if (is_array($children_age) && count($children_age)) {
1200 - $url_query_args['children_age'] = $children_age;
1201 - }
1202 - if (!empty($user_currency)) {
1203 - $url_query_args['user_currency'] = $user_currency;
1204 - }
1205 - if (!empty($pcategory_ids)) {
1206 - $url_query_args['category_ids'] = $pcategory_ids;
1207 - }
1208 - if (!empty($pitemid)) {
1209 - $url_query_args['Itemid'] = $pitemid;
1210 - }
1211 -
1212 - $mainframe->redirect(JRoute::rewrite('index.php?' . http_build_query($url_query_args), false));
1213 - exit;
1219 + //
1220 + $results[$movedata[1]][0][$kpr]['diffusage'] = $arrpeople[$movedata[1]]['adults'];
1221 + if ($diffusageprice['chdisc'] == 1) {
1222 + //charge
1223 + if ($diffusageprice['valpcent'] == 1) {
1224 + //fixed value
1225 + $results[$movedata[1]][0][$kpr]['diffusagecostpernight'] = $diffusageprice['pernight'] == 1 ? 1 : 0;
1226 + $aduseval = $diffusageprice['pernight'] == 1 ? $diffusageprice['value'] * $results[$movedata[1]][0][$kpr]['days'] : $diffusageprice['value'];
1227 + $results[$movedata[1]][0][$kpr]['diffusagecost'] = "+".$aduseval;
1228 + $results[$movedata[1]][0][$kpr]['cost'] = $vpr['cost'] + $aduseval;
1214 1229 } else {
1215 - if (!empty($proomdetail) && $proomsnum == 1) {
1216 - $q = "SELECT `id`,`name` FROM `#__vikbooking_rooms` WHERE `id`=".intval($proomdetail).";";
1217 - $dbo->setQuery($q);
1218 - $cdet = $dbo->loadAssocList();
1219 - if ($cdet) {
1220 - $vbo_tn->translateContents($cdet, '#__vikbooking_rooms');
1221 - $msg = JText::sprintf('VBDETAILCNOTAVAIL', $cdet[0]['name'], $daysdiff);
1222 - VikError::raiseWarning('', $msg);
1223 - // VBO 1.11 - push data to tracker and close
1224 - VikBooking::getTracker()->pushRooms($proomdetail)->pushMessage($msg, 'warning')->closeTrack();
1225 - //
1226 - }
1227 - } elseif (!empty($proomdetail) && $proomsnum > 1) {
1228 - //check whether the user is coming from roomdetails and if the room is available for any room party
1229 - $room_missing = false;
1230 - foreach ($results as $indroom => $rooms) {
1231 - $room_found = false;
1232 - foreach ($rooms as $room) {
1233 - if ($room[0]['idroom'] == $proomdetail && (!array_key_exists('unitsavail', $room[0]) || $room[0]['unitsavail'] >= $proomsnum)) {
1234 - $room_found = true;
1235 - break;
1236 - }
1237 - }
1238 - if (!$room_found) {
1239 - $room_missing = true;
1240 - break;
1241 - }
1242 - }
1243 - if ($room_missing === false) {
1244 - $aduchild_str = '';
1245 - foreach ($arrpeople as $people) {
1246 - $aduchild_str .= '&adults[]='.$people['adults'].'&children[]='.$people['children'];
1247 - }
1248 - $roomopt_str = '';
1249 - for ($ri = 0; $ri < $proomsnum; $ri++) {
1250 - $roomopt_str .= '&roomopt[]='.$proomdetail;
1251 - }
1252 - // store in the session that we are coming from the room details page
1253 - $session->set('vboSearchRoomId', $proomdetail);
1254 - //
1255 - $mainframe->redirect(JRoute::rewrite("index.php?option=com_vikbooking&task=showprc&roomsnum=".$proomsnum.$roomopt_str.$aduchild_str."&days=".$daysdiff."&checkin=".$first."&checkout=".$second.(!empty($ppkg_id) ? "&pkg_id=" . $ppkg_id : "").(!empty($pitemid) ? "&Itemid=" . $pitemid : ""), false));
1256 - // VBO 1.11 - push data to tracker and close
1257 - VikBooking::getTracker()->pushRooms(array_fill(0, $proomsnum, $proomdetail))->closeTrack();
1258 - //
1259 - exit;
1260 - } else {
1261 - $q = "SELECT `id`,`name` FROM `#__vikbooking_rooms` WHERE `id`=".intval($proomdetail).";";
1262 - $dbo->setQuery($q);
1263 - $cdet = $dbo->loadAssocList();
1264 - if ($cdet) {
1265 - $vbo_tn->translateContents($cdet, '#__vikbooking_rooms');
1266 - $msg = JText::sprintf('VBDETAILMULTIRNOTAVAIL', $proomsnum, $cdet[0]['name'], $daysdiff);
1267 - VikError::raiseWarning('', $msg);
1268 - // VBO 1.11 - push data to tracker and close
1269 - VikBooking::getTracker()->pushMessage($msg, 'warning')->closeTrack();
1270 - //
1271 - }
1272 - }
1273 - }
1274 - $this->res = $results;
1275 - $this->days = $daysdiff;
1276 - $this->checkin = $first;
1277 - $this->checkout = $second;
1278 - $this->roomsnum = $proomsnum;
1279 - $this->arrpeople = $arrpeople;
1280 - $showchildren = $showchildren ? 1 : 0;
1281 - $this->showchildren = $showchildren;
1282 - $this->js_overcounter = $js_overcounter;
1283 - $this->mod_booking = $mod_booking;
1284 - $this->vbo_tn = $vbo_tn;
1285 - //theme
1286 - $theme = VikBooking::getTheme();
1287 - if ($theme != 'default') {
1288 - $thdir = VBO_SITE_PATH.DS.'themes'.DS.$theme.DS.'search';
1289 - if (is_dir($thdir)) {
1290 - $this->_setPath('template', $thdir.DS);
1291 - }
1292 - }
1293 -
1294 - // unset the session if we were coming from the room details page
1295 - $session->set('vboSearchRoomId', '');
1296 -
1297 - // VBO 1.11 - close tracker
1298 - VikBooking::getTracker()
1299 - ->setExtraInfo('results', $results)
1300 - ->closeTrack();
1301 -
1302 - parent::display($tpl);
1230 + //percentage value
1231 + $results[$movedata[1]][0][$kpr]['diffusagecostpernight'] = $diffusageprice['pernight'] == 1 ? $vpr['cost'] : 0;
1232 + $aduseval = $diffusageprice['pernight'] == 1 ? round(($vpr['cost'] * $diffusageprice['value'] / 100) * $results[$movedata[1]][0][$kpr]['days'] + $vpr['cost'], 2) : round(($vpr['cost'] * (100 + $diffusageprice['value']) / 100), 2);
1233 + $results[$movedata[1]][0][$kpr]['diffusagecost'] = "+".$diffusageprice['value']."%";
1234 + $results[$movedata[1]][0][$kpr]['cost'] = $aduseval;
1303 1235 }
1304 - //
1305 1236 } else {
1306 - //zero results for some room
1307 - $errmess = array();
1308 - if (isset($critic) && count($critic) > 0) {
1309 - foreach ($critic as $nroom) {
1310 - $errmess[] = $arrpeople[$nroom]['adults']." ".($arrpeople[$nroom]['adults'] == 1 ? JText::translate('VBSEARCHRESADULT') : JText::translate('VBSEARCHRESADULTS')).($arrpeople[$nroom]['children'] > 0 ? ", ".$arrpeople[$nroom]['children']." ".($arrpeople[$nroom]['children'] == 1 ? JText::translate('VBSEARCHRESCHILD') : JText::translate('VBSEARCHRESCHILDREN')) : "");
1311 - }
1312 - $errmess = array_unique($errmess);
1237 + //discount
1238 + if ($diffusageprice['valpcent'] == 1) {
1239 + //fixed value
1240 + $results[$movedata[1]][0][$kpr]['diffusagecostpernight'] = $diffusageprice['pernight'] == 1 ? 1 : 0;
1241 + $aduseval = $diffusageprice['pernight'] == 1 ? $diffusageprice['value'] * $results[$movedata[1]][0][$kpr]['days'] : $diffusageprice['value'];
1242 + $results[$movedata[1]][0][$kpr]['diffusagecost'] = "-".$aduseval;
1243 + $results[$movedata[1]][0][$kpr]['cost'] = $vpr['cost'] - $aduseval;
1313 1244 } else {
1314 - $errmess[] = JText::translate('VBOSEARCHERRCODETHREEBASE');
1245 + //percentage value
1246 + $results[$movedata[1]][0][$kpr]['diffusagecostpernight'] = $diffusageprice['pernight'] == 1 ? $vpr['cost'] : 0;
1247 + $aduseval = $diffusageprice['pernight'] == 1 ? round($vpr['cost'] - ((($vpr['cost'] / $results[$movedata[1]][0][$kpr]['days']) * $diffusageprice['value'] / 100) * $results[$movedata[1]][0][$kpr]['days']), 2) : round(($vpr['cost'] * (100 - $diffusageprice['value']) / 100), 2);
1248 + $results[$movedata[1]][0][$kpr]['diffusagecost'] = "-".$diffusageprice['value']."%";
1249 + $results[$movedata[1]][0][$kpr]['cost'] = $aduseval;
1315 1250 }
1316 - $err_code_info = array(
1317 - 'code' => 3,
1318 - 'fromts' => $first,
1319 - 'tots' => $second,
1320 - 'party' => $arrpeople
1321 - );
1322 - $msg = JText::sprintf('VBSEARCHERRNOTENOUGHROOMS', implode(" - ", $errmess));
1323 - // VBO 1.11 - push data to tracker and close
1324 - VikBooking::getTracker()->pushMessage($msg, 'error')->closeTrack();
1325 - //
1326 - $this->setVboError($msg, $err_code_info);
1327 1251 }
1328 - } else {
1329 - $err_code_info = array();
1330 - if (strlen($restrictionerrmsg) > 0) {
1331 - VikError::raiseWarning('', $restrictionerrmsg);
1332 - } else {
1333 - $err_code_info = array(
1334 - 'code' => 1,
1335 - 'fromts' => $first,
1336 - 'tots' => $second,
1337 - 'party' => $arrpeople
1338 - );
1339 - }
1340 - $msg = JText::translate('VBNOROOMSINDATE');
1341 - // VBO 1.11 - push data to tracker and close
1342 - VikBooking::getTracker()->pushMessage($msg, 'error')->closeTrack();
1343 - //
1344 - $this->setVboError($msg, $err_code_info);
1345 1252 }
1346 - } else {
1347 - $sayerr = JText::translate('VBNOROOMAVFOR') . " " . $daysdiff . " " . ($daysdiff > 1 ? JText::translate('VBDAYS') : JText::translate('VBDAY'));
1348 - if (count($padults) == 1) {
1349 - $sayerr .= ", ".$arrpeople[1]['adults']." ".($arrpeople[1]['adults'] > 1 ? JText::translate('VBSEARCHRESADULTS') : JText::translate('VBSEARCHRESADULT'));
1350 - if ($arrpeople[1]['children'] > 0) {
1351 - $sayerr .= ", ".$arrpeople[1]['children']." ".($arrpeople[1]['children'] > 1 ? JText::translate('VBSEARCHRESCHILDREN') : JText::translate('VBSEARCHRESCHILD'));
1352 - }
1353 - }
1354 - $err_code_info = array(
1355 - 'code' => 2,
1356 - 'fromts' => $first,
1357 - 'tots' => $second,
1358 - 'party' => $arrpeople
1359 - );
1360 - // VBO 1.11 - push data to tracker and close
1361 - VikBooking::getTracker()->pushMessage($sayerr, 'error')->closeTrack();
1362 - //
1363 - $this->setVboError($sayerr, $err_code_info);
1364 1253 }
1365 - } else {
1366 - $this->setVboError($restrictionerrmsg);
1367 1254 }
1368 - } else {
1369 - $session->set('vbcheckin', '');
1370 - $session->set('vbcheckout', '');
1371 - if ($first <= $actnow) {
1372 - if (date('d/m/Y', $first) == date('d/m/Y', $actnow)) {
1373 - $emess = JText::translate('VBSRCHERRCHKINPASSED');
1374 - } else {
1375 - $emess = JText::translate('VBSRCHERRCHKINPAST');
1255 + }
1256 + //end check if moved rooms had charges/discounts for adults occupancy to update it
1257 + }
1258 + //
1259 + }
1260 + }
1261 + //
1262 + $results = VikBooking::sortMultipleResults($results);
1263 +
1264 + // save prices in session for the modules
1265 + $sessvals = [];
1266 + $modprices = [];
1267 + $sessvals['roomsnum'] = $proomsnum;
1268 + $sessvals['checkin'] = $first;
1269 + $sessvals['checkout'] = $second;
1270 + for ($i = 1; $i <= $proomsnum; $i++) {
1271 + if (!isset($results[$i])) {
1272 + continue;
1273 + }
1274 + foreach ($results[$i] as $indres => $res) {
1275 + $modprices[$i][] = $res[0]['cost'];
1276 + }
1277 + }
1278 + for ($i = 1; $i <= $proomsnum; $i++) {
1279 + if (!isset($modprices[$i])) {
1280 + continue;
1281 + }
1282 + $mincost = min($modprices[$i]);
1283 + $maxcost = max($modprices[$i]);
1284 + $sessvals[$i]['min'] = $mincost;
1285 + $sessvals[$i]['max'] = $maxcost;
1286 + $sessvals[$i]['adults'] = $arrpeople[$i]['adults'];
1287 + $sessvals[$i]['children'] = $arrpeople[$i]['children'];
1288 + }
1289 + $session->set('vbsearchdata', $sessvals);
1290 +
1291 + /**
1292 + * Build a pool of room rates in the search results before filtering by price.
1293 + *
1294 + * @since 1.18.3 (J) - 1.8.3 (WP)
1295 + */
1296 + $rates_pool = [];
1297 + foreach ($results as $roomPartyIndex => $roomPartyRooms) {
1298 + foreach ($roomPartyRooms as $roomPartyRoom) {
1299 + foreach ($roomPartyRoom as $roomRateResult) {
1300 + // take only the first (lowest) rate plan
1301 + $rates_pool[] = (float) ($roomRateResult['cost'] ?? 0);
1302 + break;
1303 + }
1304 + }
1305 + }
1306 + $rates_pool = array_values(array_filter($rates_pool));
1307 +
1308 + /**
1309 + * Apply price filters (legacy compatibility also available with "pricefilter module").
1310 + *
1311 + * @since 1.18.3 (J) - 1.8.3 (WP) added support to search results filtering options.
1312 + */
1313 + $ppricefrom = VikRequest::getInt('r1pricefrom', '', 'request');
1314 + $ppriceto = VikRequest::getInt('r1priceto', '', 'request');
1315 + $price_range_filtering = false;
1316 + if (($resultFilters['price']['min'] ?? 0) && ($resultFilters['price']['max'] ?? 0)) {
1317 + // use search results filtering options
1318 + $ppricefrom = (float) $resultFilters['price']['min'];
1319 + $ppriceto = (float) $resultFilters['price']['max'];
1320 + $price_range_filtering = true;
1321 + }
1322 + if (!empty($ppricefrom) && !empty($ppriceto)) {
1323 + foreach ($results as $oknroom => $res) {
1324 + $totroomres = count($res);
1325 + foreach ($res as $kr => $rr) {
1326 + if ($oknroom > 1 && !$price_range_filtering) {
1327 + $ppricefrom = VikRequest::getInt('r'.$oknroom.'pricefrom', '', 'request');
1328 + $ppriceto = VikRequest::getInt('r'.$oknroom.'priceto', '', 'request');
1329 + }
1330 + if (!empty($ppricefrom) && !empty($ppriceto)) {
1331 + if ($rr[0]['cost'] < $ppricefrom || $rr[0]['cost'] > $ppriceto) {
1332 + if ($totroomres > 1) {
1333 + unset($results[$oknroom][$kr]);
1334 + $totroomres--;
1376 1335 }
1377 - } else {
1378 - $emess = JText::translate('VBPICKBRET');
1379 1336 }
1380 - $this->setVboError($emess);
1381 1337 }
1382 - } else {
1383 - $this->setVboError(JText::translate('VBWRONGDF') . ": " . VikBooking::sayDateFormat());
1384 1338 }
1339 + }
1340 + }
1341 +
1342 + if (count($results) == $proomsnum) {
1343 + // check whether the user is coming from roomdetails
1344 + $proomdetail = VikRequest::getInt('roomdetail', 0, 'request');
1345 + $rate_plan_id = VikRequest::getInt('rate_plan_id', 0, 'request');
1346 + $user_currency = VikRequest::getString('user_currency', '', 'request');
1347 + $children_age = VikRequest::getVar('children_age', []);
1348 + $pitemid = VikRequest::getInt('Itemid', 0, 'request');
1349 + if (!empty($proomdetail) && array_key_exists($proomdetail, $arrtar) && $proomsnum == 1) {
1350 + // push data to tracker and close
1351 + VikBooking::getTracker()->pushRooms($proomdetail)->closeTrack();
1352 + // store in the session that we are coming from the room details page
1353 + $session->set('vboSearchRoomId', $proomdetail);
1354 +
1355 + /**
1356 + * Build redirect URI to the "showprc" View to continue the booking process, and
1357 + * keep some special vars that may serve to reflect the original booking link.
1358 + *
1359 + * @since 1.15.0 (J) - 1.5.0 (WP)
1360 + */
1361 + $url_query_args = [
1362 + 'option' => 'com_vikbooking',
1363 + 'task' => 'showprc',
1364 + 'roomsnum' => '1',
1365 + 'roomopt' => [
1366 + $proomdetail,
1367 + ],
1368 + 'adults' => [
1369 + $arrpeople[1]['adults'],
1370 + ],
1371 + 'children' => [
1372 + $arrpeople[1]['children'],
1373 + ],
1374 + 'days' => $daysdiff,
1375 + 'checkin' => $first,
1376 + 'checkout' => $second,
1377 + ];
1378 + if (!empty($ppkg_id)) {
1379 + $url_query_args['pkg_id'] = $ppkg_id;
1380 + }
1381 + if (!empty($rate_plan_id)) {
1382 + $url_query_args['rate_plan_id'] = $rate_plan_id;
1383 + }
1384 + if (is_array($children_age) && $children_age) {
1385 + $url_query_args['children_age'] = $children_age;
1386 + }
1387 + if (!empty($user_currency)) {
1388 + $url_query_args['user_currency'] = $user_currency;
1389 + }
1390 + if (!empty($pcategory_ids)) {
1391 + $url_query_args['category_ids'] = $pcategory_ids;
1392 + }
1393 + if (!empty($pitemid)) {
1394 + $url_query_args['Itemid'] = $pitemid;
1395 + }
1396 +
1397 + $app->redirect(JRoute::rewrite('index.php?' . http_build_query($url_query_args), false));
1398 + exit;
1385 1399 } else {
1386 - $this->setVboError(JText::translate('VBSELPRDATE'));
1400 + if (!empty($proomdetail) && $proomsnum == 1) {
1401 + $q = "SELECT `id`,`name` FROM `#__vikbooking_rooms` WHERE `id`=".intval($proomdetail).";";
1402 + $dbo->setQuery($q);
1403 + $cdet = $dbo->loadAssocList();
1404 + if ($cdet) {
1405 + $vbo_tn->translateContents($cdet, '#__vikbooking_rooms');
1406 + $msg = JText::sprintf('VBDETAILCNOTAVAIL', $cdet[0]['name'], $daysdiff);
1407 + VikError::raiseWarning('', $msg);
1408 + // push data to tracker and close
1409 + VikBooking::getTracker()->pushRooms($proomdetail)->pushMessage($msg, 'warning')->closeTrack();
1410 + }
1411 + } elseif (!empty($proomdetail) && $proomsnum > 1) {
1412 + //check whether the user is coming from roomdetails and if the room is available for any room party
1413 + $room_missing = false;
1414 + foreach ($results as $indroom => $rooms) {
1415 + $room_found = false;
1416 + foreach ($rooms as $room) {
1417 + if ($room[0]['idroom'] == $proomdetail && (!array_key_exists('unitsavail', $room[0]) || $room[0]['unitsavail'] >= $proomsnum)) {
1418 + $room_found = true;
1419 + break;
1420 + }
1421 + }
1422 + if (!$room_found) {
1423 + $room_missing = true;
1424 + break;
1425 + }
1426 + }
1427 + if ($room_missing === false) {
1428 + $aduchild_str = '';
1429 + foreach ($arrpeople as $people) {
1430 + $aduchild_str .= '&adults[]='.$people['adults'].'&children[]='.$people['children'];
1431 + }
1432 + $roomopt_str = '';
1433 + for ($ri = 0; $ri < $proomsnum; $ri++) {
1434 + $roomopt_str .= '&roomopt[]='.$proomdetail;
1435 + }
1436 + // store in the session that we are coming from the room details page
1437 + $session->set('vboSearchRoomId', $proomdetail);
1438 + //
1439 + $app->redirect(JRoute::rewrite("index.php?option=com_vikbooking&task=showprc&roomsnum=".$proomsnum.$roomopt_str.$aduchild_str."&days=".$daysdiff."&checkin=".$first."&checkout=".$second.(!empty($ppkg_id) ? "&pkg_id=" . $ppkg_id : "").(!empty($pitemid) ? "&Itemid=" . $pitemid : ""), false));
1440 + // push data to tracker and close
1441 + VikBooking::getTracker()->pushRooms(array_fill(0, $proomsnum, $proomdetail))->closeTrack();
1442 + exit;
1443 + } else {
1444 + $q = "SELECT `id`,`name` FROM `#__vikbooking_rooms` WHERE `id`=".intval($proomdetail).";";
1445 + $dbo->setQuery($q);
1446 + $cdet = $dbo->loadAssocList();
1447 + if ($cdet) {
1448 + $vbo_tn->translateContents($cdet, '#__vikbooking_rooms');
1449 + $msg = JText::sprintf('VBDETAILMULTIRNOTAVAIL', $proomsnum, $cdet[0]['name'], $daysdiff);
1450 + VikError::raiseWarning('', $msg);
1451 + // push data to tracker and close
1452 + VikBooking::getTracker()->pushMessage($msg, 'warning')->closeTrack();
1453 + }
1454 + }
1455 + }
1456 +
1457 + // filter unavailable listing IDs
1458 + $unavailable_listings = array_filter(array_map('intval', array_unique($unavailable_listings)));
1459 +
1460 + // set View properties
1461 + $this->res = $results;
1462 + $this->days = $daysdiff;
1463 + $this->checkin = $first;
1464 + $this->checkout = $second;
1465 + $this->roomsnum = $proomsnum;
1466 + $this->arrpeople = $arrpeople;
1467 + $showchildren = $showchildren ? 1 : 0;
1468 + $this->showchildren = $showchildren;
1469 + $this->js_overcounter = $js_overcounter;
1470 + $this->mod_booking = $mod_booking;
1471 + $this->unavailable_listings = $unavailable_listings;
1472 + $this->rates_pool = $rates_pool;
1473 + $this->vbo_tn = $vbo_tn;
1474 + // theme
1475 + $theme = VikBooking::getTheme();
1476 + if ($theme != 'default') {
1477 + $thdir = VBO_SITE_PATH.DS.'themes'.DS.$theme.DS.'search';
1478 + if (is_dir($thdir)) {
1479 + $this->_setPath('template', $thdir.DS);
1480 + }
1481 + }
1482 +
1483 + // unset the session if we were coming from the room details page
1484 + $session->set('vboSearchRoomId', '');
1485 +
1486 + // close tracker
1487 + VikBooking::getTracker()
1488 + ->setExtraInfo('results', $results)
1489 + ->closeTrack();
1490 +
1491 + parent::display($tpl);
1387 1492 }
1388 1493 } else {
1389 - echo VikBooking::getDisabledBookingMsg();
1494 + // zero results for some room
1495 + $errmess = [];
1496 + if (isset($critic) && $critic) {
1497 + foreach ($critic as $nroom) {
1498 + $errmess[] = $arrpeople[$nroom]['adults']." ".($arrpeople[$nroom]['adults'] == 1 ? JText::translate('VBSEARCHRESADULT') : JText::translate('VBSEARCHRESADULTS')).($arrpeople[$nroom]['children'] > 0 ? ", ".$arrpeople[$nroom]['children']." ".($arrpeople[$nroom]['children'] == 1 ? JText::translate('VBSEARCHRESCHILD') : JText::translate('VBSEARCHRESCHILDREN')) : "");
1499 + }
1500 + $errmess = array_unique($errmess);
1501 + } else {
1502 + $errmess[] = JText::translate('VBOSEARCHERRCODETHREEBASE');
1503 + }
1504 + $err_code_info = [
1505 + 'code' => 3,
1506 + 'fromts' => $first,
1507 + 'tots' => $second,
1508 + 'party' => $arrpeople
1509 + ];
1510 + $msg = JText::sprintf('VBSEARCHERRNOTENOUGHROOMS', implode(" - ", $errmess));
1511 +
1512 + // push data to tracker and close
1513 + VikBooking::getTracker()->pushMessage($msg, 'error')->closeTrack();
1514 +
1515 + $this->setVboError($msg, $err_code_info);
1390 1516 }
1391 1517 }
1392 1518
1393 1519 protected function setVboError($err, $err_code_info = [])