PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.6.4
VikBooking Hotel Booking Engine & PMS v1.6.4
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 / helpers / tac.vikbooking.php

tac.vikbooking.php in VikBooking Hotel Booking Engine & PMS 1.6.4, at site/helpers/tac.vikbooking.php

603 lines 21.8 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 /**
14 * Helper class originally introcued to get the hotel availability and rates.
15 */
16 class TACVBO
17 {
18 /**
19 * @var bool whether to return an array.
20 */
21 public static $getArray = false;
22
23 /**
24 * @var bool flag to ignore booking restrictions.
25 *
26 * @since 1.15.0 (J) - 1.5.0 (WP)
27 */
28 public static $ignoreRestrictions = false;
29
30 /**
31 * Error code identifier:
32 *
33 * 1 = missing/invalid request options.
34 * 2 = invalid authentication.
35 * 3 = no rooms found for the given party.
36 * 4 = not compliant with booking restrictions.
37 * 5 = not compliant with global closing dates.
38 * 6 = no rates defined for the given length of stay.
39 * 7 = no availability for the dates requested (error code 8 might have occurred as well).
40 * 8 = no rooms available due to restrictions at room or rate plan level.
41 *
42 * @var int the error code identifier.
43 *
44 * @since 1.15.0 (J) - 1.5.0 (WP)
45 */
46 protected static $errorCode = 0;
47
48 /**
49 * Given the request or injected arguments, calulcates the availability and rates.
50 *
51 * @param array $options forced options injected rather than request variables.
52 *
53 * @return mixed array with values or error description if getArray=true, or void.
54 *
55 * @since 1.15.0 (J) - 1.5.0 (WP) added $options argument.
56 */
57 public static function tac_av_l($options = array())
58 {
59 $dbo = JFactory::getDbo();
60 $vbo_tn = VikBooking::getTranslator();
61
62 $response = 'e4j.error';
63 $args = $options;
64
65 /**
66 * All the calls to VikRequest's methods should not use 'request' as 3rd argument,
67 * but rather 'default' to get the right $input object in the VikRequest Class.
68 * This will resolve issues after the setVar() method was called by other functions.
69 * POST and GET requests will still provide non-empty values by using 'default'.
70 *
71 * @since 1.10
72 */
73 $args['hash'] = empty($args['hash']) ? VikRequest::getString('e4jauth', '', 'default') : $args['hash'];
74 $args['start_date'] = empty($args['start_date']) ? VikRequest::getString('start_date', '', 'default') : $args['start_date'];
75 $args['end_date'] = empty($args['end_date']) ? VikRequest::getString('end_date', '', 'default') : $args['end_date'];
76 $args['nights'] = empty($args['nights']) ? VikRequest::getInt('nights', 1, 'default') : $args['nights'];
77 $args['num_rooms'] = empty($args['num_rooms']) ? VikRequest::getInt('num_rooms', 1, 'default') : $args['num_rooms'];
78
79 $args['start_ts'] = strtotime($args['start_date']);
80 $args['end_ts'] = strtotime($args['end_date']);
81
82 $valid = true;
83 $mandatory_keys = array(
84 'start_date',
85 'end_date',
86 'nights',
87 'num_rooms',
88 );
89 foreach ($mandatory_keys as $man_key) {
90 $valid = $valid && isset($args[$man_key]) && !empty($args[$man_key]);
91 }
92
93 // request type
94 $req_type = VikRequest::getString('req_type', '', 'default');
95 $req_type = empty($req_type) && !empty($args['req_type']) ? $args['req_type'] : $req_type;
96
97 // API version
98 $tac_apiv = 4;
99 // API v4
100 $args['num_adults'] = empty($args['num_adults']) ? VikRequest::getInt('num_adults', 1, 'request') : $args['num_adults'];
101 // API v5
102 $args['adults'] = empty($args['adults']) ? VikRequest::getVar('adults', array()) : $args['adults'];
103 $args['children'] = empty($args['children']) ? VikRequest::getVar('children', array()) : $args['children'];
104 $args['children_age'] = empty($args['children_age']) ? VikRequest::getVar('children_age', array()) : $args['children_age'];
105 if (!empty($args['adults']) && !empty($args['children'])) {
106 $tac_apiv = 5;
107 }
108
109 if ($tac_apiv == 4) {
110 $valid = !empty($args['num_adults']) ? $valid : false;
111 } elseif ($tac_apiv == 5) {
112 $valid = !empty($args['adults']) ? $valid : false;
113 }
114
115 /**
116 * The back-end page Calendar can allow the admin to force bookings in case of
117 * no-availability. Its AJAX requests will contain "only_rates=1" and we compose
118 * an extra array-key with all the fully-booked rooms for the requested dates.
119 *
120 * @since 1.14 (J) - 1.4.0 (WP)
121 */
122 $only_rates = VikRequest::getInt('only_rates', 0, 'request');
123 $only_rates = empty($only_rates) && !empty($args['only_rates']) ? $args['only_rates'] : $only_rates;
124 $fullybooked = array();
125
126 if (!$valid) {
127 // set error code
128 self::$errorCode = 1;
129
130 if (self::$getArray) {
131 return $response;
132 }
133 echo $response;
134 exit;
135 }
136
137 $checkauth = md5('vbo.e4j.vbo');
138 if ($checkauth != $args['hash'] && !count($options)) {
139 // set error code
140 self::$errorCode = 2;
141
142 $response = 'e4j.error.auth';
143 if (self::$getArray) {
144 return $response;
145 }
146 echo $response;
147 exit;
148 }
149
150 $avail_rooms = array();
151 if ($tac_apiv == 5) {
152 // compose adults-children array and sql clause
153 $arradultsrooms = array();
154 $arradultsclause = array();
155 $arrpeople = array();
156 if (count($args['adults']) > 0) {
157 foreach ($args['adults'] as $kad => $adu) {
158 $roomnumb = $kad + 1;
159 if (strlen($adu)) {
160 $numadults = intval($adu);
161 if ($numadults >= 0) {
162 $arradultsrooms[$roomnumb] = $numadults;
163 $arrpeople[$roomnumb]['adults'] = $numadults;
164 $strclause = "(`fromadult`<=".$numadults." AND `toadult`>=".$numadults."";
165 if (!empty($args['children'][$kad]) && intval($args['children'][$kad]) > 0) {
166 $numchildren = intval($args['children'][$kad]);
167 $arrpeople[$roomnumb]['children'] = $numchildren;
168 $arrpeople[$roomnumb]['children_age'] = isset($args['children_age'][$roomnumb]) && count($args['children_age'][$roomnumb]) ? $args['children_age'][$roomnumb] : array();
169 $strclause .= " AND `fromchild`<=".$numchildren." AND `tochild`>=".$numchildren."";
170 } else {
171 $arrpeople[$roomnumb]['children'] = 0;
172 $arrpeople[$roomnumb]['children_age'] = array();
173 if (intval($args['children'][$kad]) == 0) {
174 $strclause .= " AND `fromchild` = 0";
175 }
176 }
177 $strclause .= " AND `totpeople` >= ".($arrpeople[$roomnumb]['adults'] + $arrpeople[$roomnumb]['children']);
178 $strclause .= " AND `mintotpeople` <= ".($arrpeople[$roomnumb]['adults'] + $arrpeople[$roomnumb]['children']);
179 $strclause .= ")";
180 $arradultsclause[] = $strclause;
181 }
182 }
183 }
184 }
185 // set $args['adults'] to the number of adults occupying the first room but it could be a party of multiple rooms
186 $args['num_adults'] = $arrpeople[1]['adults'];
187 // this clause would return one room type for each party type: implode(" OR ", $arradultsclause) - the AND clause must be used rather than OR.
188 $q = "SELECT `id`, `units` FROM `#__vikbooking_rooms` WHERE `avail`=1 AND (".implode(" AND ", $arradultsclause).");";
189 } else {
190 // API v4
191 $arrpeople = array();
192 $arrpeople[1]['adults'] = $args['num_adults'];
193 $arrpeople[1]['children'] = 0;
194 $q = "SELECT `id`, `units` FROM `#__vikbooking_rooms` WHERE `avail`=1 AND `toadult`>=".$args['num_adults'].";";
195 }
196 $dbo->setQuery($q);
197 $avail_rooms = $dbo->loadAssocList();
198 if (!$avail_rooms) {
199 // set error code
200 self::$errorCode = 3;
201
202 if (self::$getArray) {
203 return array('e4j.error' => 'The Query for fetching the rooms returned an empty result');
204 }
205 echo json_encode(array('e4j.error' => 'The Query for fetching the rooms returned an empty result'));
206 exit;
207 }
208
209 // arr[0] = (sec) checkin, arr[1] = (sec) checkout
210 $check_in_out = VikBooking::getTimeOpenStore();
211 if (is_array($check_in_out)) {
212 $args['start_ts'] += $check_in_out[0];
213 $args['end_ts'] += $check_in_out[1];
214 }
215
216 $room_ids = array();
217 for ($i = 0; $i < count($avail_rooms); $i++) {
218 $room_ids[$i] = $avail_rooms[$i]['id'];
219 }
220
221 $all_restrictions = VikBooking::loadRestrictions(true, $room_ids);
222 $glob_restrictions = VikBooking::globalRestrictions($all_restrictions);
223
224 // validate restrictions error message
225 $x_restr = count($glob_restrictions) ? VikBooking::validateRoomRestriction($glob_restrictions, getdate($args['start_ts']), getdate($args['end_ts']), $args['nights']) : '';
226
227 if (!self::$ignoreRestrictions && strlen($x_restr) > 0) {
228 // set error code
229 self::$errorCode = 4;
230
231 if (self::$getArray) {
232 return array('e4j.error' => 'Unable to proceed because of booking Restrictions in these dates (' . $x_restr . ')');
233 }
234 echo json_encode(array('e4j.error' => 'Unable to proceed because of booking Restrictions in these dates (' . $x_restr . ')'));
235 exit;
236 }
237
238 $nowdf = VikBooking::getDateFormat();
239 if ($nowdf == "%d/%m/%Y") {
240 $df = 'd/m/Y';
241 } elseif ($nowdf == "%m/%d/%Y") {
242 $df = 'm/d/Y';
243 } else {
244 $df = 'Y/m/d';
245 }
246 // closing dates
247 $err_closingdates = VikBooking::validateClosingDates($args['start_ts'], $args['end_ts'], $df);
248 if (!self::$ignoreRestrictions && !empty($err_closingdates)) {
249 // set error code
250 self::$errorCode = 5;
251
252 if (self::$getArray) {
253 return array('e4j.error' => JText::sprintf('VBERRDATESCLOSED', $err_closingdates));
254 }
255 echo json_encode(array('e4j.error' => JText::sprintf('VBERRDATESCLOSED', $err_closingdates)));
256 exit;
257 }
258
259 // hours to arrival may affect rate plan restrictions
260 $hoursdiff = VikBooking::countHoursToArrival($args['start_ts']);
261
262 // get rates
263 $room_ids = array();
264 foreach ($avail_rooms as $k => $room) {
265 $room_ids[$room['id']] = $room;
266 }
267 $rates = array();
268 $q = "SELECT `p`.*, `r`.`id` AS `r_reference_id`, `r`.`name` AS `r_short_desc`, `r`.`img`, `r`.`units`, `r`.`moreimgs`, `r`.`imgcaptions`, `prices`.`id` AS `price_reference_id`, `prices`.`name` AS `pricename`, `prices`.`breakfast_included`, `prices`.`free_cancellation`, `prices`.`canc_deadline`, `prices`.`minlos`, `prices`.`minhadv` FROM `#__vikbooking_dispcost` AS `p`, `#__vikbooking_rooms` AS `r`, `#__vikbooking_prices` AS `prices` WHERE `r`.`id`=`p`.`idroom` AND `p`.`idprice`=`prices`.`id` AND `p`.`days`=".$args['nights']." AND `r`.`id` IN (".implode(',', array_keys($room_ids)).") ORDER BY `p`.`cost` ASC;";
269 $dbo->setQuery($q);
270 $rates = $dbo->loadAssocList();
271 if (!$rates) {
272 // set error code
273 self::$errorCode = 6;
274
275 if (self::$getArray) {
276 return array('e4j.error' => 'The Query for fetching the rates returned an empty result');
277 }
278 echo json_encode(array('e4j.error' => 'The Query for fetching the rates returned an empty result'));
279 exit;
280 }
281 $vbo_tn->translateContents($rates, '#__vikbooking_rooms', array('id' => 'r_reference_id', 'r_short_desc' => 'name'));
282 $vbo_tn->translateContents($rates, '#__vikbooking_prices', array('id' => 'price_reference_id', 'pricename' => 'name'));
283 $arr_rates = array();
284 /**
285 * If all results are excluded because of restrictions at rate plan level, we use this flag
286 * to know that the rate plans have a Min LOS or a Min Hours in Advance (Advance Booking Offset).
287 * This is to avoid users to say "why do I get no availability?"
288 *
289 * @since 1.12.1
290 */
291 $err_rplan_restr = false;
292 //
293 foreach ($rates as $rate) {
294 // rate plans with a minlos, or with a min hours in advance
295 if ((!empty($rate['minlos']) && $rate['minlos'] > $args['nights']) || $hoursdiff < $rate['minhadv']) {
296 // this flag will tell us that some results were excluded due to restrictions at rate plan level
297 $err_rplan_restr = true;
298 continue;
299 } else {
300 // we don't want the properties 'minlos' and 'minhadv' in the response.
301 unset($rate['minlos']);
302 unset($rate['minhadv']);
303 }
304 if (!isset($arr_rates[$rate['idroom']])) {
305 $arr_rates[$rate['idroom']] = array();
306 }
307 $arr_rates[$rate['idroom']][] = $rate;
308 }
309
310 // flags to understand exactly what's making some rooms unavailable
311 $err_rtype_restr = false;
312 $err_rtype_booked = false;
313
314 // check availability for the rooms with a rate for this number of nights
315 $minus_units = 0;
316 if (count($arr_rates) < $args['num_rooms']) {
317 $minus_units = $args['num_rooms'] - count($arr_rates);
318 }
319 foreach ($arr_rates as $k => $datarate) {
320 $room = $room_ids[$k];
321 $consider_units = $room['units'] - $minus_units;
322 if (!VikBooking::roomBookable($room['id'], $consider_units, $args['start_ts'], $args['end_ts']) || $consider_units <= 0) {
323 // unset room from results
324 unset($arr_rates[$k]);
325 // push room as fully booked
326 array_push($fullybooked, (int)$room['id']);
327 // turn flag on
328 $err_rtype_booked = true;
329 } else {
330 if (!self::$ignoreRestrictions && count($all_restrictions)) {
331 $room_restr = VikBooking::roomRestrictions($room['id'], $all_restrictions);
332 if (count($room_restr)) {
333 if (strlen(VikBooking::validateRoomRestriction($room_restr, getdate($args['start_ts']), getdate($args['end_ts']), $args['nights'])) > 0) {
334 // unset room from results
335 unset($arr_rates[$k]);
336 // turn flag on
337 $err_rtype_restr = true;
338 }
339 }
340 }
341 }
342 }
343
344 if (!count($arr_rates)) {
345 // set error code
346 self::$errorCode = $err_rtype_booked ? 7 : 8;
347
348 // build error response
349 $res = array('e4j.error' => 'No availability for these dates');
350 if ($only_rates && count($fullybooked)) {
351 $res['fullybooked'] = $fullybooked;
352 }
353
354 if (self::$getArray) {
355 return $res;
356 }
357
358 // concatenate rate plan restriction errors, if any
359 if ($err_rplan_restr === true) {
360 $res['e4j.error'] .= ' (Rate Plan Restrictions)';
361 }
362
363 echo json_encode($res);
364 exit;
365 }
366
367 // apply special prices
368 $arr_rates = VikBooking::applySeasonalPrices($arr_rates, $args['start_ts'], $args['end_ts']);
369 $multi_rates = 1;
370 foreach ($arr_rates as $idr => $tars) {
371 $multi_rates = count($tars) > $multi_rates ? count($tars) : $multi_rates;
372 }
373 if ($multi_rates > 1) {
374 for ($r = 1; $r < $multi_rates; $r++) {
375 $deeper_rates = array();
376 foreach ($arr_rates as $idr => $tars) {
377 foreach ($tars as $tk => $tar) {
378 if ($tk == $r) {
379 $deeper_rates[$idr][0] = $tar;
380 break;
381 }
382 }
383 }
384 if (!count($deeper_rates) > 0) {
385 continue;
386 }
387 $deeper_rates = VikBooking::applySeasonalPrices($deeper_rates, $args['start_ts'], $args['end_ts']);
388 foreach ($deeper_rates as $idr => $dtars) {
389 foreach ($dtars as $dtk => $dtar) {
390 $arr_rates[$idr][$r] = $dtar;
391 }
392 }
393 }
394 }
395
396 // children ages charge
397 $children_sums = array();
398
399 // sum charges/discounts per occupancy for each room party
400 foreach ($arrpeople as $roomnumb => $party) {
401 // charges/discounts per adults occupancy
402 foreach ($arr_rates as $r => $rates) {
403 $children_charges = VikBooking::getChildrenCharges($r, $party['children'], $party['children_age'], $args['nights']);
404 if (count($children_charges) > 0) {
405 $children_sums[$r] += $children_charges['total'];
406 }
407 $diffusageprice = VikBooking::loadAdultsDiff($r, $party['adults']);
408 // Occupancy Override - Special Price may be setting a charge/discount for this occupancy while default price had no occupancy pricing
409 if (!is_array($diffusageprice)) {
410 foreach ($rates as $kpr => $vpr) {
411 if (array_key_exists('occupancy_ovr', $vpr) && array_key_exists($party['adults'], $vpr['occupancy_ovr']) && strlen($vpr['occupancy_ovr'][$party['adults']]['value'])) {
412 $diffusageprice = $vpr['occupancy_ovr'][$party['adults']];
413 break;
414 }
415 }
416 reset($rates);
417 }
418 if (is_array($diffusageprice)) {
419 foreach ($rates as $kpr => $vpr) {
420 if ($roomnumb == 1) {
421 $arr_rates[$r][$kpr]['costbeforeoccupancy'] = $arr_rates[$r][$kpr]['cost'];
422 }
423 // Occupancy Override
424 if (array_key_exists('occupancy_ovr', $vpr) && array_key_exists($party['adults'], $vpr['occupancy_ovr']) && strlen($vpr['occupancy_ovr'][$party['adults']]['value'])) {
425 $diffusageprice = $vpr['occupancy_ovr'][$party['adults']];
426 }
427 $arr_rates[$r][$kpr]['diffusage'] = $party['adults'];
428 if ($diffusageprice['chdisc'] == 1) {
429 // charge
430 if ($diffusageprice['valpcent'] == 1) {
431 // fixed value
432 $aduseval = $diffusageprice['pernight'] == 1 ? $diffusageprice['value'] * $arr_rates[$r][$kpr]['days'] : $diffusageprice['value'];
433 $arr_rates[$r][$kpr]['diffusagecost'][$roomnumb] = $aduseval;
434 $arr_rates[$r][$kpr]['cost'] += $aduseval;
435 } else {
436 // percentage value
437 $aduseval = $diffusageprice['pernight'] == 1 ? round(($arr_rates[$r][$kpr]['costbeforeoccupancy'] * $diffusageprice['value'] / 100) * $arr_rates[$r][$kpr]['days'], 2) : round(($arr_rates[$r][$kpr]['costbeforeoccupancy'] * $diffusageprice['value'] / 100), 2);
438 $arr_rates[$r][$kpr]['diffusagecost'][$roomnumb] = $aduseval;
439 $arr_rates[$r][$kpr]['cost'] += $aduseval;
440 }
441 } else {
442 // discount
443 if ($diffusageprice['valpcent'] == 1) {
444 // fixed value
445 $aduseval = $diffusageprice['pernight'] == 1 ? $diffusageprice['value'] * $arr_rates[$r][$kpr]['days'] : $diffusageprice['value'];
446 $arr_rates[$r][$kpr]['diffusagediscount'][$roomnumb] = $aduseval;
447 $arr_rates[$r][$kpr]['cost'] -= $aduseval;
448 } else {
449 // percentage value
450 $aduseval = $diffusageprice['pernight'] == 1 ? round(((($arr_rates[$r][$kpr]['costbeforeoccupancy'] / $arr_rates[$r][$kpr]['days']) * $diffusageprice['value'] / 100) * $arr_rates[$r][$kpr]['days']), 2) : round(($arr_rates[$r][$kpr]['costbeforeoccupancy'] * $diffusageprice['value'] / 100), 2);
451 $arr_rates[$r][$kpr]['diffusagediscount'][$roomnumb] = $aduseval;
452 $arr_rates[$r][$kpr]['cost'] -= $aduseval;
453 }
454 }
455 }
456 } elseif ($roomnumb == 1) {
457 foreach ($rates as $kpr => $vpr) {
458 $arr_rates[$r][$kpr]['costbeforeoccupancy'] = $arr_rates[$r][$kpr]['cost'];
459 }
460 }
461 }
462 }
463
464 // if the rooms are given to a party of multiple rooms, multiply the basic rates per room per number of rooms
465 for($i = 2; $i <= $args['num_rooms']; $i++) {
466 foreach ($arr_rates as $r => $rates) {
467 foreach ($rates as $kpr => $vpr) {
468 $arr_rates[$r][$kpr]['cost'] += $arr_rates[$r][$kpr]['costbeforeoccupancy'];
469 }
470 }
471 }
472
473 // children ages charge
474 if (count($children_sums) > 0) {
475 foreach ($arr_rates as $r => $rates) {
476 if (array_key_exists($r, $children_sums)) {
477 foreach ($rates as $kpr => $vpr) {
478 $arr_rates[$r][$kpr]['cost'] += $children_sums[$r];
479 }
480 }
481 }
482 }
483
484 //sort results by price ASC
485 $arr_rates = VikBooking::sortResults($arr_rates);
486
487 // compose taxes information
488 $ivainclusa = VikBooking::ivaInclusa();
489 $rates_ids = array();
490 foreach ($arr_rates as $r => $rate) {
491 foreach ($rate as $ids) {
492 if (!in_array($ids['idprice'], $rates_ids)) {
493 $rates_ids[] = $ids['idprice'];
494 }
495 }
496 }
497 $tax_rates = array();
498 $q = "SELECT `p`.`id`,`t`.`aliq`,`t`.`taxcap` FROM `#__vikbooking_prices` AS `p` LEFT JOIN `#__vikbooking_iva` `t` ON `p`.`idiva`=`t`.`id` WHERE `p`.`id` IN (".implode(',', $rates_ids).");";
499 $dbo->setQuery($q);
500 $alltaxrates = $dbo->loadAssocList();
501 if ($alltaxrates) {
502 foreach ($alltaxrates as $tx) {
503 if (!empty($tx['aliq']) && $tx['aliq'] > 0) {
504 /**
505 * Tax Cap implementation.
506 *
507 * @since 1.12
508 */
509 $tax_rates[$tx['id']] = array($tx['aliq'], (float)$tx['taxcap']);
510 }
511 }
512 }
513 if (count($tax_rates) > 0) {
514 foreach ($arr_rates as $r => $rates) {
515 foreach ($rates as $k => $rate) {
516 if (array_key_exists($rate['idprice'], $tax_rates)) {
517 if (intval($ivainclusa) == 1) {
518 // prices tax included
519 $realcost = $rate['cost'];
520 $tax_oper = ($tax_rates[$rate['idprice']][0] + 100) / 100;
521 $taxes = $rate['cost'] - ($rate['cost'] / $tax_oper);
522 /**
523 * Tax Cap implementation.
524 *
525 * @since 1.12
526 */
527 if ($tax_rates[$rate['idprice']][1] > 0 && $taxes > $tax_rates[$rate['idprice']][1]) {
528 $taxes = $tax_rates[$rate['idprice']][1];
529 }
530 } else {
531 // prices tax excluded
532 $realcost = $rate['cost'] * (100 + $tax_rates[$rate['idprice']][0]) / 100;
533 $taxes = $realcost - $rate['cost'];
534 /**
535 * Tax Cap implementation.
536 *
537 * @since 1.12
538 */
539 if ($tax_rates[$rate['idprice']][1] > 0 && $taxes > $tax_rates[$rate['idprice']][1]) {
540 $realcost = $rate['cost'] + $tax_rates[$rate['idprice']][1];
541 $taxes = $tax_rates[$rate['idprice']][1];
542 }
543 }
544 if ($req_type == 'hotel_availability' || $req_type == 'booking_availability') {
545 // always set 'cost' to the base rate tax excluded
546 $realcost = $realcost - $taxes;
547 }
548 $arr_rates[$r][$k]['cost'] = round($realcost, 2);
549 $arr_rates[$r][$k]['taxes'] = round($taxes, 2);
550 }
551 }
552 }
553 // sum taxes/fees for each room party
554 foreach ($arrpeople as $roomnumb => $party) {
555 foreach ($arr_rates as $r => $rates) {
556 $city_tax_fees = VikBooking::getMandatoryTaxesFees(array($r), $party['adults'], $args['nights']);
557 foreach ($rates as $k => $rate) {
558 if (!isset($arr_rates[$r][$k]['city_taxes'])) {
559 $arr_rates[$r][$k]['city_taxes'] = 0;
560 }
561 if (!isset($arr_rates[$r][$k]['fees'])) {
562 $arr_rates[$r][$k]['fees'] = 0;
563 }
564 $arr_rates[$r][$k]['city_taxes'] += round($city_tax_fees['city_taxes'], 2);
565 $arr_rates[$r][$k]['fees'] += round($city_tax_fees['fees'], 2);
566 }
567 }
568 }
569 } else {
570 foreach ($arr_rates as $r => $rates) {
571 foreach ($rates as $k => $rate) {
572 $arr_rates[$r][$k]['taxes'] = round(0, 2);
573 $arr_rates[$r][$k]['city_taxes'] = round(0, 2);
574 $arr_rates[$r][$k]['fees'] = round(0, 2);
575 }
576 }
577 }
578
579 if (self::$getArray) {
580 return $arr_rates;
581 }
582
583 if ($only_rates && count($fullybooked)) {
584 $arr_rates['fullybooked'] = $fullybooked;
585 }
586
587 echo json_encode($arr_rates);
588 exit;
589 }
590
591 /**
592 * Returns the error code to understand what produced an error.
593 *
594 * @return int the error code identifier.
595 *
596 * @since 1.15.0 (J) - 1.5.0 (WP)
597 */
598 public static function getErrorCode()
599 {
600 return self::$errorCode;
601 }
602 }
603