PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.6.6
VikBooking Hotel Booking Engine & PMS v1.6.6
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
vikbooking / site / views / search / view.html.php

view.html.php in VikBooking Hotel Booking Engine & PMS 1.6.6, at site/views/search/view.html.php

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