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