PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.6.8
VikBooking Hotel Booking Engine & PMS v1.6.8
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 / admin / controller.php

controller.php in VikBooking Hotel Booking Engine & PMS 1.6.8, at admin/controller.php

15,239 lines 576.7 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 // import Joomla controller library
14 jimport('joomla.application.component.controller');
15
16 class VikBookingController extends JControllerVikBooking
17 {
18 /**
19 * Default controller's method when no task is defined,
20 * or no method exists for that task. If a View is requested.
21 * attempts to set it, otherwise sets the default View.
22 */
23 public function display($cachable = false, $urlparams = array()) {
24
25 $view = VikRequest::getVar('view', '');
26 $header_val = '';
27
28 if (!empty($view)) {
29 $header_val = $view;
30 VikRequest::setVar('view', $view);
31 } else {
32 $header_val = '18';
33 VikRequest::setVar('view', 'dashboard');
34 }
35
36 $hide_menu = JFactory::getApplication()->input->getBool('hide_menu', false);
37
38 if ($hide_menu === false)
39 {
40 VikBookingHelper::printHeader($header_val);
41 }
42
43 parent::display();
44
45 if (VikBooking::showFooter() && $hide_menu === false) {
46 VikBookingHelper::printFooter();
47 }
48 }
49
50 /**
51 * AJAX request for building dynamic donut charts.
52 *
53 * @return void
54 *
55 * @since 1.12.1
56 */
57 public function donut_charts_data() {
58 $fromdt = VikRequest::getString('fromdt', date('Y-m-d'), 'request');
59 $direction = VikRequest::getString('direction', 'next', 'request');
60 $days = VikRequest::getInt('days', 7, 'request');
61 if (empty($fromdt) || !strtotime($fromdt) || empty($days) || $days < 1) {
62 throw new Exception('Missing required data', 400);
63 }
64
65 $from_info = getdate(strtotime($fromdt));
66 if ($direction != 'next') {
67 // fromdt is always the next day after the end of the loop, so the very first next day from the last displayed
68 $from_info = getdate(mktime(0, 0, 0, $from_info['mon'], ($from_info['mday'] - ($days * 2)), $from_info['year']));
69 }
70 // always push the start date to the last second (23:59:59)
71 $from_info = getdate(mktime(23, 59, 59, $from_info['mon'], $from_info['mday'], $from_info['year']));
72
73 // months front-end language map
74 $monthsmap = array(
75 JText::translate('VBSHORTMONTHONE'),
76 JText::translate('VBSHORTMONTHTWO'),
77 JText::translate('VBSHORTMONTHTHREE'),
78 JText::translate('VBSHORTMONTHFOUR'),
79 JText::translate('VBSHORTMONTHFIVE'),
80 JText::translate('VBSHORTMONTHSIX'),
81 JText::translate('VBSHORTMONTHSEVEN'),
82 JText::translate('VBSHORTMONTHEIGHT'),
83 JText::translate('VBSHORTMONTHNINE'),
84 JText::translate('VBSHORTMONTHTEN'),
85 JText::translate('VBSHORTMONTHELEVEN'),
86 JText::translate('VBSHORTMONTHTWELVE'),
87 );
88
89 // weekdays front-end language map
90 $wdaysmap = array(
91 JText::translate('VBSUNDAY'),
92 JText::translate('VBMONDAY'),
93 JText::translate('VBTUESDAY'),
94 JText::translate('VBWEDNESDAY'),
95 JText::translate('VBTHURSDAY'),
96 JText::translate('VBFRIDAY'),
97 JText::translate('VBSATURDAY'),
98 );
99
100 // gather information about the rooms and availability
101 $dbo = JFactory::getDbo();
102 $all_rooms_ids = array();
103 $unpublished_rooms = array();
104 $todayymd = date('Y-m-d');
105 $q = "SELECT `id`,`name`,`units`,`params`,`avail` FROM `#__vikbooking_rooms`;";
106 $dbo->setQuery($q);
107 $dbo->execute();
108 if ($dbo->getNumRows()) {
109 $all_rooms = $dbo->loadAssocList();
110 foreach ($all_rooms as $k => $r) {
111 if ($r['avail'] < 1) {
112 $unpublished_rooms[] = $r['id'];
113 }
114 $all_rooms_ids[$r['id']] = $r['name'];
115 }
116 }
117 $q = "SELECT SUM(`units`) FROM `#__vikbooking_rooms` WHERE `avail`=1;";
118 $dbo->setQuery($q);
119 $dbo->execute();
120 $tot_rooms_units = (int)$dbo->loadResult();
121
122 // load busy records
123 $expected_max_ts = mktime(23, 59, 59, $from_info['mon'], ($from_info['mday'] + $days), $from_info['year']);
124 $busy = VikBooking::loadBusyRecordsUnclosed(array_keys($all_rooms_ids), $from_info[0], $expected_max_ts);
125
126 // response body
127 $response = new stdClass;
128 $response->prevweek = ($todayymd != date('Y-m-d', $from_info[0]));
129 $response->nextweek = true;
130 $response->fromd = date('Y-m-d', $from_info[0]);
131 $response->tot_units = $tot_rooms_units;
132 $response->data = array();
133
134 for ($i = 0; $i < $days; $i++) {
135 $tot_booked_today = 0;
136 $today_ts = $from_info[0];
137 $data_obj = new stdClass;
138 $data_obj->ymd = date('Y-m-d', $from_info[0]);
139 $data_obj->lbl = $wdaysmap[(int)$from_info['wday']] . ', ' . $from_info['mday'];
140 $data_obj->lbl = $data_obj->ymd == $todayymd ? JText::translate('VBTODAY') . ', ' . $data_obj->lbl : $data_obj->lbl . ' ' . $monthsmap[($from_info['mon'] - 1)];
141 foreach ($busy as $idroom => $rbusy) {
142 if (in_array($idroom, $unpublished_rooms)) {
143 continue;
144 }
145 foreach ($rbusy as $b) {
146 $tmpone = getdate($b['checkin']);
147 $ritts = mktime(0, 0, 0, $tmpone['mon'], $tmpone['mday'], $tmpone['year']);
148 $tmptwo = getdate($b['checkout']);
149 $conts = mktime(0, 0, 0, $tmptwo['mon'], $tmptwo['mday'], $tmptwo['year']);
150 if ($today_ts >= $ritts && $today_ts < $conts) {
151 $tot_booked_today++;
152 }
153 }
154 }
155
156 $data_obj->tot_booked = $tot_booked_today;
157 $percentage_booked = round((100 * $tot_booked_today / $tot_rooms_units), 2);
158
159 $data_obj->color = '#ff4d4d'; //red
160 if ($percentage_booked > 33 && $percentage_booked <= 66) {
161 $data_obj->color = '#ffa64d'; //orange
162 } elseif ($percentage_booked > 66 && $percentage_booked < 100) {
163 $data_obj->color = '#2a762c'; //green
164 } elseif ($percentage_booked >= 100) {
165 $data_obj->color = '#2482b4'; //light-blue
166 }
167
168 // push today's data
169 array_push($response->data, $data_obj);
170
171 // next day
172 $from_info = getdate(mktime(23, 59, 59, $from_info['mon'], ($from_info['mday'] + 1), $from_info['year']));
173 }
174
175 // update last date (not displayed/included)
176 $response->tod = date('Y-m-d', $from_info[0]);
177
178 echo json_encode($response);
179 exit;
180 }
181
182 /**
183 * AJAX request for adding a new fest.
184 *
185 * @return void
186 *
187 * @since 1.2.0
188 */
189 public function add_fest() {
190 $dt = VikRequest::getString('dt', '', 'request');
191 $type = VikRequest::getString('type', '', 'request');
192 $type = empty($type) ? 'custom' : $type;
193 $name = VikRequest::getString('name', '', 'request');
194 $descr = VikRequest::getString('descr', '', 'request');
195 if (empty($name) || empty($dt) || !strtotime($dt)) {
196 echo 'e4j.error.1';
197 exit;
198 }
199 // build fest array
200 $new_fest = array(
201 'trans_name' => $name
202 );
203
204 $fests = VikBooking::getFestivitiesInstance();
205 $result = $fests->storeFestivity($dt, $new_fest, $type, $descr);
206 if (!$result) {
207 echo 'e4j.error.2';
208 exit;
209 }
210
211 // reload all festivities for this day for the AJAX response
212 $all_fests = $fests->loadFestDates($dt, $dt);
213 foreach ($all_fests as $k => $v) {
214 // we expect just one record to be returned due to the from/to date limit passed to loadFestDates()
215 echo json_encode($v);
216 exit;
217 }
218
219 // no fests found even after storing it
220 echo 'e4j.error.3';
221 exit;
222 }
223
224 /**
225 * AJAX request for removing a fest.
226 *
227 * @return void
228 *
229 * @since 1.2.0
230 */
231 public function remove_fest()
232 {
233 if (!JFactory::getUser()->authorise('core.delete', 'com_vikbooking')) {
234 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
235 }
236
237 $dt = VikRequest::getString('dt', '', 'request');
238 $ind = VikRequest::getInt('ind', 0, 'request');
239 $type = VikRequest::getString('type', '', 'request');
240 $type = empty($type) ? 'custom' : $type;
241 if (empty($dt) || !strtotime($dt)) {
242 echo 'e4j.error.1';
243 exit;
244 }
245
246 $fests = VikBooking::getFestivitiesInstance();
247 $result = $fests->deleteFestivity($dt, $ind, $type);
248 if (!$result) {
249 echo 'e4j.error.2';
250 exit;
251 }
252
253 echo 'e4j.ok';
254 exit;
255 }
256
257 public function einvoicing() {
258 VikBookingHelper::printHeader("einvoicing");
259
260 VikRequest::setVar('view', VikRequest::getCmd('view', 'einvoicing'));
261
262 parent::display();
263
264 if (VikBooking::showFooter()) {
265 VikBookingHelper::printFooter();
266 }
267 }
268
269 public function pmsreports() {
270 VikBookingHelper::printHeader("pmsreports");
271
272 VikRequest::setVar('view', VikRequest::getCmd('view', 'pmsreports'));
273
274 parent::display();
275
276 if (VikBooking::showFooter()) {
277 VikBookingHelper::printFooter();
278 }
279 }
280
281 public function ratesoverv() {
282 VikBookingHelper::printHeader("20");
283
284 VikRequest::setVar('view', VikRequest::getCmd('view', 'ratesoverv'));
285
286 parent::display();
287
288 if (VikBooking::showFooter()) {
289 VikBookingHelper::printFooter();
290 }
291 }
292
293 public function stats() {
294 VikBookingHelper::printHeader("stats");
295
296 VikRequest::setVar('view', VikRequest::getCmd('view', 'stats'));
297
298 parent::display();
299
300 if (VikBooking::showFooter()) {
301 VikBookingHelper::printFooter();
302 }
303 }
304
305 /**
306 * AJAX endpoint to calculate the website rates.
307 *
308 * @return void
309 */
310 public function calc_rates()
311 {
312 $response = 'e4j.error.ErrorCode(1) Server is blocking the self-request';
313 $response_code = 0;
314
315 // availability helper
316 $av_helper = VikBooking::getAvailabilityInstance();
317
318 $currencysymb = VikBooking::getCurrencySymb();
319 $vbo_df = VikBooking::getDateFormat();
320 $df = $vbo_df == "%d/%m/%Y" ? 'd/m/Y' : ($vbo_df == "%m/%d/%Y" ? 'm/d/Y' : 'Y/m/d');
321 $id_room = VikRequest::getInt('id_room', '', 'request');
322 $checkin = VikRequest::getString('checkin', '', 'request');
323 $nights = VikRequest::getInt('num_nights', 1, 'request');
324 $adults = VikRequest::getInt('num_adults', 0, 'request');
325 $children = VikRequest::getInt('num_children', 0, 'request');
326 /**
327 * The page Calendar may call this task via AJAX to obtain information
328 * about the various rate plans and final costs associated.
329 *
330 * @since 1.13 (J) - 1.3.0 (WP)
331 */
332 $only_rates = VikRequest::getInt('only_rates', 0, 'request');
333 $units = VikRequest::getInt('units', 1, 'request');
334 $checkinfdate = VikRequest::getString('checkinfdate', '', 'request');
335 $checkoutfdate = VikRequest::getString('checkoutfdate', '', 'request');
336 if (!empty($checkinfdate) && empty($checkin)) {
337 $checkin = date('Y-m-d', VikBooking::getDateTimestamp($checkinfdate, 0, 0, 0));
338 }
339
340 $checkin_ts = strtotime($checkin);
341 if (empty($checkin_ts)) {
342 $checkin = date('Y-m-d');
343 $checkin_ts = strtotime($checkin);
344 }
345
346 if (!empty($checkoutfdate) && !empty($checkinfdate) && $nights < 2) {
347 // checkout date was given rather than number of nights
348 $checkout_ts = VikBooking::getDateTimestamp($checkoutfdate, 0, 0, 0);
349 $checkout = date('Y-m-d', $checkout_ts);
350 $nights = $av_helper->countNightsOfStay($checkin_ts, $checkout_ts);
351 } else {
352 // calculate checkout depending on number of nights of stay
353 $is_dst = date('I', $checkin_ts);
354 $checkout_ts = $checkin_ts;
355 for ($i = 1; $i <= $nights; $i++) {
356 $checkout_ts += 86400;
357 $is_now_dst = date('I', $checkout_ts);
358 if ($is_dst != $is_now_dst) {
359 if ((int)$is_dst == 1) {
360 $checkout_ts += 3600;
361 } else {
362 $checkout_ts -= 3600;
363 }
364 $is_dst = $is_now_dst;
365 }
366 }
367 $checkout = date('Y-m-d', $checkout_ts);
368 }
369
370 /**
371 * We got rid of the CURL request to the front-end task of VBO "tac_av_l"
372 * by replacing the call with the new helper class VikBookingAvailability.
373 *
374 * @since 1.15.0 (J) - 1.5.0 (WP)
375 */
376 $av_helper->setStayDates($checkin, $checkout);
377 $av_helper->setRoomParty($adults, $children);
378 // build extra params to obtain the necessary data
379 $params = array(
380 'hash' => md5('vbo.e4j.vbo'),
381 'req_type' => 'hotel_availability',
382 'nights' => $nights,
383 'num_rooms' => 1,
384 'only_rates' => $only_rates,
385 );
386 $arr_res = $av_helper->getRates($params);
387
388 // pricing pool
389 $price_details = array();
390
391 if (is_array($arr_res)) {
392 if (!strlen($av_helper->getError())) {
393 if (array_key_exists($id_room, $arr_res)) {
394 $response = '';
395 foreach ($arr_res[$id_room] as $rate) {
396 // build pricing object
397 $rplan_details = new stdClass;
398 $rplan_details->idprice = $rate['idprice'];
399 $rplan_details->name = $rate['pricename'];
400 $rplan_details->net = $rate['cost'];
401 $rplan_details->fnet = $currencysymb . ' ' . VikBooking::numberFormat($rate['cost']);
402 $rplan_details->tax = $rate['taxes'];
403 $rplan_details->ftax = $currencysymb . ' ' . VikBooking::numberFormat($rate['taxes']);
404 $rplan_details->tot = $rate['cost'] + $rate['taxes'];
405 $rplan_details->ftot = $currencysymb . ' ' . VikBooking::numberFormat(($rate['cost'] + $rate['taxes']));
406 array_push($price_details, $rplan_details);
407 //
408 $extra_response = '';
409 $response .= '<div class="vbo-calcrates-rateblock" data-idprice="' . $rate['idprice'] . '" data-idroom="' . $id_room . '" data-checkin="' . $checkin . '" data-checkout="' . $checkout . '" data-adults="' . $adults . '" data-children="' . $children . '">';
410 $response .= '<span class="vbo-calcrates-ratename">'.$rate['pricename'].'</span>';
411 $response .= '<span class="vbo-calcrates-pricedet vbo-calcrates-ratenet"><span>'.JText::translate('VBCALCRATESNET').'</span>'.$currencysymb.' '.VikBooking::numberFormat($rate['cost']).'</span>';
412 $response .= '<span class="vbo-calcrates-pricedet vbo-calcrates-ratetax"><span>'.JText::translate('VBCALCRATESTAX').'</span>'.$currencysymb.' '.VikBooking::numberFormat($rate['taxes']).'</span>';
413 if (!empty($rate['city_taxes'])) {
414 $response .= '<span class="vbo-calcrates-pricedet vbo-calcrates-ratecitytax"><span>'.JText::translate('VBCALCRATESCITYTAX').'</span>'.$currencysymb.' '.VikBooking::numberFormat($rate['city_taxes']).'</span>';
415 }
416 if (!empty($rate['fees'])) {
417 $response .= '<span class="vbo-calcrates-pricedet vbo-calcrates-ratefees"><span>'.JText::translate('VBCALCRATESFEES').'</span>'.$currencysymb.' '.VikBooking::numberFormat($rate['fees']).'</span>';
418 }
419 if (array_key_exists('affdays', $rate) && $rate['affdays'] > 0) {
420 $extra_response .= '<span class="vbo-calcrates-extrapricedet vbo-calcrates-ratespaffdays"><span>'.JText::translate('VBCALCRATESSPAFFDAYS').'</span>'.$rate['affdays'].'</span>';
421 }
422 if (array_key_exists('diffusagediscount', $rate) && count($rate['diffusagediscount']) > 0) {
423 foreach ($rate['diffusagediscount'] as $roomnumb => $disc) {
424 $extra_response .= '<span class="vbo-calcrates-extrapricedet vbo-calcrates-rateoccupancydisc"><span>'.JText::sprintf('VBCALCRATESADUOCCUPANCY', $rate['diffusage']).'</span>- '.$currencysymb.' '.VikBooking::numberFormat($disc).'</span>';
425 break;
426 }
427 } elseif (array_key_exists('diffusagecost', $rate) && count($rate['diffusagecost']) > 0) {
428 foreach ($rate['diffusagecost'] as $roomnumb => $charge) {
429 $extra_response .= '<span class="vbo-calcrates-extrapricedet vbo-calcrates-rateoccupancycharge"><span>'.JText::sprintf('VBCALCRATESADUOCCUPANCY', $rate['diffusage']).'</span>+ '.$currencysymb.' '.VikBooking::numberFormat($charge).'</span>';
430 break;
431 }
432 }
433 $tot = $rate['cost'] + $rate['taxes'] + $rate['city_taxes'] + $rate['fees'];
434 $tot = round($tot, 2);
435 $response .= '<span class="vbo-calcrates-ratetotal"><span>'.JText::translate('VBCALCRATESTOT').'</span>'.$currencysymb.' '.VikBooking::numberFormat($tot).'</span>';
436 if (!empty($extra_response)) {
437 $response .= '<div class="vbo-calcrates-info">'.$extra_response.'</div>';
438 }
439 $response .= '</div>';
440 }
441 } else {
442 $response = 'e4j.error.'.JText::sprintf('VBCALCRATESROOMNOTAVAILCOMBO', date($df, $checkin_ts), date($df, $checkout_ts));
443 /**
444 * Set a response code so that the View calendar can understand that the room is not available or has no rates.
445 *
446 * @since 1.14 (J) - 1.4.0 (WP)
447 */
448 if (isset($arr_res['fullybooked']) && in_array($id_room, $arr_res['fullybooked'])) {
449 $response_code = -1;
450 }
451 }
452 } else {
453 $response = 'e4j.error.' . $av_helper->getError();
454 /**
455 * Set a response code so that the View calendar can understand that the room is not available or has no rates.
456 *
457 * @since 1.14 (J) - 1.4.0 (WP)
458 */
459 if (isset($arr_res['fullybooked']) && in_array($id_room, $arr_res['fullybooked'])) {
460 $response_code = -1;
461 }
462 }
463 } else {
464 $response = 'e4j.error.' . $av_helper->getError();
465 }
466
467 if ($only_rates && strpos($response, 'e4j.error') === false) {
468 echo json_encode($price_details);
469 exit;
470 }
471
472 // do not do only echo trim($response); or the currency symbol will not be encoded on some servers
473 $safe_response = array(trim($response));
474 if ($only_rates && !empty($response_code)) {
475 array_push($safe_response, $response_code);
476 }
477
478 echo json_encode($safe_response);
479 exit;
480 }
481
482 /**
483 * This is an AJAX endpoint.
484 */
485 public function cron_exec()
486 {
487 ob_start();
488
489 VikRequest::setVar('view', VikRequest::getCmd('view', 'cronexec'));
490
491 parent::display();
492
493 $content = ob_get_contents();
494 ob_end_clean();
495
496 VBOHttpDocument::getInstance()->json([$content]);
497 }
498
499 public function downloadcron()
500 {
501 /**
502 * @wponly no more executable files need to be downloaded for WordPress.
503 */
504 VBOHttpDocument::getInstance()->close(406, 'Cron Jobs must be executed through WPCron');
505 }
506
507 /**
508 * This is an AJAX endpoint.
509 */
510 public function cronlogs()
511 {
512 $dbo = JFactory::getDBO();
513 $pcron_id = VikRequest::getInt('cron_id', '', 'request');
514
515 ob_start();
516
517 $q = "SELECT * FROM `#__vikbooking_cronjobs` WHERE `id`=".(int)$pcron_id.";";
518 $dbo->setQuery($q);
519 $dbo->execute();
520 if ($dbo->getNumRows() == 1) {
521 $cron_data = $dbo->loadAssoc();
522 $cron_data['logs'] = empty($cron_data['logs']) ? '--------' : $cron_data['logs'];
523 echo '<pre>'.print_r($cron_data['logs'], true).'</pre>';
524 }
525
526 $content = ob_get_contents();
527 ob_end_clean();
528
529 VBOHttpDocument::getInstance()->json([$content]);
530 }
531
532 public function packages() {
533 VikBookingHelper::printHeader("packages");
534
535 VikRequest::setVar('view', VikRequest::getCmd('view', 'packages'));
536
537 parent::display();
538
539 if (VikBooking::showFooter()) {
540 VikBookingHelper::printFooter();
541 }
542 }
543
544 public function newpackage() {
545 VikBookingHelper::printHeader("packages");
546
547 VikRequest::setVar('view', VikRequest::getCmd('view', 'managepackage'));
548
549 parent::display();
550
551 if (VikBooking::showFooter()) {
552 VikBookingHelper::printFooter();
553 }
554 }
555
556 public function editpackage() {
557 VikBookingHelper::printHeader("packages");
558
559 VikRequest::setVar('view', VikRequest::getCmd('view', 'managepackage'));
560
561 parent::display();
562
563 if (VikBooking::showFooter()) {
564 VikBookingHelper::printFooter();
565 }
566 }
567
568 public function createpackage()
569 {
570 if (!JSession::checkToken()) {
571 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
572 }
573
574 if (!JFactory::getUser()->authorise('core.create', 'com_vikbooking')) {
575 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
576 }
577
578 $this->do_createpackage();
579 }
580
581 public function createpackagestay()
582 {
583 if (!JSession::checkToken()) {
584 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
585 }
586
587 if (!JFactory::getUser()->authorise('core.create', 'com_vikbooking')) {
588 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
589 }
590
591 $this->do_createpackage(true);
592 }
593
594 private function do_createpackage($stay = false) {
595 $dbo = JFactory::getDBO();
596 $mainframe = JFactory::getApplication();
597 $pname = VikRequest::getString('name', '', 'request');
598 $palias = VikRequest::getString('alias', '', 'request');
599 $palias = empty($palias) ? $pname : $palias;
600 $palias = JFilterOutput::stringURLSafe($palias);
601 $pimg = VikRequest::getVar('img', null, 'files', 'array');
602 $pfrom = VikRequest::getString('from', '', 'request');
603 $pto = VikRequest::getString('to', '', 'request');
604 $pexcludeday = VikRequest::getVar('excludeday', array());
605 $strexcldates = array();
606 foreach ($pexcludeday as $exclday) {
607 if (!empty($exclday)) {
608 $strexcldates[] = $exclday;
609 }
610 }
611 $strexcldates = implode(';', $strexcldates);
612 $prooms = VikRequest::getVar('rooms', array());
613 $pminlos = VikRequest::getInt('minlos', '', 'request');
614 $pminlos = $pminlos < 1 ? 1 : $pminlos;
615 $pmaxlos = VikRequest::getInt('maxlos', '', 'request');
616 $pmaxlos = $pmaxlos < 0 ? 0 : $pmaxlos;
617 $pmaxlos = $pmaxlos < $pminlos ? 0 : $pmaxlos;
618 $pcost = VikRequest::getFloat('cost', '', 'request');
619 $paliq = VikRequest::getInt('aliq', '', 'request');
620 $ppernight_total = VikRequest::getInt('pernight_total', '', 'request');
621 $ppernight_total = $ppernight_total == 1 ? 1 : 2;
622 $pperperson = VikRequest::getInt('perperson', '', 'request');
623 $pperperson = $pperperson > 0 ? 1 : 0;
624 $pshowoptions = VikRequest::getInt('showoptions', '', 'request');
625 $pshowoptions = $pshowoptions >= 1 && $pshowoptions <= 3 ? $pshowoptions : 1;
626 $pdescr = VikRequest::getString('descr', '', 'request', VIKREQUEST_ALLOWRAW);
627 $pshortdescr = VikRequest::getString('shortdescr', '', 'request', VIKREQUEST_ALLOWHTML);
628 $pconditions = VikRequest::getString('conditions', '', 'request', VIKREQUEST_ALLOWRAW);
629 $pbenefits = VikRequest::getString('benefits', '', 'request', VIKREQUEST_ALLOWHTML);
630 $ptsinit = VikBooking::getDateTimestamp($pfrom, '0', '0');
631 $ptsend = VikBooking::getDateTimestamp($pto, '23', '59');
632 $ptsinit = empty($ptsinit) ? time() : $ptsinit;
633 $ptsend = empty($ptsend) || $ptsend < $ptsinit ? $ptsinit : $ptsend;
634 //file upload
635 jimport('joomla.filesystem.file');
636 $gimg = "";
637 if (isset($pimg) && strlen(trim($pimg['name']))) {
638 $pautoresize = VikRequest::getString('autoresize', '', 'request');
639 $presizeto = VikRequest::getInt('resizeto', '', 'request');
640 $creativik = new vikResizer();
641 $filename = JFile::makeSafe(str_replace(" ", "_", strtolower($pimg['name'])));
642 $src = $pimg['tmp_name'];
643 $dest = VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR;
644 $j = "";
645 if (file_exists($dest.$filename)) {
646 $j = rand(171, 1717);
647 while (file_exists($dest.$j.$filename)) {
648 $j++;
649 }
650 }
651 $finaldest = $dest.$j.$filename;
652 $check = getimagesize($pimg['tmp_name']);
653 if ($check[2] & imagetypes()) {
654 if (VikBooking::uploadFile($src, $finaldest)) {
655 $gimg = $j.$filename;
656 //orig img
657 $origmod = true;
658 if ($pautoresize == "1" && !empty($presizeto)) {
659 $origmod = $creativik->proportionalImage($finaldest, $dest.'big_'.$j.$filename, $presizeto, $presizeto);
660 } else {
661 VikBooking::uploadFile($finaldest, $dest.'big_'.$j.$filename, true);
662 }
663 //thumb
664 $thumbsize = VikBooking::getThumbSize();
665 $thumb = $creativik->proportionalImage($finaldest, $dest.'thumb_'.$j.$filename, $thumbsize, $thumbsize);
666 if (!$thumb || !$origmod) {
667 if (file_exists($dest.'big_'.$j.$filename)) @unlink($dest.'big_'.$j.$filename);
668 if (file_exists($dest.'thumb_'.$j.$filename)) @unlink($dest.'thumb_'.$j.$filename);
669 VikError::raiseWarning('', 'Error Uploading the File: '.$pimg['name']);
670 }
671 @unlink($finaldest);
672 } else {
673 VikError::raiseWarning('', 'Error while uploading image');
674 }
675 } else {
676 VikError::raiseWarning('', 'Uploaded file is not an Image');
677 }
678 }
679 //
680 $goto = "index.php?option=com_vikbooking&task=packages";
681 $q = "INSERT INTO `#__vikbooking_packages` (`name`,`alias`,`img`,`dfrom`,`dto`,`excldates`,`minlos`,`maxlos`,`cost`,`idiva`,`pernight_total`,`perperson`,`descr`,`shortdescr`,`benefits`,`conditions`,`showoptions`) VALUES (".$dbo->quote($pname).", ".$dbo->quote($palias).", ".$dbo->quote($gimg).", ".(int)$ptsinit.", ".(int)$ptsend.", ".$dbo->quote($strexcldates).", ".(int)$pminlos.", ".(int)$pmaxlos.", ".$dbo->quote($pcost).",'".$paliq."', ".(int)$ppernight_total.", ".(int)$pperperson.", ".$dbo->quote($pdescr).", ".$dbo->quote($pshortdescr).", ".$dbo->quote($pbenefits).", ".$dbo->quote($pconditions).", ".(int)$pshowoptions.");";
682 $dbo->setQuery($q);
683 $dbo->execute();
684 $lid = $dbo->insertid();
685 if (!empty($lid)) {
686 $mainframe->enqueueMessage(JText::translate('VBOPKGSAVED'));
687 if ($stay) {
688 $goto = "index.php?option=com_vikbooking&task=editpackage&cid[]=".$lid;
689 }
690 foreach ($prooms as $roomid) {
691 if (!empty($roomid)) {
692 $q = "INSERT INTO `#__vikbooking_packages_rooms` (`idpackage`,`idroom`) VALUES (".(int)$lid.", ".(int)$roomid.");";
693 $dbo->setQuery($q);
694 $dbo->execute();
695 }
696 }
697 }
698 $mainframe->redirect($goto);
699 }
700
701 public function updatepackage()
702 {
703 if (!JSession::checkToken()) {
704 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
705 }
706
707 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
708 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
709 }
710
711 $this->do_updatepackage();
712 }
713
714 public function updatepackagestay()
715 {
716 if (!JSession::checkToken()) {
717 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
718 }
719
720 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
721 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
722 }
723
724 $this->do_updatepackage(true);
725 }
726
727 private function do_updatepackage($stay = false) {
728 $dbo = JFactory::getDBO();
729 $mainframe = JFactory::getApplication();
730 $pwhereup = VikRequest::getInt('whereup', '', 'request');
731 $q = "SELECT * FROM `#__vikbooking_packages` WHERE `id`=".(int)$pwhereup.";";
732 $dbo->setQuery($q);
733 $dbo->execute();
734 if ($dbo->getNumRows() == 1) {
735 $pkg_data = $dbo->loadAssoc();
736 } else {
737 VikError::raiseWarning('', 'Not Found.');
738 $mainframe->redirect("index.php?option=com_vikbooking&task=packages");
739 exit;
740 }
741 $pname = VikRequest::getString('name', '', 'request');
742 $palias = VikRequest::getString('alias', '', 'request');
743 $palias = empty($palias) ? $pname : $palias;
744 $palias = JFilterOutput::stringURLSafe($palias);
745 $pimg = VikRequest::getVar('img', null, 'files', 'array');
746 $pfrom = VikRequest::getString('from', '', 'request');
747 $pto = VikRequest::getString('to', '', 'request');
748 $pexcludeday = VikRequest::getVar('excludeday', array());
749 $strexcldates = array();
750 foreach ($pexcludeday as $exclday) {
751 if (!empty($exclday)) {
752 $strexcldates[] = $exclday;
753 }
754 }
755 $strexcldates = implode(';', $strexcldates);
756 $prooms = VikRequest::getVar('rooms', array());
757 $pminlos = VikRequest::getInt('minlos', '', 'request');
758 $pminlos = $pminlos < 1 ? 1 : $pminlos;
759 $pmaxlos = VikRequest::getInt('maxlos', '', 'request');
760 $pmaxlos = $pmaxlos < 0 ? 0 : $pmaxlos;
761 $pmaxlos = $pmaxlos < $pminlos ? 0 : $pmaxlos;
762 $pcost = VikRequest::getFloat('cost', '', 'request');
763 $paliq = VikRequest::getInt('aliq', '', 'request');
764 $ppernight_total = VikRequest::getInt('pernight_total', '', 'request');
765 $ppernight_total = $ppernight_total == 1 ? 1 : 2;
766 $pperperson = VikRequest::getInt('perperson', '', 'request');
767 $pperperson = $pperperson > 0 ? 1 : 0;
768 $pshowoptions = VikRequest::getInt('showoptions', '', 'request');
769 $pshowoptions = $pshowoptions >= 1 && $pshowoptions <= 3 ? $pshowoptions : 1;
770 $pdescr = VikRequest::getString('descr', '', 'request', VIKREQUEST_ALLOWRAW);
771 $pshortdescr = VikRequest::getString('shortdescr', '', 'request', VIKREQUEST_ALLOWHTML);
772 $pconditions = VikRequest::getString('conditions', '', 'request', VIKREQUEST_ALLOWRAW);
773 $pbenefits = VikRequest::getString('benefits', '', 'request', VIKREQUEST_ALLOWHTML);
774 $ptsinit = VikBooking::getDateTimestamp($pfrom, '0', '0');
775 $ptsend = VikBooking::getDateTimestamp($pto, '23', '59');
776 $ptsinit = empty($ptsinit) ? time() : $ptsinit;
777 $ptsend = empty($ptsend) || $ptsend < $ptsinit ? $ptsinit : $ptsend;
778 //file upload
779 jimport('joomla.filesystem.file');
780 $gimg = "";
781 if (isset($pimg) && strlen(trim($pimg['name']))) {
782 $pautoresize = VikRequest::getString('autoresize', '', 'request');
783 $presizeto = VikRequest::getInt('resizeto', '', 'request');
784 $creativik = new vikResizer();
785 $filename = JFile::makeSafe(str_replace(" ", "_", strtolower($pimg['name'])));
786 $src = $pimg['tmp_name'];
787 $dest = VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR;
788 $j = "";
789 if (file_exists($dest.$filename)) {
790 $j = rand(171, 1717);
791 while (file_exists($dest.$j.$filename)) {
792 $j++;
793 }
794 }
795 $finaldest = $dest.$j.$filename;
796 $check = getimagesize($pimg['tmp_name']);
797 if ($check[2] & imagetypes()) {
798 if (VikBooking::uploadFile($src, $finaldest)) {
799 $gimg = $j.$filename;
800 //orig img
801 $origmod = true;
802 if ($pautoresize == "1" && !empty($presizeto)) {
803 $origmod = $creativik->proportionalImage($finaldest, $dest.'big_'.$j.$filename, $presizeto, $presizeto);
804 } else {
805 VikBooking::uploadFile($finaldest, $dest.'big_'.$j.$filename, true);
806 }
807 //thumb
808 $thumbsize = VikBooking::getThumbSize();
809 $thumb = $creativik->proportionalImage($finaldest, $dest.'thumb_'.$j.$filename, $thumbsize, $thumbsize);
810 if (!$thumb || !$origmod) {
811 if (file_exists($dest.'big_'.$j.$filename)) @unlink($dest.'big_'.$j.$filename);
812 if (file_exists($dest.'thumb_'.$j.$filename)) @unlink($dest.'thumb_'.$j.$filename);
813 VikError::raiseWarning('', 'Error Uploading the File: '.$pimg['name']);
814 }
815 @unlink($finaldest);
816 } else {
817 VikError::raiseWarning('', 'Error while uploading image');
818 }
819 } else {
820 VikError::raiseWarning('', 'Uploaded file is not an Image');
821 }
822 }
823 //
824 $goto = "index.php?option=com_vikbooking&task=packages";
825 $q = "UPDATE `#__vikbooking_packages` SET `name`=".$dbo->quote($pname).",`alias`=".$dbo->quote($palias)."".(!empty($gimg) ? ",`img`=".$dbo->quote($gimg) : "").",`dfrom`=".(int)$ptsinit.",`dto`=".(int)$ptsend.",`excldates`=".$dbo->quote($strexcldates).",`minlos`=".(int)$pminlos.",`maxlos`=".(int)$pmaxlos.",`cost`=".$dbo->quote($pcost).",`idiva`='".$paliq."',`pernight_total`=".(int)$ppernight_total.",`perperson`=".(int)$pperperson.",`descr`=".$dbo->quote($pdescr).",`shortdescr`=".$dbo->quote($pshortdescr).",`benefits`=".$dbo->quote($pbenefits).",`conditions`=".$dbo->quote($pconditions).",`showoptions`=".(int)$pshowoptions." WHERE `id`=".(int)$pwhereup.";";
826 $dbo->setQuery($q);
827 $dbo->execute();
828 $q = "DELETE FROM `#__vikbooking_packages_rooms` WHERE `idpackage`=".(int)$pwhereup.";";
829 $dbo->setQuery($q);
830 $dbo->execute();
831 foreach ($prooms as $roomid) {
832 if (!empty($roomid)) {
833 $q = "INSERT INTO `#__vikbooking_packages_rooms` (`idpackage`,`idroom`) VALUES (".(int)$pwhereup.", ".(int)$roomid.");";
834 $dbo->setQuery($q);
835 $dbo->execute();
836 }
837 }
838 $mainframe->enqueueMessage(JText::translate('VBOPKGUPDATED'));
839 if ($stay) {
840 $goto = "index.php?option=com_vikbooking&task=editpackage&cid[]=".$pwhereup;
841 }
842 $mainframe->redirect($goto);
843 }
844
845 public function removepackages()
846 {
847 if (!JSession::checkToken()) {
848 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
849 }
850
851 if (!JFactory::getUser()->authorise('core.delete', 'com_vikbooking')) {
852 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
853 }
854
855 $ids = VikRequest::getVar('cid', array());
856 $dbo = JFactory::getDbo();
857
858 foreach ($ids as $d) {
859 $q = "DELETE FROM `#__vikbooking_packages` WHERE `id`=".(int)$d.";";
860 $dbo->setQuery($q);
861 $dbo->execute();
862 $q = "DELETE FROM `#__vikbooking_packages_rooms` WHERE `idpackage`=".(int)$d.";";
863 $dbo->setQuery($q);
864 $dbo->execute();
865 }
866
867 $mainframe = JFactory::getApplication();
868 $mainframe->redirect("index.php?option=com_vikbooking&task=packages");
869 }
870
871 public function calendar() {
872 VikBookingHelper::printHeader("19");
873
874 VikRequest::setVar('view', VikRequest::getCmd('view', 'calendar'));
875
876 parent::display();
877
878 if (VikBooking::showFooter()) {
879 VikBookingHelper::printFooter();
880 }
881 }
882
883 public function rooms() {
884 VikBookingHelper::printHeader("7");
885
886 VikRequest::setVar('view', VikRequest::getCmd('view', 'rooms'));
887
888 parent::display();
889
890 if (VikBooking::showFooter()) {
891 VikBookingHelper::printFooter();
892 }
893 }
894
895 public function newroom() {
896 VikBookingHelper::printHeader("7");
897
898 VikRequest::setVar('view', VikRequest::getCmd('view', 'manageroom'));
899
900 parent::display();
901
902 if (VikBooking::showFooter()) {
903 VikBookingHelper::printFooter();
904 }
905 }
906
907 public function editroom() {
908 VikBookingHelper::printHeader("7");
909
910 VikRequest::setVar('view', VikRequest::getCmd('view', 'manageroom'));
911
912 parent::display();
913
914 if (VikBooking::showFooter()) {
915 VikBookingHelper::printFooter();
916 }
917 }
918
919 public function createroom()
920 {
921 if (!JSession::checkToken()) {
922 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
923 }
924
925 if (!JFactory::getUser()->authorise('core.create', 'com_vikbooking')) {
926 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
927 }
928
929 $this->do_createroom();
930 }
931
932 public function createroomstay()
933 {
934 if (!JSession::checkToken()) {
935 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
936 }
937
938 if (!JFactory::getUser()->authorise('core.create', 'com_vikbooking')) {
939 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
940 }
941
942 $this->do_createroom(true);
943 }
944
945 private function do_createroom($stay = false) {
946 $app = JFactory::getApplication();
947 $pcname = VikRequest::getString('cname', '', 'request');
948 $pccat = VikRequest::getVar('ccat', array(0));
949 $pcdescr = VikRequest::getString('cdescr', '', 'request', VIKREQUEST_ALLOWRAW);
950 $psmalldesc = VikRequest::getString('smalldesc', '', 'request', VIKREQUEST_ALLOWRAW);
951 $pccarat = VikRequest::getVar('ccarat', array(0));
952 $pcoptional = VikRequest::getVar('coptional', array(0));
953 $pcavail = VikRequest::getString('cavail', '', 'request');
954 $pautoresize = VikRequest::getString('autoresize', '', 'request');
955 $presizeto = VikRequest::getString('resizeto', '', 'request');
956 $pautoresizemore = VikRequest::getString('autoresizemore', '', 'request');
957 $presizetomore = VikRequest::getString('resizetomore', '', 'request');
958 $punits = VikRequest::getInt('units', '', 'request');
959 $pimages = VikRequest::getVar('cimgmore', null, 'files', 'array');
960 $pfromadult = VikRequest::getInt('fromadult', '', 'request');
961 $ptoadult = VikRequest::getInt('toadult', '', 'request');
962 $pfromchild = VikRequest::getInt('fromchild', '', 'request');
963 $ptochild = VikRequest::getInt('tochild', '', 'request');
964 $ptotpeople = VikRequest::getInt('totpeople', '', 'request');
965 $pmintotpeople = VikRequest::getInt('mintotpeople', '', 'request');
966 $pmintotpeople = $pmintotpeople < 1 ? 1 : $pmintotpeople;
967 $plastavail = VikRequest::getString('lastavail', '', 'request');
968 $plastavail = empty($plastavail) ? 0 : intval($plastavail);
969 $psuggocc = VikRequest::getInt('suggocc', 1, 'request');
970 $pcustprice = VikRequest::getString('custprice', '', 'request');
971 $pcustprice = empty($pcustprice) ? '' : floatval($pcustprice);
972 $pcustpricetxt = VikRequest::getString('custpricetxt', '', 'request', VIKREQUEST_ALLOWRAW);
973 $pcustpricesubtxt = VikRequest::getString('custpricesubtxt', '', 'request', VIKREQUEST_ALLOWRAW);
974 $preqinfo = VikRequest::getInt('reqinfo', '', 'request');
975 $ppricecal = VikRequest::getInt('pricecal', '', 'request');
976 $pdefcalcost = VikRequest::getString('defcalcost', '', 'request');
977 $pmaxminpeople = VikRequest::getString('maxminpeople', '', 'request');
978 $pcimgcaption = VikRequest::getVar('cimgcaption', array());
979 $pmaxminpeople = in_array($pmaxminpeople, array('0', '1', '2', '3', '4', '5')) ? $pmaxminpeople : '0';
980 $pseasoncal = VikRequest::getInt('seasoncal', 0, 'request');
981 $pseasoncal = $pseasoncal >= 0 || $pseasoncal <= 3 ? $pseasoncal : 0;
982 $pseasoncal_nights = VikRequest::getString('seasoncal_nights', '', 'request');
983 $pseasoncal_prices = VikRequest::getString('seasoncal_prices', '', 'request');
984 $pseasoncal_restr = VikRequest::getString('seasoncal_restr', '', 'request');
985 $pmulti_units = VikRequest::getInt('multi_units', '', 'request');
986 $pmulti_units = $punits > 1 ? $pmulti_units : 0;
987 $psefalias = VikRequest::getString('sefalias', '', 'request');
988 $psefalias = empty($psefalias) ? JFilterOutput::stringURLSafe($pcname) : JFilterOutput::stringURLSafe($psefalias);
989 $pcustptitle = VikRequest::getString('custptitle', '', 'request');
990 $pcustptitlew = VikRequest::getString('custptitlew', '', 'request');
991 $pcustptitlew = in_array($pcustptitlew, array('before', 'after', 'replace')) ? $pcustptitlew : 'before';
992 $pmetakeywords = VikRequest::getString('metakeywords', '', 'request');
993 $pmetadescription = VikRequest::getString('metadescription', '', 'request');
994 $pshare_with = VikRequest::getVar('share_with', array());
995 $scalnights_arr = array();
996 if (!empty($pseasoncal_nights)) {
997 $scalnights = explode(',', $pseasoncal_nights);
998 foreach ($scalnights as $scalnight) {
999 if (intval(trim($scalnight)) > 0) {
1000 $scalnights_arr[] = intval(trim($scalnight));
1001 }
1002 }
1003 }
1004 if (count($scalnights_arr) > 0) {
1005 $pseasoncal_nights = implode(', ', $scalnights_arr);
1006 } else {
1007 $pseasoncal_nights = '';
1008 $pseasoncal = 0;
1009 }
1010 $roomparams = array('lastavail' => $plastavail, 'suggocc' => $psuggocc, 'custprice' => $pcustprice, 'custpricetxt' => $pcustpricetxt, 'custpricesubtxt' => $pcustpricesubtxt, 'reqinfo' => $preqinfo, 'pricecal' => $ppricecal, 'defcalcost' => floatval($pdefcalcost), 'maxminpeople' => $pmaxminpeople, 'seasoncal' => $pseasoncal, 'seasoncal_nights' => $pseasoncal_nights, 'seasoncal_prices' => $pseasoncal_prices, 'seasoncal_restr' => $pseasoncal_restr, 'multi_units' => $pmulti_units, 'custptitle' => $pcustptitle, 'custptitlew' => $pcustptitlew, 'metakeywords' => $pmetakeywords, 'metadescription' => $pmetadescription);
1011 //distinctive features
1012 $roomparams['features'] = array();
1013 if ($punits > 0) {
1014 for ($i=1; $i <= $punits; $i++) {
1015 $distf_name = VikRequest::getVar('feature-name'.$i, array());
1016 $distf_lang = VikRequest::getVar('feature-lang'.$i, array());
1017 $distf_value = VikRequest::getVar('feature-value'.$i, array());
1018 foreach ($distf_name as $distf_k => $distf) {
1019 if (strlen($distf) > 0 && strlen($distf_value[$distf_k]) > 0) {
1020 $use_key = strlen($distf_lang[$distf_k]) > 0 ? $distf_lang[$distf_k] : $distf;
1021 $roomparams['features'][$i][$use_key] = $distf_value[$distf_k];
1022 }
1023 }
1024 }
1025 }
1026
1027 /**
1028 * Store room geo params information.
1029 *
1030 * @since 1.14 (J) - 1.4.0 (WP)
1031 */
1032 $geo = VikBooking::getGeocodingInstance();
1033 $geo_params = $geo->getRoomGeoTransient(0);
1034 if ($geo_params !== false) {
1035 // make sure the geocoding service was not turned off
1036 $geo_enabled = VikRequest::getInt('geo_enabled', 0, 'request');
1037 if (!$geo_enabled) {
1038 $geo_params->enabled = 0;
1039 }
1040 //
1041 $roomparams['geo'] = $geo_params;
1042 }
1043 //
1044
1045 $roomparamstr = json_encode($roomparams);
1046
1047 if (empty($pcname)) {
1048 $app->enqueueMessage(JText::translate('VBO_PLEASE_FILL_FIELDS'), 'error');
1049 $app->redirect("index.php?option=com_vikbooking&task=rooms");
1050 $app->close();
1051 }
1052
1053 jimport('joomla.filesystem.file');
1054 $updpath = VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR;
1055
1056 if (intval($_FILES['cimg']['error']) == 0 && VikBooking::caniWrite($updpath) && trim($_FILES['cimg']['name'])!="") {
1057 if (@is_uploaded_file($_FILES['cimg']['tmp_name'])) {
1058 $safename = JFile::makeSafe(str_replace(" ", "_", strtolower($_FILES['cimg']['name'])));
1059 if (file_exists($updpath.$safename)) {
1060 $j = 1;
1061 while (file_exists($updpath.$j.$safename)) {
1062 $j++;
1063 }
1064 $pwhere = $updpath.$j.$safename;
1065 } else {
1066 $j = "";
1067 $pwhere = $updpath.$safename;
1068 }
1069 if (!getimagesize($_FILES['cimg']['tmp_name']) || !preg_match("/\.(a?png|jpe?g|bmp|gif|ico|webp)\z/i", $safename)) {
1070 @unlink($pwhere);
1071 $picon = "";
1072 } else {
1073 VikBooking::uploadFile($_FILES['cimg']['tmp_name'], $pwhere);
1074 @chmod($pwhere, 0644);
1075 $picon = $j.$safename;
1076 if ($pautoresize=="1" && !empty($presizeto)) {
1077 $eforj = new vikResizer();
1078 $origmod = $eforj->proportionalImage($pwhere, $updpath.'r_'.$j.$safename, $presizeto, $presizeto);
1079 if ($origmod) {
1080 @unlink($pwhere);
1081 $picon = 'r_'.$j.$safename;
1082 }
1083 }
1084 }
1085 } else {
1086 $picon = "";
1087 }
1088 } else {
1089 $picon = "";
1090 }
1091 //more images
1092 $creativik = new vikResizer();
1093 $bigsdest = $updpath;
1094 $thumbsdest = $updpath;
1095 $dest = $updpath;
1096 $moreimagestr = "";
1097 $arrimgs = array();
1098 $captiontexts = array();
1099 $imgcaptions = array();
1100 foreach ($pimages['name'] as $kk=>$ci) {
1101 if (!empty($ci)) {
1102 $arrimgs[] = $kk;
1103 $captiontexts[] = isset($pcimgcaption[$kk]) ? $pcimgcaption[$kk] : '';
1104 }
1105 }
1106 foreach ($arrimgs as $ki => $imgk) {
1107 if (strlen(trim($pimages['name'][$imgk]))) {
1108 $filename = JFile::makeSafe(str_replace(" ", "_", strtolower($pimages['name'][$imgk])));
1109 $src = $pimages['tmp_name'][$imgk];
1110 $j = "";
1111 if (file_exists($dest.$filename)) {
1112 $j = rand(171, 1717);
1113 while (file_exists($dest.$j.$filename)) {
1114 $j++;
1115 }
1116 }
1117 $finaldest = $dest.$j.$filename;
1118 $check = getimagesize($pimages['tmp_name'][$imgk]);
1119 if (($check[2] & imagetypes()) && preg_match("/\.(a?png|jpe?g|bmp|gif|ico|webp)\z/i", $filename)) {
1120 if (VikBooking::uploadFile($src, $finaldest)) {
1121 $gimg = $j.$filename;
1122 //orig img
1123 $origmod = true;
1124 if ($pautoresizemore == "1" && !empty($presizetomore)) {
1125 $origmod = $creativik->proportionalImage($finaldest, $bigsdest.'big_'.$j.$filename, $presizetomore, $presizetomore);
1126 } else {
1127 VikBooking::uploadFile($finaldest, $bigsdest.'big_'.$j.$filename, true);
1128 }
1129 //thumb
1130 $thumbsize = VikBooking::getThumbSize();
1131 $thumb = $creativik->proportionalImage($finaldest, $thumbsdest.'thumb_'.$j.$filename, $thumbsize, $thumbsize);
1132 if (!$thumb || !$origmod) {
1133 if (file_exists($bigsdest.'big_'.$j.$filename)) @unlink($bigsdest.'big_'.$j.$filename);
1134 if (file_exists($thumbsdest.'thumb_'.$j.$filename)) @unlink($thumbsdest.'thumb_'.$j.$filename);
1135 VikError::raiseWarning('', 'Error While Uploading the File: '.$pimages['name'][$imgk]);
1136 } else {
1137 $moreimagestr .= $j.$filename.";;";
1138 $imgcaptions[] = $captiontexts[$ki];
1139 }
1140 @unlink($finaldest);
1141 } else {
1142 VikError::raiseWarning('', 'Error While Uploading the File: '.$pimages['name'][$imgk]);
1143 }
1144 } else {
1145 VikError::raiseWarning('', 'Error While Uploading the File: '.$pimages['name'][$imgk]);
1146 }
1147 }
1148 }
1149 //end more images
1150 if (is_array($pccat) && count($pccat)) {
1151 $pccatdef="";
1152 foreach ($pccat as $ccat) {
1153 if (!empty($ccat)) {
1154 $pccatdef.=$ccat.";";
1155 }
1156 }
1157 } else {
1158 $pccatdef="";
1159 }
1160 if (is_array($pccarat) && count($pccarat)) {
1161 $pccaratdef="";
1162 foreach ($pccarat as $ccarat) {
1163 $pccaratdef.=$ccarat.";";
1164 }
1165 } else {
1166 $pccaratdef="";
1167 }
1168 if (is_array($pcoptional) && count($pcoptional)) {
1169 $pcoptionaldef="";
1170 foreach ($pcoptional as $coptional) {
1171 $pcoptionaldef.=$coptional.";";
1172 }
1173 } else {
1174 $pcoptionaldef="";
1175 }
1176 $pcavaildef=($pcavail=="yes" ? "1" : "0");
1177 if ($pfromadult > $ptoadult) {
1178 $pfromadult = 1;
1179 $ptoadult = 1;
1180 }
1181 if ($pfromchild > $ptochild) {
1182 $pfromchild = 1;
1183 $ptochild = 1;
1184 }
1185 $dbo = JFactory::getDbo();
1186 $q = "INSERT INTO `#__vikbooking_rooms` (`name`,`img`,`idcat`,`idcarat`,`idopt`,`info`,`avail`,`units`,`moreimgs`,`fromadult`,`toadult`,`fromchild`,`tochild`,`smalldesc`,`totpeople`,`mintotpeople`,`params`,`imgcaptions`,`alias`) VALUES(".$dbo->quote($pcname).",".$dbo->quote($picon).",".$dbo->quote($pccatdef).",".$dbo->quote($pccaratdef).",".$dbo->quote($pcoptionaldef).",".$dbo->quote($pcdescr).",".$dbo->quote($pcavaildef).",".($punits > 0 ? $dbo->quote($punits) : "'1'").", ".$dbo->quote($moreimagestr).", '".$pfromadult."', '".$ptoadult."', '".$pfromchild."', '".$ptochild."', ".$dbo->quote($psmalldesc).", ".$ptotpeople.", ".$pmintotpeople.", ".$dbo->quote($roomparamstr).", ".$dbo->quote(json_encode($imgcaptions)).",".$dbo->quote($psefalias).");";
1187 $dbo->setQuery($q);
1188 $dbo->execute();
1189 $lid = $dbo->insertid();
1190 if (empty($lid)) {
1191 $app->enqueueMessage('Could not store the record on the database', 'error');
1192 $app->redirect("index.php?option=com_vikbooking&task=rooms");
1193 $app->close();
1194 }
1195
1196 /**
1197 * Share availability calendars with other rooms.
1198 *
1199 * @since 1.13
1200 */
1201 // always reset relations for this main room
1202 $q = "DELETE FROM `#__vikbooking_calendars_xref` WHERE `mainroom`={$lid};";
1203 $dbo->setQuery($q);
1204 $dbo->execute();
1205 $newxref = array();
1206 foreach ($pshare_with as $cldroom) {
1207 if (!empty($cldroom)) {
1208 array_push($newxref, (int)$cldroom);
1209 }
1210 }
1211 foreach ($newxref as $cldroom) {
1212 $q = "INSERT INTO `#__vikbooking_calendars_xref` (`mainroom`, `childroom`) VALUES ({$lid}, {$cldroom});";
1213 $dbo->setQuery($q);
1214 $dbo->execute();
1215 }
1216
1217 /**
1218 * Room upgrade options.
1219 *
1220 * @since 1.16.0 (J) - 1.6.0 (WP)
1221 */
1222 $config = VBOFactory::getConfig();
1223 $room_upgrade_options = [];
1224 $room_upgrade = VikRequest::getInt('room_upgrade', 0, 'request');
1225 $upgrade_rooms = VikRequest::getVar('upgrade_rooms', array());
1226 $upgrade_discount = VikRequest::getFloat('upgrade_discount', 0, 'request');
1227 if ($room_upgrade && is_array($upgrade_rooms) && count($upgrade_rooms)) {
1228 $upgrade_rooms = array_map(function($rid) {
1229 return (int)$rid;
1230 }, $upgrade_rooms);
1231
1232 $room_upgrade_options = [
1233 'rooms' => $upgrade_rooms,
1234 'discount' => $upgrade_discount,
1235 ];
1236 }
1237 $config->set('room_upgrade_options_' . $lid, json_encode($room_upgrade_options));
1238
1239 if ($stay === true) {
1240 $app->enqueueMessage(JText::translate('VBOROOMSAVEOK').' - <a href="index.php?option=com_vikbooking&task=tariffs&cid[]='.$lid.'">'.JText::translate('VBOGOTORATES').'</a>');
1241 $app->redirect("index.php?option=com_vikbooking&task=editroom&cid[]=".$lid);
1242 $app->close();
1243 }
1244
1245 $app->redirect("index.php?option=com_vikbooking&task=tariffs&cid[]=".$lid);
1246 $app->close();
1247 }
1248
1249 public function updateroom()
1250 {
1251 if (!JSession::checkToken()) {
1252 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
1253 }
1254
1255 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
1256 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
1257 }
1258
1259 $this->do_updateroom();
1260 }
1261
1262 public function updateroomstay()
1263 {
1264 if (!JSession::checkToken()) {
1265 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
1266 }
1267
1268 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
1269 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
1270 }
1271
1272 $this->do_updateroom(true);
1273 }
1274
1275 private function do_updateroom($stay = false)
1276 {
1277 $app = JFactory::getApplication();
1278 $config = VBOFactory::getConfig();
1279
1280 $pcname = VikRequest::getString('cname', '', 'request');
1281 $pccat = VikRequest::getVar('ccat', array(0));
1282 $pcdescr = VikRequest::getString('cdescr', '', 'request', VIKREQUEST_ALLOWRAW);
1283 $psmalldesc = VikRequest::getString('smalldesc', '', 'request', VIKREQUEST_ALLOWRAW);
1284 $pccarat = VikRequest::getVar('ccarat', array(0));
1285 $pcoptional = VikRequest::getVar('coptional', array(0));
1286 $pcavail = VikRequest::getString('cavail', '', 'request');
1287 $pwhereup = VikRequest::getInt('whereup', 0, 'request');
1288 $pautoresize = VikRequest::getString('autoresize', '', 'request');
1289 $presizeto = VikRequest::getString('resizeto', '', 'request');
1290 $pautoresizemore = VikRequest::getString('autoresizemore', '', 'request');
1291 $presizetomore = VikRequest::getString('resizetomore', '', 'request');
1292 $punits = VikRequest::getInt('units', '', 'request');
1293 $pimages = VikRequest::getVar('cimgmore', null, 'files', 'array');
1294 $pactmoreimgs = VikRequest::getString('actmoreimgs', '', 'request');
1295 $pfromadult = VikRequest::getInt('fromadult', '', 'request');
1296 $ptoadult = VikRequest::getInt('toadult', '', 'request');
1297 $pfromchild = VikRequest::getInt('fromchild', '', 'request');
1298 $ptochild = VikRequest::getInt('tochild', '', 'request');
1299 $padultsdiffchdisc = VikRequest::getVar('adultsdiffchdisc', array(0));
1300 $padultsdiffval = VikRequest::getVar('adultsdiffval', array(0));
1301 $padultsdiffnum = VikRequest::getVar('adultsdiffnum', array(0));
1302 $padultsdiffvalpcent = VikRequest::getVar('adultsdiffvalpcent', array(0));
1303 $padultsdiffpernight = VikRequest::getVar('adultsdiffpernight', array(0));
1304 $ptotpeople = VikRequest::getInt('totpeople', '', 'request');
1305 $pmintotpeople = VikRequest::getInt('mintotpeople', '', 'request');
1306 $pmintotpeople = $pmintotpeople < 1 ? 1 : $pmintotpeople;
1307 $plastavail = VikRequest::getString('lastavail', '', 'request');
1308 $plastavail = empty($plastavail) ? 0 : intval($plastavail);
1309 $psuggocc = VikRequest::getInt('suggocc', 1, 'request');
1310 $pcustprice = VikRequest::getString('custprice', '', 'request');
1311 $pcustprice = empty($pcustprice) ? '' : floatval($pcustprice);
1312 $pcustpricetxt = VikRequest::getString('custpricetxt', '', 'request', VIKREQUEST_ALLOWRAW);
1313 $pcustpricesubtxt = VikRequest::getString('custpricesubtxt', '', 'request', VIKREQUEST_ALLOWRAW);
1314 $preqinfo = VikRequest::getInt('reqinfo', '', 'request');
1315 $ppricecal = VikRequest::getInt('pricecal', '', 'request');
1316 $pdefcalcost = VikRequest::getString('defcalcost', '', 'request');
1317 $pdefrplan = VikRequest::getInt('defrplan', 0, 'request');
1318 $pmaxminpeople = VikRequest::getString('maxminpeople', '', 'request');
1319 $pcimgcaption = VikRequest::getVar('cimgcaption', array());
1320 $pimgsorting = VikRequest::getVar('imgsorting', array());
1321 $pupdatecaption = VikRequest::getInt('updatecaption', '', 'request');
1322 $pmaxminpeople = in_array($pmaxminpeople, array('0', '1', '2', '3', '4', '5')) ? $pmaxminpeople : '0';
1323 $pseasoncal = VikRequest::getInt('seasoncal', 0, 'request');
1324 $pseasoncal = $pseasoncal >= 0 || $pseasoncal <= 3 ? $pseasoncal : 0;
1325 $pseasoncal_nights = VikRequest::getString('seasoncal_nights', '', 'request');
1326 $pseasoncal_prices = VikRequest::getString('seasoncal_prices', '', 'request');
1327 $pseasoncal_restr = VikRequest::getString('seasoncal_restr', '', 'request');
1328 $pmulti_units = VikRequest::getInt('multi_units', '', 'request');
1329 $pmulti_units = $punits > 1 ? $pmulti_units : 0;
1330 $psefalias = VikRequest::getString('sefalias', '', 'request');
1331 $psefalias = empty($psefalias) ? JFilterOutput::stringURLSafe($pcname) : JFilterOutput::stringURLSafe($psefalias);
1332 $pcustptitle = VikRequest::getString('custptitle', '', 'request');
1333 $pcustptitlew = VikRequest::getString('custptitlew', '', 'request');
1334 $pcustptitlew = in_array($pcustptitlew, array('before', 'after', 'replace')) ? $pcustptitlew : 'before';
1335 $pmetakeywords = VikRequest::getString('metakeywords', '', 'request');
1336 $pmetadescription = VikRequest::getString('metadescription', '', 'request');
1337 $pshare_with = VikRequest::getVar('share_with', array());
1338 $scalnights_arr = array();
1339 if (!empty($pseasoncal_nights)) {
1340 $scalnights = explode(',', $pseasoncal_nights);
1341 foreach ($scalnights as $scalnight) {
1342 if (intval(trim($scalnight)) > 0) {
1343 $scalnights_arr[] = intval(trim($scalnight));
1344 }
1345 }
1346 }
1347 if (count($scalnights_arr) > 0) {
1348 $pseasoncal_nights = implode(', ', $scalnights_arr);
1349 } else {
1350 $pseasoncal_nights = '';
1351 $pseasoncal = 0;
1352 }
1353 $roomparams = [
1354 'lastavail' => $plastavail,
1355 'suggocc' => $psuggocc,
1356 'custprice' => $pcustprice,
1357 'custpricetxt' => $pcustpricetxt,
1358 'custpricesubtxt' => $pcustpricesubtxt,
1359 'reqinfo' => $preqinfo,
1360 'pricecal' => $ppricecal,
1361 'defcalcost' => floatval($pdefcalcost),
1362 'defrplan' => $pdefrplan,
1363 'maxminpeople' => $pmaxminpeople,
1364 'seasoncal' => $pseasoncal,
1365 'seasoncal_nights' => $pseasoncal_nights,
1366 'seasoncal_prices' => $pseasoncal_prices,
1367 'seasoncal_restr' => $pseasoncal_restr,
1368 'multi_units' => $pmulti_units,
1369 'custptitle' => $pcustptitle,
1370 'custptitlew' => $pcustptitlew,
1371 'metakeywords' => $pmetakeywords,
1372 'metadescription' => $pmetadescription,
1373 ];
1374 //distinctive features
1375 $roomparams['features'] = array();
1376 $newfeatures = array();
1377 if ($punits > 0) {
1378 for ($i=1; $i <= $punits; $i++) {
1379 $distf_name = VikRequest::getVar('feature-name'.$i, array());
1380 $distf_lang = VikRequest::getVar('feature-lang'.$i, array());
1381 $distf_value = VikRequest::getVar('feature-value'.$i, array());
1382 foreach ($distf_name as $distf_k => $distf) {
1383 if (strlen($distf) > 0 && strlen($distf_value[$distf_k]) > 0) {
1384 $use_key = strlen($distf_lang[$distf_k]) > 0 ? $distf_lang[$distf_k] : $distf;
1385 $roomparams['features'][$i][$use_key] = $distf_value[$distf_k];
1386 if ($distf_k < 1) {
1387 //check only the first feature
1388 $newfeatures[$i][$use_key] = $distf_value[$distf_k];
1389 }
1390 }
1391 }
1392 }
1393 }
1394
1395 /**
1396 * Store room geo params information.
1397 *
1398 * @since 1.14 (J) - 1.4.0 (WP)
1399 */
1400 $geo = VikBooking::getGeocodingInstance();
1401 $geo_params = $geo->getRoomGeoTransient($pwhereup);
1402 if ($geo_params !== false) {
1403 // make sure the geocoding service was not turned off
1404 $geo_enabled = VikRequest::getInt('geo_enabled', 0, 'request');
1405 if (!$geo_enabled) {
1406 $geo_params->enabled = 0;
1407 }
1408 //
1409 $roomparams['geo'] = $geo_params;
1410 }
1411 //
1412
1413 $roomparamstr = json_encode($roomparams);
1414
1415 jimport('joomla.filesystem.file');
1416 $updpath = VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR;
1417 if (!empty($pcname)) {
1418 if (intval($_FILES['cimg']['error']) == 0 && VikBooking::caniWrite($updpath) && trim($_FILES['cimg']['name'])!="") {
1419 if (@is_uploaded_file($_FILES['cimg']['tmp_name'])) {
1420 $safename = JFile::makeSafe(str_replace(" ", "_", strtolower($_FILES['cimg']['name'])));
1421 if (file_exists($updpath.$safename)) {
1422 $j = 1;
1423 while (file_exists($updpath.$j.$safename)) {
1424 $j++;
1425 }
1426 $pwhere = $updpath.$j.$safename;
1427 } else {
1428 $j = "";
1429 $pwhere = $updpath.$safename;
1430 }
1431 if (!getimagesize($_FILES['cimg']['tmp_name']) || !preg_match("/\.(a?png|jpe?g|bmp|gif|ico|webp)\z/i", $safename)) {
1432 @unlink($pwhere);
1433 $picon = "";
1434 } else {
1435 VikBooking::uploadFile($_FILES['cimg']['tmp_name'], $pwhere);
1436 @chmod($pwhere, 0644);
1437 $picon = $j.$safename;
1438 if ($pautoresize == "1" && !empty($presizeto)) {
1439 $eforj = new vikResizer();
1440 $origmod = $eforj->proportionalImage($pwhere, $updpath.'r_'.$j.$safename, $presizeto, $presizeto);
1441 if ($origmod) {
1442 @unlink($pwhere);
1443 $picon = 'r_'.$j.$safename;
1444 }
1445 }
1446 }
1447 } else {
1448 $picon = "";
1449 }
1450 } else {
1451 $picon = "";
1452 }
1453 //more images
1454 $creativik = new vikResizer();
1455 $bigsdest = $updpath;
1456 $thumbsdest = $updpath;
1457 $dest = $updpath;
1458 $moreimagestr = $pactmoreimgs;
1459 $arrimgs = array();
1460 $captiontexts = array();
1461 $imgcaptions = array();
1462 //captions of uploaded extra images
1463 if (!empty($pactmoreimgs)) {
1464 $sploimgs = explode(';;', $pactmoreimgs);
1465 foreach ($sploimgs as $ki => $oimg) {
1466 if (!empty($oimg)) {
1467 $oldcaption = VikRequest::getString('caption'.$ki, '', 'request', VIKREQUEST_ALLOWHTML);
1468 $imgcaptions[] = $oldcaption;
1469 }
1470 }
1471 }
1472 //
1473 foreach ($pimages['name'] as $kk=>$ci) {
1474 if (!empty($ci)) {
1475 $arrimgs[] = $kk;
1476 $captiontexts[] = isset($pcimgcaption[$kk]) ? $pcimgcaption[$kk] : '';
1477 }
1478 }
1479 foreach ($arrimgs as $ki => $imgk) {
1480 if (strlen(trim($pimages['name'][$imgk]))) {
1481 $filename = JFile::makeSafe(str_replace(" ", "_", strtolower($pimages['name'][$imgk])));
1482 $src = $pimages['tmp_name'][$imgk];
1483 $j = "";
1484 if (file_exists($dest.$filename)) {
1485 $j = rand(171, 1717);
1486 while (file_exists($dest.$j.$filename)) {
1487 $j++;
1488 }
1489 }
1490 $finaldest = $dest.$j.$filename;
1491 $check = getimagesize($pimages['tmp_name'][$imgk]);
1492 if (($check[2] & imagetypes()) && preg_match("/\.(a?png|jpe?g|bmp|gif|ico|webp)\z/i", $filename)) {
1493 if (VikBooking::uploadFile($src, $finaldest)) {
1494 $gimg = $j.$filename;
1495 //orig img
1496 $origmod = true;
1497 if ($pautoresizemore == "1" && !empty($presizetomore)) {
1498 $origmod = $creativik->proportionalImage($finaldest, $bigsdest.'big_'.$j.$filename, $presizetomore, $presizetomore);
1499 } else {
1500 VikBooking::uploadFile($finaldest, $bigsdest.'big_'.$j.$filename, true);
1501 }
1502 //thumb
1503 $thumbsize = VikBooking::getThumbSize();
1504 $thumb = $creativik->proportionalImage($finaldest, $thumbsdest.'thumb_'.$j.$filename, $thumbsize, $thumbsize);
1505 if (!$thumb || !$origmod) {
1506 if (file_exists($bigsdest.'big_'.$j.$filename)) @unlink($bigsdest.'big_'.$j.$filename);
1507 if (file_exists($thumbsdest.'thumb_'.$j.$filename)) @unlink($thumbsdest.'thumb_'.$j.$filename);
1508 VikError::raiseWarning('', 'Error While Uploading the File: '.$pimages['name'][$imgk]);
1509 } else {
1510 $moreimagestr .= $j.$filename.";;";
1511 $imgcaptions[] = $captiontexts[$ki];
1512 }
1513 @unlink($finaldest);
1514 } else {
1515 VikError::raiseWarning('', 'Error While Uploading the File: '.$pimages['name'][$imgk]);
1516 }
1517 } else {
1518 VikError::raiseWarning('', 'Error While Uploading the File: '.$pimages['name'][$imgk]);
1519 }
1520 }
1521 }
1522 //sorting of extra images
1523 $sorted_extraim = array();
1524 $sorted_captions = array();
1525 $extraim_parts = explode(';;', $moreimagestr);
1526 foreach ($pimgsorting as $k => $v) {
1527 $capkey = -1;
1528 if (isset($extraim_parts[$k])) {
1529 $sorted_extraim[] = $v;
1530 foreach ($extraim_parts as $oldk => $oldv) {
1531 if ($oldv == $v) {
1532 $capkey = $oldk;
1533 break;
1534 }
1535 }
1536 }
1537 if (isset($imgcaptions[$capkey])) {
1538 $sorted_captions[] = $imgcaptions[$capkey];
1539 }
1540 }
1541 $tot_sorted_im = count($sorted_extraim);
1542 if ($tot_sorted_im != count($extraim_parts)) {
1543 foreach ($extraim_parts as $k => $v) {
1544 if ($k <= ($tot_sorted_im - 1)) {
1545 continue;
1546 }
1547 $sorted_extraim[] = $v;
1548 if (isset($imgcaptions[$k])) {
1549 $sorted_captions[] = $imgcaptions[$k];
1550 }
1551 }
1552 }
1553 $moreimagestr = implode(';;', $sorted_extraim);
1554 $imgcaptions = $sorted_captions;
1555 //end more images
1556 if (is_array($pccat) && count($pccat)) {
1557 $pccatdef = "";
1558 foreach ($pccat as $ccat) {
1559 if (!empty($ccat)) {
1560 $pccatdef .= $ccat.";";
1561 }
1562 }
1563 } else {
1564 $pccatdef = "";
1565 }
1566 if (is_array($pccarat) && count($pccarat)) {
1567 $pccaratdef = "";
1568 foreach ($pccarat as $ccarat) {
1569 $pccaratdef .= $ccarat.";";
1570 }
1571 } else {
1572 $pccaratdef = "";
1573 }
1574 if (is_array($pcoptional) && count($pcoptional)) {
1575 $pcoptionaldef = "";
1576 foreach ($pcoptional as $coptional) {
1577 $pcoptionaldef .= $coptional.";";
1578 }
1579 } else {
1580 $pcoptionaldef = "";
1581 }
1582 $pcavaildef=($pcavail=="yes" ? "1" : "0");
1583 if ($pfromadult > $ptoadult) {
1584 $pfromadult = 1;
1585 $ptoadult = 1;
1586 }
1587 if ($pfromchild > $ptochild) {
1588 $pfromchild = 1;
1589 $ptochild = 1;
1590 }
1591 $dbo = JFactory::getDBO();
1592 //adults charges/discounts
1593 $adchdisctouch = false;
1594 $q = "SELECT * FROM `#__vikbooking_rooms` WHERE `id`='".$pwhereup."';";
1595 $dbo->setQuery($q);
1596 $dbo->execute();
1597 $oldroom = $dbo->loadAssocList();
1598 $oldroom = $oldroom[0];
1599 if ($oldroom['fromadult'] == $pfromadult && $oldroom['toadult'] == $ptoadult) {
1600 if ($oldroom['toadult'] > 1 && $oldroom['fromadult'] < $oldroom['toadult'] && @count($padultsdiffnum) > 0) {
1601 $startadind = $oldroom['fromadult'] > 0 ? $oldroom['fromadult'] : 1;
1602 for($adi = $startadind; $adi <= $oldroom['toadult']; $adi++) {
1603 foreach ($padultsdiffnum as $kad=>$vad) {
1604 if (intval($vad) == intval($adi) && strlen($padultsdiffval[$kad]) > 0) {
1605 $adchdisctouch = true;
1606 $inschdisc = intval($padultsdiffchdisc[$kad]) == 1 ? 1 : 2;
1607 $insvalpcent = intval($padultsdiffvalpcent[$kad]) == 1 ? 1 : 2;
1608 $inspernight = intval($padultsdiffpernight[$kad]) == 1 ? 1 : 0;
1609 $insvalue = floatval($padultsdiffval[$kad]);
1610 //check if it exists
1611 $q = "SELECT `id` FROM `#__vikbooking_adultsdiff` WHERE `idroom`='".$oldroom['id']."' AND `adults`='".$adi."';";
1612 $dbo->setQuery($q);
1613 $dbo->execute();
1614 if ($dbo->getNumRows() > 0) {
1615 if ($insvalue > 0) {
1616 //update
1617 $q = "UPDATE `#__vikbooking_adultsdiff` SET `chdisc`='".$inschdisc."', `valpcent`='".$insvalpcent."', `value`='".$insvalue."', `pernight`='".$inspernight."' WHERE `idroom`='".$oldroom['id']."' AND `adults`='".$adi."';";
1618 $dbo->setQuery($q);
1619 $dbo->execute();
1620 } else {
1621 //delete
1622 $q = "DELETE FROM `#__vikbooking_adultsdiff` WHERE `idroom`='".$oldroom['id']."' AND `adults`='".$adi."';";
1623 $dbo->setQuery($q);
1624 $dbo->execute();
1625 }
1626 } else {
1627 //insert
1628 $q = "INSERT INTO `#__vikbooking_adultsdiff` (`idroom`,`chdisc`,`valpcent`,`value`,`adults`,`pernight`) VALUES('".$oldroom['id']."', '".$inschdisc."', '".$insvalpcent."', '".$insvalue."', '".$adi."', '".$inspernight."');";
1629 $dbo->setQuery($q);
1630 $dbo->execute();
1631 }
1632 }
1633 }
1634 }
1635 }
1636 } else {
1637 //min and max adults num have changed, delete
1638 $q = "DELETE FROM `#__vikbooking_adultsdiff` WHERE `idroom`='".$oldroom['id']."';";
1639 $dbo->setQuery($q);
1640 $dbo->execute();
1641 }
1642 if ($adchdisctouch == true) {
1643 $app->enqueueMessage(JText::translate('VBUPDROOMADCHDISCSAVED'));
1644 }
1645 //
1646 //check distinctive features if there were any changes
1647 $old_rparams = json_decode($oldroom['params'], true);
1648 $old_rparams = is_array($old_rparams) ? $old_rparams : array();
1649 if (array_key_exists('features', $old_rparams)) {
1650 $oldfeatures = array();
1651 foreach ($old_rparams['features'] as $rnumunit => $oldfeat) {
1652 foreach ($oldfeat as $featname => $featval) {
1653 $oldfeatures[$rnumunit][$featname] = $featval;
1654 break;
1655 }
1656 }
1657 /**
1658 * We reset the sub-unit information to all bookings only in case the new
1659 * number of units is reduced. When we add new units or we modify the contents,
1660 * we keep everything as is for the past reservations.
1661 *
1662 * @since 1.15.2 (J) - 1.5.5 (WP)
1663 */
1664 if ($oldfeatures != $newfeatures && count($newfeatures) < count($oldfeatures)) {
1665 // changes were made to the first index (Room Number by default) of the distinctive features
1666 // set to NULL all the already set roomindexes in bookings
1667 $q = "UPDATE `#__vikbooking_ordersrooms` SET `roomindex`=NULL WHERE `idroom`=".(int)$oldroom['id'].";";
1668 $dbo->setQuery($q);
1669 $dbo->execute();
1670 }
1671 }
1672 //
1673 $q = "UPDATE `#__vikbooking_rooms` SET `name`=".$dbo->quote($pcname).",".(strlen($picon) > 0 ? "`img`='".$picon."'," : "")."`idcat`=".$dbo->quote($pccatdef).",`idcarat`=".$dbo->quote($pccaratdef).",`idopt`=".$dbo->quote($pcoptionaldef).",`info`=".$dbo->quote($pcdescr).",`avail`=".$dbo->quote($pcavaildef).",`units`=".($punits > 0 ? $dbo->quote($punits) : "'1'").",`moreimgs`=".$dbo->quote($moreimagestr).",`fromadult`='".$pfromadult."',`toadult`='".$ptoadult."',`fromchild`='".$pfromchild."',`tochild`='".$ptochild."',`smalldesc`=".$dbo->quote($psmalldesc).",`totpeople`=".$ptotpeople.",`mintotpeople`=".$pmintotpeople.",`params`=".$dbo->quote($roomparamstr).",`imgcaptions`=".$dbo->quote(json_encode($imgcaptions)).",`alias`=".$dbo->quote($psefalias)." WHERE `id`=".$dbo->quote($pwhereup).";";
1674 $dbo->setQuery($q);
1675 $dbo->execute();
1676
1677 /**
1678 * Share availability calendars with other rooms.
1679 *
1680 * @since 1.13
1681 */
1682 // always reset relations for this main room
1683 $q = "DELETE FROM `#__vikbooking_calendars_xref` WHERE `mainroom`={$pwhereup};";
1684 $dbo->setQuery($q);
1685 $dbo->execute();
1686 $newxref = array();
1687 foreach ($pshare_with as $cldroom) {
1688 if (!empty($cldroom)) {
1689 array_push($newxref, (int)$cldroom);
1690 }
1691 }
1692 foreach ($newxref as $cldroom) {
1693 $q = "INSERT INTO `#__vikbooking_calendars_xref` (`mainroom`, `childroom`) VALUES ({$pwhereup}, {$cldroom});";
1694 $dbo->setQuery($q);
1695 $dbo->execute();
1696 }
1697
1698 /**
1699 * Room upgrade options.
1700 *
1701 * @since 1.16.0 (J) - 1.6.0 (WP)
1702 */
1703 $room_upgrade_options = [];
1704 $room_upgrade = VikRequest::getInt('room_upgrade', 0, 'request');
1705 $upgrade_rooms = VikRequest::getVar('upgrade_rooms', array());
1706 $upgrade_discount = VikRequest::getFloat('upgrade_discount', 0, 'request');
1707 if ($room_upgrade && is_array($upgrade_rooms) && count($upgrade_rooms)) {
1708 $upgrade_rooms = array_map(function($rid) {
1709 return (int)$rid;
1710 }, $upgrade_rooms);
1711
1712 $room_upgrade_options = [
1713 'rooms' => $upgrade_rooms,
1714 'discount' => $upgrade_discount,
1715 ];
1716 }
1717 $config->set('room_upgrade_options_' . $pwhereup, json_encode($room_upgrade_options));
1718
1719 /**
1720 * Maximum advance booking offset can be defined at room-level.
1721 *
1722 * @since 1.16.3 (J) - 1.6.3 (WP)
1723 */
1724 $pmax_adv_notice_room = VikRequest::getInt('max_adv_notice_room', 0, 'request');
1725 $pmaxdate = VikRequest::getInt('maxdate', 0, 'request');
1726 $pmaxdateinterval = VikRequest::getString('maxdateinterval', '', 'request');
1727 $maxdate_str = '';
1728 if ($pmax_adv_notice_room && $pmaxdate > 0) {
1729 $pmaxdateinterval = !in_array($pmaxdateinterval, array('d', 'w', 'm', 'y')) ? 'y' : $pmaxdateinterval;
1730 $maxdate_str = '+' . $pmaxdate . $pmaxdateinterval;
1731 }
1732 $config->set("room_{$pwhereup}_max_adv_notice", $maxdate_str);
1733
1734 $app->enqueueMessage(JText::translate('VBUPDROOMOK'));
1735 }
1736
1737 if ($pupdatecaption == 1 || $stay === true) {
1738 $app->redirect("index.php?option=com_vikbooking&task=editroom&cid[]=".$pwhereup);
1739 } else {
1740 $app->redirect("index.php?option=com_vikbooking&task=rooms");
1741 }
1742 }
1743
1744 public function modavail() {
1745 if (!JSession::checkToken() && !JSession::checkToken('get')) {
1746 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
1747 }
1748 $cid = VikRequest::getVar('cid', array(0));
1749 $room = $cid[0];
1750 if (!empty($room)) {
1751 $dbo = JFactory::getDBO();
1752 $q = "SELECT `avail` FROM `#__vikbooking_rooms` WHERE `id`=".$dbo->quote($room).";";
1753 $dbo->setQuery($q);
1754 $dbo->execute();
1755 $get = $dbo->loadAssocList();
1756 $q = "UPDATE `#__vikbooking_rooms` SET `avail`='".(intval($get[0]['avail'])==1 ? 0 : 1)."' WHERE `id`=".$dbo->quote($room).";";
1757 $dbo->setQuery($q);
1758 $dbo->execute();
1759 }
1760 $mainframe = JFactory::getApplication();
1761 $mainframe->redirect("index.php?option=com_vikbooking&task=rooms");
1762 }
1763
1764 public function removeroom()
1765 {
1766 if (!JSession::checkToken()) {
1767 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
1768 }
1769
1770 if (!JFactory::getUser()->authorise('core.delete', 'com_vikbooking')) {
1771 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
1772 }
1773
1774 $ids = VikRequest::getVar('cid', array(0));
1775 if (@count($ids)) {
1776 $dbo = JFactory::getDBO();
1777 foreach ($ids as $d) {
1778 $q = "DELETE FROM `#__vikbooking_rooms` WHERE `id`=".$dbo->quote($d).";";
1779 $dbo->setQuery($q);
1780 $dbo->execute();
1781 $q = "DELETE FROM `#__vikbooking_dispcost` WHERE `idroom`=".$dbo->quote($d).";";
1782 $dbo->setQuery($q);
1783 $dbo->execute();
1784 }
1785 }
1786 $mainframe = JFactory::getApplication();
1787 $mainframe->redirect("index.php?option=com_vikbooking&task=rooms");
1788 }
1789
1790 public function tariffs() {
1791 VikBookingHelper::printHeader("fares");
1792
1793 VikRequest::setVar('view', VikRequest::getCmd('view', 'tariffs'));
1794
1795 parent::display();
1796
1797 if (VikBooking::showFooter()) {
1798 VikBookingHelper::printFooter();
1799 }
1800 }
1801
1802 public function removetariffs()
1803 {
1804 if (!JFactory::getUser()->authorise('core.delete', 'com_vikbooking')) {
1805 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
1806 }
1807
1808 $ids = VikRequest::getVar('cid', array(0));
1809 $proomid = VikRequest::getInt('roomid', '', 'request');
1810 if (@count($ids)) {
1811 $dbo = JFactory::getDBO();
1812 foreach ($ids as $r) {
1813 $x=explode(";", $r);
1814 foreach ($x as $rm) {
1815 if (!empty($rm)) {
1816 $q = "DELETE FROM `#__vikbooking_dispcost` WHERE `id`=".$dbo->quote($rm).";";
1817 $dbo->setQuery($q);
1818 $dbo->execute();
1819 }
1820 }
1821 }
1822 }
1823 $mainframe = JFactory::getApplication();
1824 $mainframe->redirect("index.php?option=com_vikbooking&task=tariffs&cid[]=".$proomid);
1825 }
1826
1827 public function editbusy() {
1828 VikBookingHelper::printHeader("8");
1829
1830 VikRequest::setVar('view', VikRequest::getCmd('view', 'editbusy'));
1831
1832 parent::display();
1833
1834 if (VikBooking::showFooter()) {
1835 VikBookingHelper::printFooter();
1836 }
1837 }
1838
1839 public function updatebusy()
1840 {
1841 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
1842 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
1843 }
1844
1845 $this->do_updatebusy();
1846 }
1847
1848 public function updatebusydoinv()
1849 {
1850 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
1851 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
1852 }
1853
1854 $this->do_updatebusy('geninvoices');
1855 }
1856
1857 private function do_updatebusy($callback = '')
1858 {
1859 $pidorder = VikRequest::getInt('idorder', 0, 'request');
1860 $pcheckindate = VikRequest::getString('checkindate', '', 'request');
1861 $pcheckoutdate = VikRequest::getString('checkoutdate', '', 'request');
1862 $pcheckinh = VikRequest::getString('checkinh', '', 'request');
1863 $pcheckinm = VikRequest::getString('checkinm', '', 'request');
1864 $pcheckouth = VikRequest::getString('checkouth', '', 'request');
1865 $pcheckoutm = VikRequest::getString('checkoutm', '', 'request');
1866 $pcustdata = VikRequest::getString('custdata', '', 'request');
1867 $pareprices = VikRequest::getString('areprices', '', 'request');
1868 $ptotpaid = VikRequest::getString('totpaid', '', 'request');
1869 $prefund = VikRequest::getString('refund', '', 'request');
1870 $pfrominv = VikRequest::getInt('frominv', '', 'request');
1871 $pvcm = VikRequest::getInt('vcm', '', 'request');
1872 $pgoto = VikRequest::getString('goto', '', 'request');
1873 $pextracn = VikRequest::getVar('extracn', []);
1874 $pextracc = VikRequest::getVar('extracc', []);
1875 $pextractx = VikRequest::getVar('extractx', []);
1876 /**
1877 * This is a "foreign key" integer value useful for other Vik plugins
1878 * to store custom extra services within a VBO reservation. Another
1879 * custom value "extra foreign data" (extracdata) is added. We also
1880 * support a "type" string useful for VCM to determine the type of service.
1881 *
1882 * @since 1.16.0 (J) - 1.6.0 (WP)
1883 * @since 1.16.1 (J) - 1.6.1 (WP) added the "type" string.
1884 */
1885 $pextractype = VikRequest::getVar('extractype', []);
1886 $pextracfk = VikRequest::getVar('extracfk', []);
1887 $pextracdata = VikRequest::getVar('extracdata', [], 'request', 'array', VIKREQUEST_ALLOWRAW);
1888
1889 $dbo = JFactory::getDbo();
1890 $user = JFactory::getUser();
1891 $app = JFactory::getApplication();
1892
1893 // availability helper
1894 $av_helper = VikBooking::getAvailabilityInstance();
1895
1896 $actnow = time();
1897 $nowdf = VikBooking::getDateFormat(true);
1898 if ($nowdf == "%d/%m/%Y") {
1899 $df = 'd/m/Y';
1900 } elseif ($nowdf == "%m/%d/%Y") {
1901 $df = 'm/d/Y';
1902 } else {
1903 $df = 'Y/m/d';
1904 }
1905
1906 $q = "SELECT * FROM `#__vikbooking_orders` WHERE `id`=" . $pidorder;
1907 $dbo->setQuery($q, 0, 1);
1908 $ord = $dbo->loadAssoc();
1909 if (!$ord) {
1910 $app->redirect("index.php?option=com_vikbooking&task=rooms");
1911 exit;
1912 }
1913
1914 $q = "SELECT `or`.*,`r`.`name`,`r`.`idopt`,`r`.`units`,`r`.`fromadult`,`r`.`toadult` FROM `#__vikbooking_ordersrooms` AS `or`,`#__vikbooking_rooms` AS `r` WHERE `or`.`idorder`=".$ord['id']." AND `or`.`idroom`=`r`.`id` ORDER BY `or`.`id` ASC;";
1915 $dbo->setQuery($q);
1916 $ordersrooms = $dbo->loadAssocList();
1917
1918 // do not touch this array property because it's used by VCM
1919 $ord['rooms_info'] = $ordersrooms;
1920
1921 // room stay dates in case of split stay
1922 $room_stay_dates = [];
1923 if ($ord['split_stay']) {
1924 if ($ord['status'] == 'confirmed') {
1925 $room_stay_dates = $av_helper->loadSplitStayBusyRecords($ord['id']);
1926 } else {
1927 $room_stay_dates = VBOFactory::getConfig()->getArray('split_stay_' . $ord['id'], []);
1928 }
1929 // immediately count the number of nights of stay for each split room
1930 foreach ($room_stay_dates as $sps_r_k => $sps_r_v) {
1931 if (!empty($sps_r_v['checkin_ts']) && !empty($sps_r_v['checkout_ts'])) {
1932 // overwrite values for compatibility with non-confirmed bookings
1933 $sps_r_v['checkin'] = $sps_r_v['checkin_ts'];
1934 $sps_r_v['checkout'] = $sps_r_v['checkout_ts'];
1935 }
1936 $sps_r_v['nights'] = $av_helper->countNightsOfStay($sps_r_v['checkin'], $sps_r_v['checkout']);
1937 // overwrite the whole array
1938 $room_stay_dates[$sps_r_k] = $sps_r_v;
1939 }
1940 }
1941
1942 // package or custom rate
1943 $is_package = !empty($ord['pkg']) ? true : false;
1944 $is_cust_cost = false;
1945 foreach ($ordersrooms as $kor => $or) {
1946 if ($is_package !== true && !empty($or['cust_cost']) && $or['cust_cost'] > 0.00) {
1947 $is_cust_cost = true;
1948 break;
1949 }
1950 }
1951
1952 // room switching
1953 $toswitch = array();
1954 $idbooked = array();
1955 $rooms_units = array();
1956
1957 $q = "SELECT `id`,`name`,`units` FROM `#__vikbooking_rooms`;";
1958 $dbo->setQuery($q);
1959 $all_rooms = $dbo->loadAssocList();
1960 foreach ($all_rooms as $rr) {
1961 $rooms_units[$rr['id']]['name'] = $rr['name'];
1962 $rooms_units[$rr['id']]['units'] = $rr['units'];
1963 }
1964
1965 foreach ($ordersrooms as $ind => $or) {
1966 $switch_command = VikRequest::getString('switch_'.$or['id'], '', 'request');
1967 if (!empty($switch_command) && intval($switch_command) != $or['idroom'] && array_key_exists(intval($switch_command), $rooms_units)) {
1968 if (!isset($idbooked[$or['idroom']])) {
1969 $idbooked[$or['idroom']] = 0;
1970 }
1971 $idbooked[$or['idroom']]++;
1972 $orkey = count($toswitch);
1973 $toswitch[$orkey]['from'] = $or['idroom'];
1974 $toswitch[$orkey]['to'] = intval($switch_command);
1975 $toswitch[$orkey]['record'] = $or;
1976 $toswitch[$orkey]['record_ind'] = $ind;
1977 }
1978 }
1979
1980 if (count($toswitch) && (!empty($ordersrooms[0]['idtar']) || $is_package || $is_cust_cost)) {
1981 foreach ($toswitch as $ksw => $rsw) {
1982 $plusunit = array_key_exists($rsw['to'], $idbooked) ? $idbooked[$rsw['to']] : 0;
1983 $room_checkin = $ord['checkin'];
1984 $room_checkout = $ord['checkout'];
1985 if ($ord['split_stay'] && count($room_stay_dates) && isset($room_stay_dates[$rsw['record_ind']]) && $room_stay_dates[$rsw['record_ind']]['idroom'] == $rsw['from']) {
1986 $room_checkin = $room_stay_dates[$rsw['record_ind']]['checkin'];
1987 $room_checkout = $room_stay_dates[$rsw['record_ind']]['checkout'];
1988 }
1989 if (!VikBooking::roomBookable($rsw['to'], ($rooms_units[$rsw['to']]['units'] + $plusunit), $room_checkin, $room_checkout)) {
1990 // the room is not available
1991 unset($toswitch[$ksw]);
1992 VikError::raiseWarning('', JText::sprintf('VBSWITCHRERR', $rsw['record']['name'], $rooms_units[$rsw['to']]['name']));
1993 }
1994 }
1995 if (count($toswitch)) {
1996 // reset first record rate
1997 reset($ordersrooms);
1998 $q = "UPDATE `#__vikbooking_ordersrooms` SET `idtar`=NULL,`roomindex`=NULL,`room_cost`=NULL WHERE `id`=".$ordersrooms[0]['id'].";";
1999 $dbo->setQuery($q);
2000 $dbo->execute();
2001
2002 // flag for invoking VCM at a proper time
2003 $vcm_should_run = false;
2004
2005 foreach ($toswitch as $ksw => $rsw) {
2006 // update room reservation record
2007 $q = "UPDATE `#__vikbooking_ordersrooms` SET `idroom`=".$rsw['to'].",`idtar`=NULL,`roomindex`=NULL,`room_cost`=NULL WHERE `id`=".$rsw['record']['id'].";";
2008 $dbo->setQuery($q);
2009 $dbo->execute();
2010 $app->enqueueMessage(JText::sprintf('VBSWITCHROK', $rsw['record']['name'], $rooms_units[$rsw['to']]['name']));
2011
2012 // update Notes field for this booking to keep track of the previous room that was assigned
2013 $prev_room_name = array_key_exists($rsw['from'], $rooms_units) ? $rooms_units[$rsw['from']]['name'] : '';
2014 if (!empty($prev_room_name)) {
2015 $new_notes = JText::sprintf('VBOPREVROOMMOVED', $prev_room_name, date($df.' H:i:s'))."\n".$ord['adminnotes'];
2016 $q = "UPDATE `#__vikbooking_orders` SET `adminnotes`=".$dbo->quote($new_notes)." WHERE `id`=".(int)$ord['id'].";";
2017 $dbo->setQuery($q);
2018 $dbo->execute();
2019 }
2020
2021 if ($ord['status'] == 'confirmed') {
2022 // update room record in _busy
2023 if ($ord['split_stay'] && count($room_stay_dates) && isset($room_stay_dates[$rsw['record_ind']]) && $room_stay_dates[$rsw['record_ind']]['idroom'] == $rsw['from'] && !empty($room_stay_dates[$rsw['record_ind']]['id'])) {
2024 // in case of a split stay it is fundamental to update the exact busy record ID
2025 $q = "UPDATE `#__vikbooking_busy` SET `idroom`=" . $rsw['to'] . " WHERE `id`=" . (int)$room_stay_dates[$rsw['record_ind']]['id'];
2026 $dbo->setQuery($q);
2027 $dbo->execute();
2028 } else {
2029 // regular processing of a room ID for a reservation, no matter which one, we switch it
2030 $q = "SELECT `b`.`id`,`b`.`idroom`,`ob`.`idorder` FROM `#__vikbooking_busy` AS `b`,`#__vikbooking_ordersbusy` AS `ob` WHERE `b`.`idroom`=" . $rsw['from'] . " AND `b`.`id`=`ob`.`idbusy` AND `ob`.`idorder`=" . $ord['id'];
2031 $dbo->setQuery($q, 0, 1);
2032 $cur_busy = $dbo->loadAssoc();
2033 if ($cur_busy) {
2034 $q = "UPDATE `#__vikbooking_busy` SET `idroom`=".$rsw['to']." WHERE `id`=".$cur_busy['id']." AND `idroom`=".$cur_busy['idroom']." LIMIT 1;";
2035 $dbo->setQuery($q);
2036 $dbo->execute();
2037 }
2038 }
2039
2040 /**
2041 * Make sure to take care of the shared calendars before invoking VCM.
2042 * Register the flag to run the Channel Manager and leave the booking
2043 * array unchanged to run just one update request.
2044 *
2045 * @since 1.16.0 (J) - 1.6.0 (WP)
2046 */
2047 $vcm_should_run = true;
2048
2049 } elseif ($ord['status'] == 'standby') {
2050 // remove record in _tmplock
2051 $q = "DELETE FROM `#__vikbooking_tmplock` WHERE `idorder`=" . intval($ord['id']) . ";";
2052 $dbo->setQuery($q);
2053 $dbo->execute();
2054 // check if it's a split stay
2055 if ($ord['split_stay'] && count($room_stay_dates) && isset($room_stay_dates[$rsw['record_ind']]) && $room_stay_dates[$rsw['record_ind']]['idroom'] == $rsw['from']) {
2056 // update room ID in split stay data
2057 $room_stay_dates[$rsw['record_ind']]['idroom'] = $rsw['to'];
2058 // update configuration record
2059 VBOFactory::getConfig()->set('split_stay_' . $ord['id'], json_encode($room_stay_dates));
2060 }
2061 }
2062 }
2063
2064 // unset any previously booked room due to calendar sharing
2065 VikBooking::cleanSharedCalendarsBusy($ord['id']);
2066 // check if some of the rooms booked have shared calendars
2067 VikBooking::updateSharedCalendars($ord['id']);
2068
2069 if ($vcm_should_run) {
2070 // we can now run the Channel Manager after having updated the shared calendars
2071 $vcm_autosync = VikBooking::vcmAutoUpdate();
2072 if ($vcm_autosync > 0) {
2073 $vcm_obj = VikBooking::getVcmInvoker();
2074 $vcm_obj->setOids(array($ord['id']))->setSyncType('modify')->setOriginalBooking($ord);
2075 $sync_result = $vcm_obj->doSync();
2076 if ($sync_result === false) {
2077 $vcm_err = $vcm_obj->getError();
2078 VikError::raiseWarning('', JText::translate('VBCHANNELMANAGERRESULTKO').' <a href="index.php?option=com_vikchannelmanager" target="_blank">'.JText::translate('VBCHANNELMANAGEROPEN').'</a> '.(strlen($vcm_err) > 0 ? '('.$vcm_err.')' : ''));
2079 }
2080 } elseif (file_exists(VCM_SITE_PATH . DIRECTORY_SEPARATOR . "helpers" . DIRECTORY_SEPARATOR . "synch.vikbooking.php")) {
2081 VikError::raiseNotice('', JText::translate('VBCHANNELMANAGERINVOKEASK').' <form action="index.php?option=com_vikbooking" method="post"><input type="hidden" name="option" value="com_vikbooking"/><input type="hidden" name="task" value="invoke_vcm"/><input type="hidden" name="stype" value="modify"/><input type="hidden" name="cid[]" value="'.$ord['id'].'"/><input type="hidden" name="origb" value="'.urlencode(json_encode($ord)).'"/><input type="hidden" name="returl" value="'.urlencode("index.php?option=com_vikbooking&task=editbusy".($pvcm == 1 ? '&vcm=1' : '')."&cid[]=".$ord['id']).'"/><button type="submit" class="btn btn-primary">'.JText::translate('VBCHANNELMANAGERSENDRQ').'</button></form>');
2082 }
2083 }
2084
2085 //Booking History
2086 VikBooking::getBookingHistoryInstance()->setBid($ord['id'])->store('MB', "({$user->name}) " . VikBooking::getLogBookingModification($ord));
2087 //
2088 $app->redirect("index.php?option=com_vikbooking&task=editbusy".($pvcm == 1 ? '&vcm=1' : '').($pfrominv == 1 ? '&frominv=1' : '')."&cid[]=".$ord['id'].($pgoto == 'overv' ? "&goto=overv" : ""));
2089 exit;
2090 }
2091 }
2092
2093 // update booking data
2094 $first = VikBooking::getDateTimestamp($pcheckindate, $pcheckinh, $pcheckinm);
2095 $second = VikBooking::getDateTimestamp($pcheckoutdate, $pcheckouth, $pcheckoutm);
2096 if ($second <= $first) {
2097 VikError::raiseWarning('', JText::translate('ERRPREV'));
2098 $app->redirect("index.php?option=com_vikbooking&task=editbusy".($pvcm == 1 ? '&vcm=1' : '').($pfrominv == 1 ? '&frominv=1' : '')."&cid[]=".$ord['id'].($pgoto == 'overv' ? "&goto=overv" : ""));
2099 exit;
2100 }
2101
2102 $secdiff = $second - $first;
2103 $daysdiff = $secdiff / 86400;
2104 if (is_int($daysdiff)) {
2105 if ($daysdiff < 1) {
2106 $daysdiff = 1;
2107 }
2108 } else {
2109 if ($daysdiff < 1) {
2110 $daysdiff = 1;
2111 } else {
2112 $sum = floor($daysdiff) * 86400;
2113 $newdiff = $secdiff - $sum;
2114 $maxhmore = VikBooking::getHoursMoreRb() * 3600;
2115 if ($maxhmore >= $newdiff) {
2116 $daysdiff = floor($daysdiff);
2117 } else {
2118 $daysdiff = ceil($daysdiff);
2119 }
2120 }
2121 }
2122
2123 $groupdays = VikBooking::getGroupDays($first, $second, $daysdiff);
2124 $opertwounits = true;
2125
2126 $units_counter = array();
2127 $prm_room_oid = VikRequest::getInt('rm_room_oid', 0, 'request');
2128 foreach ($ordersrooms as $ind => $or) {
2129 if (!isset($units_counter[$or['idroom']])) {
2130 $units_counter[$or['idroom']] = -1;
2131 }
2132 if ($prm_room_oid != $or['id']) {
2133 $units_counter[$or['idroom']]++;
2134 }
2135 }
2136
2137 /**
2138 * Split stay data for booking and rooms different stay dates.
2139 *
2140 * @since 1.16.0 (J) - 1.6.0 (WP)
2141 */
2142 $split_stay_data = VikRequest::getVar('split_stay_data', array());
2143 $room_modify_dates = VikRequest::getVar('room_modify_dates', array());
2144 $split_stay_checkins = [];
2145 $split_stay_checkouts = [];
2146
2147 if ($ord['split_stay'] && !empty($split_stay_data)) {
2148 // make sure the min/max split stay dates match the booking global dates
2149 foreach ($split_stay_data as $sps_k => $split_stay) {
2150 if (empty($split_stay['checkin']) || empty($split_stay['checkout'])) {
2151 continue;
2152 }
2153 $new_room_checkin = VikBooking::getDateTimestamp($split_stay['checkin'], $pcheckinh, $pcheckinm);
2154 $new_room_checkout = VikBooking::getDateTimestamp($split_stay['checkout'], $pcheckouth, $pcheckoutm);
2155 $split_stay_checkins[] = $new_room_checkin;
2156 $split_stay_checkouts[] = $new_room_checkout;
2157 if (isset($room_stay_dates[$sps_k])) {
2158 $room_stay_dates[$sps_k]['new_checkin'] = $new_room_checkin;
2159 $room_stay_dates[$sps_k]['new_checkout'] = $new_room_checkout;
2160 $room_stay_dates[$sps_k]['new_nights'] = $av_helper->countNightsOfStay($new_room_checkin, $new_room_checkout);
2161 }
2162 }
2163 if (empty($split_stay_checkins) || empty($split_stay_checkouts)) {
2164 // error
2165 VikError::raiseWarning('', 'Error, split stay rooms must have their own stay dates matching the booking check-in and check-out dates');
2166 $app->redirect("index.php?option=com_vikbooking&task=editbusy".($pvcm == 1 ? '&vcm=1' : '').($pfrominv == 1 ? '&frominv=1' : '')."&cid[]=".$ord['id'].($pgoto == 'overv' ? "&goto=overv" : ""));
2167 exit;
2168 }
2169 if (min($split_stay_checkins) != $first) {
2170 // error
2171 VikError::raiseWarning('', sprintf('Error, the earliest check-in (%s) for the split stay rooms must match the booking check-in date (%s)', date('Y-m-d H:i:s', min($split_stay_checkins)), date('Y-m-d H:i:s', $first)));
2172 $app->redirect("index.php?option=com_vikbooking&task=editbusy".($pvcm == 1 ? '&vcm=1' : '').($pfrominv == 1 ? '&frominv=1' : '')."&cid[]=".$ord['id'].($pgoto == 'overv' ? "&goto=overv" : ""));
2173 exit;
2174 }
2175 if (max($split_stay_checkouts) != $second) {
2176 // error
2177 VikError::raiseWarning('', sprintf('Error, the latest check-out (%s) for the split stay rooms must match the booking check-out date (%s)', date('Y-m-d H:i:s', max($split_stay_checkouts)), date('Y-m-d H:i:s', $second)));
2178 $app->redirect("index.php?option=com_vikbooking&task=editbusy".($pvcm == 1 ? '&vcm=1' : '').($pfrominv == 1 ? '&frominv=1' : '')."&cid[]=".$ord['id'].($pgoto == 'overv' ? "&goto=overv" : ""));
2179 exit;
2180 }
2181 }
2182
2183 /**
2184 * We need to make sure the sub-units of the rooms involved are not being overbooked.
2185 * In this case, we simply raise an error message by not stopping the process.
2186 *
2187 * @since 1.13.0 (J) - 1.3.0 (WP)
2188 */
2189 $subunits_involved_bids = array();
2190 //
2191
2192 foreach ($ordersrooms as $ind => $or) {
2193 $num = $ind + 1;
2194 $check = "SELECT `b`.`id`,`b`.`checkin`,`b`.`realback`,`ob`.`idorder` FROM `#__vikbooking_busy` AS `b`,`#__vikbooking_ordersbusy` AS `ob` WHERE `b`.`idroom`=" . $or['idroom'] . " AND `b`.`realback`>=" . $first . " AND `b`.`id`=`ob`.`idbusy` AND `ob`.`idorder`!=" . $ord['id'] . ";";
2195 $dbo->setQuery($check);
2196 $busy = $dbo->loadAssocList();
2197 if ($busy) {
2198 // determine the days to consider for the count of the availability
2199 $use_groupdays = $groupdays;
2200 $room_checkin = $first;
2201 $room_checkout = $second;
2202 if ($ord['split_stay'] && count($room_stay_dates) && isset($room_stay_dates[$ind]) && $room_stay_dates[$ind]['idroom'] == $or['idroom'] && !empty($room_stay_dates[$ind]['new_nights'])) {
2203 $use_groupdays = VikBooking::getGroupDays($room_stay_dates[$ind]['new_checkin'], $room_stay_dates[$ind]['new_checkout'], $room_stay_dates[$ind]['new_nights']);
2204 $room_checkin = $room_stay_dates[$ind]['new_checkin'];
2205 $room_checkout = $room_stay_dates[$ind]['new_checkout'];
2206 } elseif (!$ord['split_stay'] && !$ord['closure'] && $ord['roomsnum'] > 1 && $ord['days'] > 1 && $ord['status'] == 'confirmed' && VikRequest::getInt('room_modify_dates' . $ind, 0, 'request')) {
2207 // room may have individual stay dates
2208 if (isset($room_modify_dates[$ind]) && !empty($room_modify_dates[$ind]['checkin']) && !empty($room_modify_dates[$ind]['checkout'])) {
2209 // get new stay dates (if changed)
2210 $new_room_checkin = VikBooking::getDateTimestamp($room_modify_dates[$ind]['checkin'], $pcheckinh, $pcheckinm);
2211 $new_room_checkout = VikBooking::getDateTimestamp($room_modify_dates[$ind]['checkout'], $pcheckouth, $pcheckoutm);
2212 $use_groupdays = VikBooking::getGroupDays($new_room_checkin, $new_room_checkout, $av_helper->countNightsOfStay($new_room_checkin, $new_room_checkout));
2213 $room_checkin = $new_room_checkin;
2214 $room_checkout = $new_room_checkout;
2215 }
2216 }
2217
2218 foreach ($use_groupdays as $gday) {
2219 // count units booked for each stay timestamp
2220 $bfound = 0;
2221 foreach ($busy as $bu) {
2222 if ($gday >= $bu['checkin'] && $gday <= $bu['realback']) {
2223 // increase units booked found
2224 $bfound++;
2225 // keep track of the IDs involved to avoid overbooking for the sub-units
2226 if (!empty($or['roomindex'])) {
2227 if (!isset($subunits_involved_bids[$bu['idorder']])) {
2228 $subunits_involved_bids[$bu['idorder']] = array();
2229 }
2230 array_push($subunits_involved_bids[$bu['idorder']], array(
2231 'idroom' => $or['idroom'],
2232 'roomindex' => $or['roomindex'],
2233 ));
2234 }
2235 }
2236 }
2237
2238 // units booked must be greater than zero in case of split stays involving the same room multiple times
2239 $detract_multi_units = $units_counter[$or['idroom']];
2240 if ($ord['split_stay'] && count($room_stay_dates) && isset($room_stay_dates[$ind]) && $room_stay_dates[$ind]['idroom'] == $or['idroom']) {
2241 // split stay bookings never occupy the same room on the same dates
2242 $detract_multi_units = 0;
2243 }
2244 if ($bfound > 0 && $bfound >= ($or['units'] - $detract_multi_units)) {
2245 $opertwounits = false;
2246 break 2;
2247 }
2248
2249 // make sure the room is not temporarily locked while waiting to be paid/confirmed
2250 if ($ord['status'] == 'confirmed' && !VikBooking::roomNotLocked($or['idroom'], $or['units'], $room_checkin, $room_checkout)) {
2251 $opertwounits = false;
2252 break 2;
2253 }
2254 }
2255 }
2256 }
2257
2258 /**
2259 * Make sure no sub-units are overbooked even though the main room is available.
2260 *
2261 * @since 1.13.0 (J) - 1.3.0 (WP)
2262 */
2263 if ($opertwounits === true && count($subunits_involved_bids)) {
2264 $subunits_involved_bids = array_unique($subunits_involved_bids);
2265 // grab all the information about the bids involved and the related rooms/indexes
2266 $q = "SELECT `or`.`idorder`, `or`.`idroom`, `or`.`roomindex`, `o`.`checkin`, `o`.`checkout`, `r`.`name`, `r`.`params`
2267 FROM `#__vikbooking_ordersrooms` AS `or` LEFT JOIN `#__vikbooking_orders` AS `o` ON `or`.`idorder`=`o`.`id`
2268 LEFT JOIN `#__vikbooking_rooms` AS `r` ON `or`.`idroom`=`r`.`id`
2269 WHERE `or`.`idorder` IN (" . implode(', ', array_keys($subunits_involved_bids)) . ");";
2270 $dbo->setQuery($q);
2271 $involved_data = $dbo->loadAssocList();
2272 if ($involved_data) {
2273 foreach ($involved_data as $invb) {
2274 if (empty($invb['roomindex'])) {
2275 continue;
2276 }
2277 foreach ($subunits_involved_bids[$invb['idorder']] as $bookedindex) {
2278 if ($bookedindex['idroom'] == $invb['idroom'] && $bookedindex['roomindex'] == $invb['roomindex']) {
2279 // this same sub-unit is occupied by this booking ID: raise an error message to inform the administrator
2280 $subunit_name = $invb['roomindex'];
2281 $room_params = json_decode($invb['params'], true);
2282 if (is_array($room_params) && isset($room_params['features']) && @count($room_params['features'])) {
2283 foreach ($room_params['features'] as $rind => $rfeatures) {
2284 if ($rind == $invb['roomindex']) {
2285 foreach ($rfeatures as $fname => $fval) {
2286 if (strlen($fval)) {
2287 $subunit_name = '#' . $rind . ' - ' . JText::translate($fname) . ': ' . $fval;
2288 break;
2289 }
2290 }
2291 }
2292 }
2293 }
2294 $adjust_link = '<br/><a class="btn btn-danger" target="_blank" href="index.php?option=com_vikbooking&task=editorder&cid[]=' . $invb['idorder'] . '">' . JText::translate('VBOSUBUNITOVERBOOKEDGOTO') . '</a>';
2295 VikError::raiseWarning('', JText::sprintf('VBOSUBUNITOVERBOOKEDERR', $subunit_name, $invb['name'], date($df, $invb['checkin']), date($df, $invb['checkout']), $invb['idorder']) . $adjust_link);
2296 }
2297 }
2298 }
2299 }
2300 }
2301
2302 $forcebooking = VikRequest::getInt('forcebooking', 0, 'request');
2303 if ($opertwounits === true || $forcebooking) {
2304 // update dates, customer information, amount paid and busy records before checking the rates
2305 $turnover_secs = VikBooking::getHoursRoomAvail() * 3600;
2306 $realback = $turnover_secs + $second;
2307
2308 $newtotalpaid = strlen($ptotpaid) > 0 ? floatval($ptotpaid) : "";
2309 $newrefund = strlen($prefund) > 0 ? floatval($prefund) : null;
2310 $roomsnum = $ord['roomsnum'];
2311
2312 // add room to existing booking
2313 $room_added = false;
2314 $padd_room_id = VikRequest::getInt('add_room_id', '', 'request');
2315 $padd_room_adults = VikRequest::getInt('add_room_adults', 2, 'request');
2316 $padd_room_children = VikRequest::getInt('add_room_children', 0, 'request');
2317 $padd_room_fname = VikRequest::getString('add_room_fname', '', 'request');
2318 $padd_room_lname = VikRequest::getString('add_room_lname', '', 'request');
2319 $padd_room_price = VikRequest::getFloat('add_room_price', 0, 'request');
2320 $paliq_add_room = VikRequest::getInt('aliq_add_room', 0, 'request');
2321 if ($padd_room_id > 0 && ($padd_room_adults + $padd_room_children) > 0) {
2322 // no need to re-validate the availability for this new room, as it was made via JS in the View.
2323 // increase the rooms number for later update, and insert the new room record
2324 $roomsnum++;
2325 $q = "INSERT INTO `#__vikbooking_ordersrooms` (`idorder`,`idroom`,`adults`,`children`,`t_first_name`,`t_last_name`,`cust_cost`,`cust_idiva`) VALUES(".$ord['id'].", ".$padd_room_id.", ".$padd_room_adults.", ".$padd_room_children.", ".$dbo->quote($padd_room_fname).", ".$dbo->quote($padd_room_lname).", ".($padd_room_price > 0 ? $dbo->quote($padd_room_price) : 'NULL').", ".($padd_room_price > 0 && !empty($paliq_add_room) ? $dbo->quote($paliq_add_room) : 'NULL').");";
2326 $dbo->setQuery($q);
2327 $dbo->execute();
2328 $room_added = true;
2329 }
2330
2331 // remove room from existing booking
2332 $room_removed = false;
2333 $room_removed_index = null;
2334 if ($prm_room_oid > 0 && $roomsnum > 1) {
2335 // check if the requested room record exists for removal
2336 $q = "SELECT * FROM `#__vikbooking_ordersrooms` WHERE `id`=".$prm_room_oid." AND `idorder`=".$ord['id'].";";
2337 $dbo->setQuery($q);
2338 $room_before_rm = $dbo->loadAssoc();
2339 if ($room_before_rm) {
2340 // decrease the rooms number for later update, and remove the requested room record
2341 $roomsnum--;
2342 // find the index of this room in the current list before removal
2343 foreach ($ordersrooms as $kor => $or) {
2344 if ($or['id'] == $prm_room_oid) {
2345 $room_removed_index = $kor;
2346 break;
2347 }
2348 }
2349 // go ahead with the deletion of the room record
2350 $q = "DELETE FROM `#__vikbooking_ordersrooms` WHERE `id`=".$prm_room_oid." AND `idorder`=".$ord['id']." LIMIT 1;";
2351 $dbo->setQuery($q);
2352 $dbo->execute();
2353 $room_removed = $room_before_rm['idroom'];
2354 }
2355 }
2356
2357 if ($ord['split_stay'] && !empty($split_stay_data) && count($split_stay_checkins) && ($room_added !== false || $room_removed !== false)) {
2358 // split stay booking (even if only 1 room left) and one room was either added or removed: set new global stay dates
2359 if ($room_removed !== false && isset($room_removed_index) && isset($split_stay_checkins[$room_removed_index])) {
2360 // exclude the split stay dates of this room that was just removed
2361 unset($split_stay_checkins[$room_removed_index], $split_stay_checkouts[$room_removed_index]);
2362 }
2363 if (count($split_stay_checkins) && count($split_stay_checkouts)) {
2364 // if we still have rooms, and we should, update the booking global stay dates
2365 $first = min($split_stay_checkins);
2366 $second = max($split_stay_checkouts);
2367 $daysdiff = $av_helper->countNightsOfStay($first, $second);
2368 }
2369 }
2370
2371 // update booking's basic information (customer data, dates, tot paid, number of rooms, refund)
2372 $basic_booking = new stdClass;
2373 $basic_booking->id = $ord['id'];
2374 $basic_booking->custdata = $pcustdata;
2375 $basic_booking->days = (int)$daysdiff;
2376 $basic_booking->checkin = $first;
2377 $basic_booking->checkout = $second;
2378 if (strlen($newtotalpaid) > 0) {
2379 $basic_booking->totpaid = $newtotalpaid;
2380 }
2381 $basic_booking->roomsnum = (int)$roomsnum;
2382 if ($newrefund !== null) {
2383 $basic_booking->refund = $newrefund;
2384 }
2385 if ($ord['split_stay'] && $roomsnum < 2 && $room_removed !== false) {
2386 // there is no point in keep treating this reservation as a split stay
2387 $basic_booking->split_stay = 0;
2388 }
2389 $dbo->updateObject('#__vikbooking_orders', $basic_booking, 'id');
2390
2391 // Booking History log for new amount paid (payment update)
2392 if ($newtotalpaid > 0 && $newtotalpaid > (float)$ord['totpaid']) {
2393 $extra_data = new stdClass;
2394 $extra_data->amount_paid = ($newtotalpaid - (float)$ord['totpaid']);
2395 VikBooking::getBookingHistoryInstance()->setBid($ord['id'])->setExtraData($extra_data)->store('PU', JText::sprintf('VBOPREVAMOUNTPAID', VikBooking::numberFormat((float)$ord['totpaid'])));
2396 }
2397
2398 // booking history log for new refund amount
2399 if ($newrefund !== null && $newrefund != (float)$ord['refund']) {
2400 // update current refund value
2401 $ord['refund'] = $newrefund;
2402 // store event
2403 VikBooking::getBookingHistoryInstance()->setBid($ord['id'])->setExtraData(null)->store('RU', JText::sprintf('VBO_NEWREFUND_AMOUNT', VikBooking::numberFormat($ord['refund']), VikBooking::numberFormat($newrefund)));
2404 }
2405
2406 // update busy records
2407 if ($ord['status'] == 'confirmed') {
2408 $allbusy = [];
2409 if ($ord['split_stay'] && !empty($split_stay_data)) {
2410 // in case of split stay we need to update the busy records according to the nights selected
2411 foreach ($split_stay_data as $sps_k => $split_stay) {
2412 if (empty($split_stay['idbusy']) || empty($split_stay['checkin']) || empty($split_stay['checkout'])) {
2413 // missing data
2414 continue;
2415 }
2416 // get selected dates
2417 $room_checkin = VikBooking::getDateTimestamp($split_stay['checkin'], $pcheckinh, $pcheckinm);
2418 $room_checkout = VikBooking::getDateTimestamp($split_stay['checkout'], $pcheckouth, $pcheckoutm);
2419 $room_realback = $turnover_secs + $room_checkout;
2420 // update the exact record
2421 $q = "UPDATE `#__vikbooking_busy` SET `checkin`=" . $room_checkin . ", `checkout`=" . $room_checkout . ", `realback`=" . $room_realback . " WHERE `id`=" . (int)$split_stay['idbusy'] . ";";
2422 $dbo->setQuery($q);
2423 $dbo->execute();
2424 }
2425 } else {
2426 // regularly update busy records for all rooms involved
2427 $q = "SELECT `b`.`id`,`b`.`idroom` FROM `#__vikbooking_busy` AS `b`,`#__vikbooking_ordersbusy` AS `ob` WHERE `b`.`id`=`ob`.`idbusy` AND `ob`.`idorder`=" . $ord['id'] . ";";
2428 $dbo->setQuery($q);
2429 $allbusy = $dbo->loadAssocList();
2430 foreach ($allbusy as $bb) {
2431 $q = "UPDATE `#__vikbooking_busy` SET `checkin`=" . $first . ", `checkout`=" . $second . ", `realback`=" . $realback . " WHERE `id`=" . $bb['id'] . ";";
2432 $dbo->setQuery($q);
2433 $dbo->execute();
2434 }
2435 }
2436
2437 /**
2438 * Check if some rooms have modified stay dates different than the booking stay dates.
2439 *
2440 * @since 1.16.0 (J) - 1.6.0 (WP)
2441 */
2442 if (!$ord['split_stay'] && !$ord['closure'] && $ord['roomsnum'] > 1 && $ord['days'] > 1) {
2443 // load the occupied stay dates for each room in case they were modified
2444 $room_stay_records = $av_helper->loadSplitStayBusyRecords($ord['id']);
2445 // loop over all rooms to check the requested operations
2446 foreach ($ordersrooms as $ind => $or) {
2447 if (!VikRequest::getInt('room_modify_dates' . $ind, 0, 'request') || !isset($room_stay_records[$ind]) || empty($room_stay_records[$ind]['id'])) {
2448 // toggle is disabled or data is missing
2449 continue;
2450 }
2451 if (isset($room_modify_dates[$ind]) && !empty($room_modify_dates[$ind]['checkin']) && !empty($room_modify_dates[$ind]['checkout'])) {
2452 // calculate the check-in and check-out timestamps, we expect them to be different from the global booking dates
2453 $room_checkin = VikBooking::getDateTimestamp($room_modify_dates[$ind]['checkin'], $pcheckinh, $pcheckinm);
2454 $room_checkout = VikBooking::getDateTimestamp($room_modify_dates[$ind]['checkout'], $pcheckouth, $pcheckoutm);
2455 $room_realback = $turnover_secs + $room_checkout;
2456 // we don't need to check if the dates are different, we just update the record
2457 $q = "UPDATE `#__vikbooking_busy` SET `checkin`=" . $room_checkin . ", `checkout`=" . $room_checkout . ", `realback`=" . $room_realback . " WHERE `id`=" . (int)$room_stay_records[$ind]['id'] . ";";
2458 $dbo->setQuery($q);
2459 $dbo->execute();
2460 // inject new room stay timestamps
2461 $ordersrooms[$ind]['modified_checkin'] = $room_checkin;
2462 $ordersrooms[$ind]['modified_checkout'] = $room_checkout;
2463 }
2464 }
2465 }
2466
2467 // add room to existing (confirmed) booking
2468 if ($room_added === true) {
2469 // add busy record for the new room unit
2470 $q = "INSERT INTO `#__vikbooking_busy` (`idroom`,`checkin`,`checkout`,`realback`) VALUES(".$padd_room_id.", ".$dbo->quote($first).", ".$dbo->quote($second).", ".$dbo->quote($realback).");";
2471 $dbo->setQuery($q);
2472 $dbo->execute();
2473 $newbusyid = $dbo->insertid();
2474 $q = "INSERT INTO `#__vikbooking_ordersbusy` (`idorder`,`idbusy`) VALUES(".$ord['id'].", ".(int)$newbusyid.");";
2475 $dbo->setQuery($q);
2476 $dbo->execute();
2477 }
2478
2479 // remove room from existing (confirmed) booking
2480 if ($room_removed !== false) {
2481 // remove busy record for the removed room
2482 if ($ord['split_stay'] && !empty($split_stay_data) && !empty($room_removed_index)) {
2483 // in case of split stay we want to remove the exact dates of the previously booked room
2484 if (count($room_stay_dates) && isset($room_stay_dates[$room_removed_index]) && $room_stay_dates[$room_removed_index]['idroom'] == $room_removed && !empty($room_stay_dates[$room_removed_index]['id'])) {
2485 // remove the exact records
2486 $q = "DELETE FROM `#__vikbooking_busy` WHERE `id`=" . $room_stay_dates[$room_removed_index]['id'] . " AND `idroom`=" . $room_removed . ";";
2487 $dbo->setQuery($q);
2488 $dbo->execute();
2489 $q = "DELETE FROM `#__vikbooking_ordersbusy` WHERE `idorder`=" . $ord['id'] . " AND `idbusy`=" . $room_stay_dates[$room_removed_index]['id'] . ";";
2490 $dbo->setQuery($q);
2491 $dbo->execute();
2492 }
2493 } else {
2494 // regularly remove the first matching room
2495 foreach ($allbusy as $bb) {
2496 if ($bb['idroom'] == $room_removed) {
2497 // remove the first room with this ID that was booked
2498 $q = "DELETE FROM `#__vikbooking_busy` WHERE `id`=".$bb['id']." AND `idroom`=".$room_removed.";";
2499 $dbo->setQuery($q);
2500 $dbo->execute();
2501 $q = "DELETE FROM `#__vikbooking_ordersbusy` WHERE `idorder`=".$ord['id']." AND `idbusy`=".$bb['id'].";";
2502 $dbo->setQuery($q);
2503 $dbo->execute();
2504 break;
2505 }
2506 }
2507 }
2508 }
2509
2510 if ($ord['checkin'] != $first || $ord['checkout'] != $second || $room_added === true || $room_removed !== false) {
2511 // unset any previously booked room due to calendar sharing
2512 VikBooking::cleanSharedCalendarsBusy($ord['id']);
2513 // check if some of the rooms booked have shared calendars
2514 VikBooking::updateSharedCalendars($ord['id'], array(), $first, $second);
2515
2516 // invoke Channel Manager
2517 $vcm_autosync = VikBooking::vcmAutoUpdate();
2518 if ($vcm_autosync > 0) {
2519 $vcm_obj = VikBooking::getVcmInvoker();
2520 $vcm_obj->setOids(array($ord['id']))->setSyncType('modify')->setOriginalBooking($ord);
2521 $sync_result = $vcm_obj->doSync();
2522 if ($sync_result === false) {
2523 $vcm_err = $vcm_obj->getError();
2524 VikError::raiseWarning('', JText::translate('VBCHANNELMANAGERRESULTKO').' <a href="index.php?option=com_vikchannelmanager" target="_blank">'.JText::translate('VBCHANNELMANAGEROPEN').'</a> '.(strlen($vcm_err) > 0 ? '('.$vcm_err.')' : ''));
2525 }
2526 } elseif (file_exists(VCM_SITE_PATH . DIRECTORY_SEPARATOR . "helpers" . DIRECTORY_SEPARATOR . "synch.vikbooking.php")) {
2527 VikError::raiseNotice('', JText::translate('VBCHANNELMANAGERINVOKEASK').' <form action="index.php?option=com_vikbooking" method="post"><input type="hidden" name="option" value="com_vikbooking"/><input type="hidden" name="task" value="invoke_vcm"/><input type="hidden" name="stype" value="modify"/><input type="hidden" name="cid[]" value="'.$ord['id'].'"/><input type="hidden" name="origb" value="'.urlencode(json_encode($ord)).'"/><input type="hidden" name="returl" value="'.urlencode("index.php?option=com_vikbooking&task=editbusy".($pvcm == 1 ? '&vcm=1' : '')."&cid[]=".$ord['id']).'"/><button type="submit" class="btn btn-primary">'.JText::translate('VBCHANNELMANAGERSENDRQ').'</button></form>');
2528 }
2529 //
2530 }
2531 }
2532
2533 $upd_esit = JText::translate('RESUPDATED');
2534
2535 // update the room rates
2536 $isdue = 0;
2537 $tot_taxes = 0;
2538 $tot_city_taxes = 0;
2539 $tot_fees = 0;
2540 $doup = true;
2541 $tars = array();
2542 $cust_costs = array();
2543 $rooms_costs_map = array();
2544 $arrpeople = array();
2545 foreach ($ordersrooms as $kor => $or) {
2546 // remove from existing booking
2547 if ($room_removed !== false) {
2548 if ($or['id'] == $prm_room_oid) {
2549 // do not consider this room for the calculation of the new total amount
2550 // we can unset this array for later use, because the channel manager has already been invoked.
2551 unset($ordersrooms[$kor]);
2552 continue;
2553 }
2554 }
2555
2556 // room index starting from 1
2557 $num = $kor + 1;
2558
2559 // default values to be considered
2560 $room_nights = $daysdiff;
2561 $room_checkin = $ord['checkin'];
2562 $room_checkout = $ord['checkout'];
2563 if ($ord['split_stay'] && count($room_stay_dates) && isset($room_stay_dates[$kor]) && $room_stay_dates[$kor]['idroom'] == $or['idroom'] && !empty($room_stay_dates[$kor]['new_nights'])) {
2564 $room_nights = $room_stay_dates[$kor]['new_nights'];
2565 $room_checkin = $room_stay_dates[$kor]['new_checkin'];
2566 $room_checkout = $room_stay_dates[$kor]['new_checkout'];
2567 }
2568
2569 $padults = VikRequest::getString('adults' . $num, '', 'request');
2570 $pchildren = VikRequest::getString('children' . $num, '', 'request');
2571 $ppets = VikRequest::getInt('pets' . $num, 0, 'request');
2572 if (strlen($padults) || strlen($pchildren)) {
2573 $arrpeople[$num]['adults'] = (int)$padults;
2574 $arrpeople[$num]['children'] = (int)$pchildren;
2575 $arrpeople[$num]['pets'] = $ppets;
2576 }
2577 $ppriceid = VikRequest::getString('priceid'.$num, '', 'request');
2578 $polderpriceid = VikRequest::getString('olderpriceid'.$num, '', 'request');
2579 $ppkgid = VikRequest::getString('pkgid'.$num, '', 'request');
2580 $pcust_cost = VikRequest::getString('cust_cost'.$num, '', 'request');
2581 $paliq = VikRequest::getString('aliq'.$num, '', 'request');
2582 if ($is_package === true && !empty($ppkgid)) {
2583 $pkg_cost = $or['cust_cost'];
2584 $pkg_idiva = $or['cust_idiva'];
2585 $pkg_info = VikBooking::getPackage($ppkgid);
2586 if (is_array($pkg_info) && count($pkg_info) > 0) {
2587 $use_adults = array_key_exists($num, $arrpeople) && array_key_exists('adults', $arrpeople[$num]) ? $arrpeople[$num]['adults'] : $or['adults'];
2588 $pkg_cost = $pkg_info['pernight_total'] == 1 ? ($pkg_info['cost'] * $room_nights) : $pkg_info['cost'];
2589 $pkg_cost = $pkg_info['perperson'] == 1 ? ($pkg_cost * ($use_adults > 0 ? $use_adults : 1)) : $pkg_cost;
2590 $pkg_cost = VikBooking::sayPackagePlusIva($pkg_cost, $pkg_info['idiva']);
2591 }
2592 $cust_costs[$num] = array('pkgid' => $ppkgid, 'cust_cost' => $pkg_cost, 'aliq' => $pkg_idiva);
2593 $isdue += $pkg_cost;
2594 $cost_minus_tax = VikBooking::sayPackageMinusIva($pkg_cost, $pkg_idiva);
2595 $tot_taxes += ($pkg_cost - $cost_minus_tax);
2596 continue;
2597 }
2598 if (empty($ppriceid) && !empty($pcust_cost) && floatval($pcust_cost) > 0) {
2599 $cust_costs[$num] = array('cust_cost' => $pcust_cost, 'aliq' => $paliq);
2600 $cost_after_tax = VikBooking::sayPackagePlusIva((float)$pcust_cost, (int)$paliq);
2601 $isdue += $cost_after_tax;
2602 $cost_minus_tax = VikBooking::sayPackageMinusIva((float)$pcust_cost, (int)$paliq);
2603 $tot_taxes += ($cost_after_tax - $cost_minus_tax);
2604 continue;
2605 }
2606
2607 // load room rates for the requested rate plan and nights
2608 $q = "SELECT * FROM `#__vikbooking_dispcost` WHERE `idroom`=" . (int)$or['idroom'] . " AND `days`=" . $room_nights . " AND `idprice`=" . (int)$ppriceid . ";";
2609 $dbo->setQuery($q);
2610 $tar = $dbo->loadAssocList();
2611 if (!$tar) {
2612 $doup = false;
2613 break;
2614 }
2615
2616 /**
2617 * The current price may be different from the price paid at the time of booking.
2618 * Check whether it has been asked to keep the old price of the time of booking.
2619 *
2620 * @since 1.13.0 (J) - 1.3.0 (WP)
2621 */
2622 $old_price_used = false;
2623 if (!empty($polderpriceid)) {
2624 $older_info = explode(':', $polderpriceid);
2625 if ((int)$older_info[0] == (int)$ppriceid) {
2626 $old_price = isset($older_info[1]) ? (float)$older_info[1] : 0;
2627 if ($old_price > 0) {
2628 // we override the 'cost' property of the tar array by taking the previous cost
2629 $old_price_used = true;
2630 $tar[0]['cost'] = $old_price;
2631 }
2632 }
2633 }
2634
2635 if (!$old_price_used) {
2636 // apply seasonal rates
2637 $tar = VikBooking::applySeasonsRoom($tar, $room_checkin, $room_checkout);
2638 }
2639
2640 // different usage
2641 if (!$old_price_used && $or['fromadult'] <= $or['adults'] && $or['toadult'] >= $or['adults']) {
2642 // apply OBP rules
2643 $tar = VBORoomHelper::getInstance()->applyOBPRules($tar, $or, $or['adults']);
2644 }
2645
2646 $cost_plus_tax = VikBooking::sayCostPlusIva($tar[0]['cost'], $tar[0]['idprice']);
2647 $isdue += $cost_plus_tax;
2648 if ($cost_plus_tax == $tar[0]['cost']) {
2649 $cost_minus_tax = VikBooking::sayCostMinusIva($tar[0]['cost'], $tar[0]['idprice']);
2650 $tot_taxes += ($tar[0]['cost'] - $cost_minus_tax);
2651 } else {
2652 $tot_taxes += ($cost_plus_tax - $tar[0]['cost']);
2653 }
2654 $tars[$num] = $tar;
2655 $rooms_costs_map[$num] = $tar[0]['cost'];
2656 }
2657
2658 if ($doup === true) {
2659 if ($room_added === true) {
2660 // add room to existing booking may require to increase the total amount, and taxes
2661 $padd_room_price = VikRequest::getFloat('add_room_price', 0, 'request');
2662 $paliq_add_room = VikRequest::getInt('aliq_add_room', 0, 'request');
2663 if (!empty($padd_room_price) && floatval($padd_room_price) > 0) {
2664 $isdue += (float)$padd_room_price;
2665 $cost_minus_tax = VikBooking::sayPackageMinusIva((float)$padd_room_price, (int)$paliq_add_room);
2666 $tot_taxes += ((float)$padd_room_price - $cost_minus_tax);
2667 }
2668 }
2669
2670 // load options
2671 $q = "SELECT * FROM `#__vikbooking_optionals` ORDER BY `#__vikbooking_optionals`.`ordering` ASC;";
2672 $dbo->setQuery($q);
2673 $toptionals = $dbo->loadAssocList();
2674
2675 foreach ($ordersrooms as $kor => $or) {
2676 $num = $kor + 1;
2677
2678 // default values to be considered
2679 $room_nights = $daysdiff;
2680 $room_checkin = $ord['checkin'];
2681 $room_checkout = $ord['checkout'];
2682 if ($ord['split_stay'] && count($room_stay_dates) && isset($room_stay_dates[$kor]) && $room_stay_dates[$kor]['idroom'] == $or['idroom'] && !empty($room_stay_dates[$kor]['new_nights'])) {
2683 $room_nights = $room_stay_dates[$kor]['new_nights'];
2684 $room_checkin = $room_stay_dates[$kor]['new_checkin'];
2685 $room_checkout = $room_stay_dates[$kor]['new_checkout'];
2686 }
2687
2688 $pt_first_name = VikRequest::getString('t_first_name'.$num, '', 'request');
2689 $pt_last_name = VikRequest::getString('t_last_name'.$num, '', 'request');
2690 $wop = "";
2691
2692 foreach ($toptionals as $opt) {
2693 if (!empty($opt['ageintervals']) && ($or['children'] > 0 || (array_key_exists($num, $arrpeople) && array_key_exists('children', $arrpeople[$num]))) ) {
2694 $tmpvar = VikRequest::getInt('optid'.$num.$opt['id'], []);
2695 if (is_array($tmpvar) && $tmpvar) {
2696 $opt['quan'] = 1;
2697 $optagenames = VikBooking::getOptionIntervalsAges($opt['ageintervals']);
2698 $optagepcent = VikBooking::getOptionIntervalsPercentage($opt['ageintervals']);
2699 $optageovrct = VikBooking::getOptionIntervalChildOverrides($opt, (isset($arrpeople[$num]) ? $arrpeople[$num]['adults'] : 0), (isset($arrpeople[$num]) ? $arrpeople[$num]['children'] : 0));
2700 $optorigname = $opt['name'];
2701 foreach ($tmpvar as $child_num => $chvar) {
2702 $ageintervals_child_string = isset($optageovrct['ageintervals_child' . ($child_num + 1)]) ? $optageovrct['ageintervals_child' . ($child_num + 1)] : $opt['ageintervals'];
2703 $optagecosts = VikBooking::getOptionIntervalsCosts($ageintervals_child_string);
2704 $optorigcost = $optagecosts[($chvar - 1)];
2705 if (array_key_exists(($chvar - 1), $optagepcent) && $optagepcent[($chvar - 1)] == 1) {
2706 //percentage value of the adults tariff
2707 if ($is_package !== true && array_key_exists($num, $tars)) {
2708 //type of price
2709 $optorigcost = $tars[$num][0]['cost'] * $optagecosts[($chvar - 1)] / 100;
2710 } elseif ($is_package === true && array_key_exists($num, $cust_costs)) {
2711 //package
2712 $optorigcost = $cust_costs[$num]['cust_cost'] * $optagecosts[($chvar - 1)] / 100;
2713 } elseif (array_key_exists($num, $cust_costs) && array_key_exists('cust_cost', $cust_costs[$num])) {
2714 //custom rate + custom tax rate
2715 $optorigcost = $cust_costs[$num]['cust_cost'] * $optagecosts[($chvar - 1)] / 100;
2716 }
2717 } elseif (array_key_exists(($chvar - 1), $optagepcent) && $optagepcent[($chvar - 1)] == 2) {
2718 //VBO 1.10 - percentage value of room base cost
2719 if ($is_package !== true && array_key_exists($num, $tars)) {
2720 //type of price
2721 $usecost = isset($tars[$num][0]['room_base_cost']) ? $tars[$num][0]['room_base_cost'] : $tars[$num][0]['cost'];
2722 $optorigcost = $usecost * $optagecosts[($chvar - 1)] / 100;
2723 } elseif ($is_package === true && array_key_exists($num, $cust_costs)) {
2724 //package
2725 $optorigcost = $cust_costs[$num]['cust_cost'] * $optagecosts[($chvar - 1)] / 100;
2726 } elseif (array_key_exists($num, $cust_costs) && array_key_exists('cust_cost', $cust_costs[$num])) {
2727 //custom rate + custom tax rate
2728 $optorigcost = $cust_costs[$num]['cust_cost'] * $optagecosts[($chvar - 1)] / 100;
2729 }
2730 }
2731 $opt['cost'] = $optorigcost;
2732 $opt['name'] = $optorigname.' ('.$optagenames[($chvar - 1)].')';
2733 $opt['chageintv'] = $chvar;
2734 $wop.=$opt['id'].":".$opt['quan']."-".$chvar.";";
2735 $realcost = (intval($opt['perday']) == 1 ? ($opt['cost'] * $room_nights * $opt['quan']) : ($opt['cost'] * $opt['quan']));
2736 if (!empty($opt['maxprice']) && $opt['maxprice'] > 0 && $realcost > $opt['maxprice']) {
2737 $realcost = $opt['maxprice'];
2738 }
2739 $tmpopr = VikBooking::sayOptionalsPlusIva($realcost, $opt['idiva']);
2740 if ($opt['is_citytax'] == 1) {
2741 $tot_city_taxes += $tmpopr;
2742 } elseif ($opt['is_fee'] == 1) {
2743 $tot_fees += $tmpopr;
2744 }
2745 // VBO 1.11 - always calculate the amount of tax no matter if this is already a tax or a fee
2746 if ($tmpopr == $realcost) {
2747 $opt_minus_iva = VikBooking::sayOptionalsMinusIva($realcost, $opt['idiva']);
2748 $tot_taxes += ($realcost - $opt_minus_iva);
2749 } else {
2750 $tot_taxes += ($tmpopr - $realcost);
2751 }
2752 //
2753 $isdue += $tmpopr;
2754 }
2755 }
2756 } else {
2757 $tmpvar = VikRequest::getString('optid'.$num.$opt['id'], '', 'request');
2758 //options forced per child fix, no age intervals, like children tourist taxes
2759 $forcedquan = 1;
2760 $forceperday = false;
2761 $forceperchild = false;
2762 if (intval($opt['forcesel']) == 1 && strlen($opt['forceval']) > 0 && strlen($tmpvar) > 0) {
2763 $forceparts = explode("-", $opt['forceval']);
2764 $forcedquan = intval($forceparts[0]);
2765 $forceperday = intval($forceparts[1]) == 1 ? true : false;
2766 $forceperchild = intval($forceparts[2]) == 1 ? true : false;
2767 $tmpvar = $forcedquan;
2768 $tmpvar = $forceperchild === true && array_key_exists($num, $arrpeople) && array_key_exists('children', $arrpeople[$num]) ? ($tmpvar * $arrpeople[$num]['children']) : $tmpvar;
2769 }
2770 //
2771 if (!empty($tmpvar)) {
2772 $wop .= $opt['id'].":".$tmpvar.";";
2773 // VBO 1.11 - options percentage cost of the room total fee
2774 if ($is_package !== true && array_key_exists($num, $tars)) {
2775 //type of price
2776 $deftar_basecosts = $tars[$num][0]['cost'];
2777 } elseif ($is_package === true && array_key_exists($num, $cust_costs)) {
2778 //package
2779 $deftar_basecosts = $cust_costs[$num]['cust_cost'];
2780 } elseif (array_key_exists($num, $cust_costs) && array_key_exists('cust_cost', $cust_costs[$num])) {
2781 //custom rate + custom tax rate
2782 $deftar_basecosts = $cust_costs[$num]['cust_cost'];
2783 }
2784 $opt['cost'] = (int)$opt['pcentroom'] ? ($deftar_basecosts * $opt['cost'] / 100) : $opt['cost'];
2785 //
2786 $realcost = (intval($opt['perday']) == 1 ? ($opt['cost'] * $room_nights * $tmpvar) : ($opt['cost'] * $tmpvar));
2787 if (!empty($opt['maxprice']) && $opt['maxprice'] > 0 && $realcost > $opt['maxprice']) {
2788 $realcost = $opt['maxprice'];
2789 if (intval($opt['hmany']) == 1 && intval($tmpvar) > 1) {
2790 $realcost = $opt['maxprice'] * $tmpvar;
2791 }
2792 }
2793 if ($opt['perperson'] == 1) {
2794 $num_adults = array_key_exists($num, $arrpeople) && array_key_exists('adults', $arrpeople[$num]) ? $arrpeople[$num]['adults'] : 1;
2795 $realcost = $realcost * $num_adults;
2796 }
2797 $tmpopr = VikBooking::sayOptionalsPlusIva($realcost, $opt['idiva']);
2798 if ($opt['is_citytax'] == 1) {
2799 $tot_city_taxes += $tmpopr;
2800 } elseif ($opt['is_fee'] == 1) {
2801 $tot_fees += $tmpopr;
2802 }
2803 // VBO 1.11 - always calculate the amount of tax no matter if this is already a tax or a fee
2804 if ($tmpopr == $realcost) {
2805 $opt_minus_iva = VikBooking::sayOptionalsMinusIva($realcost, $opt['idiva']);
2806 $tot_taxes += ($realcost - $opt_minus_iva);
2807 } else {
2808 $tot_taxes += ($tmpopr - $realcost);
2809 }
2810 //
2811 $isdue += $tmpopr;
2812 }
2813 }
2814 }
2815
2816 $upd_fields = array();
2817 if ($is_package !== true && array_key_exists($num, $tars)) {
2818 // type of price
2819 $upd_fields[] = "`idtar`='".$tars[$num][0]['id']."'";
2820 $upd_fields[] = "`cust_cost`=NULL";
2821 $upd_fields[] = "`cust_idiva`=NULL";
2822 $upd_fields[] = "`room_cost`=".(array_key_exists($num, $rooms_costs_map) ? $dbo->quote($rooms_costs_map[$num]) : "NULL");
2823 } elseif ($is_package === true && array_key_exists($num, $cust_costs)) {
2824 // packages do not update name or cost, just set again the same package ID to avoid risks of empty upd_fields to update
2825 $upd_fields[] = "`idtar`=NULL";
2826 $upd_fields[] = "`pkg_id`='".$cust_costs[$num]['pkgid']."'";
2827 $upd_fields[] = "`cust_cost`='".$cust_costs[$num]['cust_cost']."'";
2828 $upd_fields[] = "`cust_idiva`='".$cust_costs[$num]['aliq']."'";
2829 $upd_fields[] = "`room_cost`=NULL";
2830 } elseif (array_key_exists($num, $cust_costs) && array_key_exists('cust_cost', $cust_costs[$num])) {
2831 // custom rate + custom tax rate
2832 $upd_fields[] = "`idtar`=NULL";
2833 $upd_fields[] = "`cust_cost`='".$cust_costs[$num]['cust_cost']."'";
2834 $upd_fields[] = "`cust_idiva`='".$cust_costs[$num]['aliq']."'";
2835 $upd_fields[] = "`room_cost`=NULL";
2836 // inject new room price
2837 $ordersrooms[$kor]['modified_price'] = $cust_costs[$num]['cust_cost'];
2838 }
2839 if ($toptionals) {
2840 $upd_fields[] = "`optionals`='".$wop."'";
2841 }
2842 if (!empty($pt_first_name) || !empty($pt_last_name)) {
2843 $upd_fields[] = "`t_first_name`=".$dbo->quote($pt_first_name);
2844 $upd_fields[] = "`t_last_name`=".$dbo->quote($pt_last_name);
2845 }
2846 if (array_key_exists($num, $arrpeople) && array_key_exists('adults', $arrpeople[$num])) {
2847 $upd_fields[] = "`adults`=".intval($arrpeople[$num]['adults']);
2848 $upd_fields[] = "`children`=".intval($arrpeople[$num]['children']);
2849 if (isset($arrpeople[$num]['pets'])) {
2850 $upd_fields[] = "`pets`=" . $arrpeople[$num]['pets'];
2851 }
2852 }
2853
2854 /**
2855 * Meal plans at room-reservation level.
2856 *
2857 * @since 1.16.1 (J) - 1.6.1 (WP)
2858 */
2859 $pmealplans = VikRequest::getVar('mealplan' . $num, []);
2860 $upd_fields[] = "`meals`=" . ($pmealplans ? $dbo->q(json_encode($pmealplans)) : 'NULL');
2861
2862 // calculate the extra costs and increase taxes + isdue
2863 $extracosts_arr = array();
2864 if (count($pextracn) && isset($pextracn[$num]) && count($pextracn[$num])) {
2865 foreach ($pextracn[$num] as $eck => $ecn) {
2866 if ($ecn && array_key_exists($eck, $pextracc[$num]) && is_numeric($pextracc[$num][$eck])) {
2867 $ecidtax = array_key_exists($eck, $pextractx[$num]) && intval($pextractx[$num][$eck]) > 0 ? (int)$pextractx[$num][$eck] : '';
2868 $extracosts_arr[] = array(
2869 'name' => $ecn,
2870 'cost' => (float)$pextracc[$num][$eck],
2871 'idtax' => $ecidtax,
2872 'type' => isset($pextractype[$num][$eck]) ? $pextractype[$num][$eck] : '',
2873 'fk' => isset($pextracfk[$num][$eck]) ? (string)$pextracfk[$num][$eck] : '',
2874 'data' => isset($pextracdata[$num][$eck]) ? json_decode($pextracdata[$num][$eck]) : null,
2875 );
2876 $ecplustax = !empty($ecidtax) ? VikBooking::sayOptionalsPlusIva((float)$pextracc[$num][$eck], $ecidtax) : (float)$pextracc[$num][$eck];
2877 $ecminustax = !empty($ecidtax) ? VikBooking::sayOptionalsMinusIva((float)$pextracc[$num][$eck], $ecidtax) : (float)$pextracc[$num][$eck];
2878 $ectottax = (float)$pextracc[$num][$eck] - $ecminustax;
2879 $isdue += $ecplustax;
2880 $tot_taxes += $ectottax;
2881 }
2882 }
2883 }
2884
2885 if ($extracosts_arr) {
2886 $upd_fields[] = "`extracosts`=".$dbo->quote(json_encode($extracosts_arr));
2887 } else {
2888 $upd_fields[] = "`extracosts`=NULL";
2889 }
2890
2891 if ($upd_fields) {
2892 $q = "UPDATE `#__vikbooking_ordersrooms` SET ".implode(', ', $upd_fields)." WHERE `idorder`=".$ord['id']." AND `idroom`='".$or['idroom']."' AND `id`='".$or['id']."';";
2893 $dbo->setQuery($q);
2894 $dbo->execute();
2895 }
2896 }
2897
2898 // update split stay transient record if not confirmed booking
2899 if ($ord['split_stay'] && $ord['status'] != 'confirmed' && !empty($room_stay_dates) && !empty($split_stay_data)) {
2900 /**
2901 * Important: if no rates have been selected for all rooms, we won't enter this inner statement.
2902 * It is necessary to select a rate plan for each room in order to update the split stay data.
2903 */
2904 $new_room_stay_dates = [];
2905 foreach ($room_stay_dates as $kor => $room_stay_info) {
2906 // clone the current information
2907 $clean_room_stay_info = $room_stay_info;
2908 // set new stay values
2909 if (!empty($clean_room_stay_info['checkin_ts'])) {
2910 $clean_room_stay_info['checkin_ts'] = $clean_room_stay_info['new_checkin'];
2911 $clean_room_stay_info['checkout_ts'] = $clean_room_stay_info['new_checkout'];
2912 } else {
2913 $clean_room_stay_info['checkin'] = $clean_room_stay_info['new_checkin'];
2914 $clean_room_stay_info['checkout'] = $clean_room_stay_info['new_checkout'];
2915 }
2916 $clean_room_stay_info['nights'] = $clean_room_stay_info['new_nights'];
2917 // clean up unnecessary keys
2918 unset($clean_room_stay_info['new_checkin'], $clean_room_stay_info['new_checkout'], $clean_room_stay_info['new_nights']);
2919 // push new array info
2920 $new_room_stay_dates[$kor] = $clean_room_stay_info;
2921 }
2922 // update configuration record
2923 VBOFactory::getConfig()->set('split_stay_' . $ord['id'], json_encode($new_room_stay_dates));
2924 }
2925
2926 // make sure to re-apply the discount with the coupon code
2927 if ($ord['coupon']) {
2928 $expcoupon = explode(";", $ord['coupon']);
2929 $isdue -= $expcoupon[1];
2930 }
2931
2932 // make sure to apply any previously refunded amount
2933 if ($ord['refund'] > 0) {
2934 $isdue -= $ord['refund'];
2935 }
2936
2937 // update totals
2938 $q = "UPDATE `#__vikbooking_orders` SET `total`='".$isdue."', `tot_taxes`='".$tot_taxes."', `tot_city_taxes`='".$tot_city_taxes."', `tot_fees`='".$tot_fees."' WHERE `id`=".$ord['id'].";";
2939 $dbo->setQuery($q);
2940 $dbo->execute();
2941 $upd_esit = JText::translate('VBORESRATESUPDATED');
2942
2943 // Customer Booking
2944 if ($ord['status'] == 'confirmed') {
2945 $q = "SELECT `idcustomer` FROM `#__vikbooking_customers_orders` WHERE `idorder`=".$ord['id'].";";
2946 $dbo->setQuery($q);
2947 $customer_id = $dbo->loadResult();
2948 if ($customer_id) {
2949 $cpin = VikBooking::getCPinIstance();
2950 $cpin->is_admin = true;
2951 $cpin->updateBookingCommissions($ord['id'], $customer_id);
2952 }
2953 }
2954
2955 /**
2956 * Check for any OTA reporting action.
2957 *
2958 * @since 1.16.8 (J) - 1.6.8 (WP)
2959 */
2960 if (class_exists('VCMOtaReporting') && VCMOtaReporting::getInstance($ord)->stayChangeAllowed()) {
2961 // check if an OTA reporting action was selected
2962 $ota_stay_change_data = [];
2963 $ota_stay_change_all = $app->input->getInt('ota_stay_change_all', 0);
2964 foreach ($ordersrooms as $kor => $or) {
2965 $ota_stay_change_room = [];
2966 if ($ota_stay_change_all) {
2967 // set room data for stay change
2968 $ota_stay_change_room = [
2969 'idroom' => $or['idroom'],
2970 'checkin' => date('Y-m-d', $first),
2971 'checkout' => date('Y-m-d', $second),
2972 ];
2973 if (isset($or['modified_price'])) {
2974 $ota_stay_change_room['price'] = $or['modified_price'];
2975 }
2976 } elseif ($app->input->getInt('ota_stay_change_room_' . $kor, 0) && !empty($or['modified_checkin']) && !empty($or['modified_checkout'])) {
2977 // set room index data for stay change
2978 $ota_stay_change_room = [
2979 'idroom' => $or['idroom'],
2980 'index' => $kor,
2981 'checkin' => date('Y-m-d', $or['modified_checkin']),
2982 'checkout' => date('Y-m-d', $or['modified_checkout']),
2983 ];
2984 if (isset($or['modified_price'])) {
2985 $ota_stay_change_room['price'] = $or['modified_price'];
2986 }
2987 }
2988 if ($ota_stay_change_room) {
2989 // push room data for stay change
2990 $ota_stay_change_data[] = $ota_stay_change_room;
2991 }
2992 }
2993
2994 if ($ota_stay_change_data) {
2995 // notify the OTA through Vik Channel Manager
2996 $ota_reporting = VCMOtaReporting::getInstance();
2997 $ota_result = $ota_reporting->notifyStayChange($ota_stay_change_data);
2998 if (!$ota_result) {
2999 // enqueue error message
3000 $app->enqueueMessage($ota_reporting->getError(), 'error');
3001 }
3002 }
3003 }
3004 }
3005
3006 // Booking History
3007 $history_descr = "({$user->name}) " . VikBooking::getLogBookingModification($ord, $room_stay_dates);
3008 if (!$opertwounits && $forcebooking) {
3009 $history_descr .= "\n" . JText::translate('VBO_FORCED_BOOKDATES');
3010 }
3011 VikBooking::getBookingHistoryInstance()->setBid($ord['id'])->store('MB', $history_descr);
3012
3013 // enqueue result message
3014 $app->enqueueMessage($upd_esit);
3015 } else {
3016 VikError::raiseWarning('', JText::translate('VBROOMNOTRIT')." ".date($df.' H:i', $first)." ".JText::translate('VBROOMNOTCONSTO')." ".date($df.' H:i', $second));
3017 $allow_force = 1;
3018 $app->enqueueMessage(JText::translate('VBO_BOOKING_SHOULDFORCE'), 'notice');
3019 }
3020
3021 if ($callback == 'geninvoices') {
3022 $app->redirect("index.php?option=com_vikbooking&task=orders&cid[]=".$ord['id']."&confirmgen=1");
3023 } else {
3024 $app->redirect("index.php?option=com_vikbooking&task=editbusy".($pvcm == 1 ? '&vcm=1' : '').(isset($allow_force) ? '&canforce=1' : '').($pfrominv == 1 ? '&frominv=1' : '')."&cid[]=".$ord['id'].($pgoto == 'overv' ? "&goto=overv" : ""));
3025 }
3026 }
3027
3028 public function removebusy()
3029 {
3030 if (!JFactory::getUser()->authorise('core.delete', 'com_vikbooking')) {
3031 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
3032 }
3033
3034 $dbo = JFactory::getDbo();
3035 $app = JFactory::getApplication();
3036
3037 $user = JFactory::getUser();
3038 $config = VBOFactory::getConfig();
3039
3040 $prev_conf_ids = [];
3041 $pidorder = VikRequest::getInt('idorder', 0, 'request');
3042 $pgoto = VikRequest::getString('goto', '', 'request');
3043
3044 $purged = false;
3045
3046 $q = "SELECT * FROM `#__vikbooking_orders` WHERE `id`=" . $pidorder;
3047 $dbo->setQuery($q, 0, 1);
3048 $row = $dbo->loadAssoc();
3049
3050 // check for any cancellation constraints
3051 $canc_denied = false;
3052 if ($row && class_exists('VCMFeesCancellation')) {
3053 // let VCM detect if there are any constraints for the cancellation
3054 $canc_denied = VCMFeesCancellation::getInstance($row, $anew = true)->isBookingConstrained();
3055 if ($canc_denied) {
3056 // set error message
3057 $canc_deny_error = VCMFeesCancellation::getInstance()->getError();
3058 if ($canc_deny_error) {
3059 $app->enqueueMessage($canc_deny_error, 'error');
3060 }
3061 }
3062 }
3063
3064 if ($row && !$canc_denied) {
3065 // set status to cancelled
3066 if ($row['status'] != 'cancelled') {
3067 $q = "UPDATE `#__vikbooking_orders` SET `status`='cancelled' WHERE `id`=".(int)$row['id'].";";
3068 $dbo->setQuery($q);
3069 $dbo->execute();
3070 $q = "DELETE FROM `#__vikbooking_tmplock` WHERE `idorder`=" . intval($row['id']) . ";";
3071 $dbo->setQuery($q);
3072 $dbo->execute();
3073 if ($row['status'] == 'confirmed') {
3074 $prev_conf_ids[] = $row['id'];
3075 }
3076 // Booking History
3077 VikBooking::getBookingHistoryInstance()->setBid($row['id'])->store('CB', "({$user->name})");
3078 }
3079
3080 // free records up
3081 $q = "SELECT * FROM `#__vikbooking_ordersbusy` WHERE `idorder`=".(int)$row['id'].";";
3082 $dbo->setQuery($q);
3083 $ordbusy = $dbo->loadAssocList();
3084 if ($ordbusy) {
3085 foreach ($ordbusy as $ob) {
3086 $q = "DELETE FROM `#__vikbooking_busy` WHERE `id`='".$ob['idbusy']."';";
3087 $dbo->setQuery($q);
3088 $dbo->execute();
3089 }
3090 }
3091
3092 $q = "DELETE FROM `#__vikbooking_ordersbusy` WHERE `idorder`=".(int)$row['id'].";";
3093 $dbo->setQuery($q);
3094 $dbo->execute();
3095
3096 // check for purge removal
3097 if ($row['status'] == 'cancelled') {
3098 $q = "DELETE FROM `#__vikbooking_customers_orders` WHERE `idorder`=" . intval($row['id']) . ";";
3099 $dbo->setQuery($q);
3100 $dbo->execute();
3101 $q = "DELETE FROM `#__vikbooking_ordersrooms` WHERE `idorder`=".(int)$row['id'].";";
3102 $dbo->setQuery($q);
3103 $dbo->execute();
3104 $q = "DELETE FROM `#__vikbooking_orderhistory` WHERE `idorder`=".(int)$row['id'].";";
3105 $dbo->setQuery($q);
3106 $dbo->execute();
3107 $q = "DELETE FROM `#__vikbooking_orders` WHERE `id`=".(int)$row['id'].";";
3108 $dbo->setQuery($q);
3109 $dbo->execute();
3110 // in case of split stay booking, remove the transient
3111 if ($row['split_stay']) {
3112 $config->remove('split_stay_' . $row['id']);
3113 }
3114 // turn flag on
3115 $purged = true;
3116 }
3117
3118 // enqueue message
3119 $app->enqueueMessage(JText::translate('VBMESSDELBUSY'));
3120 }
3121
3122 if ($prev_conf_ids) {
3123 $prev_conf_ids_str = '';
3124 foreach ($prev_conf_ids as $prev_id) {
3125 $prev_conf_ids_str .= '&cid[]='.$prev_id;
3126 }
3127 //Invoke Channel Manager
3128 $vcm_autosync = VikBooking::vcmAutoUpdate();
3129 if ($vcm_autosync > 0) {
3130 $vcm_obj = VikBooking::getVcmInvoker();
3131 $vcm_obj->setOids($prev_conf_ids)->setSyncType('cancel');
3132 $sync_result = $vcm_obj->doSync();
3133 if ($sync_result === false) {
3134 $vcm_err = $vcm_obj->getError();
3135 VikError::raiseWarning('', JText::translate('VBCHANNELMANAGERRESULTKO').' <a href="index.php?option=com_vikchannelmanager" target="_blank">'.JText::translate('VBCHANNELMANAGEROPEN').'</a> '.(strlen($vcm_err) > 0 ? '('.$vcm_err.')' : ''));
3136 }
3137 } elseif (file_exists(VCM_SITE_PATH . DIRECTORY_SEPARATOR . "helpers" . DIRECTORY_SEPARATOR . "synch.vikbooking.php")) {
3138 $vcm_sync_url = 'index.php?option=com_vikbooking&task=invoke_vcm&stype=cancel'.$prev_conf_ids_str.'&returl='.urlencode('index.php?option=com_vikbooking&task=orders');
3139 VikError::raiseNotice('', JText::translate('VBCHANNELMANAGERINVOKEASK').' <button type="button" class="btn btn-primary" onclick="document.location.href=\''.$vcm_sync_url.'\';">'.JText::translate('VBCHANNELMANAGERSENDRQ').'</button>');
3140 }
3141 //
3142 }
3143
3144 if ($pgoto == 'overv') {
3145 $app->redirect("index.php?option=com_vikbooking&task=overv");
3146 } elseif (!$purged) {
3147 $app->redirect("index.php?option=com_vikbooking&task=editorder&cid[]=" . $pidorder);
3148 } else {
3149 $app->redirect("index.php?option=com_vikbooking&task=orders");
3150 }
3151
3152 $app->close();
3153 }
3154
3155 public function unlockrecords()
3156 {
3157 if (!JFactory::getUser()->authorise('core.delete', 'com_vikbooking')) {
3158 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
3159 }
3160
3161 $ids = VikRequest::getVar('cid', array(0));
3162 if (@count($ids)) {
3163 $dbo = JFactory::getDBO();
3164 foreach ($ids as $d) {
3165 $q = "DELETE FROM `#__vikbooking_tmplock` WHERE `id`=".$dbo->quote($d).";";
3166 $dbo->setQuery($q);
3167 $dbo->execute();
3168 }
3169 }
3170 $mainframe = JFactory::getApplication();
3171 $mainframe->redirect("index.php?option=com_vikbooking");
3172 }
3173
3174 public function sortoption() {
3175 if (!JSession::checkToken('get')) {
3176 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
3177 }
3178 $sortid = VikRequest::getVar('cid', array(0));
3179 $pmode = VikRequest::getString('mode', '', 'request');
3180 $dbo = JFactory::getDBO();
3181 $mainframe = JFactory::getApplication();
3182 if (!empty($pmode)) {
3183 $q = "SELECT `id`,`ordering` FROM `#__vikbooking_optionals` ORDER BY `#__vikbooking_optionals`.`ordering` ASC;";
3184 $dbo->setQuery($q);
3185 $dbo->execute();
3186 $totr = $dbo->getNumRows();
3187 if ($totr > 1) {
3188 $data = $dbo->loadAssocList();
3189 if ($pmode == "up") {
3190 foreach ($data as $v) {
3191 if ($v['id'] == $sortid[0]) {
3192 $y = $v['ordering'];
3193 }
3194 }
3195 if ($y && $y > 1) {
3196 $vik = $y - 1;
3197 $found = false;
3198 foreach ($data as $v) {
3199 if (intval($v['ordering']) == intval($vik)) {
3200 $found = true;
3201 $q = "UPDATE `#__vikbooking_optionals` SET `ordering`='".$y."' WHERE `id`='".$v['id']."' LIMIT 1;";
3202 $dbo->setQuery($q);
3203 $dbo->execute();
3204 $q = "UPDATE `#__vikbooking_optionals` SET `ordering`='".$vik."' WHERE `id`='".$sortid[0]."' LIMIT 1;";
3205 $dbo->setQuery($q);
3206 $dbo->execute();
3207 break;
3208 }
3209 }
3210 if (!$found) {
3211 $q = "UPDATE `#__vikbooking_optionals` SET `ordering`='".$vik."' WHERE `id`='".$sortid[0]."' LIMIT 1;";
3212 $dbo->setQuery($q);
3213 $dbo->execute();
3214 }
3215 }
3216 } elseif ($pmode == "down") {
3217 foreach ($data as $v) {
3218 if ($v['id'] == $sortid[0]) {
3219 $y = $v['ordering'];
3220 }
3221 }
3222 if ($y) {
3223 $vik = $y + 1;
3224 $found = false;
3225 foreach ($data as $v) {
3226 if (intval($v['ordering']) == intval($vik)) {
3227 $found = true;
3228 $q = "UPDATE `#__vikbooking_optionals` SET `ordering`='".$y."' WHERE `id`='".$v['id']."' LIMIT 1;";
3229 $dbo->setQuery($q);
3230 $dbo->execute();
3231 $q = "UPDATE `#__vikbooking_optionals` SET `ordering`='".$vik."' WHERE `id`='".$sortid[0]."' LIMIT 1;";
3232 $dbo->setQuery($q);
3233 $dbo->execute();
3234 break;
3235 }
3236 }
3237 if (!$found) {
3238 $q = "UPDATE `#__vikbooking_optionals` SET `ordering`='".$vik."' WHERE `id`='".$sortid[0]."' LIMIT 1;";
3239 $dbo->setQuery($q);
3240 $dbo->execute();
3241 }
3242 }
3243 }
3244 }
3245 $mainframe->redirect("index.php?option=com_vikbooking&task=optionals");
3246 } else {
3247 $mainframe->redirect("index.php?option=com_vikbooking");
3248 }
3249 }
3250
3251 public function sortpayment() {
3252 if (!JSession::checkToken('get')) {
3253 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
3254 }
3255 $cid = VikRequest::getVar('cid', array(0));
3256 $sortid = $cid[0];
3257 $dbo = JFactory::getDBO();
3258 $mainframe = JFactory::getApplication();
3259 $pmode = VikRequest::getString('mode', '', 'request');
3260 if (!empty($pmode) && !empty($sortid)) {
3261 $q = "SELECT `id`,`ordering` FROM `#__vikbooking_gpayments` ORDER BY `#__vikbooking_gpayments`.`ordering` ASC;";
3262 $dbo->setQuery($q);
3263 $dbo->execute();
3264 $totr=$dbo->getNumRows();
3265 if ($totr > 1) {
3266 $data = $dbo->loadAssocList();
3267 if ($pmode == "up") {
3268 foreach ($data as $v) {
3269 if ($v['id'] == $sortid) {
3270 $y = $v['ordering'];
3271 }
3272 }
3273 if ($y && $y > 1) {
3274 $vik = $y - 1;
3275 $found = false;
3276 foreach ($data as $v) {
3277 if (intval($v['ordering']) == intval($vik)) {
3278 $found = true;
3279 $q = "UPDATE `#__vikbooking_gpayments` SET `ordering`='".$y."' WHERE `id`='".$v['id']."' LIMIT 1;";
3280 $dbo->setQuery($q);
3281 $dbo->execute();
3282 $q = "UPDATE `#__vikbooking_gpayments` SET `ordering`='".$vik."' WHERE `id`='".$sortid."' LIMIT 1;";
3283 $dbo->setQuery($q);
3284 $dbo->execute();
3285 break;
3286 }
3287 }
3288 if (!$found) {
3289 $q = "UPDATE `#__vikbooking_gpayments` SET `ordering`='".$vik."' WHERE `id`='".$sortid."' LIMIT 1;";
3290 $dbo->setQuery($q);
3291 $dbo->execute();
3292 }
3293 }
3294 } elseif ($pmode == "down") {
3295 foreach ($data as $v) {
3296 if ($v['id'] == $sortid) {
3297 $y = $v['ordering'];
3298 }
3299 }
3300 if ($y) {
3301 $vik = $y + 1;
3302 $found = false;
3303 foreach ($data as $v) {
3304 if (intval($v['ordering']) == intval($vik)) {
3305 $found=true;
3306 $q = "UPDATE `#__vikbooking_gpayments` SET `ordering`='".$y."' WHERE `id`='".$v['id']."' LIMIT 1;";
3307 $dbo->setQuery($q);
3308 $dbo->execute();
3309 $q = "UPDATE `#__vikbooking_gpayments` SET `ordering`='".$vik."' WHERE `id`='".$sortid."' LIMIT 1;";
3310 $dbo->setQuery($q);
3311 $dbo->execute();
3312 break;
3313 }
3314 }
3315 if (!$found) {
3316 $q = "UPDATE `#__vikbooking_gpayments` SET `ordering`='".$vik."' WHERE `id`='".$sortid."' LIMIT 1;";
3317 $dbo->setQuery($q);
3318 $dbo->execute();
3319 }
3320 }
3321 }
3322 }
3323 $mainframe->redirect("index.php?option=com_vikbooking&task=payments");
3324 } else {
3325 $mainframe->redirect("index.php?option=com_vikbooking");
3326 }
3327 }
3328
3329 public function sortcarat() {
3330 if (!JSession::checkToken('get')) {
3331 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
3332 }
3333 $sortid = VikRequest::getVar('cid', array(0));
3334 $pmode = VikRequest::getString('mode', '', 'request');
3335 $dbo = JFactory::getDBO();
3336 $mainframe = JFactory::getApplication();
3337 if (!empty($pmode)) {
3338 $q = "SELECT `id`,`ordering` FROM `#__vikbooking_characteristics` ORDER BY `#__vikbooking_characteristics`.`ordering` ASC;";
3339 $dbo->setQuery($q);
3340 $dbo->execute();
3341 $totr = $dbo->getNumRows();
3342 if ($totr > 1) {
3343 $data = $dbo->loadAssocList();
3344 if ($pmode == "up") {
3345 foreach ($data as $v) {
3346 if ($v['id'] == $sortid[0]) {
3347 $y = $v['ordering'];
3348 }
3349 }
3350 if ($y && $y > 1) {
3351 $vik = $y - 1;
3352 $found = false;
3353 foreach ($data as $v) {
3354 if (intval($v['ordering']) == intval($vik)) {
3355 $found = true;
3356 $q = "UPDATE `#__vikbooking_characteristics` SET `ordering`='".$y."' WHERE `id`='".$v['id']."' LIMIT 1;";
3357 $dbo->setQuery($q);
3358 $dbo->execute();
3359 $q = "UPDATE `#__vikbooking_characteristics` SET `ordering`='".$vik."' WHERE `id`='".$sortid[0]."' LIMIT 1;";
3360 $dbo->setQuery($q);
3361 $dbo->execute();
3362 break;
3363 }
3364 }
3365 if (!$found) {
3366 $q = "UPDATE `#__vikbooking_characteristics` SET `ordering`='".$vik."' WHERE `id`='".$sortid[0]."' LIMIT 1;";
3367 $dbo->setQuery($q);
3368 $dbo->execute();
3369 }
3370 }
3371 } elseif ($pmode == "down") {
3372 foreach ($data as $v) {
3373 if ($v['id'] == $sortid[0]) {
3374 $y = $v['ordering'];
3375 }
3376 }
3377 if ($y) {
3378 $vik = $y + 1;
3379 $found = false;
3380 foreach ($data as $v) {
3381 if (intval($v['ordering']) == intval($vik)) {
3382 $found = true;
3383 $q = "UPDATE `#__vikbooking_characteristics` SET `ordering`='".$y."' WHERE `id`='".$v['id']."' LIMIT 1;";
3384 $dbo->setQuery($q);
3385 $dbo->execute();
3386 $q = "UPDATE `#__vikbooking_characteristics` SET `ordering`='".$vik."' WHERE `id`='".$sortid[0]."' LIMIT 1;";
3387 $dbo->setQuery($q);
3388 $dbo->execute();
3389 break;
3390 }
3391 }
3392 if (!$found) {
3393 $q = "UPDATE `#__vikbooking_characteristics` SET `ordering`='".$vik."' WHERE `id`='".$sortid[0]."' LIMIT 1;";
3394 $dbo->setQuery($q);
3395 $dbo->execute();
3396 }
3397 }
3398 }
3399 }
3400 $mainframe->redirect("index.php?option=com_vikbooking&task=carat");
3401 } else {
3402 $mainframe->redirect("index.php?option=com_vikbooking");
3403 }
3404 }
3405
3406 public function resendordemail() {
3407 $this->do_resendorderemail();
3408 }
3409
3410 public function sendcancordemail() {
3411 $this->do_resendorderemail(true);
3412 }
3413
3414 private function do_resendorderemail($cancellation = false)
3415 {
3416 $dbo = JFactory::getDbo();
3417 $app = JFactory::getApplication();
3418 $vbo_tn = VikBooking::getTranslator();
3419
3420 $cid = VikRequest::getVar('cid', array(0));
3421 $oid = (int)$cid[0];
3422
3423 $q = "SELECT * FROM `#__vikbooking_orders` WHERE `id`=" . $oid . ";";
3424 $dbo->setQuery($q);
3425 $dbo->execute();
3426 if (!$dbo->getNumRows()) {
3427 $app->redirect("index.php?option=com_vikbooking&task=orders");
3428 $app->close();
3429 }
3430 $order = $dbo->loadAssoc();
3431
3432 // check if the language in use is the same as the one used during the checkout
3433 if (!empty($order['lang'])) {
3434 $lang = JFactory::getLanguage();
3435 if ($lang->getTag() != $order['lang']) {
3436 $lang->load('com_vikbooking', (VBOPlatformDetection::isWordPress() ? VIKBOOKING_LANG : JPATH_ADMINISTRATOR), $order['lang'], true);
3437 if (defined('_JEXEC') && !defined('ABSPATH')) {
3438 $lang->load('joomla', JPATH_ADMINISTRATOR, $order['lang'], true);
3439 }
3440 }
3441 if ($vbo_tn->getDefaultLang() != $order['lang']) {
3442 // force the translation to start because contents should be translated
3443 $vbo_tn::$force_tolang = $order['lang'];
3444 }
3445 }
3446
3447 // availability helper
3448 $av_helper = VikBooking::getAvailabilityInstance();
3449
3450 /**
3451 * Split stay reservation.
3452 *
3453 * @since 1.16.0 (J) - 1.6.0 (WP)
3454 */
3455 $room_stay_dates = [];
3456 if ($order['split_stay']) {
3457 if ($order['status'] == 'confirmed') {
3458 $room_stay_dates = $av_helper->loadSplitStayBusyRecords($order['id']);
3459 } else {
3460 $room_stay_dates = VBOFactory::getConfig()->getArray('split_stay_' . $order['id'], []);
3461 }
3462 // immediately count the number of nights of stay for each split room
3463 foreach ($room_stay_dates as $sps_r_k => $sps_r_v) {
3464 if (!empty($sps_r_v['checkin_ts']) && !empty($sps_r_v['checkout_ts'])) {
3465 // overwrite values for compatibility with non-confirmed bookings
3466 $sps_r_v['checkin'] = $sps_r_v['checkin_ts'];
3467 $sps_r_v['checkout'] = $sps_r_v['checkout_ts'];
3468 }
3469 $sps_r_v['nights'] = $av_helper->countNightsOfStay($sps_r_v['checkin'], $sps_r_v['checkout']);
3470 // overwrite the whole array
3471 $room_stay_dates[$sps_r_k] = $sps_r_v;
3472 }
3473 }
3474
3475 // load rooms booked
3476 $q = "SELECT `or`.*,`r`.`id` AS `r_reference_id`,`r`.`name`,`r`.`units`,`r`.`fromadult`,`r`.`toadult`,`r`.`params` FROM `#__vikbooking_ordersrooms` AS `or`,`#__vikbooking_rooms` AS `r` WHERE `or`.`idorder`=" . (int)$order['id'] . " AND `or`.`idroom`=`r`.`id` ORDER BY `or`.`id` ASC;";
3477 $dbo->setQuery($q);
3478 $dbo->execute();
3479 $ordersrooms = $dbo->loadAssocList();
3480 $vbo_tn->translateContents($ordersrooms, '#__vikbooking_rooms', array('id' => 'r_reference_id'));
3481
3482 $ftitle = VikBooking::getFrontTitle();
3483 $currencyname = VikBooking::getCurrencyName();
3484
3485 $turnover_secs = VikBooking::getHoursRoomAvail() * 3600;
3486 $realback = $turnover_secs + $order['checkout'];
3487
3488 $rooms = array();
3489 $tars = array();
3490 $arrpeople = array();
3491 $is_package = !empty($order['pkg']) ? true : false;
3492 $nowts = time();
3493 foreach ($ordersrooms as $kor => $or) {
3494 $num = $kor + 1;
3495 $rooms[$num] = $or;
3496 $arrpeople[$num]['adults'] = $or['adults'];
3497 $arrpeople[$num]['children'] = $or['children'];
3498 if ($is_package === true || (!empty($or['cust_cost']) && $or['cust_cost'] > 0.00)) {
3499 // package or custom cost set from the back-end
3500 continue;
3501 }
3502
3503 // determine the proper values for this room
3504 $room_nights = $order['days'];
3505 $room_checkin = $order['checkin'];
3506 $room_checkout = $order['checkout'];
3507 if ($order['split_stay'] && !empty($room_stay_dates) && isset($room_stay_dates[$kor]) && $room_stay_dates[$kor]['idroom'] == $or['idroom']) {
3508 $room_nights = $room_stay_dates[$kor]['nights'];
3509 $room_checkin = $room_stay_dates[$kor]['checkin'];
3510 $room_checkout = $room_stay_dates[$kor]['checkout'];
3511 }
3512
3513 // load tariff
3514 $q = "SELECT * FROM `#__vikbooking_dispcost` WHERE `id`=" . (int)$or['idtar'] . ";";
3515 $dbo->setQuery($q);
3516 $dbo->execute();
3517 if ($dbo->getNumRows() > 0) {
3518 $tar = $dbo->loadAssocList();
3519 $tar = VikBooking::applySeasonsRoom($tar, $room_checkin, $room_checkout);
3520
3521 // different usage
3522 $tar = VBORoomHelper::getInstance()->applyOBPRules($tar, $or, $or['adults']);
3523
3524 $tars[$num] = $tar[0];
3525 } else {
3526 VikError::raiseWarning('', JText::translate('VBERRNOFAREFOUND'));
3527 }
3528 }
3529
3530 $secdiff = $order['checkout'] - $order['checkin'];
3531 $daysdiff = $secdiff / 86400;
3532 if (is_int($daysdiff)) {
3533 if ($daysdiff < 1) {
3534 $daysdiff = 1;
3535 }
3536 } else {
3537 if ($daysdiff < 1) {
3538 $daysdiff = 1;
3539 } else {
3540 $sum = floor($daysdiff) * 86400;
3541 $newdiff = $secdiff - $sum;
3542 $maxhmore = VikBooking::getHoursMoreRb() * 3600;
3543 if ($maxhmore >= $newdiff) {
3544 $daysdiff = floor($daysdiff);
3545 } else {
3546 $daysdiff = ceil($daysdiff);
3547 }
3548 }
3549 }
3550
3551 $isdue = 0;
3552 $pricestr = array();
3553 $optstr = array();
3554 foreach ($ordersrooms as $kor => $or) {
3555 $num = $kor + 1;
3556
3557 // determine the proper values for this room
3558 $room_nights = $order['days'];
3559 $room_checkin = $order['checkin'];
3560 $room_checkout = $order['checkout'];
3561 if ($order['split_stay'] && !empty($room_stay_dates) && isset($room_stay_dates[$kor]) && $room_stay_dates[$kor]['idroom'] == $or['idroom']) {
3562 $room_nights = $room_stay_dates[$kor]['nights'];
3563 $room_checkin = $room_stay_dates[$kor]['checkin'];
3564 $room_checkout = $room_stay_dates[$kor]['checkout'];
3565 }
3566
3567 if ($is_package === true || (!empty($or['cust_cost']) && $or['cust_cost'] > 0.00)) {
3568 // package cost or cust_cost may not be inclusive of taxes if prices tax included is off
3569 $calctar = VikBooking::sayPackagePlusIva($or['cust_cost'], $or['cust_idiva']);
3570 $isdue += $calctar;
3571 $pricestr[$num] = (!empty($or['pkg_name']) ? $or['pkg_name'] : (!empty($or['otarplan']) ? ucwords($or['otarplan']) : JText::translate('VBOROOMCUSTRATEPLAN'))).": ".$calctar." ".$currencyname;
3572 } elseif (array_key_exists($num, $tars) && is_array($tars[$num])) {
3573 $display_rate = !empty($or['room_cost']) ? $or['room_cost'] : $tars[$num]['cost'];
3574 $calctar = VikBooking::sayCostPlusIva($display_rate, $tars[$num]['idprice']);
3575 $tars[$num]['calctar'] = $calctar;
3576 $isdue += $calctar;
3577 $pricestr[$num] = VikBooking::getPriceName($tars[$num]['idprice'], $vbo_tn) . ": " . $calctar . " " . $currencyname . (!empty($tars[$num]['attrdata']) ? "\n" . VikBooking::getPriceAttr($tars[$num]['idprice'], $vbo_tn) . ": " . $tars[$num]['attrdata'] : "");
3578 }
3579 if (!empty($or['optionals'])) {
3580 $stepo = explode(";", $or['optionals']);
3581 foreach ($stepo as $roptkey => $oo) {
3582 if (empty($oo)) {
3583 continue;
3584 }
3585 $stept = explode(":", $oo);
3586 $q = "SELECT * FROM `#__vikbooking_optionals` WHERE `id`=" . $dbo->quote($stept[0]) . ";";
3587 $dbo->setQuery($q);
3588 $dbo->execute();
3589 if (!$dbo->getNumRows()) {
3590 continue;
3591 }
3592 $actopt = $dbo->loadAssocList();
3593 $vbo_tn->translateContents($actopt, '#__vikbooking_optionals', array(), array(), (!empty($order['lang']) ? $order['lang'] : null));
3594 $chvar = '';
3595 if (!empty($actopt[0]['ageintervals']) && $or['children'] > 0 && strstr($stept[1], '-') != false) {
3596 $optagenames = VikBooking::getOptionIntervalsAges($actopt[0]['ageintervals']);
3597 $optagepcent = VikBooking::getOptionIntervalsPercentage($actopt[0]['ageintervals']);
3598 $optageovrct = VikBooking::getOptionIntervalChildOverrides($actopt[0], $or['adults'], $or['children']);
3599 $child_num = VikBooking::getRoomOptionChildNumber($or['optionals'], $actopt[0]['id'], $roptkey, $or['children']);
3600 $optagecosts = VikBooking::getOptionIntervalsCosts(isset($optageovrct['ageintervals_child' . ($child_num + 1)]) ? $optageovrct['ageintervals_child' . ($child_num + 1)] : $actopt[0]['ageintervals']);
3601 $agestept = explode('-', $stept[1]);
3602 $stept[1] = $agestept[0];
3603 $chvar = $agestept[1];
3604 if (array_key_exists(($chvar - 1), $optagepcent) && $optagepcent[($chvar - 1)] == 1) {
3605 //percentage value of the adults tariff
3606 if ($is_package === true || (!empty($or['cust_cost']) && $or['cust_cost'] > 0.00)) {
3607 $optagecosts[($chvar - 1)] = $or['cust_cost'] * $optagecosts[($chvar - 1)] / 100;
3608 } else {
3609 $display_rate = !empty($or['room_cost']) ? $or['room_cost'] : $tars[$num]['cost'];
3610 $optagecosts[($chvar - 1)] = $display_rate * $optagecosts[($chvar - 1)] / 100;
3611 }
3612 } elseif (array_key_exists(($chvar - 1), $optagepcent) && $optagepcent[($chvar - 1)] == 2) {
3613 //VBO 1.10 - percentage value of room base cost
3614 if ($is_package === true || (!empty($or['cust_cost']) && $or['cust_cost'] > 0.00)) {
3615 $optagecosts[($chvar - 1)] = $or['cust_cost'] * $optagecosts[($chvar - 1)] / 100;
3616 } else {
3617 $display_rate = isset($tars[$num]['room_base_cost']) ? $tars[$num]['room_base_cost'] : (!empty($or['room_cost']) ? $or['room_cost'] : $tars[$num]['cost']);
3618 $optagecosts[($chvar - 1)] = $display_rate * $optagecosts[($chvar - 1)] / 100;
3619 }
3620 }
3621 $actopt[0]['chageintv'] = $chvar;
3622 $actopt[0]['name'] .= ' ('.$optagenames[($chvar - 1)].')';
3623 $actopt[0]['quan'] = $stept[1];
3624 $realcost = (intval($actopt[0]['perday']) == 1 ? (floatval($optagecosts[($chvar - 1)]) * $room_nights * $stept[1]) : (floatval($optagecosts[($chvar - 1)]) * $stept[1]));
3625 } else {
3626 $actopt[0]['quan'] = $stept[1];
3627 // VBO 1.11 - options percentage cost of the room total fee
3628 if ($is_package === true || (!empty($or['cust_cost']) && $or['cust_cost'] > 0.00)) {
3629 $deftar_basecosts = $or['cust_cost'];
3630 } else {
3631 $deftar_basecosts = !empty($or['room_cost']) ? $or['room_cost'] : $tars[$num]['cost'];
3632 }
3633 $actopt[0]['cost'] = (int)$actopt[0]['pcentroom'] ? ($deftar_basecosts * $actopt[0]['cost'] / 100) : $actopt[0]['cost'];
3634 //
3635 $realcost = (intval($actopt[0]['perday']) == 1 ? ($actopt[0]['cost'] * $room_nights * $stept[1]) : ($actopt[0]['cost'] * $stept[1]));
3636 }
3637 if (!empty($actopt[0]['maxprice']) && $actopt[0]['maxprice'] > 0 && $realcost > $actopt[0]['maxprice']) {
3638 $realcost = $actopt[0]['maxprice'];
3639 if (intval($actopt[0]['hmany']) == 1 && intval($stept[1]) > 1) {
3640 $realcost = $actopt[0]['maxprice'] * $stept[1];
3641 }
3642 }
3643 if ($actopt[0]['perperson'] == 1) {
3644 $realcost = $realcost * $or['adults'];
3645 }
3646 $tmpopr = VikBooking::sayOptionalsPlusIva($realcost, $actopt[0]['idiva']);
3647 $isdue += $tmpopr;
3648 $optstr[$num][] = ($stept[1] > 1 ? $stept[1] . " " : "") . $actopt[0]['name'] . ": " . $tmpopr . " " . $currencyname . "\n";
3649 }
3650 }
3651
3652 // custom extra costs
3653 if (!empty($or['extracosts'])) {
3654 $cur_extra_costs = json_decode($or['extracosts'], true);
3655 foreach ($cur_extra_costs as $eck => $ecv) {
3656 $ecplustax = !empty($ecv['idtax']) ? VikBooking::sayOptionalsPlusIva($ecv['cost'], $ecv['idtax']) : $ecv['cost'];
3657 $isdue += $ecplustax;
3658 $optstr[$num][] = $ecv['name'] . ": " . $ecplustax . " " . $currencyname."\n";
3659 }
3660 }
3661 }
3662
3663 // coupon
3664 $usedcoupon = false;
3665 $origisdue = $isdue;
3666 if (strlen($order['coupon']) > 0) {
3667 $usedcoupon = true;
3668 $expcoupon = explode(";", $order['coupon']);
3669 $isdue = $isdue - $expcoupon[1];
3670 }
3671
3672 // make sure to apply any previously refunded amount
3673 if ($order['refund'] > 0) {
3674 $isdue -= $order['refund'];
3675 }
3676
3677 // ConfirmationNumber
3678 $confirmnumber = $order['confirmnumber'];
3679
3680 $esit_mess = JText::sprintf('VBORDEREMAILRESENT', $order['custmail']);
3681 $status_str = JText::translate('VBCOMPLETED');
3682 if ($cancellation) {
3683 $confirmnumber = '';
3684 $esit_mess = JText::sprintf('VBCANCORDEREMAILSENT', $order['custmail']);
3685 $status_str = JText::translate('VBCANCELLED');
3686 } elseif ($order['status'] == 'standby') {
3687 $confirmnumber = '';
3688 $status_str = JText::translate('VBWAITINGFORPAYMENT');
3689 }
3690 $app->enqueueMessage($esit_mess);
3691
3692 // force the original total amount if rates have changed
3693 if (number_format($isdue, 2) != number_format($order['total'], 2)) {
3694 $isdue = $order['total'];
3695 }
3696
3697 // send email notification to guest (by ignoring the configuration settings)
3698 VikBooking::sendBookingEmail($order['id'], ['guest'], $send = true, $no_config = true);
3699
3700 if ($cancellation) {
3701 /**
3702 * If "send cancellation email", we log the event in the history.
3703 *
3704 * @since 1.14 (J) - 1.4.0 (WP)
3705 */
3706 VikBooking::getBookingHistoryInstance()->setBid($order['id'])->store('EC');
3707 } else {
3708 /**
3709 * Instead, we store an event log to remind that the email was re-sent to the guest
3710 *
3711 * @since 1.16.3 (J) - 1.6.3 (WP)
3712 */
3713 VikBooking::getBookingHistoryInstance()->setBid($order['id'])->store('ER', $esit_mess);
3714 }
3715
3716 $app->redirect("index.php?option=com_vikbooking&task=editorder&cid[]=".$oid);
3717 $app->close();
3718 }
3719
3720 public function setordconfirmed()
3721 {
3722 $dbo = JFactory::getDbo();
3723 $app = JFactory::getApplication();
3724
3725 $cid = VikRequest::getVar('cid', array(0));
3726 $oid = $cid[0];
3727
3728 $q = "SELECT * FROM `#__vikbooking_orders` WHERE `id`=" . (int)$oid . " AND `status` != 'confirmed';";
3729 $dbo->setQuery($q);
3730 $dbo->execute();
3731 if (!$dbo->getNumRows()) {
3732 $app->redirect("index.php?option=com_vikbooking&task=editorder&cid[]=" . $oid);
3733 exit;
3734 }
3735 $order = $dbo->loadAssoc();
3736
3737 /**
3738 * Memorize the original booking status for VCM in case of OTA booking.
3739 *
3740 * @since 1.14 (J) - 1.4.0 (WP)
3741 */
3742 $original_book_status = null;
3743 if (!empty($order['idorderota']) && !empty($order['channel'])) {
3744 $original_book_status = $order['status'];
3745 }
3746
3747 // availability helper
3748 $av_helper = VikBooking::getAvailabilityInstance();
3749
3750 // room stay dates in case of split stay
3751 $room_stay_dates = [];
3752 if ($order['split_stay']) {
3753 $room_stay_dates = VBOFactory::getConfig()->getArray('split_stay_' . $order['id'], []);
3754 }
3755
3756 $vbo_tn = VikBooking::getTranslator();
3757 // check if the language in use is the same as the one used during the checkout
3758 if (!empty($order['lang'])) {
3759 $lang = JFactory::getLanguage();
3760 if ($lang->getTag() != $order['lang']) {
3761 $lang->load('com_vikbooking', (VBOPlatformDetection::isWordPress() ? VIKBOOKING_LANG : JPATH_ADMINISTRATOR), $order['lang'], true);
3762 if (defined('_JEXEC') && !defined('ABSPATH')) {
3763 $lang->load('joomla', JPATH_ADMINISTRATOR, $order['lang'], true);
3764 }
3765 }
3766 if ($vbo_tn->getDefaultLang() != $order['lang']) {
3767 // force the translation to start because contents should be translated
3768 $vbo_tn::$force_tolang = $order['lang'];
3769 }
3770 }
3771
3772 // load order rooms
3773 $q = "SELECT `or`.*,`r`.`id` AS `r_reference_id`,`r`.`name`,`r`.`units`,`r`.`fromadult`,`r`.`toadult`,`r`.`params` FROM `#__vikbooking_ordersrooms` AS `or`,`#__vikbooking_rooms` AS `r` WHERE `or`.`idorder`=" . (int)$order['id'] . " AND `or`.`idroom`=`r`.`id` ORDER BY `or`.`id` ASC;";
3774 $dbo->setQuery($q);
3775 $dbo->execute();
3776 $ordersrooms = $dbo->loadAssocList();
3777 $vbo_tn->translateContents($ordersrooms, '#__vikbooking_rooms', array('id' => 'r_reference_id'));
3778
3779 $currencyname = VikBooking::getCurrencyName();
3780 $turnover_secs = VikBooking::getHoursRoomAvail() * 3600;
3781 $realback = $turnover_secs + $order['checkout'];
3782 $allbook = true;
3783 $notavail = [];
3784
3785 /**
3786 * We need to calculate a minus operator for each room that was booked more than once.
3787 * In case we are confirming a booking for more than one unit of the same room, we need to
3788 * make sure the calculation is made properly, as only one unit of that room could be free.
3789 *
3790 * @since 1.13 (J) - 1.3.0 (WP)
3791 */
3792 $units_minus_oper = [];
3793 foreach ($ordersrooms as $ind => $or) {
3794 if (!isset($units_minus_oper[$or['idroom']])) {
3795 $units_minus_oper[$or['idroom']] = -1;
3796 }
3797 // increase counter
3798 $units_minus_oper[$or['idroom']]++;
3799 if (!empty($room_stay_dates)) {
3800 // split stay rooms never have the same stay dates, but they should also be different rooms
3801 $units_minus_oper[$or['idroom']] = 0;
3802 }
3803 }
3804
3805 foreach ($ordersrooms as $ind => $or) {
3806 // determine proper values for this room
3807 $room_stay_checkin = $order['checkin'];
3808 $room_stay_checkout = $order['checkout'];
3809 $room_stay_nights = $order['days'];
3810 if ($order['split_stay'] && count($room_stay_dates) && isset($room_stay_dates[$ind]) && $room_stay_dates[$ind]['idroom'] == $or['idroom']) {
3811 $room_stay_checkin = !empty($room_stay_dates[$ind]['checkin_ts']) ? $room_stay_dates[$ind]['checkin_ts'] : $room_stay_dates[$ind]['checkin'];
3812 $room_stay_checkout = !empty($room_stay_dates[$ind]['checkout_ts']) ? $room_stay_dates[$ind]['checkout_ts'] : $room_stay_dates[$ind]['checkout'];
3813 $room_stay_nights = $av_helper->countNightsOfStay($room_stay_checkin, $room_stay_checkout);
3814 // inject nights calculated for this room
3815 $room_stay_dates[$ind]['nights'] = $room_stay_nights;
3816 }
3817
3818 // check if the room is available
3819 if (!VikBooking::roomBookable($or['idroom'], ($or['units'] - $units_minus_oper[$or['idroom']]), $room_stay_checkin, $room_stay_checkout)) {
3820 $allbook = false;
3821 $notavail[] = $or['name']." (".JText::translate('VBMAILADULTS').": ".$or['adults'].($or['children'] > 0 ? " - ".JText::translate('VBMAILCHILDREN').": ".$or['children'] : "").")";
3822 }
3823 }
3824
3825 if (!$allbook) {
3826 VikError::raiseWarning('', JText::translate('VBERRCONFORDERNOTAVROOM').' '.implode(", ", $notavail).'<br/>'.JText::translate('VBUNABLESETRESCONF'));
3827 $app->redirect("index.php?option=com_vikbooking&task=editorder&cid[]=" . $oid);
3828 exit;
3829 }
3830
3831 $rooms = [];
3832 $tars = [];
3833 $arrpeople = [];
3834 $is_package = !empty($order['pkg']) ? true : false;
3835 $rooms_booked = [];
3836 foreach ($ordersrooms as $ind => $or) {
3837 // push room booked
3838 array_push($rooms_booked, (int)$or['idroom']);
3839
3840 // determine proper values for this room
3841 $room_stay_checkin = $order['checkin'];
3842 $room_stay_checkout = $order['checkout'];
3843 $room_stay_realback = $realback;
3844 if ($order['split_stay'] && count($room_stay_dates) && isset($room_stay_dates[$ind]) && $room_stay_dates[$ind]['idroom'] == $or['idroom']) {
3845 $room_stay_checkin = !empty($room_stay_dates[$ind]['checkin_ts']) ? $room_stay_dates[$ind]['checkin_ts'] : $room_stay_dates[$ind]['checkin'];
3846 $room_stay_checkout = !empty($room_stay_dates[$ind]['checkout_ts']) ? $room_stay_dates[$ind]['checkout_ts'] : $room_stay_dates[$ind]['checkout'];
3847 $room_stay_realback = $turnover_secs + $room_stay_checkout;
3848 }
3849
3850 $q = "INSERT INTO `#__vikbooking_busy` (`idroom`,`checkin`,`checkout`,`realback`) VALUES(" . (int)$or['idroom'] . ", " . (int)$room_stay_checkin . ", " . (int)$room_stay_checkout . ", " . (int)$room_stay_realback . ");";
3851 $dbo->setQuery($q);
3852 $dbo->execute();
3853 $lid = $dbo->insertid();
3854
3855 $q = "INSERT INTO `#__vikbooking_ordersbusy` (`idorder`,`idbusy`) VALUES(" . (int)$oid . ", " . (int)$lid . ");";
3856 $dbo->setQuery($q);
3857 $dbo->execute();
3858 }
3859
3860 // update status
3861 $q = "UPDATE `#__vikbooking_orders` SET `status`='confirmed' WHERE `id`=" . (int)$order['id'] . ";";
3862 $dbo->setQuery($q);
3863 $dbo->execute();
3864
3865 // remove any previous temporary locked record
3866 $q = "DELETE FROM `#__vikbooking_tmplock` WHERE `idorder`=" . (int)$order['id'] . ";";
3867 $dbo->setQuery($q);
3868 $dbo->execute();
3869
3870 // Booking History
3871 $now_user = JFactory::getUser();
3872 VikBooking::getBookingHistoryInstance()->setBid($order['id'])->store('TC', "({$now_user->name})");
3873
3874 // check if some of the rooms booked have shared calendars
3875 VikBooking::updateSharedCalendars($order['id'], $rooms_booked, $order['checkin'], $order['checkout']);
3876
3877 // send mail
3878 $ftitle = VikBooking::getFrontTitle();
3879 $nowts = time();
3880 // assign room specific unit
3881 $set_room_indexes = VikBooking::autoRoomUnit();
3882 $room_indexes_usemap = [];
3883
3884 foreach ($ordersrooms as $kor => $or) {
3885 $num = $kor + 1;
3886
3887 // determine proper values for this room
3888 $room_stay_checkin = $order['checkin'];
3889 $room_stay_checkout = $order['checkout'];
3890 $room_stay_nights = $order['days'];
3891 if ($order['split_stay'] && count($room_stay_dates) && isset($room_stay_dates[$kor]) && $room_stay_dates[$kor]['idroom'] == $or['idroom']) {
3892 $room_stay_checkin = !empty($room_stay_dates[$kor]['checkin_ts']) ? $room_stay_dates[$kor]['checkin_ts'] : $room_stay_dates[$kor]['checkin'];
3893 $room_stay_checkout = !empty($room_stay_dates[$kor]['checkout_ts']) ? $room_stay_dates[$kor]['checkout_ts'] : $room_stay_dates[$kor]['checkout'];
3894 $room_stay_nights = $room_stay_dates[$kor]['nights'];
3895 }
3896
3897 $rooms[$num] = $or;
3898 $arrpeople[$num]['adults'] = $or['adults'];
3899 $arrpeople[$num]['children'] = $or['children'];
3900
3901 // assign room specific unit
3902 if ($set_room_indexes === true) {
3903 $room_indexes = VikBooking::getRoomUnitNumsAvailable($order, $or['r_reference_id']);
3904 $use_ind_key = 0;
3905 if (count($room_indexes)) {
3906 if (!array_key_exists($or['r_reference_id'], $room_indexes_usemap)) {
3907 $room_indexes_usemap[$or['r_reference_id']] = $use_ind_key;
3908 } else {
3909 $use_ind_key = $room_indexes_usemap[$or['r_reference_id']];
3910 }
3911 $q = "UPDATE `#__vikbooking_ordersrooms` SET `roomindex`=".(int)$room_indexes[$use_ind_key]." WHERE `id`=".(int)$or['id'].";";
3912 $dbo->setQuery($q);
3913 $dbo->execute();
3914 // update rooms references for the customer email sending function
3915 $rooms[$num]['roomindex'] = (int)$room_indexes[$use_ind_key];
3916 //
3917 $room_indexes_usemap[$or['r_reference_id']]++;
3918 }
3919 }
3920
3921 if ($is_package === true || (!empty($or['cust_cost']) && $or['cust_cost'] > 0.00)) {
3922 // package or custom cost set from the back-end
3923 continue;
3924 }
3925
3926 $q = "SELECT * FROM `#__vikbooking_dispcost` WHERE `id`=" . (int)$or['idtar'] . ";";
3927 $dbo->setQuery($q);
3928 $dbo->execute();
3929 if ($dbo->getNumRows() > 0) {
3930 $tar = $dbo->loadAssocList();
3931 $tar = VikBooking::applySeasonsRoom($tar, $room_stay_checkin, $room_stay_checkout);
3932
3933 // different usage
3934 $tar = VBORoomHelper::getInstance()->applyOBPRules($tar, $or, $or['adults']);
3935
3936 $tars[$num] = $tar[0];
3937 } else {
3938 VikError::raiseWarning('', JText::translate('VBERRNOFAREFOUND'));
3939 }
3940 }
3941
3942 $pcheckin = $order['checkin'];
3943 $pcheckout = $order['checkout'];
3944 $secdiff = $pcheckout - $pcheckin;
3945 $daysdiff = $secdiff / 86400;
3946 if (is_int($daysdiff)) {
3947 if ($daysdiff < 1) {
3948 $daysdiff = 1;
3949 }
3950 } else {
3951 if ($daysdiff < 1) {
3952 $daysdiff = 1;
3953 } else {
3954 $sum = floor($daysdiff) * 86400;
3955 $newdiff = $secdiff - $sum;
3956 $maxhmore = VikBooking::getHoursMoreRb() * 3600;
3957 if ($maxhmore >= $newdiff) {
3958 $daysdiff = floor($daysdiff);
3959 } else {
3960 $daysdiff = ceil($daysdiff);
3961 }
3962 }
3963 }
3964
3965 $isdue = 0;
3966 $pricestr = [];
3967 $optstr = [];
3968 foreach ($ordersrooms as $kor => $or) {
3969 $num = $kor + 1;
3970
3971 // determine proper values for this room
3972 $room_stay_checkin = $order['checkin'];
3973 $room_stay_checkout = $order['checkout'];
3974 $room_stay_nights = $order['days'];
3975 if ($order['split_stay'] && count($room_stay_dates) && isset($room_stay_dates[$kor]) && $room_stay_dates[$kor]['idroom'] == $or['idroom']) {
3976 $room_stay_checkin = !empty($room_stay_dates[$kor]['checkin_ts']) ? $room_stay_dates[$kor]['checkin_ts'] : $room_stay_dates[$kor]['checkin'];
3977 $room_stay_checkout = !empty($room_stay_dates[$kor]['checkout_ts']) ? $room_stay_dates[$kor]['checkout_ts'] : $room_stay_dates[$kor]['checkout'];
3978 $room_stay_nights = $room_stay_dates[$kor]['nights'];
3979 }
3980
3981 if ($is_package === true || (!empty($or['cust_cost']) && $or['cust_cost'] > 0.00)) {
3982 // package cost or cust_cost may not be inclusive of taxes if prices tax included is off
3983 $calctar = VikBooking::sayPackagePlusIva($or['cust_cost'], $or['cust_idiva']);
3984 $isdue += $calctar;
3985 $pricestr[$num] = (!empty($or['pkg_name']) ? $or['pkg_name'] : (!empty($or['otarplan']) ? ucwords($or['otarplan']) : JText::translate('VBOROOMCUSTRATEPLAN'))).": ".$calctar." ".$currencyname;
3986 } elseif (array_key_exists($num, $tars) && is_array($tars[$num])) {
3987 $display_rate = !empty($or['room_cost']) ? $or['room_cost'] : $tars[$num]['cost'];
3988 $calctar = VikBooking::sayCostPlusIva($display_rate, $tars[$num]['idprice']);
3989 $tars[$num]['calctar'] = $calctar;
3990 $isdue += $calctar;
3991 $pricestr[$num] = VikBooking::getPriceName($tars[$num]['idprice'], $vbo_tn) . ": " . $calctar . " " . $currencyname . (!empty($tars[$num]['attrdata']) ? "\n" . VikBooking::getPriceAttr($tars[$num]['idprice'], $vbo_tn) . ": " . $tars[$num]['attrdata'] : "");
3992 }
3993 if (!empty($or['optionals'])) {
3994 $stepo = explode(";", $or['optionals']);
3995 foreach ($stepo as $roptkey => $oo) {
3996 if (empty($oo)) {
3997 continue;
3998 }
3999 $stept = explode(":", $oo);
4000 $q = "SELECT * FROM `#__vikbooking_optionals` WHERE `id`=" . $dbo->quote($stept[0]) . ";";
4001 $dbo->setQuery($q);
4002 $dbo->execute();
4003 if (!$dbo->getNumRows()) {
4004 continue;
4005 }
4006 $actopt = $dbo->loadAssocList();
4007 $vbo_tn->translateContents($actopt, '#__vikbooking_optionals');
4008 $chvar = '';
4009 if (!empty($actopt[0]['ageintervals']) && $or['children'] > 0 && strstr($stept[1], '-') != false) {
4010 $optagenames = VikBooking::getOptionIntervalsAges($actopt[0]['ageintervals']);
4011 $optagepcent = VikBooking::getOptionIntervalsPercentage($actopt[0]['ageintervals']);
4012 $optageovrct = VikBooking::getOptionIntervalChildOverrides($actopt[0], $or['adults'], $or['children']);
4013 $child_num = VikBooking::getRoomOptionChildNumber($or['optionals'], $actopt[0]['id'], $roptkey, $or['children']);
4014 $optagecosts = VikBooking::getOptionIntervalsCosts(isset($optageovrct['ageintervals_child' . ($child_num + 1)]) ? $optageovrct['ageintervals_child' . ($child_num + 1)] : $actopt[0]['ageintervals']);
4015 $agestept = explode('-', $stept[1]);
4016 $stept[1] = $agestept[0];
4017 $chvar = $agestept[1];
4018 if (array_key_exists(($chvar - 1), $optagepcent) && $optagepcent[($chvar - 1)] == 1) {
4019 //percentage value of the adults tariff
4020 if ($is_package === true || (!empty($or['cust_cost']) && $or['cust_cost'] > 0.00)) {
4021 $optagecosts[($chvar - 1)] = $or['cust_cost'] * $optagecosts[($chvar - 1)] / 100;
4022 } else {
4023 $display_rate = !empty($or['room_cost']) ? $or['room_cost'] : $tars[$num]['cost'];
4024 $optagecosts[($chvar - 1)] = $display_rate * $optagecosts[($chvar - 1)] / 100;
4025 }
4026 } elseif (array_key_exists(($chvar - 1), $optagepcent) && $optagepcent[($chvar - 1)] == 2) {
4027 //VBO 1.10 - percentage value of room base cost
4028 if ($is_package === true || (!empty($or['cust_cost']) && $or['cust_cost'] > 0.00)) {
4029 $optagecosts[($chvar - 1)] = $or['cust_cost'] * $optagecosts[($chvar - 1)] / 100;
4030 } else {
4031 $display_rate = isset($tars[$num]['room_base_cost']) ? $tars[$num]['room_base_cost'] : (!empty($or['room_cost']) ? $or['room_cost'] : $tars[$num]['cost']);
4032 $optagecosts[($chvar - 1)] = $display_rate * $optagecosts[($chvar - 1)] / 100;
4033 }
4034 }
4035 $actopt[0]['chageintv'] = $chvar;
4036 $actopt[0]['name'] .= ' ('.$optagenames[($chvar - 1)].')';
4037 $actopt[0]['quan'] = $stept[1];
4038 $realcost = (intval($actopt[0]['perday']) == 1 ? (floatval($optagecosts[($chvar - 1)]) * $room_stay_nights * $stept[1]) : (floatval($optagecosts[($chvar - 1)]) * $stept[1]));
4039 } else {
4040 $actopt[0]['quan'] = $stept[1];
4041 // VBO 1.11 - options percentage cost of the room total fee
4042 if ($is_package === true || (!empty($or['cust_cost']) && $or['cust_cost'] > 0.00)) {
4043 $deftar_basecosts = $or['cust_cost'];
4044 } else {
4045 $deftar_basecosts = !empty($or['room_cost']) ? $or['room_cost'] : $tars[$num]['cost'];
4046 }
4047 $actopt[0]['cost'] = (int)$actopt[0]['pcentroom'] ? ($deftar_basecosts * $actopt[0]['cost'] / 100) : $actopt[0]['cost'];
4048 //
4049 $realcost = (intval($actopt[0]['perday']) == 1 ? ($actopt[0]['cost'] * $room_stay_nights * $stept[1]) : ($actopt[0]['cost'] * $stept[1]));
4050 }
4051 if (!empty($actopt[0]['maxprice']) && $actopt[0]['maxprice'] > 0 && $realcost > $actopt[0]['maxprice']) {
4052 $realcost = $actopt[0]['maxprice'];
4053 if (intval($actopt[0]['hmany']) == 1 && intval($stept[1]) > 1) {
4054 $realcost = $actopt[0]['maxprice'] * $stept[1];
4055 }
4056 }
4057 if ($actopt[0]['perperson'] == 1) {
4058 $realcost = $realcost * $or['adults'];
4059 }
4060 $tmpopr = VikBooking::sayOptionalsPlusIva($realcost, $actopt[0]['idiva']);
4061 $isdue += $tmpopr;
4062 $optstr[$num][] = ($stept[1] > 1 ? $stept[1] . " " : "") . $actopt[0]['name'] . ": " . $tmpopr . " " . $currencyname . "\n";
4063 }
4064 }
4065
4066 // custom extra costs
4067 if (!empty($or['extracosts'])) {
4068 $cur_extra_costs = json_decode($or['extracosts'], true);
4069 foreach ($cur_extra_costs as $eck => $ecv) {
4070 $ecplustax = !empty($ecv['idtax']) ? VikBooking::sayOptionalsPlusIva($ecv['cost'], $ecv['idtax']) : $ecv['cost'];
4071 $isdue += $ecplustax;
4072 $optstr[$num][] = $ecv['name'] . ": " . $ecplustax . " " . $currencyname."\n";
4073 }
4074 }
4075 }
4076
4077 // coupon
4078 $usedcoupon = false;
4079 $origisdue = $isdue;
4080 if (strlen($order['coupon']) > 0) {
4081 $usedcoupon = true;
4082 $expcoupon = explode(";", $order['coupon']);
4083 $isdue = $isdue - $expcoupon[1];
4084 }
4085
4086 // make sure to apply any previously refunded amount
4087 if ($order['refund'] > 0) {
4088 $isdue -= $order['refund'];
4089 }
4090
4091 // ConfirmationNumber
4092 $confirmnumber = VikBooking::generateConfirmNumber($order['id'], true);
4093
4094 $app->enqueueMessage(JText::translate('VBORDERSETASCONF'));
4095
4096 // notify the customer unless it was a re-confirmation
4097 $pskip = VikRequest::getInt('skip_notification', 0, 'request');
4098 if ($pskip < 1) {
4099 // send email notification to guest
4100 VikBooking::sendBookingEmail($order['id'], array('guest'));
4101
4102 // SMS skipping the administrator
4103 VikBooking::sendBookingSMS($order['id'], array('admin'));
4104 }
4105
4106 // Invoke Channel Manager
4107 $vcm_autosync = VikBooking::vcmAutoUpdate();
4108 if ($vcm_autosync > 0) {
4109 $vcm_obj = VikBooking::getVcmInvoker();
4110 $vcm_obj->setOids(array($order['id']))->setSyncType('new')->setOriginalStatuses(array($original_book_status));
4111 $sync_result = $vcm_obj->doSync();
4112 if ($sync_result === false) {
4113 $vcm_err = $vcm_obj->getError();
4114 VikError::raiseWarning('', JText::translate('VBCHANNELMANAGERRESULTKO').' <a href="index.php?option=com_vikchannelmanager" target="_blank">'.JText::translate('VBCHANNELMANAGEROPEN').'</a> '.(strlen($vcm_err) > 0 ? '('.$vcm_err.')' : ''));
4115 }
4116 } elseif (file_exists(VCM_SITE_PATH . DIRECTORY_SEPARATOR . "helpers" . DIRECTORY_SEPARATOR . "synch.vikbooking.php")) {
4117 $vcm_sync_url = 'index.php?option=com_vikbooking&task=invoke_vcm&stype=new&cid[]='.$order['id'].'&returl='.urlencode('index.php?option=com_vikbooking&task=editorder&cid[]='.$order['id']);
4118 VikError::raiseNotice('', JText::translate('VBCHANNELMANAGERINVOKEASK').' <button type="button" class="btn btn-primary" onclick="document.location.href=\''.$vcm_sync_url.'\';">'.JText::translate('VBCHANNELMANAGERSENDRQ').'</button>');
4119 }
4120
4121 $app->redirect("index.php?option=com_vikbooking&task=editorder&cid[]=" . $oid);
4122 }
4123
4124 public function payments() {
4125 VikBookingHelper::printHeader("14");
4126
4127 VikRequest::setVar('view', VikRequest::getCmd('view', 'payments'));
4128
4129 parent::display();
4130
4131 if (VikBooking::showFooter()) {
4132 VikBookingHelper::printFooter();
4133 }
4134 }
4135
4136 public function newpayment() {
4137 VikBookingHelper::printHeader("14");
4138
4139 VikRequest::setVar('view', VikRequest::getCmd('view', 'managepayment'));
4140
4141 parent::display();
4142
4143 if (VikBooking::showFooter()) {
4144 VikBookingHelper::printFooter();
4145 }
4146 }
4147
4148 public function editpayment() {
4149 VikBookingHelper::printHeader("14");
4150
4151 VikRequest::setVar('view', VikRequest::getCmd('view', 'managepayment'));
4152
4153 parent::display();
4154
4155 if (VikBooking::showFooter()) {
4156 VikBookingHelper::printFooter();
4157 }
4158 }
4159
4160 public function createpayment()
4161 {
4162 if (!JSession::checkToken()) {
4163 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
4164 }
4165
4166 if (!JFactory::getUser()->authorise('core.create', 'com_vikbooking')) {
4167 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
4168 }
4169
4170 $mainframe = JFactory::getApplication();
4171 $pname = VikRequest::getString('name', '', 'request');
4172 $ppayment = VikRequest::getString('payment', '', 'request');
4173 $ppublished = VikRequest::getString('published', '', 'request');
4174 $pcharge = VikRequest::getFloat('charge', '', 'request');
4175 $psetconfirmed = VikRequest::getString('setconfirmed', '', 'request');
4176 $phidenonrefund = VikRequest::getInt('hidenonrefund', '', 'request');
4177 $ponlynonrefund = VikRequest::getInt('onlynonrefund', '', 'request');
4178 $pshownotealw = VikRequest::getString('shownotealw', '', 'request');
4179 $pnote = VikRequest::getString('note', '', 'request', VIKREQUEST_ALLOWHTML);
4180 $pval_pcent = VikRequest::getString('val_pcent', '', 'request');
4181 $pval_pcent = !in_array($pval_pcent, array('1', '2')) ? 1 : $pval_pcent;
4182 $pch_disc = VikRequest::getString('ch_disc', '', 'request');
4183 $pch_disc = !in_array($pch_disc, array('1', '2')) ? 1 : $pch_disc;
4184 $poutposition = VikRequest::getString('outposition', 'top', 'request');
4185 $plogo = VikRequest::getString('logo', '', 'request');
4186 $pall_rooms = VikRequest::getInt('all_rooms', 0, 'request');
4187 $pidrooms = VikRequest::getVar('idrooms', array());
4188 $vikpaymentparams = VikRequest::getVar('vikpaymentparams', array(0));
4189 $payparamarr = array();
4190 $payparamstr = '';
4191 if (count($vikpaymentparams) > 0) {
4192 foreach ($vikpaymentparams as $setting => $cont) {
4193 if (strlen($setting) > 0) {
4194 $payparamarr[$setting] = $cont;
4195 }
4196 }
4197 if (count($payparamarr) > 0) {
4198 $payparamstr = json_encode($payparamarr);
4199 }
4200 }
4201
4202 $dbo = JFactory::getDbo();
4203
4204 $set_idrooms = [];
4205 if (empty($pall_rooms) && !empty($pidrooms)) {
4206 $pidrooms = array_map(function($idroom) {
4207 return (int)$idroom;
4208 }, $pidrooms);
4209 foreach ($pidrooms as $idroom) {
4210 if (empty($idroom) || in_array($idroom, $set_idrooms)) {
4211 continue;
4212 }
4213 $set_idrooms[] = $idroom;
4214 }
4215 }
4216
4217 if (!empty($pname) && !empty($ppayment)) {
4218 $setpub = $ppublished == "1" ? 1 : 0;
4219 $psetconfirmed = $psetconfirmed == "1" ? 1 : 0;
4220 $pshownotealw = $pshownotealw == "1" ? 1 : 0;
4221 $q = "SELECT `id` FROM `#__vikbooking_gpayments` WHERE `file`=".$dbo->quote($ppayment).";";
4222 $dbo->setQuery($q);
4223 $dbo->execute();
4224 if ($dbo->getNumRows() >= 0) {
4225 $q = "INSERT INTO `#__vikbooking_gpayments` (`name`,`file`,`published`,`note`,`charge`,`setconfirmed`,`shownotealw`,`val_pcent`,`ch_disc`,`params`,`hidenonrefund`,`onlynonrefund`,`outposition`,`logo`,`idrooms`) VALUES(".$dbo->quote($pname).",".$dbo->quote($ppayment).",'".$setpub."',".$dbo->quote($pnote).",".$dbo->quote($pcharge).",'".$psetconfirmed."','".$pshownotealw."','".$pval_pcent."','".$pch_disc."',".$dbo->quote($payparamstr).",".($phidenonrefund > 0 ? '1' : '0').",".($ponlynonrefund > 0 ? '1' : '0').", " . $dbo->quote($poutposition) . ", " . $dbo->quote($plogo) . ", " . (count($set_idrooms) ? $dbo->quote(json_encode($set_idrooms)) : 'NULL') . ");";
4226 $dbo->setQuery($q);
4227 $dbo->execute();
4228 $mainframe->enqueueMessage(JText::translate('VBPAYMENTSAVED'));
4229 $mainframe->redirect("index.php?option=com_vikbooking&task=payments");
4230 } else {
4231 VikError::raiseWarning('', JText::translate('ERRINVFILEPAYMENT'));
4232 $mainframe->redirect("index.php?option=com_vikbooking&task=newpayment");
4233 }
4234 } else {
4235 $mainframe->redirect("index.php?option=com_vikbooking&task=newpayment");
4236 }
4237 }
4238
4239 public function updatepayment()
4240 {
4241 if (!JSession::checkToken()) {
4242 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
4243 }
4244
4245 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
4246 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
4247 }
4248
4249 $this->do_updatepayment($stay = false);
4250 }
4251
4252 public function updatepaymentstay()
4253 {
4254 if (!JSession::checkToken()) {
4255 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
4256 }
4257
4258 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
4259 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
4260 }
4261
4262 $this->do_updatepayment($stay = true);
4263 }
4264
4265 protected function do_updatepayment($stay = false)
4266 {
4267 $mainframe = JFactory::getApplication();
4268
4269 $pwhere = VikRequest::getString('where', '', 'request');
4270 $pname = VikRequest::getString('name', '', 'request');
4271 $ppayment = VikRequest::getString('payment', '', 'request');
4272 $ppublished = VikRequest::getString('published', '', 'request');
4273 $pcharge = VikRequest::getFloat('charge', '', 'request');
4274 $psetconfirmed = VikRequest::getString('setconfirmed', '', 'request');
4275 $phidenonrefund = VikRequest::getInt('hidenonrefund', '', 'request');
4276 $ponlynonrefund = VikRequest::getInt('onlynonrefund', '', 'request');
4277 $pshownotealw = VikRequest::getString('shownotealw', '', 'request');
4278 $pnote = VikRequest::getString('note', '', 'request', VIKREQUEST_ALLOWRAW);
4279 $pval_pcent = VikRequest::getString('val_pcent', '', 'request');
4280 $pval_pcent = !in_array($pval_pcent, array('1', '2')) ? 1 : $pval_pcent;
4281 $pch_disc = VikRequest::getString('ch_disc', '', 'request');
4282 $pch_disc = !in_array($pch_disc, array('1', '2')) ? 1 : $pch_disc;
4283 $poutposition = VikRequest::getString('outposition', 'top', 'request');
4284 $plogo = VikRequest::getString('logo', '', 'request');
4285 $pall_rooms = VikRequest::getInt('all_rooms', 0, 'request');
4286 $pidrooms = VikRequest::getVar('idrooms', array());
4287 $vikpaymentparams = VikRequest::getVar('vikpaymentparams', array(0));
4288 $payparamarr = array();
4289 $payparamstr = '';
4290 if (count($vikpaymentparams) > 0) {
4291 foreach ($vikpaymentparams as $setting => $cont) {
4292 if (strlen($setting) > 0) {
4293 $payparamarr[$setting] = $cont;
4294 }
4295 }
4296 if (count($payparamarr) > 0) {
4297 $payparamstr = json_encode($payparamarr);
4298 }
4299 }
4300
4301 $dbo = JFactory::getDbo();
4302
4303 $set_idrooms = [];
4304 if (empty($pall_rooms) && !empty($pidrooms)) {
4305 $pidrooms = array_map(function($idroom) {
4306 return (int)$idroom;
4307 }, $pidrooms);
4308 foreach ($pidrooms as $idroom) {
4309 if (empty($idroom) || in_array($idroom, $set_idrooms)) {
4310 continue;
4311 }
4312 $set_idrooms[] = $idroom;
4313 }
4314 }
4315
4316 if (!empty($pname) && !empty($ppayment) && !empty($pwhere)) {
4317 $setpub = $ppublished == "1" ? 1 : 0;
4318 $psetconfirmed = $psetconfirmed == "1" ? 1 : 0;
4319 $pshownotealw = $pshownotealw == "1" ? 1 : 0;
4320 $q = "SELECT `id` FROM `#__vikbooking_gpayments` WHERE `file`=".$dbo->quote($ppayment)." AND `id`!='".$pwhere."';";
4321 $dbo->setQuery($q);
4322 $dbo->execute();
4323 if ($dbo->getNumRows() >= 0) {
4324 $q = "UPDATE `#__vikbooking_gpayments` SET `name`=".$dbo->quote($pname).",`file`=".$dbo->quote($ppayment).",`published`='".$setpub."',`note`=".$dbo->quote($pnote).",`charge`=".$dbo->quote($pcharge).",`setconfirmed`='".$psetconfirmed."',`shownotealw`='".$pshownotealw."',`val_pcent`='".$pval_pcent."',`ch_disc`='".$pch_disc."',`params`=".$dbo->quote($payparamstr).",`hidenonrefund`=".($phidenonrefund > 0 ? '1' : '0').",`onlynonrefund`=".($ponlynonrefund > 0 ? '1' : '0').",`outposition`=" . $dbo->quote($poutposition) . ",`logo`=" . $dbo->quote($plogo) . ",`idrooms`=" . (count($set_idrooms) ? $dbo->quote(json_encode($set_idrooms)) : 'NULL') . " WHERE `id`=".$dbo->quote($pwhere).";";
4325 $dbo->setQuery($q);
4326 $dbo->execute();
4327
4328 $mainframe->enqueueMessage(JText::translate('VBPAYMENTUPDATED'));
4329 if ($stay) {
4330 $mainframe->redirect("index.php?option=com_vikbooking&task=editpayment&cid[]=".$pwhere);
4331 } else {
4332 $mainframe->redirect("index.php?option=com_vikbooking&task=payments");
4333 }
4334 } else {
4335 VikError::raiseWarning('', JText::translate('ERRINVFILEPAYMENT'));
4336 $mainframe->redirect("index.php?option=com_vikbooking&task=editpayment&cid[]=".$pwhere);
4337 }
4338 } else {
4339 $mainframe->redirect("index.php?option=com_vikbooking&task=editpayment&cid[]=".$pwhere);
4340 }
4341 }
4342
4343 public function removepayments()
4344 {
4345 if (!JSession::checkToken()) {
4346 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
4347 }
4348
4349 if (!JFactory::getUser()->authorise('core.delete', 'com_vikbooking')) {
4350 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
4351 }
4352
4353 $ids = VikRequest::getVar('cid', array(0));
4354 if ($ids) {
4355 $dbo = JFactory::getDBO();
4356 foreach ($ids as $d) {
4357 $q = "DELETE FROM `#__vikbooking_gpayments` WHERE `id`=".$dbo->quote($d).";";
4358 $dbo->setQuery($q);
4359 $dbo->execute();
4360 }
4361 }
4362 $mainframe = JFactory::getApplication();
4363 $mainframe->redirect("index.php?option=com_vikbooking&task=payments");
4364 }
4365
4366 public function modavailpayment() {
4367 if (!JSession::checkToken('get')) {
4368 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
4369 }
4370 $cid = VikRequest::getVar('cid', array(0));
4371 $idp = $cid[0];
4372 if (!empty($idp)) {
4373 $dbo = JFactory::getDBO();
4374 $q = "SELECT `published` FROM `#__vikbooking_gpayments` WHERE `id`=".intval($idp).";";
4375 $dbo->setQuery($q);
4376 $dbo->execute();
4377 $get = $dbo->loadAssocList();
4378 $q = "UPDATE `#__vikbooking_gpayments` SET `published`=".(intval($get[0]['published']) == 1 ? '0' : '1')." WHERE `id`=".intval($idp).";";
4379 $dbo->setQuery($q);
4380 $dbo->execute();
4381 }
4382 $mainframe = JFactory::getApplication();
4383 $mainframe->redirect("index.php?option=com_vikbooking&task=payments");
4384 }
4385
4386 public function seasons() {
4387 VikBookingHelper::printHeader("13");
4388
4389 VikRequest::setVar('view', VikRequest::getCmd('view', 'seasons'));
4390
4391 parent::display();
4392
4393 if (VikBooking::showFooter()) {
4394 VikBookingHelper::printFooter();
4395 }
4396 }
4397
4398 public function newseason() {
4399 VikBookingHelper::printHeader("13");
4400
4401 VikRequest::setVar('view', VikRequest::getCmd('view', 'manageseason'));
4402
4403 parent::display();
4404
4405 if (VikBooking::showFooter()) {
4406 VikBookingHelper::printFooter();
4407 }
4408 }
4409
4410 public function editseason() {
4411 VikBookingHelper::printHeader("13");
4412
4413 VikRequest::setVar('view', VikRequest::getCmd('view', 'manageseason'));
4414
4415 parent::display();
4416
4417 if (VikBooking::showFooter()) {
4418 VikBookingHelper::printFooter();
4419 }
4420 }
4421
4422 public function updateseason()
4423 {
4424 if (!JSession::checkToken()) {
4425 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
4426 }
4427
4428 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
4429 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
4430 }
4431
4432 $this->do_updateseason();
4433 }
4434
4435 public function updateseasonstay()
4436 {
4437 if (!JSession::checkToken()) {
4438 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
4439 }
4440
4441 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
4442 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
4443 }
4444
4445 $this->do_updateseason(true);
4446 }
4447
4448 private function do_updateseason($stay = false)
4449 {
4450 $app = JFactory::getApplication();
4451 $dbo = JFactory::getDbo();
4452 $session = JFactory::getSession();
4453
4454 $pwhere = VikRequest::getInt('where', 0, 'request');
4455
4456 $pfrom = VikRequest::getString('from', '', 'request');
4457 $pto = VikRequest::getString('to', '', 'request');
4458 $ptype = VikRequest::getString('type', '', 'request');
4459 $pdiffcost = VikRequest::getFloat('diffcost', '', 'request');
4460 $pidrooms = VikRequest::getVar('idrooms', array());
4461 $pidprices = VikRequest::getVar('idprices', array());
4462 $pwdays = VikRequest::getVar('wdays', array());
4463 $pspname = VikRequest::getString('spname', '', 'request');
4464 $pcheckinincl = VikRequest::getString('checkinincl', '', 'request');
4465 $pcheckinincl = $pcheckinincl == 1 ? 1 : 0;
4466 $pyeartied = VikRequest::getInt('yeartied', 0, 'request');
4467 $pyeartied = $pyeartied == 1 ? 1 : 0;
4468 $tieyear = 0;
4469 $ppromo = VikRequest::getInt('promo', 0, 'request');
4470 $ppromo = $ppromo == 1 ? 1 : 0;
4471 $ppromodaysadv = VikRequest::getInt('promodaysadv', '', 'request');
4472 $ppromominlos = VikRequest::getInt('promominlos', '', 'request');
4473 $ppromotxt = VikRequest::getString('promotxt', '', 'request', VIKREQUEST_ALLOWHTML);
4474 $pval_pcent = VikRequest::getString('val_pcent', '', 'request');
4475 $pval_pcent = $pval_pcent == "1" ? 1 : 2;
4476 $proundmode = VikRequest::getString('roundmode', '', 'request');
4477 $proundmode = (!empty($proundmode) && in_array($proundmode, array('PHP_ROUND_HALF_UP', 'PHP_ROUND_HALF_DOWN')) ? $proundmode : '');
4478 $pnightsoverrides = VikRequest::getVar('nightsoverrides', array());
4479 $pvaluesoverrides = VikRequest::getVar('valuesoverrides', array());
4480 $pandmoreoverride = VikRequest::getVar('andmoreoverride', array());
4481 $padultsdiffchdisc = VikRequest::getVar('adultsdiffchdisc', array());
4482 $padultsdiffval = VikRequest::getVar('adultsdiffval', array());
4483 $padultsdiffvalpcent = VikRequest::getVar('adultsdiffvalpcent', array());
4484 $padultsdiffpernight = VikRequest::getVar('adultsdiffpernight', array());
4485 $ppromolastmind = VikRequest::getInt('promolastmind', 0, 'request');
4486 $ppromolastminh = VikRequest::getInt('promolastminh', 0, 'request');
4487 $promolastmin = ($ppromolastmind * 86400) + ($ppromolastminh * 3600);
4488 $ppromofinalprice = VikRequest::getInt('promofinalprice', 0, 'request');
4489 $ppromofinalprice = $ppromo ? $ppromofinalprice : 0;
4490 $occupancy_ovr = array();
4491 $losverridestr = "";
4492
4493 $updforvcm = $session->get('vbVcmRatesUpd', '');
4494 $updforvcm = empty($updforvcm) || !is_array($updforvcm) ? array() : $updforvcm;
4495
4496 // check null dates
4497 if ($dbo->getNullDate() == $pfrom) {
4498 $pfrom = '';
4499 }
4500 if ($dbo->getNullDate() == $pto) {
4501 $pto = '';
4502 }
4503
4504 if ((empty($pfrom) || empty($pto)) && !$pwdays) {
4505 VikError::raiseWarning('', JText::translate('ERRINVDATESEASON'));
4506 $app->redirect("index.php?option=com_vikbooking&task=editseason&cid[]=" . $pwhere);
4507 exit;
4508 }
4509
4510 $skipseason = false;
4511 if (empty($pfrom) || empty($pto)) {
4512 $skipseason = true;
4513 }
4514 $skipdays = false;
4515 $wdaystr = null;
4516 if (count($pwdays) == 0) {
4517 $skipdays = true;
4518 } else {
4519 $wdaystr = "";
4520 foreach ($pwdays as $wd) {
4521 $wdaystr .= $wd.';';
4522 }
4523 }
4524 $roomstr = "";
4525 $roomids = array();
4526 foreach ($pidrooms as $room) {
4527 if (empty($room)) {
4528 continue;
4529 }
4530 $roomstr .= "-".$room."-,";
4531 $roomids[] = (int)$room;
4532 }
4533 $pricestr = "";
4534 $priceids = array();
4535 foreach ($pidprices as $price) {
4536 if (empty($price)) {
4537 continue;
4538 }
4539 $pricestr .= "-".$price."-,";
4540 $priceids[] = (int)$price;
4541 }
4542 $valid = true;
4543 $double_records = array();
4544 $sfrom = null;
4545 $sto = null;
4546
4547 // value overrides
4548 if ($pnightsoverrides && $pvaluesoverrides) {
4549 foreach ($pnightsoverrides as $ko => $no) {
4550 if (!empty($no) && strlen(trim($pvaluesoverrides[$ko])) > 0) {
4551 $infiniteclause = intval($pandmoreoverride[$ko]) == 1 ? '-i' : '';
4552 $losverridestr .= intval($no).$infiniteclause.':'.trim($pvaluesoverrides[$ko]).'_';
4553 }
4554 }
4555 }
4556
4557 if (!$skipseason) {
4558 $first = VikBooking::getDateTimestamp($pfrom, 0, 0);
4559 $second = VikBooking::getDateTimestamp($pto, 0, 0);
4560
4561 if ($second > 0 && $second == $first) {
4562 $second += 86399;
4563 }
4564
4565 if (!($second > $first)) {
4566 VikError::raiseWarning('', JText::translate('ERRINVDATESEASON'));
4567 $app->redirect("index.php?option=com_vikbooking&task=editseason&cid[]=" . $pwhere);
4568 exit;
4569 }
4570
4571 $baseone = getdate($first);
4572 $basets = mktime(0, 0, 0, 1, 1, $baseone['year']);
4573 $sfrom = $baseone[0] - $basets;
4574 $basetwo = getdate($second);
4575 $basets = mktime(0, 0, 0, 1, 1, $basetwo['year']);
4576 $sto = $basetwo[0] - $basets;
4577
4578 // check leap year
4579 if ($baseone['year'] % 4 == 0 && ($baseone['year'] % 100 != 0 || $baseone['year'] % 400 == 0)) {
4580 $leapts = mktime(0, 0, 0, 2, 29, $baseone['year']);
4581 if ($baseone[0] > $leapts) {
4582 $sfrom -= 86400;
4583 /**
4584 * To avoid issue with leap years and dates near Feb 29th, we only reduce the seconds if these were reduced
4585 * for the from-date of the seasons. Doing it just for the to-date in 2019 for 2020 (leap) produced invalid results.
4586 *
4587 * @since July 2nd 2019
4588 */
4589 if ($basetwo['year'] % 4 == 0 && ($basetwo['year'] % 100 != 0 || $basetwo['year'] % 400 == 0)) {
4590 $leapts = mktime(0, 0, 0, 2, 29, $basetwo['year']);
4591 if ($basetwo[0] > $leapts) {
4592 $sto -= 86400;
4593 }
4594 }
4595 }
4596 }
4597
4598 // tied to the year
4599 if ($pyeartied == 1) {
4600 $tieyear = $baseone['year'];
4601 }
4602
4603 // Occupancy Override
4604 if (count($padultsdiffval) > 0) {
4605 foreach ($padultsdiffval as $rid => $valovr_arr) {
4606 if (!is_array($valovr_arr) || !is_array($padultsdiffchdisc[$rid]) || !is_array($padultsdiffvalpcent[$rid]) || !is_array($padultsdiffpernight[$rid])) {
4607 continue;
4608 }
4609 foreach ($valovr_arr as $occ => $valovr) {
4610 if (!(strlen($valovr) > 0) || !(strlen($padultsdiffchdisc[$rid][$occ]) > 0) || !(strlen($padultsdiffvalpcent[$rid][$occ]) > 0) || !(strlen($padultsdiffpernight[$rid][$occ]) > 0)) {
4611 continue;
4612 }
4613 if (!array_key_exists($rid, $occupancy_ovr)) {
4614 $occupancy_ovr[$rid] = array();
4615 }
4616 $occupancy_ovr[$rid][$occ] = array('chdisc' => (int)$padultsdiffchdisc[$rid][$occ], 'valpcent' => (int)$padultsdiffvalpcent[$rid][$occ], 'pernight' => (int)$padultsdiffpernight[$rid][$occ], 'value' => (float)$valovr);
4617 }
4618 }
4619 }
4620
4621 // check if seasons dates are valid
4622 $q = "SELECT `id`,`spname` FROM `#__vikbooking_seasons` WHERE `from`<=".$dbo->quote($sfrom)." AND `to`>=".$dbo->quote($sfrom)." AND `id`!=".$dbo->quote($pwhere)." AND `idrooms`=".$dbo->quote($roomstr)."".(!$skipdays ? " AND `wdays`='".$wdaystr."'" : "").($skipdays ? " AND (`from` > 0 OR `to` > 0) AND `wdays`=''" : "").($pyeartied == 1 ? " AND `year`=".$tieyear : " AND `year` IS NULL")." AND `idprices`=".$dbo->quote($pricestr)." AND `promo`=".$ppromo." AND `promodaysadv`=" . $dbo->quote($ppromodaysadv) . " AND `promominlos`=" . $dbo->quote($ppromominlos) . " AND `promolastmin`=" . $dbo->quote($promolastmin) . " AND `losoverride`=".$dbo->quote($losverridestr)." AND `occupancy_ovr`".(count($occupancy_ovr) > 0 ? "=".$dbo->quote(json_encode($occupancy_ovr)) : " IS NULL").";";
4623 $dbo->setQuery($q);
4624 $similar = $dbo->loadAssocList();
4625 if ($similar) {
4626 $valid = false;
4627 foreach ($similar as $sim) {
4628 $double_records[] = $sim['spname'];
4629 }
4630 }
4631
4632 $q = "SELECT `id`,`spname` FROM `#__vikbooking_seasons` WHERE `from`<=".$dbo->quote($sto)." AND `to`>=".$dbo->quote($sto)." AND `id`!=".$dbo->quote($pwhere)." AND `idrooms`=".$dbo->quote($roomstr)."".(!$skipdays ? " AND `wdays`='".$wdaystr."'" : "").($skipdays ? " AND (`from` > 0 OR `to` > 0) AND `wdays`=''" : "").($pyeartied == 1 ? " AND `year`=".$tieyear : " AND `year` IS NULL")." AND `idprices`=".$dbo->quote($pricestr)." AND `promo`=".$ppromo." AND `promodaysadv`=" . $dbo->quote($ppromodaysadv) . " AND `promominlos`=" . $dbo->quote($ppromominlos) . " AND `promolastmin`=" . $dbo->quote($promolastmin) . " AND `losoverride`=".$dbo->quote($losverridestr)." AND `occupancy_ovr`".(count($occupancy_ovr) > 0 ? "=".$dbo->quote(json_encode($occupancy_ovr)) : " IS NULL").";";
4633 $dbo->setQuery($q);
4634 $similar = $dbo->loadAssocList();
4635 if ($similar) {
4636 $valid = false;
4637 foreach ($similar as $sim) {
4638 $double_records[] = $sim['spname'];
4639 }
4640 }
4641
4642 $q = "SELECT `id`,`spname` FROM `#__vikbooking_seasons` WHERE `from`>=".$dbo->quote($sfrom)." AND `from`<=".$dbo->quote($sto)." AND `to`>=".$dbo->quote($sfrom)." AND `to`<=".$dbo->quote($sto)." AND `id`!=".$dbo->quote($pwhere)." AND `idrooms`=".$dbo->quote($roomstr)."".(!$skipdays ? " AND `wdays`='".$wdaystr."'" : "").($skipdays ? " AND (`from` > 0 OR `to` > 0) AND `wdays`=''" : "").($pyeartied == 1 ? " AND `year`=".$tieyear : " AND `year` IS NULL")." AND `idprices`=".$dbo->quote($pricestr)." AND `promo`=".$ppromo." AND `promodaysadv`=" . $dbo->quote($ppromodaysadv) . " AND `promominlos`=" . $dbo->quote($ppromominlos) . " AND `promolastmin`=" . $dbo->quote($promolastmin) . " AND `losoverride`=".$dbo->quote($losverridestr)." AND `occupancy_ovr`".(count($occupancy_ovr) > 0 ? "=".$dbo->quote(json_encode($occupancy_ovr)) : " IS NULL").";";
4643 $dbo->setQuery($q);
4644 $dbo->execute();
4645 $similar = $dbo->loadAssocList();
4646 if ($similar) {
4647 $valid = false;
4648 foreach ($similar as $sim) {
4649 $double_records[] = $sim['spname'];
4650 }
4651 }
4652 }
4653
4654 // fetch previous record before the update
4655 $q = $dbo->getQuery(true)
4656 ->select('*')
4657 ->from($dbo->qn('#__vikbooking_seasons'))
4658 ->where($dbo->qn('id') . ' = ' . $pwhere);
4659 $dbo->setQuery($q, 0, 1);
4660 $prev_record = $dbo->loadAssoc();
4661
4662 if (!$valid || !$prev_record) {
4663 VikError::raiseWarning('', JText::translate('ERRINVDATEROOMSLOCSEASON').($double_records ? ' ('.implode(', ', array_unique($double_records)).')' : ''));
4664 $app->redirect("index.php?option=com_vikbooking&task=editseason&cid[]=" . $pwhere);
4665 exit;
4666 }
4667
4668 /**
4669 * Attempt to access the promotion handlers in advance to perform additional validations.
4670 *
4671 * @since 1.16.4 (J) - 1.6.4 (WP)
4672 */
4673 try {
4674 $promo_handlers = VikBooking::getPromotionHandlers();
4675 } catch (Exception $e) {
4676 // reset the value
4677 $promo_handlers = [];
4678 }
4679
4680 if (!$prev_record['promo'] && $ppromo && $promo_handlers) {
4681 // channels supporting promotions are available, and a regular special price is
4682 // being converted into a promotion - this is not allowed so we make it a non-promotion.
4683 $ppromo = 0;
4684 $app->enqueueMessage(JText::translate('VBO_NOPROMO_UPD_CHANNELS'), 'warning');
4685 }
4686
4687 // update record
4688 $upd_record = new stdClass;
4689 $upd_record->id = $prev_record['id'];
4690 $upd_record->type = $ptype == "1" ? 1 : 2;
4691 $upd_record->from = $sfrom;
4692 $upd_record->to = $sto;
4693 $upd_record->diffcost = $pdiffcost;
4694 $upd_record->idrooms = $roomstr;
4695 $upd_record->spname = $pspname;
4696 $upd_record->wdays = $wdaystr;
4697 $upd_record->checkinincl = $pcheckinincl;
4698 $upd_record->val_pcent = $pval_pcent;
4699 $upd_record->losoverride = $losverridestr;
4700 $upd_record->roundmode = !empty($proundmode) ? $proundmode : null;
4701 $upd_record->year = $pyeartied == 1 ? $tieyear : null;
4702 $upd_record->idprices = $pricestr;
4703 $upd_record->promo = $ppromo;
4704 $upd_record->promodaysadv = !empty($ppromodaysadv) ? $ppromodaysadv : null;
4705 $upd_record->promotxt = $ppromotxt;
4706 $upd_record->promominlos = !empty($ppromominlos) ? $ppromominlos : 0;
4707 $upd_record->occupancy_ovr = $occupancy_ovr ? json_encode($occupancy_ovr) : null;
4708 $upd_record->promolastmin = (int)$promolastmin;
4709 $upd_record->promofinalprice = $ppromofinalprice;
4710
4711 $dbo->updateObject('#__vikbooking_seasons', $upd_record, 'id', $nulls = true);
4712
4713 $app->enqueueMessage(JText::translate('VBSEASONUPDATED'));
4714
4715 // update session values
4716 $updforvcm['count'] = array_key_exists('count', $updforvcm) && !empty($updforvcm['count']) ? ($updforvcm['count'] + 1) : 1;
4717 if (array_key_exists('dfrom', $updforvcm) && !empty($updforvcm['dfrom'])) {
4718 $updforvcm['dfrom'] = $updforvcm['dfrom'] > $first ? $first : $updforvcm['dfrom'];
4719 } else {
4720 $updforvcm['dfrom'] = $first;
4721 }
4722 if (array_key_exists('dto', $updforvcm) && !empty($updforvcm['dto'])) {
4723 $updforvcm['dto'] = $updforvcm['dto'] < $second ? $second : $updforvcm['dto'];
4724 } else {
4725 $updforvcm['dto'] = $second;
4726 }
4727 if (array_key_exists('rooms', $updforvcm) && is_array($updforvcm['rooms'])) {
4728 foreach ($roomids as $rid) {
4729 if (!in_array($rid, $updforvcm['rooms'])) {
4730 $updforvcm['rooms'][] = $rid;
4731 }
4732 }
4733 } else {
4734 $updforvcm['rooms'] = $roomids;
4735 }
4736 if (array_key_exists('rplans', $updforvcm) && is_array($updforvcm['rplans'])) {
4737 foreach ($roomids as $rid) {
4738 if (array_key_exists($rid, $updforvcm['rplans'])) {
4739 $updforvcm['rplans'][$rid] = $updforvcm['rplans'][$rid] + $priceids;
4740 } else {
4741 $updforvcm['rplans'][$rid] = $priceids;
4742 }
4743 }
4744 } else {
4745 $updforvcm['rplans'] = array();
4746 foreach ($roomids as $rid) {
4747 $updforvcm['rplans'][$rid] = $priceids;
4748 }
4749 }
4750 $session->set('vbVcmRatesUpd', $updforvcm);
4751
4752 /**
4753 * Query promotion handlers, if any, to trigger the update/delete promotion event.
4754 *
4755 * @since 1.15.0 (J) - 1.5.0 (WP)
4756 * @since 1.16.4 (J) - 1.6.4 (WP) added control to perform a delete operation.
4757 */
4758 $promo_update_type = $prev_record['promo'] && !$ppromo ? 'triggerDelete' : 'triggerUpdate';
4759 $promo_method_type = $prev_record['promo'] && !$ppromo ? 'delete' : 'update';
4760 try {
4761 if ($ppromo && is_array($promo_handlers) && $promo_handlers) {
4762 foreach ($promo_handlers as $promo_handler) {
4763 if (!isset($promo_handler->instance) || !is_object($promo_handler->instance) || !method_exists($promo_handler->instance, $promo_update_type)) {
4764 // outdated handler object
4765 continue;
4766 }
4767 if (!is_callable(array($promo_handler->instance, $promo_update_type)) || !$promo_handler->instance->{$promo_update_type}()) {
4768 // promotion handler does not support update/delete promotion event
4769 continue;
4770 }
4771 // invoke the update/delete promotion event for this handler
4772 $ch_result = $promo_handler->instance->createPromotion(['vbo_promo_id' => $pwhere], $promo_method_type);
4773 if (!$ch_result) {
4774 VikError::raiseWarning('', $promo_handler->instance->getName() . ': ' . $promo_handler->instance->getError());
4775 }
4776 }
4777 }
4778 } catch (Exception $e) {
4779 // do nothing
4780 }
4781
4782 if ($stay) {
4783 $app->redirect("index.php?option=com_vikbooking&task=editseason&cid[]=" . $pwhere);
4784 } else {
4785 $app->redirect("index.php?option=com_vikbooking&task=seasons");
4786 }
4787 $app->close();
4788 }
4789
4790 public function createseason()
4791 {
4792 if (!JSession::checkToken()) {
4793 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
4794 }
4795
4796 if (!JFactory::getUser()->authorise('core.create', 'com_vikbooking')) {
4797 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
4798 }
4799
4800 $this->do_createseason();
4801 }
4802
4803 public function createseason_new()
4804 {
4805 if (!JSession::checkToken()) {
4806 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
4807 }
4808
4809 if (!JFactory::getUser()->authorise('core.create', 'com_vikbooking')) {
4810 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
4811 }
4812
4813 $this->do_createseason(true);
4814 }
4815
4816 private function do_createseason($andnew = false)
4817 {
4818 $app = JFactory::getApplication();
4819 $dbo = JFactory::getDbo();
4820 $session = JFactory::getSession();
4821
4822 $pfrom = VikRequest::getString('from', '', 'request');
4823 $pto = VikRequest::getString('to', '', 'request');
4824 $ptype = VikRequest::getString('type', '', 'request');
4825 $pdiffcost = VikRequest::getFloat('diffcost', '', 'request');
4826 $pidrooms = VikRequest::getVar('idrooms', array());
4827 $pidprices = VikRequest::getVar('idprices', array());
4828 $pwdays = VikRequest::getVar('wdays', array());
4829 $pspname = VikRequest::getString('spname', '', 'request');
4830 $pcheckinincl = VikRequest::getString('checkinincl', '', 'request');
4831 $pcheckinincl = $pcheckinincl == 1 ? 1 : 0;
4832 $pyeartied = VikRequest::getInt('yeartied', 0, 'request');
4833 $pyeartied = $pyeartied == 1 ? 1 : 0;
4834 $tieyear = 0;
4835 $pval_pcent = VikRequest::getString('val_pcent', '', 'request');
4836 $pval_pcent = $pval_pcent == "1" ? 1 : 2;
4837 $proundmode = VikRequest::getString('roundmode', '', 'request');
4838 $proundmode = (!empty($proundmode) && in_array($proundmode, array('PHP_ROUND_HALF_UP', 'PHP_ROUND_HALF_DOWN')) ? $proundmode : '');
4839 $ppromo = VikRequest::getInt('promo', 0, 'request');
4840 $ppromodaysadv = VikRequest::getInt('promodaysadv', '', 'request');
4841 $ppromominlos = VikRequest::getInt('promominlos', '', 'request');
4842 $ppromotxt = VikRequest::getString('promotxt', '', 'request', VIKREQUEST_ALLOWHTML);
4843 $pnightsoverrides = VikRequest::getVar('nightsoverrides', array());
4844 $pvaluesoverrides = VikRequest::getVar('valuesoverrides', array());
4845 $pandmoreoverride = VikRequest::getVar('andmoreoverride', array());
4846 $padultsdiffchdisc = VikRequest::getVar('adultsdiffchdisc', array());
4847 $padultsdiffval = VikRequest::getVar('adultsdiffval', array());
4848 $padultsdiffvalpcent = VikRequest::getVar('adultsdiffvalpcent', array());
4849 $padultsdiffpernight = VikRequest::getVar('adultsdiffpernight', array());
4850 $ppromolastmind = VikRequest::getInt('promolastmind', 0, 'request');
4851 $ppromolastminh = VikRequest::getInt('promolastminh', 0, 'request');
4852 $promolastmin = ($ppromolastmind * 86400) + ($ppromolastminh * 3600);
4853 $ppromofinalprice = VikRequest::getInt('promofinalprice', 0, 'request');
4854 $ppromofinalprice = $ppromo ? $ppromofinalprice : 0;
4855 $pchannels = VikRequest::getVar('channels', array());
4856 $occupancy_ovr = array();
4857 $losverridestr = "";
4858
4859 $updforvcm = $session->get('vbVcmRatesUpd', '');
4860 $updforvcm = empty($updforvcm) || !is_array($updforvcm) ? array() : $updforvcm;
4861
4862 // check null dates
4863 if ($dbo->getNullDate() == $pfrom) {
4864 $pfrom = '';
4865 }
4866 if ($dbo->getNullDate() == $pto) {
4867 $pto = '';
4868 }
4869
4870 if ((empty($pfrom) || empty($pto)) && !$pwdays) {
4871 VikError::raiseWarning('', JText::translate('ERRINVDATESEASON'));
4872 $app->redirect("index.php?option=com_vikbooking&task=newseason");
4873 exit;
4874 }
4875
4876 $skipseason = false;
4877 if (empty($pfrom) || empty($pto)) {
4878 $skipseason = true;
4879 }
4880 $skipdays = false;
4881 $wdaystr = null;
4882 if (!$pwdays) {
4883 $skipdays = true;
4884 } else {
4885 $wdaystr = "";
4886 foreach ($pwdays as $wd) {
4887 $wdaystr .= $wd.';';
4888 }
4889 }
4890 $roomstr = "";
4891 $roomids = array();
4892 foreach ($pidrooms as $room) {
4893 if (empty($room)) {
4894 continue;
4895 }
4896 $roomstr .= "-".$room."-,";
4897 $roomids[] = (int)$room;
4898 }
4899 $pricestr = "";
4900 $priceids = array();
4901 foreach ($pidprices as $price) {
4902 if (empty($price)) {
4903 continue;
4904 }
4905 $pricestr .= "-".$price."-,";
4906 $priceids[] = (int)$price;
4907 }
4908 $valid = true;
4909 $double_records = array();
4910 $sfrom = null;
4911 $sto = null;
4912
4913 // value overrides
4914 if ($pnightsoverrides && $pvaluesoverrides) {
4915 foreach ($pnightsoverrides as $ko => $no) {
4916 if (!empty($no) && strlen(trim($pvaluesoverrides[$ko])) > 0) {
4917 $infiniteclause = intval($pandmoreoverride[$ko]) == 1 ? '-i' : '';
4918 $losverridestr .= intval($no).$infiniteclause.':'.trim($pvaluesoverrides[$ko]).'_';
4919 }
4920 }
4921 }
4922
4923 if (!$skipseason) {
4924 $first = VikBooking::getDateTimestamp($pfrom, 0, 0);
4925 $second = VikBooking::getDateTimestamp($pto, 0, 0);
4926
4927 if ($second > 0 && $second == $first) {
4928 $second += 86399;
4929 }
4930
4931 if (!($second > $first)) {
4932 VikError::raiseWarning('', JText::translate('ERRINVDATESEASON'));
4933 $app->redirect("index.php?option=com_vikbooking&task=newseason");
4934 exit;
4935 }
4936
4937 $baseone = getdate($first);
4938 $basets = mktime(0, 0, 0, 1, 1, $baseone['year']);
4939 $sfrom = $baseone[0] - $basets;
4940 $basetwo = getdate($second);
4941 $basets = mktime(0, 0, 0, 1, 1, $basetwo['year']);
4942 $sto = $basetwo[0] - $basets;
4943
4944 // check leap year
4945 if ($baseone['year'] % 4 == 0 && ($baseone['year'] % 100 != 0 || $baseone['year'] % 400 == 0)) {
4946 $leapts = mktime(0, 0, 0, 2, 29, $baseone['year']);
4947 if ($baseone[0] > $leapts) {
4948 $sfrom -= 86400;
4949 /**
4950 * To avoid issue with leap years and dates near Feb 29th, we only reduce the seconds if these were reduced
4951 * for the from-date of the seasons. Doing it just for the to-date in 2019 for 2020 (leap) produced invalid results.
4952 *
4953 * @since July 2nd 2019
4954 */
4955 if ($basetwo['year'] % 4 == 0 && ($basetwo['year'] % 100 != 0 || $basetwo['year'] % 400 == 0)) {
4956 $leapts = mktime(0, 0, 0, 2, 29, $basetwo['year']);
4957 if ($basetwo[0] > $leapts) {
4958 $sto -= 86400;
4959 }
4960 }
4961 }
4962 }
4963
4964 // tied to the year
4965 if ($pyeartied == 1) {
4966 $tieyear = $baseone['year'];
4967 }
4968
4969 // Occupancy Override
4970 if ($padultsdiffval) {
4971 foreach ($padultsdiffval as $rid => $valovr_arr) {
4972 if (!is_array($valovr_arr) || !is_array($padultsdiffchdisc[$rid]) || !is_array($padultsdiffvalpcent[$rid]) || !is_array($padultsdiffpernight[$rid])) {
4973 continue;
4974 }
4975 foreach ($valovr_arr as $occ => $valovr) {
4976 if (!(strlen($valovr) > 0) || !(strlen($padultsdiffchdisc[$rid][$occ]) > 0) || !(strlen($padultsdiffvalpcent[$rid][$occ]) > 0) || !(strlen($padultsdiffpernight[$rid][$occ]) > 0)) {
4977 continue;
4978 }
4979 if (!array_key_exists($rid, $occupancy_ovr)) {
4980 $occupancy_ovr[$rid] = array();
4981 }
4982 $occupancy_ovr[$rid][$occ] = array('chdisc' => (int)$padultsdiffchdisc[$rid][$occ], 'valpcent' => (int)$padultsdiffvalpcent[$rid][$occ], 'pernight' => (int)$padultsdiffpernight[$rid][$occ], 'value' => (float)$valovr);
4983 }
4984 }
4985 }
4986
4987 // check if seasons dates are valid
4988 $q = "SELECT `id`,`spname` FROM `#__vikbooking_seasons` WHERE `from`<=".$dbo->quote($sfrom)." AND `to`>".$dbo->quote($sfrom)." AND `idrooms`=".$dbo->quote($roomstr)."".(!$skipdays ? " AND `wdays`='".$wdaystr."'" : "").($skipdays ? " AND (`from` > 0 OR `to` > 0) AND `wdays`=''" : "").($pyeartied == 1 ? " AND `year`=".$tieyear : " AND `year` IS NULL")." AND `idprices`=".$dbo->quote($pricestr)." AND `promo`=".$ppromo." AND `promodaysadv`=" . $dbo->quote($ppromodaysadv) . " AND `promominlos`=" . $dbo->quote($ppromominlos) . " AND `promolastmin`=" . $dbo->quote($promolastmin) . " AND `losoverride`=".$dbo->quote($losverridestr)." AND `occupancy_ovr`".(count($occupancy_ovr) > 0 ? "=".$dbo->quote(json_encode($occupancy_ovr)) : " IS NULL").";";
4989 $dbo->setQuery($q);
4990 $similar = $dbo->loadAssocList();
4991 if ($similar) {
4992 $valid = false;
4993 foreach ($similar as $sim) {
4994 $double_records[] = $sim['spname'];
4995 }
4996 }
4997
4998 $q = "SELECT `id`,`spname` FROM `#__vikbooking_seasons` WHERE `from`<=".$dbo->quote($sto)." AND `to`>=".$dbo->quote($sto)." AND `idrooms`=".$dbo->quote($roomstr)."".(!$skipdays ? " AND `wdays`='".$wdaystr."'" : "").($skipdays ? " AND (`from` > 0 OR `to` > 0) AND `wdays`=''" : "").($pyeartied == 1 ? " AND `year`=".$tieyear : " AND `year` IS NULL")." AND `idprices`=".$dbo->quote($pricestr)." AND `promo`=".$ppromo." AND `promodaysadv`=" . $dbo->quote($ppromodaysadv) . " AND `promominlos`=" . $dbo->quote($ppromominlos) . " AND `promolastmin`=" . $dbo->quote($promolastmin) . " AND `losoverride`=".$dbo->quote($losverridestr)." AND `occupancy_ovr`".(count($occupancy_ovr) > 0 ? "=".$dbo->quote(json_encode($occupancy_ovr)) : " IS NULL").";";
4999 $dbo->setQuery($q);
5000 $similar = $dbo->loadAssocList();
5001 if ($similar) {
5002 $valid = false;
5003 foreach ($similar as $sim) {
5004 $double_records[] = $sim['spname'];
5005 }
5006 }
5007
5008 $q = "SELECT `id`,`spname` FROM `#__vikbooking_seasons` WHERE `from`>=".$dbo->quote($sfrom)." AND `from`<=".$dbo->quote($sto)." AND `to`>=".$dbo->quote($sfrom)." AND `to`<=".$dbo->quote($sto)." AND `idrooms`=".$dbo->quote($roomstr)."".(!$skipdays ? " AND `wdays`='".$wdaystr."'" : "").($skipdays ? " AND (`from` > 0 OR `to` > 0) AND `wdays`=''" : "").($pyeartied == 1 ? " AND `year`=".$tieyear : " AND `year` IS NULL")." AND `idprices`=".$dbo->quote($pricestr)." AND `promo`=".$ppromo." AND `promodaysadv`=" . $dbo->quote($ppromodaysadv) . " AND `promominlos`=" . $dbo->quote($ppromominlos) . " AND `promolastmin`=" . $dbo->quote($promolastmin) . " AND `losoverride`=".$dbo->quote($losverridestr)." AND `occupancy_ovr`".(count($occupancy_ovr) > 0 ? "=".$dbo->quote(json_encode($occupancy_ovr)) : " IS NULL").";";
5009 $dbo->setQuery($q);
5010 $similar = $dbo->loadAssocList();
5011 if ($similar) {
5012 $valid = false;
5013 foreach ($similar as $sim) {
5014 $double_records[] = $sim['spname'];
5015 }
5016 }
5017 }
5018
5019 if (!$valid && !$ppromo) {
5020 VikError::raiseWarning('', JText::translate('ERRINVDATEROOMSLOCSEASON').(count($double_records) ? ' ('.implode(', ', array_unique($double_records)).')' : ''));
5021 $app->redirect("index.php?option=com_vikbooking&task=newseason");
5022 exit;
5023 }
5024
5025 // insert new record
5026 $sea_record = new stdClass;
5027 $sea_record->type = $ptype == "1" ? 1 : 2;
5028 $sea_record->from = $sfrom;
5029 $sea_record->to = $sto;
5030 $sea_record->diffcost = $pdiffcost;
5031 $sea_record->idrooms = $roomstr;
5032 $sea_record->spname = $pspname;
5033 $sea_record->wdays = $wdaystr;
5034 $sea_record->checkinincl = $pcheckinincl;
5035 $sea_record->val_pcent = $pval_pcent;
5036 $sea_record->losoverride = $losverridestr;
5037 $sea_record->roundmode = !empty($proundmode) ? $proundmode : null;
5038 $sea_record->year = $pyeartied == 1 ? $tieyear : null;
5039 $sea_record->idprices = $pricestr;
5040 $sea_record->promo = $ppromo == 1 ? 1 : 0;
5041 $sea_record->promodaysadv = !empty($ppromodaysadv) ? $ppromodaysadv : null;
5042 $sea_record->promotxt = $ppromotxt;
5043 $sea_record->promominlos = !empty($ppromominlos) ? $ppromominlos : 0;
5044 $sea_record->occupancy_ovr = $occupancy_ovr ? json_encode($occupancy_ovr) : null;
5045 $sea_record->promolastmin = (int)$promolastmin;
5046 $sea_record->promofinalprice = $ppromofinalprice;
5047
5048 $dbo->insertObject('#__vikbooking_seasons', $sea_record, 'id');
5049
5050 $vbo_promo_id = $sea_record->id;
5051
5052 $app->enqueueMessage(JText::translate('VBSEASONSAVED'));
5053
5054 // update session values
5055 $updforvcm['count'] = array_key_exists('count', $updforvcm) && !empty($updforvcm['count']) ? ($updforvcm['count'] + 1) : 1;
5056 if (array_key_exists('dfrom', $updforvcm) && !empty($updforvcm['dfrom'])) {
5057 $updforvcm['dfrom'] = $updforvcm['dfrom'] > $first ? $first : $updforvcm['dfrom'];
5058 } else {
5059 $updforvcm['dfrom'] = $first;
5060 }
5061 if (array_key_exists('dto', $updforvcm) && !empty($updforvcm['dto'])) {
5062 $updforvcm['dto'] = $updforvcm['dto'] < $second ? $second : $updforvcm['dto'];
5063 } else {
5064 $updforvcm['dto'] = $second;
5065 }
5066 if (array_key_exists('rooms', $updforvcm) && is_array($updforvcm['rooms'])) {
5067 foreach ($roomids as $rid) {
5068 if (!in_array($rid, $updforvcm['rooms'])) {
5069 $updforvcm['rooms'][] = $rid;
5070 }
5071 }
5072 } else {
5073 $updforvcm['rooms'] = $roomids;
5074 }
5075 if (array_key_exists('rplans', $updforvcm) && is_array($updforvcm['rplans'])) {
5076 foreach ($roomids as $rid) {
5077 if (array_key_exists($rid, $updforvcm['rplans'])) {
5078 $updforvcm['rplans'][$rid] = $updforvcm['rplans'][$rid] + $priceids;
5079 } else {
5080 $updforvcm['rplans'][$rid] = $priceids;
5081 }
5082 }
5083 } else {
5084 $updforvcm['rplans'] = array();
5085 foreach ($roomids as $rid) {
5086 $updforvcm['rplans'][$rid] = $priceids;
5087 }
5088 }
5089 if (!$ppromo) {
5090 $session->set('vbVcmRatesUpd', $updforvcm);
5091 }
5092
5093 /**
5094 * Create the promotion also on the selected channels
5095 *
5096 * @since 1.13.0 (J) - 1.3.0 (WP)
5097 */
5098 if ($ppromo && $pchannels) {
5099 foreach ($pchannels as $channel_key) {
5100 $promo_obj = VikBooking::getPromotionHandlers($channel_key);
5101 if (!is_object($promo_obj)) {
5102 continue;
5103 }
5104 /**
5105 * We inject for VCM the ID of the newly created promotion in VBO.
5106 *
5107 * @since 1.15.0 (J) - 1.5.0 (WP)
5108 */
5109 $ch_result = $promo_obj->createPromotion(array('vbo_promo_id' => $vbo_promo_id), 'new');
5110 if (!$ch_result) {
5111 VikError::raiseWarning('', $promo_obj->getName() . ': ' . $promo_obj->getError());
5112 } else {
5113 $resp = $promo_obj->getResponse();
5114 $app->enqueueMessage($promo_obj->getName() . ': ' . JText::translate('VBOCHPROMOSUCCESS') . (!empty($resp) ? ' (' . str_replace('e4j.ok.', '', $resp) . ')' : ''));
5115 // in case of success, unset the current session values in VCM
5116 $session->set('vcmBPromo', '');
5117 }
5118 }
5119 }
5120
5121 $app->redirect("index.php?option=com_vikbooking&task=".($andnew ? 'newseason' : 'seasons'));
5122 $app->close();
5123 }
5124
5125 public function removeseasons()
5126 {
5127 if (!JSession::checkToken()) {
5128 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
5129 }
5130
5131 if (!JFactory::getUser()->authorise('core.delete', 'com_vikbooking')) {
5132 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
5133 }
5134
5135 $app = JFactory::getApplication();
5136 $dbo = JFactory::getDbo();
5137
5138 $ids = VikRequest::getVar('cid', array(0));
5139 $pidroom = VikRequest::getInt('idroom', '', 'request');
5140 $pwhere = VikRequest::getInt('where', '', 'request');
5141 if (!empty($pwhere)) {
5142 $ids[] = $pwhere;
5143 }
5144 $tot_removed = array();
5145 $prev_promos = array();
5146 foreach ($ids as $d) {
5147 if (empty($d)) {
5148 continue;
5149 }
5150 // check if it was a promotion
5151 $q = "SELECT `id` FROM `#__vikbooking_seasons` WHERE `id`=" . (int)$d . " AND `promo`=1;";
5152 $dbo->setQuery($q);
5153 $dbo->execute();
5154 if ($dbo->getNumRows()) {
5155 // push it as a previous promo
5156 array_push($prev_promos, $d);
5157 }
5158
5159 // delete the record
5160 $q = "DELETE FROM `#__vikbooking_seasons` WHERE `id`=".$dbo->quote($d).";";
5161 $dbo->setQuery($q);
5162 $dbo->execute();
5163 $tot_removed[] = $d;
5164 }
5165
5166 /**
5167 * Query promotion handlers, if any, to trigger the delete promotion event.
5168 *
5169 * @since 1.15.0 (J) - 1.5.0 (WP)
5170 */
5171 $promo_handlers = VikBooking::getPromotionHandlers();
5172 foreach ($prev_promos as $vbo_promo_id) {
5173 try {
5174 if (is_array($promo_handlers)) {
5175 foreach ($promo_handlers as $promo_handler) {
5176 if (!isset($promo_handler->instance) || !is_object($promo_handler->instance) || !method_exists($promo_handler->instance, 'triggerDelete')) {
5177 // outdated handler object
5178 continue;
5179 }
5180 if (!is_callable(array($promo_handler->instance, 'triggerDelete')) || !$promo_handler->instance->triggerDelete()) {
5181 // promotion handler does not support delete promotion event
5182 continue;
5183 }
5184 // invoke the delete promotion event for this handler
5185 $ch_result = $promo_handler->instance->createPromotion(array('vbo_promo_id' => $vbo_promo_id), 'delete');
5186 if (!$ch_result) {
5187 VikError::raiseWarning('', $promo_handler->instance->getName() . ': ' . $promo_handler->instance->getError());
5188 }
5189 }
5190 }
5191 } catch (Exception $e) {
5192 // do nothing
5193 }
5194 }
5195
5196 $app->enqueueMessage(JText::sprintf('VBRECORDSREMOVED', count($tot_removed)));
5197 $app->redirect("index.php?option=com_vikbooking&task=seasons".(!empty($pidroom) ? '&idroom='.$pidroom : ''));
5198 $app->close();
5199 }
5200
5201 public function updatecustomer()
5202 {
5203 if (!JSession::checkToken()) {
5204 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
5205 }
5206
5207 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
5208 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
5209 }
5210
5211 $this->do_updatecustomer();
5212 }
5213
5214 public function updatecustomerstay()
5215 {
5216 if (!JSession::checkToken()) {
5217 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
5218 }
5219
5220 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
5221 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
5222 }
5223
5224 $this->do_updatecustomer(true);
5225 }
5226
5227 private function do_updatecustomer($stay = false) {
5228 $dbo = JFactory::getDbo();
5229 $mainframe = JFactory::getApplication();
5230 $pfirst_name = VikRequest::getString('first_name', '', 'request');
5231 $plast_name = VikRequest::getString('last_name', '', 'request');
5232 $pcompany = VikRequest::getString('company', '', 'request');
5233 $pvat = VikRequest::getString('vat', '', 'request');
5234 $pemail = VikRequest::getString('email', '', 'request');
5235 $pphone = VikRequest::getString('phone', '', 'request');
5236 $pcountry = VikRequest::getString('country', '', 'request');
5237 $pstate = VikRequest::getString('state', '', 'request');
5238 $ppin = VikRequest::getString('pin', '', 'request');
5239 $pujid = VikRequest::getInt('ujid', '', 'request');
5240 $paddress = VikRequest::getString('address', '', 'request');
5241 $pcity = VikRequest::getString('city', '', 'request');
5242 $pzip = VikRequest::getString('zip', '', 'request');
5243 $pfisccode = VikRequest::getString('fisccode', '', 'request');
5244 $ppec = VikRequest::getString('pec', '', 'request');
5245 $precipcode = VikRequest::getString('recipcode', '', 'request');
5246 $pgender = VikRequest::getString('gender', '', 'request');
5247 $pgender = in_array($pgender, array('F', 'M')) ? $pgender : '';
5248 $pbdate = VikRequest::getString('bdate', '', 'request');
5249 $ppbirth = VikRequest::getString('pbirth', '', 'request');
5250 $pdoctype = VikRequest::getString('doctype', '', 'request');
5251 $pdocnum = VikRequest::getString('docnum', '', 'request');
5252 $pnotes = VikRequest::getString('notes', '', 'request');
5253 $pscandocimg = VikRequest::getString('scandocimg', '', 'request');
5254 $pischannel = VikRequest::getInt('ischannel', '', 'request');
5255 $pcommission = VikRequest::getFloat('commission', '', 'request');
5256 $pcalccmmon = VikRequest::getInt('calccmmon', '', 'request');
5257 $papplycmmon = VikRequest::getInt('applycmmon', '', 'request');
5258 $pchname = VikRequest::getString('chname', '', 'request');
5259 $pchcolor = VikRequest::getString('chcolor', '', 'request');
5260 $pwhere = VikRequest::getInt('where', '', 'request');
5261 $ptmpl = VikRequest::getString('tmpl', '', 'request');
5262 $pcheckin = VikRequest::getInt('checkin', '', 'request');
5263 $pbid = VikRequest::getInt('bid', '', 'request');
5264 $pgoto = VikRequest::getString('goto', '', 'request', VIKREQUEST_ALLOWRAW);
5265 if (!empty($pwhere) && !empty($pfirst_name) && !empty($plast_name) && !empty($pemail)) {
5266 $q = "SELECT * FROM `#__vikbooking_customers` WHERE `id`=".(int)$pwhere." LIMIT 1;";
5267 $dbo->setQuery($q);
5268 $dbo->execute();
5269 if ($dbo->getNumRows() == 1) {
5270 $customer = $dbo->loadAssoc();
5271 } else {
5272 $mainframe->redirect("index.php?option=com_vikbooking&task=customers");
5273 exit;
5274 }
5275 /**
5276 * Existing customers are recognized by equal first name, last name and email address.
5277 *
5278 * @since 1.3.0
5279 */
5280 $q = "SELECT * FROM `#__vikbooking_customers` WHERE `first_name`=".$dbo->quote($pfirst_name)." AND `last_name`=".$dbo->quote($plast_name)." AND `email`=".$dbo->quote($pemail)." AND `id`!=".(int)$pwhere." LIMIT 1;";
5281 $dbo->setQuery($q);
5282 $dbo->execute();
5283 if ($dbo->getNumRows() == 0) {
5284 $cpin = VikBooking::getCPinIstance();
5285 if (empty($ppin)) {
5286 $ppin = $customer['pin'];
5287 } elseif ($cpin->pinExists($ppin, $customer['pin'])) {
5288 $ppin = $cpin->generateUniquePin();
5289 }
5290 //file upload
5291 jimport('joomla.filesystem.file');
5292 $pimg = VikRequest::getVar('docimg', null, 'files', 'array');
5293 $gimg = "";
5294 if (isset($pimg) && strlen(trim($pimg['name']))) {
5295 $filename = JFile::makeSafe(rand(100, 9999).str_replace(" ", "_", strtolower($pimg['name'])));
5296 $src = $pimg['tmp_name'];
5297 $dest = VBO_ADMIN_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'idscans'.DIRECTORY_SEPARATOR;
5298 $j = "";
5299 if (file_exists($dest.$filename)) {
5300 $j = rand(171, 1717);
5301 while (file_exists($dest.$j.$filename)) {
5302 $j++;
5303 }
5304 }
5305 $finaldest = $dest.$j.$filename;
5306 $check = getimagesize($pimg['tmp_name']);
5307 if (($check[2] & imagetypes()) || preg_match("/application\/(zip|pdf)$/", $pimg['type'])) {
5308 if (VikBooking::uploadFile($src, $finaldest)) {
5309 $gimg = $j.$filename;
5310 } else {
5311 VikError::raiseWarning('', 'Error while uploading image');
5312 }
5313 } else {
5314 VikError::raiseWarning('', 'Uploaded file is not an Image');
5315 }
5316 } elseif (!empty($pscandocimg)) {
5317 $gimg = $pscandocimg;
5318 }
5319 //
5320 $pischannel = $pischannel > 0 ? 1 : 0;
5321 $pcalccmmon = $pcalccmmon > 0 ? 1 : 0;
5322 $papplycmmon = $papplycmmon > 0 ? 1 : 0;
5323 $pchname = str_replace(' ', '', trim($pchname));
5324 $pchname = strlen($pchname) <= 0 && $pischannel > 0 ? str_replace(' ', '', trim($pfirst_name.' '.$plast_name)) : $pchname;
5325 $chparams = array(
5326 'commission' => ($pcommission > 0.00 ? $pcommission : 0),
5327 'calccmmon' => $pcalccmmon,
5328 'applycmmon' => $papplycmmon,
5329 'chcolor' => $pchcolor,
5330 'chname' => $pchname
5331 );
5332
5333 /**
5334 * Customer profile picture (URL or uploaded file).
5335 *
5336 * @since 1.15.3 (J) - 1.5.5 (WP)
5337 */
5338 $customer_pic = VikRequest::getString('pic', '', 'request');
5339 $customer_pic_img = VikRequest::getVar('picimg', null, 'files', 'array');
5340 if (is_array($customer_pic_img) && !empty($customer_pic_img['name'])) {
5341 $filename = JFile::makeSafe(rand(100, 9999).str_replace(" ", "_", strtolower($customer_pic_img['name'])));
5342 $src = $customer_pic_img['tmp_name'];
5343 $dest = VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR;
5344 $j = "";
5345 if (is_file($dest.$filename)) {
5346 $j = rand(1, 99999);
5347 while (is_file($dest . $j .$filename)) {
5348 $j++;
5349 }
5350 }
5351 $finaldest = $dest . $j . $filename;
5352 $check = getimagesize($customer_pic_img['tmp_name']);
5353 if (($check[2] & imagetypes())) {
5354 if (VikBooking::uploadFile($src, $finaldest)) {
5355 $customer_pic = $j . $filename;
5356 } else {
5357 VikError::raiseWarning('', 'Error while uploading image');
5358 }
5359 } else {
5360 VikError::raiseWarning('', 'Uploaded file is not an Image');
5361 }
5362 }
5363
5364 // update customer object
5365 $new_customer = new stdClass;
5366 $new_customer->id = (int)$pwhere;
5367 $new_customer->first_name = $pfirst_name;
5368 $new_customer->last_name = $plast_name;
5369 $new_customer->email = $pemail;
5370 $new_customer->phone = $pphone;
5371 $new_customer->country = $pcountry;
5372 $new_customer->pin = $ppin;
5373 $new_customer->ujid = $pujid;
5374 $new_customer->address = $paddress;
5375 $new_customer->city = $pcity;
5376 $new_customer->zip = $pzip;
5377 $new_customer->state = $pstate;
5378 $new_customer->doctype = $pdoctype;
5379 $new_customer->docnum = $pdocnum;
5380 if (!empty($gimg)) {
5381 $new_customer->docimg = $gimg;
5382 }
5383 $new_customer->notes = $pnotes;
5384 $new_customer->ischannel = $pischannel;
5385 $new_customer->chdata = json_encode($chparams);
5386 $new_customer->company = $pcompany;
5387 $new_customer->vat = $pvat;
5388 $new_customer->gender = $pgender;
5389 $new_customer->bdate = $pbdate;
5390 $new_customer->pbirth = $ppbirth;
5391 $new_customer->fisccode = $pfisccode;
5392 $new_customer->pec = $ppec;
5393 $new_customer->recipcode = $precipcode;
5394 $new_customer->pic = $customer_pic;
5395 /**
5396 * We need to update the previous information stored through
5397 * the custom fields when making a reservation for/by this client.
5398 *
5399 * @since 1.13
5400 */
5401 $skip_prev_fields = array(
5402 'id',
5403 'ujid',
5404 'docimg',
5405 'ischannel',
5406 'chdata',
5407 'notes',
5408 );
5409 if (!empty($customer['cfields'])) {
5410 $custf_info = json_decode($customer['cfields'], true);
5411 foreach ($new_customer as $fname => $fnewval) {
5412 if (!isset($customer[$fname]) || in_array($fname, $skip_prev_fields)) {
5413 continue;
5414 }
5415 // seek for old value in custom fields submitted
5416 foreach ($custf_info as $k => $v) {
5417 if (!empty($customer[$fname]) && $v == $customer[$fname]) {
5418 // field found, replace it with the new value
5419 $custf_info[$k] = $fnewval;
5420 }
5421 }
5422 }
5423 // update value on db
5424 $new_customer->cfields = json_encode($custf_info);
5425 }
5426
5427 // trigger the customer before-update event
5428 $cpin->pluginCustomerSync($new_customer->id, 'update', (array)$new_customer, $before = true);
5429
5430 // update customer record
5431 $dbo->updateObject('#__vikbooking_customers', $new_customer, 'id');
5432
5433 // trigger the customer after-save event
5434 $cpin->pluginCustomerSync($new_customer->id, 'update', (array)$new_customer, $before = false);
5435
5436 // update all the bookings affected by this Customer ID as a sales channel
5437 $source_name = 'customer'.$pwhere.'_'.$pchname;
5438 if ($pischannel > 0) {
5439 $oid_clause = '';
5440 if ($customer['ischannel'] < 1) {
5441 //Was not a sales channel but now it is, so update all his bookings
5442 $q = "SELECT `idorder` FROM `#__vikbooking_customers_orders` WHERE `idcustomer`=".$customer['id'].";";
5443 $dbo->setQuery($q);
5444 $dbo->execute();
5445 if ($dbo->getNumRows() > 0) {
5446 $all_bids = $dbo->loadAssocList();
5447 $bids = array();
5448 foreach ($all_bids as $bid) {
5449 if (!in_array($bid['idorder'], $bids)) {
5450 $bids[] = $bid['idorder'];
5451 }
5452 }
5453 $oid_clause = " OR `id` IN (".implode(',', $bids).")";
5454 }
5455 }
5456 $q = "UPDATE `#__vikbooking_orders` SET `channel`=".$dbo->quote($source_name)." WHERE `channel` LIKE 'customer".$pwhere."%'".$oid_clause.";";
5457 } else {
5458 $q = "UPDATE `#__vikbooking_orders` SET `channel`=NULL,`cmms`=NULL WHERE `channel` LIKE 'customer".$pwhere."%';";
5459 }
5460 $dbo->setQuery($q);
5461 $dbo->execute();
5462 //
5463 $mainframe->enqueueMessage(JText::translate('VBCUSTOMERSAVED'));
5464 } else {
5465 //email already exists
5466 $ex_customer = $dbo->loadAssoc();
5467 //check if coming from the Check-in view or not
5468 if (!empty($pcheckin) && !empty($pbid)) {
5469 VikError::raiseWarning('', JText::translate('VBERRCUSTOMEREMAILEXISTS').' ('.$ex_customer['first_name'].' '.$ex_customer['last_name'].')');
5470 /**
5471 * @wponly - this task is executed via Ajax for the Modal forms listener. We must redirect to the booking details page and let the user restart the procedure
5472 */
5473 $mainframe->redirect("index.php?option=com_vikbooking&task=editorder&cid[]=".$pbid);
5474 //
5475 exit;
5476 } elseif (!empty($pgoto)) {
5477 // check if coming from a specific task
5478 VikError::raiseWarning('', JText::translate('VBERRCUSTOMEREMAILEXISTS').' ('.$ex_customer['first_name'].' '.$ex_customer['last_name'].')');
5479 $mainframe->redirect(base64_decode($pgoto));
5480 exit;
5481 } else {
5482 VikError::raiseWarning('', JText::translate('VBERRCUSTOMEREMAILEXISTS').'<br/><a href="index.php?option=com_vikbooking&task=editcustomer&cid[]='.$ex_customer['id'].'" target="_blank">'.$ex_customer['first_name'].' '.$ex_customer['last_name'].'</a>');
5483 $mainframe->redirect("index.php?option=com_vikbooking&task=editcustomer&cid[]=".$pwhere);
5484 exit;
5485 }
5486 }
5487 }
5488
5489 //check if coming from the Check-in view
5490 if (!empty($pcheckin) && !empty($pbid)) {
5491 /**
5492 * @wponly - this task is executed via Ajax for the Modal forms listener. We must redirect to the booking details page and let the user restart the procedure
5493 */
5494 $mainframe->redirect("index.php?option=com_vikbooking&task=editorder&cid[]=" . $pbid);
5495 exit;
5496 }
5497
5498 if ($stay) {
5499 $mainframe->redirect("index.php?option=com_vikbooking&task=editcustomer&cid[]=" . $pwhere . (!empty($pgoto) ? '&goto=' . $pgoto : ''));
5500 exit;
5501 }
5502
5503 // check if coming from a specific task
5504 if (!empty($pgoto)) {
5505 $mainframe->redirect(base64_decode($pgoto));
5506 exit;
5507 }
5508
5509 $mainframe->redirect("index.php?option=com_vikbooking&task=customers");
5510 }
5511
5512 public function savecustomer() {
5513 if (!JSession::checkToken()) {
5514 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
5515 }
5516 $dbo = JFactory::getDbo();
5517 $mainframe = JFactory::getApplication();
5518 $pfirst_name = VikRequest::getString('first_name', '', 'request');
5519 $plast_name = VikRequest::getString('last_name', '', 'request');
5520 $pcompany = VikRequest::getString('company', '', 'request');
5521 $pvat = VikRequest::getString('vat', '', 'request');
5522 $pemail = VikRequest::getString('email', '', 'request');
5523 $pphone = VikRequest::getString('phone', '', 'request');
5524 $pcountry = VikRequest::getString('country', '', 'request');
5525 $pstate = VikRequest::getString('state', '', 'request');
5526 $ppin = VikRequest::getString('pin', '', 'request');
5527 $pujid = VikRequest::getInt('ujid', '', 'request');
5528 $paddress = VikRequest::getString('address', '', 'request');
5529 $pcity = VikRequest::getString('city', '', 'request');
5530 $pzip = VikRequest::getString('zip', '', 'request');
5531 $pfisccode = VikRequest::getString('fisccode', '', 'request');
5532 $ppec = VikRequest::getString('pec', '', 'request');
5533 $precipcode = VikRequest::getString('recipcode', '', 'request');
5534 $pgender = VikRequest::getString('gender', '', 'request');
5535 $pgender = in_array($pgender, array('F', 'M')) ? $pgender : '';
5536 $pbdate = VikRequest::getString('bdate', '', 'request');
5537 $ppbirth = VikRequest::getString('pbirth', '', 'request');
5538 $pdoctype = VikRequest::getString('doctype', '', 'request');
5539 $pdocnum = VikRequest::getString('docnum', '', 'request');
5540 $pnotes = VikRequest::getString('notes', '', 'request');
5541 $pscandocimg = VikRequest::getString('scandocimg', '', 'request');
5542 $pischannel = VikRequest::getInt('ischannel', '', 'request');
5543 $pcommission = VikRequest::getFloat('commission', '', 'request');
5544 $pcalccmmon = VikRequest::getInt('calccmmon', '', 'request');
5545 $papplycmmon = VikRequest::getInt('applycmmon', '', 'request');
5546 $pchname = VikRequest::getString('chname', '', 'request');
5547 $pchcolor = VikRequest::getString('chcolor', '', 'request');
5548 $ptmpl = VikRequest::getString('tmpl', '', 'request');
5549 $pcheckin = VikRequest::getInt('checkin', '', 'request');
5550 $pgoto = VikRequest::getString('goto', '', 'request', VIKREQUEST_ALLOWRAW);
5551 $pbid = VikRequest::getInt('bid', '', 'request');
5552 if (!empty($pfirst_name) && !empty($plast_name) && !empty($pemail)) {
5553 $cpin = VikBooking::getCPinIstance();
5554 /**
5555 * Existing customers are recognized by equal first name, last name and email address.
5556 *
5557 * @since 1.3.0
5558 */
5559 $q = "SELECT * FROM `#__vikbooking_customers` WHERE `first_name`=".$dbo->quote($pfirst_name)." AND `last_name`=".$dbo->quote($plast_name)." AND `email`=".$dbo->quote($pemail)." LIMIT 1;";
5560 $dbo->setQuery($q);
5561 $dbo->execute();
5562 if ($dbo->getNumRows() == 0) {
5563 if (empty($ppin)) {
5564 $ppin = $cpin->generateUniquePin();
5565 } elseif ($cpin->pinExists($ppin)) {
5566 $ppin = $cpin->generateUniquePin();
5567 }
5568 //file upload
5569 jimport('joomla.filesystem.file');
5570 $pimg = VikRequest::getVar('docimg', null, 'files', 'array');
5571 $gimg = "";
5572 if (isset($pimg) && strlen(trim($pimg['name']))) {
5573 $filename = JFile::makeSafe(rand(100, 9999).str_replace(" ", "_", strtolower($pimg['name'])));
5574 $src = $pimg['tmp_name'];
5575 $dest = VBO_ADMIN_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'idscans'.DIRECTORY_SEPARATOR;
5576 $j = "";
5577 if (file_exists($dest.$filename)) {
5578 $j = rand(171, 1717);
5579 while (file_exists($dest.$j.$filename)) {
5580 $j++;
5581 }
5582 }
5583 $finaldest = $dest.$j.$filename;
5584 $check = getimagesize($pimg['tmp_name']);
5585 if (($check[2] & imagetypes()) || preg_match("/application\/(zip|pdf)$/", $pimg['type'])) {
5586 if (VikBooking::uploadFile($src, $finaldest)) {
5587 $gimg = $j.$filename;
5588 } else {
5589 VikError::raiseWarning('', 'Error while uploading image');
5590 }
5591 } else {
5592 VikError::raiseWarning('', 'Uploaded file is not an Image');
5593 }
5594 } elseif (!empty($pscandocimg)) {
5595 $gimg = $pscandocimg;
5596 }
5597 //
5598 $pischannel = $pischannel > 0 ? 1 : 0;
5599 $pcalccmmon = $pcalccmmon > 0 ? 1 : 0;
5600 $papplycmmon = $papplycmmon > 0 ? 1 : 0;
5601 $pchname = str_replace(' ', '', trim($pchname));
5602 $pchname = strlen($pchname) <= 0 && $pischannel > 0 ? str_replace(' ', '', trim($pfirst_name.' '.$plast_name)) : $pchname;
5603 $chparams = array(
5604 'commission' => ($pcommission > 0.00 ? $pcommission : 0),
5605 'calccmmon' => $pcalccmmon,
5606 'applycmmon' => $papplycmmon,
5607 'chcolor' => $pchcolor,
5608 'chname' => $pchname
5609 );
5610
5611 /**
5612 * Customer profile picture (URL or uploaded file).
5613 *
5614 * @since 1.15.3 (J) - 1.5.5 (WP)
5615 */
5616 $customer_pic = VikRequest::getString('pic', '', 'request');
5617 $customer_pic_img = VikRequest::getVar('picimg', null, 'files', 'array');
5618 if (is_array($customer_pic_img) && !empty($customer_pic_img['name'])) {
5619 $filename = JFile::makeSafe(rand(100, 9999).str_replace(" ", "_", strtolower($customer_pic_img['name'])));
5620 $src = $customer_pic_img['tmp_name'];
5621 $dest = VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR;
5622 $j = "";
5623 if (is_file($dest.$filename)) {
5624 $j = rand(1, 99999);
5625 while (is_file($dest . $j .$filename)) {
5626 $j++;
5627 }
5628 }
5629 $finaldest = $dest . $j . $filename;
5630 $check = getimagesize($customer_pic_img['tmp_name']);
5631 if (($check[2] & imagetypes())) {
5632 if (VikBooking::uploadFile($src, $finaldest)) {
5633 $customer_pic = $j . $filename;
5634 } else {
5635 VikError::raiseWarning('', 'Error while uploading image');
5636 }
5637 } else {
5638 VikError::raiseWarning('', 'Uploaded file is not an Image');
5639 }
5640 }
5641
5642 // build customer record
5643 $customer_obj = new stdClass;
5644 $customer_obj->first_name = $pfirst_name;
5645 $customer_obj->last_name = $plast_name;
5646 $customer_obj->email = $pemail;
5647 $customer_obj->phone = $pphone;
5648 $customer_obj->country = $pcountry;
5649 $customer_obj->pin = $ppin;
5650 $customer_obj->ujid = $pujid;
5651 $customer_obj->address = $paddress;
5652 $customer_obj->city = $pcity;
5653 $customer_obj->zip = $pzip;
5654 $customer_obj->state = $pstate;
5655 $customer_obj->doctype = $pdoctype;
5656 $customer_obj->docnum = $pdocnum;
5657 $customer_obj->docimg = $gimg;
5658 $customer_obj->notes = $pnotes;
5659 $customer_obj->ischannel = $pischannel;
5660 $customer_obj->chdata = json_encode($chparams);
5661 $customer_obj->company = $pcompany;
5662 $customer_obj->vat = $pvat;
5663 $customer_obj->gender = $pgender;
5664 $customer_obj->bdate = $pbdate;
5665 $customer_obj->pbirth = $ppbirth;
5666 $customer_obj->fisccode = $pfisccode;
5667 $customer_obj->pec = $ppec;
5668 $customer_obj->recipcode = $precipcode;
5669 $customer_obj->pic = !empty($customer_pic) ? $customer_pic : null;
5670
5671 // trigger the customer before-insert event
5672 $cpin->pluginCustomerSync(0, 'insert', (array)$customer_obj, $before = true);
5673
5674 // insert the new customer record
5675 $dbo->insertObject('#__vikbooking_customers', $customer_obj, 'id');
5676 $lid = isset($customer_obj->id) ? $customer_obj->id : null;
5677
5678 // trigger the customer after-save event
5679 $cpin->pluginCustomerSync($lid, 'insert', (array)$customer_obj, $before = false);
5680
5681 if (!empty($lid)) {
5682 $mainframe->enqueueMessage(JText::translate('VBCUSTOMERSAVED'));
5683 //check if coming from the Check-in view
5684 if (!empty($pcheckin) && !empty($pbid)) {
5685 $cpin->setNewPin($ppin);
5686 $cpin->setNewCustomerId($lid);
5687 $cpin->saveCustomerBooking($pbid);
5688 /**
5689 * @wponly - this task is executed via Ajax for the Modal forms listener. We must redirect to the booking details page and let the user restart the procedure
5690 */
5691 $mainframe->redirect("index.php?option=com_vikbooking&task=editorder&cid[]=".$pbid);
5692 //
5693 exit;
5694 }
5695 // check if coming from a specific task
5696 if (!empty($pgoto) && !empty($pbid)) {
5697 $cpin->setNewPin($ppin);
5698 $cpin->setNewCustomerId($lid);
5699 $cpin->saveCustomerBooking($pbid);
5700 $mainframe->redirect(base64_decode($pgoto));
5701 exit;
5702 }
5703 }
5704 } else {
5705 //email already exists
5706 $ex_customer = $dbo->loadAssoc();
5707 //check if coming from the Check-in view or not
5708 if (!empty($pcheckin) && !empty($pbid)) {
5709 $cpin->setNewPin($ex_customer['pin']);
5710 $cpin->setNewCustomerId($ex_customer['id']);
5711 $cpin->saveCustomerBooking($pbid);
5712 VikError::raiseWarning('', JText::translate('VBERRCUSTOMEREMAILEXISTS').' ('.$ex_customer['first_name'].' '.$ex_customer['last_name'].')');
5713 /**
5714 * @wponly - this task is executed via Ajax for the Modal forms listener. We must redirect to the booking details page and let the user restart the procedure
5715 */
5716 $mainframe->redirect("index.php?option=com_vikbooking&task=editorder&cid[]=".$pbid);
5717 //
5718 exit;
5719 } elseif (!empty($pgoto) && !empty($pbid)) {
5720 // check if coming from a specific task
5721 $cpin->setNewPin($ex_customer['pin']);
5722 $cpin->setNewCustomerId($ex_customer['id']);
5723 $cpin->saveCustomerBooking($pbid);
5724 VikError::raiseWarning('', JText::translate('VBERRCUSTOMEREMAILEXISTS').' ('.$ex_customer['first_name'].' '.$ex_customer['last_name'].')');
5725 $mainframe->redirect(base64_decode($pgoto));
5726 exit;
5727 } else {
5728 VikError::raiseWarning('', JText::translate('VBERRCUSTOMEREMAILEXISTS').'<br/><a href="index.php?option=com_vikbooking&task=editcustomer&cid[]='.$ex_customer['id'].'" target="_blank">'.$ex_customer['first_name'].' '.$ex_customer['last_name'].'</a>');
5729 }
5730 }
5731 }
5732 $mainframe->redirect("index.php?option=com_vikbooking&task=customers");
5733 }
5734
5735 public function customers() {
5736 VikBookingHelper::printHeader("22");
5737
5738 VikRequest::setVar('view', VikRequest::getCmd('view', 'customers'));
5739
5740 parent::display();
5741
5742 if (VikBooking::showFooter()) {
5743 VikBookingHelper::printFooter();
5744 }
5745 }
5746
5747 public function newcustomer() {
5748 VikBookingHelper::printHeader("22");
5749
5750 VikRequest::setVar('view', VikRequest::getCmd('view', 'managecustomer'));
5751
5752 parent::display();
5753
5754 if (VikBooking::showFooter()) {
5755 VikBookingHelper::printFooter();
5756 }
5757 }
5758
5759 public function editcustomer() {
5760 VikBookingHelper::printHeader("22");
5761
5762 VikRequest::setVar('view', VikRequest::getCmd('view', 'managecustomer'));
5763
5764 parent::display();
5765
5766 if (VikBooking::showFooter()) {
5767 VikBookingHelper::printFooter();
5768 }
5769 }
5770
5771 public function removecustomers()
5772 {
5773 if (!JSession::checkToken()) {
5774 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
5775 }
5776
5777 if (!JFactory::getUser()->authorise('core.delete', 'com_vikbooking')) {
5778 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
5779 }
5780
5781 $ids = VikRequest::getVar('cid', array(0));
5782 if ($ids) {
5783 $dbo = JFactory::getDBO();
5784 $cpin = VikBooking::getCPinIstance();
5785 foreach ($ids as $d) {
5786 $cpin->pluginCustomerSync($d, 'delete');
5787 $q = "DELETE FROM `#__vikbooking_customers` WHERE `id`=".(int)$d.";";
5788 $dbo->setQuery($q);
5789 $dbo->execute();
5790 }
5791 }
5792 $mainframe = JFactory::getApplication();
5793 $mainframe->redirect("index.php?option=com_vikbooking&task=customers");
5794 }
5795
5796 public function restrictions() {
5797 VikBookingHelper::printHeader("restrictions");
5798
5799 VikRequest::setVar('view', VikRequest::getCmd('view', 'restrictions'));
5800
5801 parent::display();
5802
5803 if (VikBooking::showFooter()) {
5804 VikBookingHelper::printFooter();
5805 }
5806 }
5807
5808 public function newrestriction() {
5809 VikBookingHelper::printHeader("restrictions");
5810
5811 VikRequest::setVar('view', VikRequest::getCmd('view', 'managerestriction'));
5812
5813 parent::display();
5814
5815 if (VikBooking::showFooter()) {
5816 VikBookingHelper::printFooter();
5817 }
5818 }
5819
5820 public function editrestriction() {
5821 VikBookingHelper::printHeader("restrictions");
5822
5823 VikRequest::setVar('view', VikRequest::getCmd('view', 'managerestriction'));
5824
5825 parent::display();
5826
5827 if (VikBooking::showFooter()) {
5828 VikBookingHelper::printFooter();
5829 }
5830 }
5831
5832 public function createrestriction()
5833 {
5834 if (!JSession::checkToken()) {
5835 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
5836 }
5837
5838 if (!JFactory::getUser()->authorise('core.create', 'com_vikbooking')) {
5839 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
5840 }
5841
5842 $dbo = JFactory::getDBO();
5843 $session = JFactory::getSession();
5844 $mainframe = JFactory::getApplication();
5845 $updforvcm = $session->get('vbVcmRatesUpd', '');
5846 $updforvcm = empty($updforvcm) || !is_array($updforvcm) ? array() : $updforvcm;
5847 $pname = VikRequest::getString('name', '', 'request');
5848 $pmonth = VikRequest::getInt('month', '', 'request');
5849 $pmonth = empty($pmonth) ? 0 : $pmonth;
5850 $pname = empty($pname) ? 'Restriction '.$pmonth : $pname;
5851 $pdfrom = VikRequest::getString('dfrom', '', 'request');
5852 $pdto = VikRequest::getString('dto', '', 'request');
5853 $pwday = VikRequest::getString('wday', '', 'request');
5854 $pwdaytwo = VikRequest::getString('wdaytwo', '', 'request');
5855 $pwdaytwo = strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday == $pwdaytwo ? '' : $pwdaytwo;
5856 $pcomboa = VikRequest::getString('comboa', '', 'request');
5857 $pcomboa = strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo ? $pcomboa : '';
5858 $pcombob = VikRequest::getString('combob', '', 'request');
5859 $pcombob = strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo ? $pcombob : '';
5860 $pcomboc = VikRequest::getString('comboc', '', 'request');
5861 $pcomboc = strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo ? $pcomboc : '';
5862 $pcombod = VikRequest::getString('combod', '', 'request');
5863 $pcombod = strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo ? $pcombod : '';
5864 $combostr = '';
5865 $combostr .= strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo && !empty($pcomboa) ? $pcomboa.':' : ':';
5866 $combostr .= strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo && !empty($pcombob) ? $pcombob.':' : ':';
5867 $combostr .= strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo && !empty($pcomboc) ? $pcomboc.':' : ':';
5868 $combostr .= strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo && !empty($pcombod) ? $pcombod : '';
5869 $pminlos = VikRequest::getInt('minlos', '', 'request');
5870 $pminlos = $pminlos < 1 ? 1 : $pminlos;
5871 $pmaxlos = VikRequest::getInt('maxlos', '', 'request');
5872 $pmaxlos = empty($pmaxlos) ? 0 : $pmaxlos;
5873 $pmultiplyminlos = VikRequest::getString('multiplyminlos', '', 'request');
5874 $pmultiplyminlos = empty($pmultiplyminlos) ? 0 : 1;
5875 $pallrooms = VikRequest::getString('allrooms', '', 'request');
5876 $pallrooms = $pallrooms == "1" ? 1 : 0;
5877 $pidrooms = VikRequest::getVar('idrooms', array(0));
5878 $ridr = '';
5879 $roomidsforsess = array();
5880 if (!empty($pidrooms) && @count($pidrooms) && $pallrooms == 0) {
5881 foreach ($pidrooms as $idr) {
5882 if (empty($idr)) {
5883 continue;
5884 }
5885 $ridr .= '-'.$idr.'-;';
5886 $roomidsforsess[] = (int)$idr;
5887 }
5888 } elseif ($pallrooms > 0) {
5889 $q = "SELECT `id` FROM `#__vikbooking_rooms`;";
5890 $dbo->setQuery($q);
5891 $dbo->execute();
5892 if ($dbo->getNumRows() > 0) {
5893 $fetchids = $dbo->loadAssocList();
5894 foreach ($fetchids as $fetchid) {
5895 $roomidsforsess[] = (int)$fetchid['id'];
5896 }
5897 }
5898 }
5899 $pcta = VikRequest::getInt('cta', '', 'request');
5900 $pctd = VikRequest::getInt('ctd', '', 'request');
5901 $pctad = VikRequest::getVar('ctad', array());
5902 $pctdd = VikRequest::getVar('ctdd', array());
5903 if ($pminlos == 1 && strlen($pwday) == 0 && empty($pctad) && empty($pctdd) && $pmaxlos < 1) {
5904 // VBO 1.11 - we now allow restrictions with just 1 night of stay
5905 // VikError::raiseWarning('', JText::translate('VBUSELESSRESTRICTION'));
5906 // $mainframe->redirect("index.php?option=com_vikbooking&task=newrestriction");
5907 // exit;
5908 }
5909
5910 //check if there are restrictions for this month
5911 if ($pmonth > 0) {
5912 $q = "SELECT `id` FROM `#__vikbooking_restrictions` WHERE `month`='".$pmonth."';";
5913 $dbo->setQuery($q);
5914 $dbo->execute();
5915 if ($dbo->getNumRows() > 0) {
5916 VikError::raiseWarning('', JText::translate('VBRESTRICTIONMONTHEXISTS'));
5917 $mainframe->redirect("index.php?option=com_vikbooking&task=newrestriction");
5918 exit;
5919 }
5920 $pdfrom = 0;
5921 $pdto = 0;
5922 } else {
5923 //dates range
5924 if (empty($pdfrom) || empty($pdto)) {
5925 VikError::raiseWarning('', JText::translate('VBRESTRICTIONERRDRANGE'));
5926 $mainframe->redirect("index.php?option=com_vikbooking&task=newrestriction");
5927 exit;
5928 } else {
5929 $housto = $pdfrom == $pdto ? 23 : 0;
5930 $minsto = $pdfrom == $pdto ? 59 : 0;
5931 $secsto = $pdfrom == $pdto ? 59 : 0;
5932 $pdfrom = VikBooking::getDateTimestamp($pdfrom, 0, 0);
5933 $pdto = VikBooking::getDateTimestamp($pdto, $housto, $minsto, $secsto);
5934 }
5935 if ($pdfrom > $pdto) {
5936 // invalid dates in the past
5937 VikError::raiseWarning('', JText::translate('VBRESTRICTIONERRDRANGE'));
5938 $mainframe->redirect("index.php?option=com_vikbooking&task=newrestriction");
5939 exit;
5940 }
5941 }
5942 //CTA and CTD
5943 $setcta = array();
5944 $setctd = array();
5945 if ($pcta > 0 && count($pctad) > 0) {
5946 foreach ($pctad as $ctwd) {
5947 if (strlen($ctwd)) {
5948 $setcta[] = '-'.(int)$ctwd.'-';
5949 }
5950 }
5951 }
5952 if ($pctd > 0 && count($pctdd) > 0) {
5953 foreach ($pctdd as $ctwd) {
5954 if (strlen($ctwd)) {
5955 $setctd[] = '-'.(int)$ctwd.'-';
5956 }
5957 }
5958 }
5959 //
5960 //update session values
5961 if (!($pdfrom > 0)) {
5962 $attemptyear = (int)date('Y');
5963 $attemptfrom = mktime(0, 0, 0, $pmonth, 1, $attemptyear);
5964 if ($attemptfrom < time()) {
5965 $attemptyear++;
5966 $attemptfrom = mktime(0, 0, 0, $pmonth, 1, $attemptyear);
5967 }
5968 $attemptto = mktime(0, 0, 0, $pmonth, date('t', $attemptfrom), $attemptyear);
5969 } else {
5970 $attemptfrom = $pdfrom;
5971 $attemptto = $pdto;
5972 }
5973 $updforvcm['count'] = array_key_exists('count', $updforvcm) && !empty($updforvcm['count']) ? ($updforvcm['count'] + 1) : 1;
5974 if (array_key_exists('dfrom', $updforvcm) && !empty($updforvcm['dfrom'])) {
5975 $updforvcm['dfrom'] = $updforvcm['dfrom'] > $attemptfrom ? $attemptfrom : $updforvcm['dfrom'];
5976 } else {
5977 $updforvcm['dfrom'] = $attemptfrom;
5978 }
5979 if (array_key_exists('dto', $updforvcm) && !empty($updforvcm['dto'])) {
5980 $updforvcm['dto'] = $updforvcm['dto'] < $attemptto ? $attemptto : $updforvcm['dto'];
5981 } else {
5982 $updforvcm['dto'] = $attemptto;
5983 }
5984 if (array_key_exists('rooms', $updforvcm) && is_array($updforvcm['rooms'])) {
5985 foreach ($roomidsforsess as $rid) {
5986 if (!in_array($rid, $updforvcm['rooms'])) {
5987 $updforvcm['rooms'][] = $rid;
5988 }
5989 }
5990 } else {
5991 $updforvcm['rooms'] = $roomidsforsess;
5992 }
5993 if (!array_key_exists('rplans', $updforvcm) || !is_array($updforvcm['rplans'])) {
5994 $updforvcm['rplans'] = array();
5995 }
5996 $session->set('vbVcmRatesUpd', $updforvcm);
5997 //
5998 $q = "INSERT INTO `#__vikbooking_restrictions` (`name`,`month`,`wday`,`minlos`,`multiplyminlos`,`maxlos`,`dfrom`,`dto`,`wdaytwo`,`wdaycombo`,`allrooms`,`idrooms`,`ctad`,`ctdd`) VALUES(".$dbo->quote($pname).", '".$pmonth."', ".(strlen($pwday) > 0 ? "'".$pwday."'" : "NULL").", '".$pminlos."', '".$pmultiplyminlos."', '".$pmaxlos."', ".$pdfrom.", ".$pdto.", ".(strlen($pwday) > 0 && strlen($pwdaytwo) > 0 ? intval($pwdaytwo) : "NULL").", ".(strlen($combostr) > 0 ? $dbo->quote($combostr) : "NULL").", ".$pallrooms.", ".(strlen($ridr) > 0 ? $dbo->quote($ridr) : "NULL").", ".(count($setcta) > 0 ? $dbo->quote(implode(',', $setcta)) : "NULL").", ".(count($setctd) > 0 ? $dbo->quote(implode(',', $setctd)) : "NULL").");";
5999 $dbo->setQuery($q);
6000 $dbo->execute();
6001 $lid = $dbo->insertid();
6002 if (!empty($lid)) {
6003 /**
6004 * Repeat restriction on the selected week days until the limit
6005 *
6006 * @since 1.13
6007 */
6008 $prepeat = VikRequest::getInt('repeat', 0, 'request');
6009 $prepeatuntil = VikRequest::getString('repeatuntil', '', 'request');
6010 if ($prepeat > 0 && !empty($prepeatuntil) && $pdfrom > 0 && $pdto > 0) {
6011 $repeat_intervals = array();
6012 $start = getdate($pdfrom);
6013 $end = getdate($pdto);
6014 $wdays = array();
6015 while ($start[0] <= $end[0]) {
6016 // push requested week day
6017 array_push($wdays, $start['wday']);
6018 // next day
6019 $start = getdate(mktime($start['hours'], $start['minutes'], $start['seconds'], $start['mon'], ($start['mday'] + 1), $start['year']));
6020 }
6021 $dtuntil = VikBooking::getDateTimestamp($prepeatuntil, 23, 59, 59);
6022 if (count($wdays) < 7 && $dtuntil > $pdto) {
6023 // increment end date for the repeat
6024 $end = getdate(mktime($end['hours'], $end['minutes'], $end['seconds'], $end['mon'], ($end['mday'] + 1), $end['year']));
6025 //
6026 $until_info = getdate($dtuntil);
6027 $interval = array();
6028 while ($end[0] <= $until_info[0]) {
6029 if (in_array($end['wday'], $wdays)) {
6030 if (!isset($interval['from'])) {
6031 $interval['from'] = $end[0];
6032 }
6033 $interval['to'] = $end[0];
6034 } else {
6035 if (isset($interval['from'])) {
6036 // append interval
6037 array_push($repeat_intervals, $interval);
6038 // reset interval
6039 $interval = array();
6040 }
6041 }
6042 // next day
6043 $end = getdate(mktime($end['hours'], $end['minutes'], $end['seconds'], $end['mon'], ($end['mday'] + 1), $end['year']));
6044 }
6045 if (isset($interval['from'])) {
6046 // append last hanging interval
6047 array_push($repeat_intervals, $interval);
6048 }
6049 if (count($repeat_intervals)) {
6050 // create the repeated records for the calculated intervals
6051 $repeat_count = 2;
6052 foreach ($repeat_intervals as $rp) {
6053 if (date('Y-m-d', $rp['from']) == date('Y-m-d', $rp['to'])) {
6054 // adjust time in case of equal dates (1 single day restriction)
6055 $rpfrom = getdate($rp['from']);
6056 $rpto = getdate($rp['to']);
6057 $rp['from'] = mktime(0, 0, 0, $rpfrom['mon'], $rpfrom['mday'], $rpfrom['year']);
6058 /**
6059 * The end date of the restriction must cover the whole day until 23:59:59.
6060 *
6061 * @since 1.15.4 (J) - 1.5.4 (WP)
6062 */
6063 $rp['to'] = mktime(23, 59, 59, $rpto['mon'], $rpto['mday'], $rpto['year']);
6064 }
6065 // adjust name
6066 $restr_rp_name = $pname . " #{$repeat_count}";
6067 //
6068 $q = "INSERT INTO `#__vikbooking_restrictions` (`name`,`month`,`wday`,`minlos`,`multiplyminlos`,`maxlos`,`dfrom`,`dto`,`wdaytwo`,`wdaycombo`,`allrooms`,`idrooms`,`ctad`,`ctdd`) VALUES(".$dbo->quote($restr_rp_name).", '".$pmonth."', ".(strlen($pwday) > 0 ? "'".$pwday."'" : "NULL").", '".$pminlos."', '".$pmultiplyminlos."', '".$pmaxlos."', ".$rp['from'].", ".$rp['to'].", ".(strlen($pwday) > 0 && strlen($pwdaytwo) > 0 ? intval($pwdaytwo) : "NULL").", ".(strlen($combostr) > 0 ? $dbo->quote($combostr) : "NULL").", ".$pallrooms.", ".(strlen($ridr) > 0 ? $dbo->quote($ridr) : "NULL").", ".(count($setcta) > 0 ? $dbo->quote(implode(',', $setcta)) : "NULL").", ".(count($setctd) > 0 ? $dbo->quote(implode(',', $setctd)) : "NULL").");";
6069 $dbo->setQuery($q);
6070 $dbo->execute();
6071 $lid = $dbo->insertid();
6072 if (!empty($lid)) {
6073 $repeat_count++;
6074 }
6075 }
6076 }
6077 }
6078 }
6079 //
6080 $mainframe->enqueueMessage(JText::translate('VBRESTRICTIONSAVED'));
6081 $mainframe->redirect("index.php?option=com_vikbooking&task=restrictions");
6082 } else {
6083 VikError::raiseWarning('', 'Error while saving');
6084 $mainframe->redirect("index.php?option=com_vikbooking&task=newrestriction");
6085 }
6086 }
6087
6088 public function updaterestriction()
6089 {
6090 if (!JSession::checkToken()) {
6091 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6092 }
6093
6094 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
6095 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
6096 }
6097
6098 $dbo = JFactory::getDBO();
6099 $session = JFactory::getSession();
6100 $mainframe = JFactory::getApplication();
6101 $updforvcm = $session->get('vbVcmRatesUpd', '');
6102 $updforvcm = empty($updforvcm) || !is_array($updforvcm) ? array() : $updforvcm;
6103 $pwhere = VikRequest::getInt('where', '', 'request');
6104 $pname = VikRequest::getString('name', '', 'request');
6105 $pmonth = VikRequest::getInt('month', '', 'request');
6106 $pmonth = empty($pmonth) ? 0 : $pmonth;
6107 $pname = empty($pname) ? 'Restriction '.$pmonth : $pname;
6108 $pdfrom = VikRequest::getString('dfrom', '', 'request');
6109 $pdto = VikRequest::getString('dto', '', 'request');
6110 $pwday = VikRequest::getString('wday', '', 'request');
6111 $pwdaytwo = VikRequest::getString('wdaytwo', '', 'request');
6112 $pwdaytwo = strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday == $pwdaytwo ? '' : $pwdaytwo;
6113 $pcomboa = VikRequest::getString('comboa', '', 'request');
6114 $pcomboa = strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo ? $pcomboa : '';
6115 $pcombob = VikRequest::getString('combob', '', 'request');
6116 $pcombob = strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo ? $pcombob : '';
6117 $pcomboc = VikRequest::getString('comboc', '', 'request');
6118 $pcomboc = strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo ? $pcomboc : '';
6119 $pcombod = VikRequest::getString('combod', '', 'request');
6120 $pcombod = strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo ? $pcombod : '';
6121 $combostr = '';
6122 $combostr .= strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo && !empty($pcomboa) ? $pcomboa.':' : ':';
6123 $combostr .= strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo && !empty($pcombob) ? $pcombob.':' : ':';
6124 $combostr .= strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo && !empty($pcomboc) ? $pcomboc.':' : ':';
6125 $combostr .= strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo && !empty($pcombod) ? $pcombod : '';
6126 $pminlos = VikRequest::getInt('minlos', '', 'request');
6127 $pminlos = $pminlos < 1 ? 1 : $pminlos;
6128 $pmaxlos = VikRequest::getInt('maxlos', '', 'request');
6129 $pmaxlos = empty($pmaxlos) ? 0 : $pmaxlos;
6130 $pmultiplyminlos = VikRequest::getString('multiplyminlos', '', 'request');
6131 $pmultiplyminlos = empty($pmultiplyminlos) ? 0 : 1;
6132 $pallrooms = VikRequest::getString('allrooms', '', 'request');
6133 $pallrooms = $pallrooms == "1" ? 1 : 0;
6134 $pidrooms = VikRequest::getVar('idrooms', array(0));
6135 $ridr = '';
6136 $roomidsforsess = array();
6137 if (!empty($pidrooms) && @count($pidrooms) && $pallrooms == 0) {
6138 foreach ($pidrooms as $idr) {
6139 if (empty($idr)) {
6140 continue;
6141 }
6142 $ridr .= '-'.$idr.'-;';
6143 $roomidsforsess[] = (int)$idr;
6144 }
6145 } elseif ($pallrooms > 0) {
6146 $q = "SELECT `id` FROM `#__vikbooking_rooms`;";
6147 $dbo->setQuery($q);
6148 $dbo->execute();
6149 if ($dbo->getNumRows() > 0) {
6150 $fetchids = $dbo->loadAssocList();
6151 foreach ($fetchids as $fetchid) {
6152 $roomidsforsess[] = (int)$fetchid['id'];
6153 }
6154 }
6155 }
6156 $pcta = VikRequest::getInt('cta', '', 'request');
6157 $pctd = VikRequest::getInt('ctd', '', 'request');
6158 $pctad = VikRequest::getVar('ctad', array());
6159 $pctdd = VikRequest::getVar('ctdd', array());
6160 if ($pminlos == 1 && strlen($pwday) == 0 && empty($pctad) && empty($pctdd) && $pmaxlos < 1) {
6161 // VBO 1.11 - we now allow restrictions with just 1 night of stay
6162 // VikError::raiseWarning('', JText::translate('VBUSELESSRESTRICTION'));
6163 // $mainframe->redirect("index.php?option=com_vikbooking&task=editrestriction&cid[]=".$pwhere);
6164 // exit;
6165 }
6166 //check if there are restrictions for this month
6167 if ($pmonth > 0) {
6168 $q = "SELECT `id` FROM `#__vikbooking_restrictions` WHERE `month`='".$pmonth."' AND `id`!='".$pwhere."';";
6169 $dbo->setQuery($q);
6170 $dbo->execute();
6171 if ($dbo->getNumRows() > 0) {
6172 VikError::raiseWarning('', JText::translate('VBRESTRICTIONMONTHEXISTS'));
6173 $mainframe->redirect("index.php?option=com_vikbooking&task=editrestriction&cid[]=".$pwhere);
6174 exit;
6175 }
6176 $pdfrom = 0;
6177 $pdto = 0;
6178 } else {
6179 //dates range
6180 if (empty($pdfrom) || empty($pdto)) {
6181 VikError::raiseWarning('', JText::translate('VBRESTRICTIONERRDRANGE'));
6182 $mainframe->redirect("index.php?option=com_vikbooking&task=editrestriction&cid[]=".$pwhere);
6183 exit;
6184 } else {
6185 $housto = $pdfrom == $pdto ? 23 : 0;
6186 $minsto = $pdfrom == $pdto ? 59 : 0;
6187 $secsto = $pdfrom == $pdto ? 59 : 0;
6188 $pdfrom = VikBooking::getDateTimestamp($pdfrom, 0, 0);
6189 $pdto = VikBooking::getDateTimestamp($pdto, $housto, $minsto, $secsto);
6190 }
6191 if ($pdfrom > $pdto) {
6192 // invalid dates in the past
6193 VikError::raiseWarning('', JText::translate('VBRESTRICTIONERRDRANGE'));
6194 $mainframe->redirect("index.php?option=com_vikbooking&task=editrestriction&cid[]=".$pwhere);
6195 exit;
6196 }
6197 }
6198 //CTA and CTD
6199 $setcta = array();
6200 $setctd = array();
6201 if ($pcta > 0 && count($pctad) > 0) {
6202 foreach ($pctad as $ctwd) {
6203 if (strlen($ctwd)) {
6204 $setcta[] = '-'.(int)$ctwd.'-';
6205 }
6206 }
6207 }
6208 if ($pctd > 0 && count($pctdd) > 0) {
6209 foreach ($pctdd as $ctwd) {
6210 if (strlen($ctwd)) {
6211 $setctd[] = '-'.(int)$ctwd.'-';
6212 }
6213 }
6214 }
6215 //
6216 //update session values
6217 if (!($pdfrom > 0)) {
6218 $attemptyear = (int)date('Y');
6219 $attemptfrom = mktime(0, 0, 0, $pmonth, 1, $attemptyear);
6220 if ($attemptfrom < time()) {
6221 $attemptyear++;
6222 $attemptfrom = mktime(0, 0, 0, $pmonth, 1, $attemptyear);
6223 }
6224 $attemptto = mktime(0, 0, 0, $pmonth, date('t', $attemptfrom), $attemptyear);
6225 } else {
6226 $attemptfrom = $pdfrom;
6227 $attemptto = $pdto;
6228 }
6229 $updforvcm['count'] = array_key_exists('count', $updforvcm) && !empty($updforvcm['count']) ? ($updforvcm['count'] + 1) : 1;
6230 if (array_key_exists('dfrom', $updforvcm) && !empty($updforvcm['dfrom'])) {
6231 $updforvcm['dfrom'] = $updforvcm['dfrom'] > $attemptfrom ? $attemptfrom : $updforvcm['dfrom'];
6232 } else {
6233 $updforvcm['dfrom'] = $attemptfrom;
6234 }
6235 if (array_key_exists('dto', $updforvcm) && !empty($updforvcm['dto'])) {
6236 $updforvcm['dto'] = $updforvcm['dto'] < $attemptto ? $attemptto : $updforvcm['dto'];
6237 } else {
6238 $updforvcm['dto'] = $attemptto;
6239 }
6240 if (array_key_exists('rooms', $updforvcm) && is_array($updforvcm['rooms'])) {
6241 foreach ($roomidsforsess as $rid) {
6242 if (!in_array($rid, $updforvcm['rooms'])) {
6243 $updforvcm['rooms'][] = $rid;
6244 }
6245 }
6246 } else {
6247 $updforvcm['rooms'] = $roomidsforsess;
6248 }
6249 if (!array_key_exists('rplans', $updforvcm) || !is_array($updforvcm['rplans'])) {
6250 $updforvcm['rplans'] = array();
6251 }
6252 $session->set('vbVcmRatesUpd', $updforvcm);
6253 //
6254 $q = "UPDATE `#__vikbooking_restrictions` SET `name`=".$dbo->quote($pname).",`month`='".$pmonth."',`wday`=".(strlen($pwday) > 0 ? "'".$pwday."'" : "NULL").",`minlos`='".$pminlos."',`multiplyminlos`='".$pmultiplyminlos."',`maxlos`='".$pmaxlos."',`dfrom`=".$pdfrom.",`dto`=".$pdto.",`wdaytwo`=".(strlen($pwday) > 0 && strlen($pwdaytwo) > 0 ? intval($pwdaytwo) : "NULL").",`wdaycombo`=".(strlen($combostr) > 0 ? $dbo->quote($combostr) : "NULL").",`allrooms`=".$pallrooms.",`idrooms`=".(strlen($ridr) > 0 ? $dbo->quote($ridr) : "NULL").", `ctad`=".(count($setcta) > 0 ? $dbo->quote(implode(',', $setcta)) : "NULL").", `ctdd`=".(count($setctd) > 0 ? $dbo->quote(implode(',', $setctd)) : "NULL")." WHERE `id`='".$pwhere."';";
6255 $dbo->setQuery($q);
6256 $dbo->execute();
6257 $mainframe->enqueueMessage(JText::translate('VBRESTRICTIONSAVED'));
6258 $mainframe->redirect("index.php?option=com_vikbooking&task=restrictions");
6259 }
6260
6261 public function removerestrictions()
6262 {
6263 if (!JSession::checkToken()) {
6264 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6265 }
6266
6267 if (!JFactory::getUser()->authorise('core.delete', 'com_vikbooking')) {
6268 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
6269 }
6270
6271 $ids = VikRequest::getVar('cid', array(0));
6272 if ($ids) {
6273 $dbo = JFactory::getDBO();
6274 foreach ($ids as $d) {
6275 $q = "DELETE FROM `#__vikbooking_restrictions` WHERE `id`=".(int)$d.";";
6276 $dbo->setQuery($q);
6277 $dbo->execute();
6278 }
6279 }
6280 $mainframe = JFactory::getApplication();
6281 $mainframe->redirect("index.php?option=com_vikbooking&task=restrictions");
6282 }
6283
6284 public function prices() {
6285 VikBookingHelper::printHeader("1");
6286
6287 VikRequest::setVar('view', VikRequest::getCmd('view', 'prices'));
6288
6289 parent::display();
6290
6291 if (VikBooking::showFooter()) {
6292 VikBookingHelper::printFooter();
6293 }
6294 }
6295
6296 public function newprice() {
6297 VikBookingHelper::printHeader("1");
6298
6299 VikRequest::setVar('view', VikRequest::getCmd('view', 'manageprice'));
6300
6301 parent::display();
6302
6303 if (VikBooking::showFooter()) {
6304 VikBookingHelper::printFooter();
6305 }
6306 }
6307
6308 public function editprice() {
6309 VikBookingHelper::printHeader("1");
6310
6311 VikRequest::setVar('view', VikRequest::getCmd('view', 'manageprice'));
6312
6313 parent::display();
6314
6315 if (VikBooking::showFooter()) {
6316 VikBookingHelper::printFooter();
6317 }
6318 }
6319
6320 public function createprice()
6321 {
6322 if (!JSession::checkToken()) {
6323 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6324 }
6325
6326 if (!JFactory::getUser()->authorise('core.create', 'com_vikbooking')) {
6327 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
6328 }
6329
6330 $this->do_createprice();
6331 }
6332
6333 public function createprice_new()
6334 {
6335 if (!JSession::checkToken()) {
6336 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6337 }
6338
6339 if (!JFactory::getUser()->authorise('core.create', 'com_vikbooking')) {
6340 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
6341 }
6342
6343 $this->do_createprice(true);
6344 }
6345
6346 private function do_createprice($new = false)
6347 {
6348 $pprice = VikRequest::getString('price', '', 'request');
6349 $pattr = VikRequest::getString('attr', '', 'request');
6350 $ppraliq = VikRequest::getInt('praliq', '', 'request');
6351 $pmeal_plans = (array)VikRequest::getVar('meal_plans', []);
6352 $pbreakfast_included = in_array('breakfast', $pmeal_plans) ? 1 : 0;
6353 $pfree_cancellation = VikRequest::getInt('free_cancellation', 0, 'request');
6354 $pfree_cancellation = $pfree_cancellation == 1 ? 1 : 0;
6355 $pcanc_deadline = VikRequest::getInt('canc_deadline', '', 'request');
6356 $pminlos = VikRequest::getInt('minlos', 0, 'request');
6357 $pminlos = $pminlos < 0 ? 0 : $pminlos;
6358 $pminhadv = VikRequest::getInt('minhadv', '', 'request');
6359 $pminhadv = $pminhadv < 0 ? 0 : $pminhadv;
6360 $pcanc_policy = VikRequest::getString('canc_policy', '', 'request', VIKREQUEST_ALLOWHTML);
6361 if (!empty($pprice)) {
6362 $dbo = JFactory::getDbo();
6363 $q = "INSERT INTO `#__vikbooking_prices` (`name`,`attr`,`idiva`,`breakfast_included`,`free_cancellation`,`canc_deadline`,`canc_policy`,`minlos`,`minhadv`,`meal_plans`) VALUES(" . $dbo->q($pprice) . ", " . $dbo->q($pattr) . ", " . $dbo->q($ppraliq) . ", " . $pbreakfast_included . ", " . $pfree_cancellation . ", " . $pcanc_deadline . ", " . $dbo->q($pcanc_policy) . ", " . $pminlos . ", " . $pminhadv . ", " . $dbo->q(json_encode($pmeal_plans)) . ");";
6364 $dbo->setQuery($q);
6365 $dbo->execute();
6366 }
6367
6368 $app = JFactory::getApplication();
6369 $app->redirect("index.php?option=com_vikbooking&task=" . ($new ? 'newprice' : 'prices'));
6370 $app->close();
6371 }
6372
6373 public function updateprice()
6374 {
6375 if (!JSession::checkToken()) {
6376 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6377 }
6378
6379 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
6380 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
6381 }
6382
6383 $this->do_updateprice();
6384 }
6385
6386 public function updatepricestay()
6387 {
6388 if (!JSession::checkToken()) {
6389 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6390 }
6391
6392 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
6393 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
6394 }
6395
6396 $this->do_updateprice(true);
6397 }
6398
6399 private function do_updateprice($stay = false)
6400 {
6401 $pprice = VikRequest::getString('price', '', 'request');
6402 $pattr = VikRequest::getString('attr', '', 'request');
6403 $ppraliq = VikRequest::getInt('praliq', '', 'request');
6404 $pmeal_plans = (array)VikRequest::getVar('meal_plans', []);
6405 $pbreakfast_included = in_array('breakfast', $pmeal_plans) ? 1 : 0;
6406 $pfree_cancellation = VikRequest::getInt('free_cancellation', '', 'request');
6407 $pfree_cancellation = $pfree_cancellation == 1 ? 1 : 0;
6408 $pcanc_deadline = VikRequest::getInt('canc_deadline', '', 'request');
6409 $pminlos = VikRequest::getInt('minlos', 0, 'request');
6410 $pminlos = $pminlos < 0 ? 0 : $pminlos;
6411 $pminhadv = VikRequest::getInt('minhadv', '', 'request');
6412 $pminhadv = $pminhadv < 0 ? 0 : $pminhadv;
6413 $pcanc_policy = VikRequest::getString('canc_policy', '', 'request', VIKREQUEST_ALLOWHTML);
6414 $pwhereup = VikRequest::getInt('whereup', 0, 'request');
6415 if (!empty($pprice) && $pwhereup) {
6416 $dbo = JFactory::getDbo();
6417 $q = "UPDATE `#__vikbooking_prices` SET `name`=" . $dbo->q($pprice) . ",`attr`=" . $dbo->q($pattr) . ",`idiva`=" . $dbo->q($ppraliq) . ",`breakfast_included`=" . $pbreakfast_included . ",`free_cancellation`=" . $pfree_cancellation . ",`canc_deadline`=" . $pcanc_deadline . ",`canc_policy`=" . $dbo->q($pcanc_policy) . ",`minlos`=" . $pminlos . ",`minhadv`=" . $pminhadv . ",`meal_plans`=" . $dbo->q(json_encode($pmeal_plans)) . " WHERE `id`=" . $dbo->q($pwhereup) . ";";
6418 $dbo->setQuery($q);
6419 $dbo->execute();
6420 }
6421
6422 $app = JFactory::getApplication();
6423 $app->redirect("index.php?option=com_vikbooking&task=" . ($stay ? 'editprice&cid[]=' . $pwhereup : 'prices'));
6424 $app->close();
6425 }
6426
6427 public function removeprice()
6428 {
6429 if (!JSession::checkToken()) {
6430 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6431 }
6432
6433 if (!JFactory::getUser()->authorise('core.delete', 'com_vikbooking')) {
6434 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
6435 }
6436
6437 $ids = VikRequest::getVar('cid', array(0));
6438 if ($ids) {
6439 $dbo = JFactory::getDBO();
6440 foreach ($ids as $d) {
6441 $q = "DELETE FROM `#__vikbooking_prices` WHERE `id`=".$dbo->quote($d).";";
6442 $dbo->setQuery($q);
6443 $dbo->execute();
6444 $q = "DELETE FROM `#__vikbooking_dispcost` WHERE `idprice`=".intval($d).";";
6445 $dbo->setQuery($q);
6446 $dbo->execute();
6447 }
6448 }
6449 $mainframe = JFactory::getApplication();
6450 $mainframe->redirect("index.php?option=com_vikbooking&task=prices");
6451 }
6452
6453 public function iva() {
6454 VikBookingHelper::printHeader("2");
6455
6456 VikRequest::setVar('view', VikRequest::getCmd('view', 'iva'));
6457
6458 parent::display();
6459
6460 if (VikBooking::showFooter()) {
6461 VikBookingHelper::printFooter();
6462 }
6463 }
6464
6465 public function newiva() {
6466 VikBookingHelper::printHeader("2");
6467
6468 VikRequest::setVar('view', VikRequest::getCmd('view', 'manageiva'));
6469
6470 parent::display();
6471
6472 if (VikBooking::showFooter()) {
6473 VikBookingHelper::printFooter();
6474 }
6475 }
6476
6477 public function editiva() {
6478 VikBookingHelper::printHeader("2");
6479
6480 VikRequest::setVar('view', VikRequest::getCmd('view', 'manageiva'));
6481
6482 parent::display();
6483
6484 if (VikBooking::showFooter()) {
6485 VikBookingHelper::printFooter();
6486 }
6487 }
6488
6489 public function createiva()
6490 {
6491 if (!JSession::checkToken()) {
6492 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6493 }
6494
6495 if (!JFactory::getUser()->authorise('core.create', 'com_vikbooking')) {
6496 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
6497 }
6498
6499 $paliqname = VikRequest::getString('aliqname', '', 'request');
6500 $paliqperc = VikRequest::getFloat('aliqperc', '', 'request');
6501 $pbreakdown_name = VikRequest::getVar('breakdown_name', array());
6502 $pbreakdown_rate = VikRequest::getVar('breakdown_rate', array());
6503 $ptaxcap = VikRequest::getFloat('taxcap', 0, 'request');
6504 if (!empty($paliqperc)) {
6505 $dbo = JFactory::getDBO();
6506 $breakdown_str = '';
6507 if (count($pbreakdown_name) > 0) {
6508 $breakdown_values = array();
6509 $bkcount = 0;
6510 $tot_sub_aliq = 0;
6511 foreach ($pbreakdown_name as $key => $subtax) {
6512 if (!empty($subtax) && floatval($pbreakdown_rate[$key]) > 0) {
6513 $breakdown_values[$bkcount]['name'] = $subtax;
6514 $breakdown_values[$bkcount]['aliq'] = (float)$pbreakdown_rate[$key];
6515 $tot_sub_aliq += (float)$pbreakdown_rate[$key];
6516 $bkcount++;
6517 }
6518 }
6519 if (count($breakdown_values) > 0) {
6520 $breakdown_str = json_encode($breakdown_values);
6521 if ($tot_sub_aliq < (float)$paliqperc || $tot_sub_aliq > (float)$paliqperc) {
6522 VikError::raiseWarning('', JText::translate('VBOTAXBKDWNERRNOMATCH'));
6523 }
6524 }
6525 }
6526 $q = "INSERT INTO `#__vikbooking_iva` (`name`,`aliq`,`breakdown`,`taxcap`) VALUES(".$dbo->quote($paliqname).", ".$dbo->quote($paliqperc).", ".(empty($breakdown_str) ? 'NULL' : $dbo->quote($breakdown_str)).", ".($ptaxcap > 0 ? $dbo->quote($ptaxcap) : 'NULL').");";
6527 $dbo->setQuery($q);
6528 $dbo->execute();
6529 }
6530 $mainframe = JFactory::getApplication();
6531 $mainframe->redirect("index.php?option=com_vikbooking&task=iva");
6532 }
6533
6534 public function updateiva()
6535 {
6536 if (!JSession::checkToken()) {
6537 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6538 }
6539
6540 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
6541 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
6542 }
6543
6544 $paliqname = VikRequest::getString('aliqname', '', 'request');
6545 $paliqperc = VikRequest::getFloat('aliqperc', '', 'request');
6546 $pbreakdown_name = VikRequest::getVar('breakdown_name', array());
6547 $pbreakdown_rate = VikRequest::getVar('breakdown_rate', array());
6548 $ptaxcap = VikRequest::getFloat('taxcap', 0, 'request');
6549 $pwhereup = VikRequest::getInt('whereup', 0, 'request');
6550 if (!empty($paliqperc)) {
6551 $dbo = JFactory::getDBO();
6552 $breakdown_str = '';
6553 if (count($pbreakdown_name) > 0) {
6554 $breakdown_values = array();
6555 $bkcount = 0;
6556 $tot_sub_aliq = 0;
6557 foreach ($pbreakdown_name as $key => $subtax) {
6558 if (!empty($subtax) && floatval($pbreakdown_rate[$key]) > 0) {
6559 $breakdown_values[$bkcount]['name'] = $subtax;
6560 $breakdown_values[$bkcount]['aliq'] = (float)$pbreakdown_rate[$key];
6561 $tot_sub_aliq += (float)$pbreakdown_rate[$key];
6562 $bkcount++;
6563 }
6564 }
6565 if (count($breakdown_values) > 0) {
6566 $breakdown_str = json_encode($breakdown_values);
6567 if ($tot_sub_aliq < (float)$paliqperc || $tot_sub_aliq > (float)$paliqperc) {
6568 VikError::raiseWarning('', JText::translate('VBOTAXBKDWNERRNOMATCH'));
6569 }
6570 }
6571 }
6572 $q = "UPDATE `#__vikbooking_iva` SET `name`=".$dbo->quote($paliqname).",`aliq`=".$dbo->quote($paliqperc).",`breakdown`=".(empty($breakdown_str) ? 'NULL' : $dbo->quote($breakdown_str)).",`taxcap`=".($ptaxcap > 0 ? $dbo->quote($ptaxcap) : 'NULL')." WHERE `id`=".$dbo->quote($pwhereup).";";
6573 $dbo->setQuery($q);
6574 $dbo->execute();
6575 }
6576 $mainframe = JFactory::getApplication();
6577 $mainframe->redirect("index.php?option=com_vikbooking&task=iva");
6578 }
6579
6580 public function removeiva()
6581 {
6582 if (!JSession::checkToken()) {
6583 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6584 }
6585
6586 if (!JFactory::getUser()->authorise('core.delete', 'com_vikbooking')) {
6587 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
6588 }
6589
6590 $ids = VikRequest::getVar('cid', array(0));
6591 if ($ids) {
6592 $dbo = JFactory::getDBO();
6593 foreach ($ids as $d) {
6594 $q = "DELETE FROM `#__vikbooking_iva` WHERE `id`=".$dbo->quote($d).";";
6595 $dbo->setQuery($q);
6596 $dbo->execute();
6597 }
6598 }
6599 $mainframe = JFactory::getApplication();
6600 $mainframe->redirect("index.php?option=com_vikbooking&task=iva");
6601 }
6602
6603 public function categories() {
6604 VikBookingHelper::printHeader("4");
6605
6606 VikRequest::setVar('view', VikRequest::getCmd('view', 'categories'));
6607
6608 parent::display();
6609
6610 if (VikBooking::showFooter()) {
6611 VikBookingHelper::printFooter();
6612 }
6613 }
6614
6615 public function newcat() {
6616 VikBookingHelper::printHeader("4");
6617
6618 VikRequest::setVar('view', VikRequest::getCmd('view', 'managecategory'));
6619
6620 parent::display();
6621
6622 if (VikBooking::showFooter()) {
6623 VikBookingHelper::printFooter();
6624 }
6625 }
6626
6627 public function editcat() {
6628 VikBookingHelper::printHeader("4");
6629
6630 VikRequest::setVar('view', VikRequest::getCmd('view', 'managecategory'));
6631
6632 parent::display();
6633
6634 if (VikBooking::showFooter()) {
6635 VikBookingHelper::printFooter();
6636 }
6637 }
6638
6639 public function createcat()
6640 {
6641 if (!JSession::checkToken()) {
6642 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6643 }
6644
6645 if (!JFactory::getUser()->authorise('core.create', 'com_vikbooking')) {
6646 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
6647 }
6648
6649 $pcatname = VikRequest::getString('catname', '', 'request');
6650 $pdescr = VikRequest::getString('descr', '', 'request', VIKREQUEST_ALLOWHTML);
6651 if (!empty($pcatname)) {
6652 $dbo = JFactory::getDBO();
6653 $q = "INSERT INTO `#__vikbooking_categories` (`name`,`descr`) VALUES(".$dbo->quote($pcatname).", ".$dbo->quote($pdescr).");";
6654 $dbo->setQuery($q);
6655 $dbo->execute();
6656 }
6657 $mainframe = JFactory::getApplication();
6658 $mainframe->redirect("index.php?option=com_vikbooking&task=categories");
6659 }
6660
6661 public function updatecat()
6662 {
6663 if (!JSession::checkToken()) {
6664 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6665 }
6666
6667 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
6668 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
6669 }
6670
6671 $pcatname = VikRequest::getString('catname', '', 'request');
6672 $pdescr = VikRequest::getString('descr', '', 'request', VIKREQUEST_ALLOWHTML);
6673 $pwhereup = VikRequest::getString('whereup', '', 'request');
6674 if (!empty($pcatname)) {
6675 $dbo = JFactory::getDBO();
6676 $q = "UPDATE `#__vikbooking_categories` SET `name`=".$dbo->quote($pcatname).", `descr`=".$dbo->quote($pdescr)." WHERE `id`=".$dbo->quote($pwhereup).";";
6677 $dbo->setQuery($q);
6678 $dbo->execute();
6679 }
6680 $mainframe = JFactory::getApplication();
6681 $mainframe->redirect("index.php?option=com_vikbooking&task=categories");
6682 }
6683
6684 public function removecat()
6685 {
6686 if (!JFactory::getUser()->authorise('core.delete', 'com_vikbooking')) {
6687 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
6688 }
6689
6690 $ids = VikRequest::getVar('cid', array(0));
6691 if ($ids) {
6692 $dbo = JFactory::getDBO();
6693 foreach ($ids as $d) {
6694 $q = "DELETE FROM `#__vikbooking_categories` WHERE `id`=".$dbo->quote($d).";";
6695 $dbo->setQuery($q);
6696 $dbo->execute();
6697 }
6698 }
6699 $mainframe = JFactory::getApplication();
6700 $mainframe->redirect("index.php?option=com_vikbooking&task=categories");
6701 }
6702
6703 public function carat() {
6704 VikBookingHelper::printHeader("5");
6705
6706 VikRequest::setVar('view', VikRequest::getCmd('view', 'carat'));
6707
6708 parent::display();
6709
6710 if (VikBooking::showFooter()) {
6711 VikBookingHelper::printFooter();
6712 }
6713 }
6714
6715 public function newcarat() {
6716 VikBookingHelper::printHeader("5");
6717
6718 VikRequest::setVar('view', VikRequest::getCmd('view', 'managecarat'));
6719
6720 parent::display();
6721
6722 if (VikBooking::showFooter()) {
6723 VikBookingHelper::printFooter();
6724 }
6725 }
6726
6727 public function editcarat() {
6728 VikBookingHelper::printHeader("5");
6729
6730 VikRequest::setVar('view', VikRequest::getCmd('view', 'managecarat'));
6731
6732 parent::display();
6733
6734 if (VikBooking::showFooter()) {
6735 VikBookingHelper::printFooter();
6736 }
6737 }
6738
6739 public function createcarat()
6740 {
6741 if (!JSession::checkToken()) {
6742 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6743 }
6744
6745 if (!JFactory::getUser()->authorise('core.create', 'com_vikbooking')) {
6746 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
6747 }
6748
6749 $pcaratname = VikRequest::getString('caratname', '', 'request');
6750 $pcarattextimg = VikRequest::getString('carattextimg', '', 'request', VIKREQUEST_ALLOWHTML);
6751 $pautoresize = VikRequest::getString('autoresize', '', 'request');
6752 $presizeto = VikRequest::getString('resizeto', '', 'request');
6753 $pidrooms = VikRequest::getVar('idrooms', array());
6754 if (!empty($pcaratname)) {
6755 if (intval($_FILES['caraticon']['error']) == 0 && VikBooking::caniWrite(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR) && trim($_FILES['caraticon']['name'])!="") {
6756 jimport('joomla.filesystem.file');
6757 $updpath = VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR;
6758 if (@is_uploaded_file($_FILES['caraticon']['tmp_name'])) {
6759 $safename=JFile::makeSafe(str_replace(" ", "_", strtolower($_FILES['caraticon']['name'])));
6760 if (file_exists($updpath.$safename)) {
6761 $j=1;
6762 while (file_exists($updpath.$j.$safename)) {
6763 $j++;
6764 }
6765 $pwhere=$updpath.$j.$safename;
6766 } else {
6767 $j="";
6768 $pwhere=$updpath.$safename;
6769 }
6770 if (!getimagesize($_FILES['caraticon']['tmp_name']) || !preg_match("/\.(a?png|jpe?g|bmp|gif|ico|webp)\z/i", $safename)) {
6771 @unlink($pwhere);
6772 $picon="";
6773 } else {
6774 VikBooking::uploadFile($_FILES['caraticon']['tmp_name'], $pwhere);
6775 @chmod($pwhere, 0644);
6776 $picon=$j.$safename;
6777 if ($pautoresize=="1" && !empty($presizeto)) {
6778 $eforj = new vikResizer();
6779 $origmod = $eforj->proportionalImage($pwhere, $updpath.'r_'.$j.$safename, $presizeto, $presizeto);
6780 if ($origmod) {
6781 @unlink($pwhere);
6782 $picon='r_'.$j.$safename;
6783 }
6784 }
6785 }
6786 } else {
6787 $picon="";
6788 }
6789 } else {
6790 $picon="";
6791 }
6792 $dbo = JFactory::getDbo();
6793 // get new ordering
6794 $q = "SELECT `ordering` FROM `#__vikbooking_characteristics` ORDER BY `#__vikbooking_characteristics`.`ordering` DESC LIMIT 1;";
6795 $dbo->setQuery($q);
6796 $dbo->execute();
6797 if ($dbo->getNumRows()) {
6798 $newsortnum = $dbo->loadResult() + 1;
6799 } else {
6800 $newsortnum = 1;
6801 }
6802 $pordering = VikRequest::getInt('ordering', 0, 'request');
6803 $newsortnum = !empty($pordering) ? $pordering : $newsortnum;
6804 //
6805 $q = "INSERT INTO `#__vikbooking_characteristics` (`name`,`icon`,`textimg`,`ordering`) VALUES(".$dbo->quote($pcaratname).", ".$dbo->quote($picon).", ".$dbo->quote($pcarattextimg).", {$newsortnum});";
6806 $dbo->setQuery($q);
6807 $dbo->execute();
6808
6809 $new_carat_id = $dbo->insertid();
6810 if (!empty($new_carat_id)) {
6811 // assign/unset carat-rooms relations
6812 $rooms_with_carat = array();
6813 if (count($pidrooms)) {
6814 // assign this new carat to the requested rooms
6815 foreach ($pidrooms as $idroom) {
6816 if (empty($idroom)) {
6817 continue;
6818 }
6819 $q = "SELECT `id`, `idcarat` FROM `#__vikbooking_rooms` WHERE `id`=" . (int)$idroom . ";";
6820 $dbo->setQuery($q);
6821 $dbo->execute();
6822 if (!$dbo->getNumRows()) {
6823 continue;
6824 }
6825 $room_data = $dbo->loadAssoc();
6826 array_push($rooms_with_carat, $room_data['id']);
6827 $current_carats = empty($room_data['idcarat']) ? array() : explode(';', rtrim($room_data['idcarat'], ';'));
6828 if (in_array((string)$new_carat_id, $current_carats)) {
6829 continue;
6830 }
6831 if (count($current_carats) === 1 && (string)$current_carats[0] == '0') {
6832 // make sure we do not concatenate a real ID to 0
6833 $current_carats = array();
6834 }
6835 array_push($current_carats, $new_carat_id);
6836 $new_opts = implode(';', $current_carats) . ';';
6837 $q = "UPDATE `#__vikbooking_rooms` SET `idcarat`=" . $dbo->quote($new_opts) . " WHERE `id`={$room_data['id']};";
6838 $dbo->setQuery($q);
6839 $dbo->execute();
6840 }
6841 }
6842 if (!count($rooms_with_carat)) {
6843 // get all rooms to unset this carat (if previously set)
6844 array_push($rooms_with_carat, '0');
6845 }
6846 // unset the carat from the other rooms that may have it
6847 $q = "SELECT `id`, `idcarat` FROM `#__vikbooking_rooms` WHERE `id` NOT IN (" . implode(', ', $rooms_with_carat) . ");";
6848 $dbo->setQuery($q);
6849 $dbo->execute();
6850 if ($dbo->getNumRows()) {
6851 $unset_rooms_carat = $dbo->loadAssocList();
6852 foreach ($unset_rooms_carat as $room_data) {
6853 $current_carats = empty($room_data['idcarat']) ? array() : explode(';', rtrim($room_data['idcarat'], ';'));
6854 if (!in_array((string)$new_carat_id, $current_carats)) {
6855 // this room is not using this carat
6856 continue;
6857 }
6858 $caratkey = array_search((string)$new_carat_id, $current_carats);
6859 if ($caratkey === false) {
6860 // key not found
6861 continue;
6862 }
6863 // unset this carat ID from the string
6864 unset($current_carats[$caratkey]);
6865 if (!count($current_carats)) {
6866 // a room with no carats assigned will be listed as "0;"
6867 $current_carats = array(0);
6868 }
6869 $new_opts = implode(';', $current_carats) . ';';
6870 $q = "UPDATE `#__vikbooking_rooms` SET `idcarat`=" . $dbo->quote($new_opts) . " WHERE `id`={$room_data['id']};";
6871 $dbo->setQuery($q);
6872 $dbo->execute();
6873 }
6874 }
6875 //
6876 }
6877 }
6878 $mainframe = JFactory::getApplication();
6879 $mainframe->redirect("index.php?option=com_vikbooking&task=carat");
6880 }
6881
6882 public function updatecarat()
6883 {
6884 if (!JSession::checkToken()) {
6885 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6886 }
6887
6888 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
6889 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
6890 }
6891
6892 $pcaratname = VikRequest::getString('caratname', '', 'request');
6893 $pcarattextimg = VikRequest::getString('carattextimg', '', 'request', VIKREQUEST_ALLOWHTML);
6894 $pwhereup = VikRequest::getString('whereup', '', 'request');
6895 $pautoresize = VikRequest::getString('autoresize', '', 'request');
6896 $presizeto = VikRequest::getString('resizeto', '', 'request');
6897 $pidrooms = VikRequest::getVar('idrooms', array());
6898 $pordering = VikRequest::getInt('ordering', 1, 'request');
6899 if (!empty($pcaratname)) {
6900 if (intval($_FILES['caraticon']['error']) == 0 && VikBooking::caniWrite(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR) && trim($_FILES['caraticon']['name'])!="") {
6901 jimport('joomla.filesystem.file');
6902 $updpath = VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR;
6903 if (@is_uploaded_file($_FILES['caraticon']['tmp_name'])) {
6904 $safename=JFile::makeSafe(str_replace(" ", "_", strtolower($_FILES['caraticon']['name'])));
6905 if (file_exists($updpath.$safename)) {
6906 $j=1;
6907 while (file_exists($updpath.$j.$safename)) {
6908 $j++;
6909 }
6910 $pwhere=$updpath.$j.$safename;
6911 } else {
6912 $j="";
6913 $pwhere=$updpath.$safename;
6914 }
6915 if (!getimagesize($_FILES['caraticon']['tmp_name']) || !preg_match("/\.(a?png|jpe?g|bmp|gif|ico|webp)\z/i", $safename)) {
6916 @unlink($pwhere);
6917 $picon="";
6918 } else {
6919 VikBooking::uploadFile($_FILES['caraticon']['tmp_name'], $pwhere);
6920 @chmod($pwhere, 0644);
6921 $picon=$j.$safename;
6922 if ($pautoresize=="1" && !empty($presizeto)) {
6923 $eforj = new vikResizer();
6924 $origmod = $eforj->proportionalImage($pwhere, $updpath.'r_'.$j.$safename, $presizeto, $presizeto);
6925 if ($origmod) {
6926 @unlink($pwhere);
6927 $picon='r_'.$j.$safename;
6928 }
6929 }
6930 }
6931 } else {
6932 $picon="";
6933 }
6934 } else {
6935 $picon="";
6936 }
6937 $dbo = JFactory::getDbo();
6938 $q = "UPDATE `#__vikbooking_characteristics` SET `name`=".$dbo->quote($pcaratname).",".(strlen($picon) > 0 ? "`icon`='".$picon."'," : "")."`textimg`=".$dbo->quote($pcarattextimg).",`ordering`={$pordering} WHERE `id`=".$dbo->quote($pwhereup).";";
6939 $dbo->setQuery($q);
6940 $dbo->execute();
6941
6942 // assign/unset carat-rooms relations
6943 $rooms_with_carat = array();
6944 if (count($pidrooms)) {
6945 // assign this new carat to the requested rooms
6946 foreach ($pidrooms as $idroom) {
6947 if (empty($idroom)) {
6948 continue;
6949 }
6950 $q = "SELECT `id`, `idcarat` FROM `#__vikbooking_rooms` WHERE `id`=" . (int)$idroom . ";";
6951 $dbo->setQuery($q);
6952 $dbo->execute();
6953 if (!$dbo->getNumRows()) {
6954 continue;
6955 }
6956 $room_data = $dbo->loadAssoc();
6957 array_push($rooms_with_carat, $room_data['id']);
6958 $current_carats = empty($room_data['idcarat']) ? array() : explode(';', rtrim($room_data['idcarat'], ';'));
6959 if (in_array((string)$pwhereup, $current_carats)) {
6960 continue;
6961 }
6962 if (count($current_carats) === 1 && (string)$current_carats[0] == '0') {
6963 // make sure we do not concatenate a real ID to 0
6964 $current_carats = array();
6965 }
6966 array_push($current_carats, $pwhereup);
6967 $new_carats = implode(';', $current_carats) . ';';
6968 $q = "UPDATE `#__vikbooking_rooms` SET `idcarat`=" . $dbo->quote($new_carats) . " WHERE `id`={$room_data['id']};";
6969 $dbo->setQuery($q);
6970 $dbo->execute();
6971 }
6972 }
6973 if (!count($rooms_with_carat)) {
6974 // get all rooms to unset this carat (if previously set)
6975 array_push($rooms_with_carat, '0');
6976 }
6977 // unset the carat from the other rooms that may have it
6978 $q = "SELECT `id`, `idcarat` FROM `#__vikbooking_rooms` WHERE `id` NOT IN (" . implode(', ', $rooms_with_carat) . ");";
6979 $dbo->setQuery($q);
6980 $dbo->execute();
6981 if ($dbo->getNumRows()) {
6982 $unset_rooms_carat = $dbo->loadAssocList();
6983 foreach ($unset_rooms_carat as $room_data) {
6984 $current_carats = empty($room_data['idcarat']) ? array() : explode(';', rtrim($room_data['idcarat'], ';'));
6985 if (!in_array((string)$pwhereup, $current_carats)) {
6986 // this room is not using this carat
6987 continue;
6988 }
6989 $caratkey = array_search((string)$pwhereup, $current_carats);
6990 if ($caratkey === false) {
6991 // key not found
6992 continue;
6993 }
6994 // unset this carat ID from the string
6995 unset($current_carats[$caratkey]);
6996 if (!count($current_carats)) {
6997 // a room with no carats assigned will be listed as "0;"
6998 $current_carats = array(0);
6999 }
7000 $new_carats = implode(';', $current_carats) . ';';
7001 $q = "UPDATE `#__vikbooking_rooms` SET `idcarat`=" . $dbo->quote($new_carats) . " WHERE `id`={$room_data['id']};";
7002 $dbo->setQuery($q);
7003 $dbo->execute();
7004 }
7005 }
7006 //
7007 }
7008 $mainframe = JFactory::getApplication();
7009 $mainframe->redirect("index.php?option=com_vikbooking&task=carat");
7010 }
7011
7012 public function removecarat()
7013 {
7014 if (!JSession::checkToken()) {
7015 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
7016 }
7017
7018 if (!JFactory::getUser()->authorise('core.delete', 'com_vikbooking')) {
7019 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
7020 }
7021
7022 $ids = VikRequest::getVar('cid', array(0));
7023 if ($ids) {
7024 $dbo = JFactory::getDBO();
7025 foreach ($ids as $d) {
7026 $q = "SELECT `icon` FROM `#__vikbooking_characteristics` WHERE `id`=".$dbo->quote($d).";";
7027 $dbo->setQuery($q);
7028 $dbo->execute();
7029 if ($dbo->getNumRows() == 1) {
7030 $rows = $dbo->loadAssocList();
7031 if (!empty($rows[0]['icon']) && file_exists(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR.$rows[0]['icon'])) {
7032 @unlink(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR.$rows[0]['icon']);
7033 }
7034 }
7035 $q = "DELETE FROM `#__vikbooking_characteristics` WHERE `id`=".$dbo->quote($d).";";
7036 $dbo->setQuery($q);
7037 $dbo->execute();
7038 }
7039 }
7040 $mainframe = JFactory::getApplication();
7041 $mainframe->redirect("index.php?option=com_vikbooking&task=carat");
7042 }
7043
7044 public function coupons() {
7045 VikBookingHelper::printHeader("17");
7046
7047 VikRequest::setVar('view', VikRequest::getCmd('view', 'coupons'));
7048
7049 parent::display();
7050
7051 if (VikBooking::showFooter()) {
7052 VikBookingHelper::printFooter();
7053 }
7054 }
7055
7056 public function newcoupon() {
7057 VikBookingHelper::printHeader("17");
7058
7059 VikRequest::setVar('view', VikRequest::getCmd('view', 'managecoupon'));
7060
7061 parent::display();
7062
7063 if (VikBooking::showFooter()) {
7064 VikBookingHelper::printFooter();
7065 }
7066 }
7067
7068 public function editcoupon() {
7069 VikBookingHelper::printHeader("17");
7070
7071 VikRequest::setVar('view', VikRequest::getCmd('view', 'managecoupon'));
7072
7073 parent::display();
7074
7075 if (VikBooking::showFooter()) {
7076 VikBookingHelper::printFooter();
7077 }
7078 }
7079
7080 public function createcoupon()
7081 {
7082 if (!JSession::checkToken()) {
7083 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
7084 }
7085
7086 if (!JFactory::getUser()->authorise('core.create', 'com_vikbooking')) {
7087 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
7088 }
7089
7090 $pcode = VikRequest::getString('code', '', 'request');
7091 $pvalue = VikRequest::getString('value', '', 'request');
7092 $pfrom = VikRequest::getString('from', '', 'request');
7093 $pto = VikRequest::getString('to', '', 'request');
7094 $pidrooms = VikRequest::getVar('idrooms', array(0));
7095 $ptype = VikRequest::getString('type', '', 'request');
7096 $ptype = $ptype == "1" ? 1 : 2;
7097 $ppercentot = VikRequest::getString('percentot', '', 'request');
7098 $ppercentot = $ppercentot == "1" ? 1 : 2;
7099 $pallvehicles = VikRequest::getString('allvehicles', '', 'request');
7100 $pallvehicles = $pallvehicles == "1" ? 1 : 0;
7101 $pmintotord = VikRequest::getFloat('mintotord', 0, 'request');
7102 $pmaxtotord = VikRequest::getFloat('maxtotord', 0, 'request');
7103 $pexcludetaxes = VikRequest::getInt('excludetaxes', 0, 'request');
7104 $pminlos = VikRequest::getInt('minlos', 0, 'request');
7105 $pcustomers = VikRequest::getVar('customers', array());
7106 $pautomatic = VikRequest::getInt('automatic', 0, 'request');
7107 $stridrooms = "";
7108 if (count($pidrooms) > 0 && $pallvehicles != 1) {
7109 foreach ($pidrooms as $ch) {
7110 if (!empty($ch)) {
7111 $stridrooms .= ";".$ch.";";
7112 }
7113 }
7114 }
7115 $strdatevalid = "";
7116 if (strlen($pfrom) > 0 && strlen($pto) > 0) {
7117 $first = VikBooking::getDateTimestamp($pfrom, 0, 0);
7118 $second = VikBooking::getDateTimestamp($pto, 0, 0);
7119 if ($first < $second) {
7120 $strdatevalid .= $first."-".$second;
7121 }
7122 }
7123
7124 $dbo = JFactory::getDbo();
7125 $app = JFactory::getApplication();
7126
7127 $q = "SELECT * FROM `#__vikbooking_coupons` WHERE `code`=".$dbo->quote($pcode).";";
7128 $dbo->setQuery($q);
7129 $dbo->execute();
7130 if ($dbo->getNumRows() > 0) {
7131 VikError::raiseWarning('', JText::translate('VBCOUPONEXISTS'));
7132 } else {
7133 $q = "INSERT INTO `#__vikbooking_coupons` (`code`,`type`,`percentot`,`value`,`datevalid`,`allvehicles`,`idrooms`,`mintotord`,`excludetaxes`,`minlos`,`maxtotord`) VALUES(".$dbo->quote($pcode).",'".$ptype."','".$ppercentot."',".$dbo->quote($pvalue).",'".$strdatevalid."','".$pallvehicles."','".$stridrooms."', ".$dbo->quote($pmintotord).", {$pexcludetaxes}, {$pminlos}, " . $dbo->quote($pmaxtotord) . ");";
7134 $dbo->setQuery($q);
7135 $dbo->execute();
7136
7137 $id_coupon = $dbo->insertid();
7138
7139 $app->enqueueMessage(JText::translate('VBCOUPONSAVEOK'));
7140
7141 // check if this coupon should be assigned to specific customers
7142 foreach ($pcustomers as $id_customer) {
7143 $customer_coupon = new stdClass;
7144 $customer_coupon->idcustomer = (int)$id_customer;
7145 $customer_coupon->idcoupon = (int)$id_coupon;
7146 $customer_coupon->automatic = $pautomatic ? 1 : 0;
7147
7148 $dbo->insertObject('#__vikbooking_customers_coupons', $customer_coupon, 'id');
7149 }
7150 }
7151 $app->redirect("index.php?option=com_vikbooking&task=coupons");
7152 }
7153
7154 public function updatecoupon()
7155 {
7156 if (!JSession::checkToken()) {
7157 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
7158 }
7159
7160 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
7161 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
7162 }
7163
7164 $this->do_updatecoupon($stay = false);
7165 }
7166
7167 public function updatecoupon_stay()
7168 {
7169 if (!JSession::checkToken()) {
7170 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
7171 }
7172
7173 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
7174 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
7175 }
7176
7177 $this->do_updatecoupon($stay = true);
7178 }
7179
7180 protected function do_updatecoupon($stay = false)
7181 {
7182 if (!JSession::checkToken()) {
7183 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
7184 }
7185 $pcode = VikRequest::getString('code', '', 'request');
7186 $pvalue = VikRequest::getString('value', '', 'request');
7187 $pfrom = VikRequest::getString('from', '', 'request');
7188 $pto = VikRequest::getString('to', '', 'request');
7189 $pidrooms = VikRequest::getVar('idrooms', array(0));
7190 $pwhere = VikRequest::getInt('where', 0, 'request');
7191 $ptype = VikRequest::getString('type', '', 'request');
7192 $ptype = $ptype == "1" ? 1 : 2;
7193 $ppercentot = VikRequest::getString('percentot', '', 'request');
7194 $ppercentot = $ppercentot == "1" ? 1 : 2;
7195 $pallvehicles = VikRequest::getString('allvehicles', '', 'request');
7196 $pallvehicles = $pallvehicles == "1" ? 1 : 0;
7197 $pmintotord = VikRequest::getFloat('mintotord', 0, 'request');
7198 $pmaxtotord = VikRequest::getFloat('maxtotord', 0, 'request');
7199 $pexcludetaxes = VikRequest::getInt('excludetaxes', 0, 'request');
7200 $pminlos = VikRequest::getInt('minlos', 0, 'request');
7201 $pcustomers = VikRequest::getVar('customers', array());
7202 $pautomatic = VikRequest::getInt('automatic', 0, 'request');
7203 $stridrooms = "";
7204 if (count($pidrooms) > 0 && $pallvehicles != 1) {
7205 foreach ($pidrooms as $ch) {
7206 if (!empty($ch)) {
7207 $stridrooms .= ";".$ch.";";
7208 }
7209 }
7210 }
7211 $strdatevalid = "";
7212 if (strlen($pfrom) > 0 && strlen($pto) > 0) {
7213 $first = VikBooking::getDateTimestamp($pfrom, 0, 0);
7214 $second = VikBooking::getDateTimestamp($pto, 0, 0);
7215 if ($first < $second) {
7216 $strdatevalid .= $first."-".$second;
7217 }
7218 }
7219
7220 $dbo = JFactory::getDbo();
7221 $app = JFactory::getApplication();
7222
7223 $q = "SELECT * FROM `#__vikbooking_coupons` WHERE `code`=".$dbo->quote($pcode)." AND `id`!='".$pwhere."';";
7224 $dbo->setQuery($q);
7225 $dbo->execute();
7226 if ($dbo->getNumRows() > 0) {
7227 VikError::raiseWarning('', JText::translate('VBCOUPONEXISTS'));
7228 } else {
7229 $q = "UPDATE `#__vikbooking_coupons` SET `code`=".$dbo->quote($pcode).",`type`='".$ptype."',`percentot`='".$ppercentot."',`value`=".$dbo->quote($pvalue).",`datevalid`='".$strdatevalid."',`allvehicles`='".$pallvehicles."',`idrooms`='".$stridrooms."',`mintotord`=".$dbo->quote($pmintotord).",`excludetaxes`={$pexcludetaxes},`minlos`={$pminlos},`maxtotord`= " . $dbo->quote($pmaxtotord) . " WHERE `id`=" . $pwhere . ";";
7230 $dbo->setQuery($q);
7231 $dbo->execute();
7232
7233 $app->enqueueMessage(JText::translate('VBCOUPONSAVEOK'));
7234
7235 // clean up any previously created record with customers
7236 $q = "DELETE FROM `#__vikbooking_customers_coupons` WHERE `idcoupon`=" . $pwhere;
7237 $dbo->setQuery($q);
7238 $dbo->execute();
7239
7240 // check if this coupon should be assigned to specific customers
7241 foreach ($pcustomers as $id_customer) {
7242 $customer_coupon = new stdClass;
7243 $customer_coupon->idcustomer = (int)$id_customer;
7244 $customer_coupon->idcoupon = (int)$pwhere;
7245 $customer_coupon->automatic = $pautomatic ? 1 : 0;
7246
7247 $dbo->insertObject('#__vikbooking_customers_coupons', $customer_coupon, 'id');
7248 }
7249 }
7250
7251 if ($stay) {
7252 $app->redirect("index.php?option=com_vikbooking&task=editcoupon&cid[]=$pwhere");
7253 } else {
7254 $app->redirect("index.php?option=com_vikbooking&task=coupons");
7255 }
7256 }
7257
7258 public function removecoupons()
7259 {
7260 if (!JSession::checkToken()) {
7261 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
7262 }
7263
7264 if (!JFactory::getUser()->authorise('core.delete', 'com_vikbooking')) {
7265 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
7266 }
7267
7268 $dbo = JFactory::getDbo();
7269
7270 $ids = VikRequest::getVar('cid', array(0));
7271
7272 if ($ids) {
7273 foreach ($ids as $d) {
7274 // delete coupon record
7275 $q = "DELETE FROM `#__vikbooking_coupons` WHERE `id`=".$dbo->quote($d).";";
7276 $dbo->setQuery($q);
7277 $dbo->execute();
7278
7279 // clean up any previously created record with customers
7280 $q = "DELETE FROM `#__vikbooking_customers_coupons` WHERE `idcoupon`=" . (int)$d;
7281 $dbo->setQuery($q);
7282 $dbo->execute();
7283 }
7284 }
7285
7286 JFactory::getApplication()->redirect("index.php?option=com_vikbooking&task=coupons");
7287 }
7288
7289 public function removemoreimgs()
7290 {
7291 if (!JFactory::getUser()->authorise('core.delete', 'com_vikbooking')) {
7292 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
7293 }
7294
7295 $mainframe = JFactory::getApplication();
7296 $proomid = VikRequest::getInt('roomid', '', 'request');
7297 $pimgind = VikRequest::getInt('imgind', '', 'request');
7298 if (!strlen($pimgind)) {
7299 $mainframe->redirect("index.php?option=com_vikbooking");
7300 exit;
7301 }
7302 $dbo = JFactory::getDBO();
7303 $q = "SELECT `moreimgs`,`imgcaptions` FROM `#__vikbooking_rooms` WHERE `id`='".$proomid."';";
7304 $dbo->setQuery($q);
7305 $dbo->execute();
7306 $row = $dbo->loadAssoc();
7307 $actmore = $row['moreimgs'];
7308 if (!empty($actmore)) {
7309 $actsplit = explode(';;', $actmore);
7310 $captions = json_decode($row['imgcaptions'], true);
7311 $captions = !is_array($captions) ? array() : $captions;
7312 if ($pimgind < 0) {
7313 foreach ($actsplit as $img) {
7314 @unlink(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR.'big_'.$img);
7315 @unlink(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR.'thumb_'.$img);
7316 }
7317 // reset images and captions
7318 $actsplit = array();
7319 $captions = array();
7320 } else {
7321 if (array_key_exists($pimgind, $actsplit)) {
7322 @unlink(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR.'big_'.$actsplit[$pimgind]);
7323 @unlink(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR.'thumb_'.$actsplit[$pimgind]);
7324 // unset current image
7325 unset($actsplit[$pimgind]);
7326 // unset caption if exists
7327 if (isset($captions[$pimgind])) {
7328 unset($captions[$pimgind]);
7329 $captions = array_values($captions);
7330 }
7331 }
7332 }
7333 $newstr = "";
7334 foreach ($actsplit as $oi) {
7335 if (!empty($oi)) {
7336 $newstr .= $oi.';;';
7337 }
7338 }
7339 $q = "UPDATE `#__vikbooking_rooms` SET `moreimgs`=".$dbo->quote($newstr).", `imgcaptions`=".$dbo->quote(json_encode($captions))." WHERE `id`='".$proomid."';";
7340 $dbo->setQuery($q);
7341 $dbo->execute();
7342 }
7343 $mainframe->redirect("index.php?option=com_vikbooking&task=editroom&cid[]=".$proomid);
7344 }
7345
7346 public function sortfield() {
7347 if (!JSession::checkToken('get')) {
7348 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
7349 }
7350 $mainframe = JFactory::getApplication();
7351 $sortid = VikRequest::getVar('cid', array(0));
7352 $pmode = VikRequest::getString('mode', '', 'request');
7353 $dbo = JFactory::getDBO();
7354 if (!empty($pmode)) {
7355 $q = "SELECT `id`,`ordering` FROM `#__vikbooking_custfields` ORDER BY `#__vikbooking_custfields`.`ordering` ASC;";
7356 $dbo->setQuery($q);
7357 $dbo->execute();
7358 $totr=$dbo->getNumRows();
7359 if ($totr > 1) {
7360 $data = $dbo->loadAssocList();
7361 if ($pmode == "up") {
7362 foreach ($data as $v) {
7363 if ($v['id'] == $sortid[0]) {
7364 $y = $v['ordering'];
7365 }
7366 }
7367 if ($y && $y > 1) {
7368 $vik = $y - 1;
7369 $found = false;
7370 foreach ($data as $v) {
7371 if (intval($v['ordering']) == intval($vik)) {
7372 $found=true;
7373 $q = "UPDATE `#__vikbooking_custfields` SET `ordering`='".$y."' WHERE `id`='".$v['id']."' LIMIT 1;";
7374 $dbo->setQuery($q);
7375 $dbo->execute();
7376 $q = "UPDATE `#__vikbooking_custfields` SET `ordering`='".$vik."' WHERE `id`='".$sortid[0]."' LIMIT 1;";
7377 $dbo->setQuery($q);
7378 $dbo->execute();
7379 break;
7380 }
7381 }
7382 if (!$found) {
7383 $q = "UPDATE `#__vikbooking_custfields` SET `ordering`='".$vik."' WHERE `id`='".$sortid[0]."' LIMIT 1;";
7384 $dbo->setQuery($q);
7385 $dbo->execute();
7386 }
7387 }
7388 } elseif ($pmode == "down") {
7389 foreach ($data as $v) {
7390 if ($v['id'] == $sortid[0]) {
7391 $y = $v['ordering'];
7392 }
7393 }
7394 if ($y) {
7395 $vik = $y + 1;
7396 $found = false;
7397 foreach ($data as $v) {
7398 if (intval($v['ordering']) == intval($vik)) {
7399 $found=true;
7400 $q = "UPDATE `#__vikbooking_custfields` SET `ordering`='".$y."' WHERE `id`='".$v['id']."' LIMIT 1;";
7401 $dbo->setQuery($q);
7402 $dbo->execute();
7403 $q = "UPDATE `#__vikbooking_custfields` SET `ordering`='".$vik."' WHERE `id`='".$sortid[0]."' LIMIT 1;";
7404 $dbo->setQuery($q);
7405 $dbo->execute();
7406 break;
7407 }
7408 }
7409 if (!$found) {
7410 $q = "UPDATE `#__vikbooking_custfields` SET `ordering`='".$vik."' WHERE `id`='".$sortid[0]."' LIMIT 1;";
7411 $dbo->setQuery($q);
7412 $dbo->execute();
7413 }
7414 }
7415 }
7416 }
7417 $mainframe->redirect("index.php?option=com_vikbooking&task=customf");
7418 } else {
7419 $mainframe->redirect("index.php?option=com_vikbooking");
7420 }
7421 }
7422
7423 public function customf() {
7424 VikBookingHelper::printHeader("16");
7425
7426 VikRequest::setVar('view', VikRequest::getCmd('view', 'customf'));
7427
7428 parent::display();
7429
7430 if (VikBooking::showFooter()) {
7431 VikBookingHelper::printFooter();
7432 }
7433 }
7434
7435 public function newcustomf() {
7436 VikBookingHelper::printHeader("16");
7437
7438 VikRequest::setVar('view', VikRequest::getCmd('view', 'managecustomf'));
7439
7440 parent::display();
7441
7442 if (VikBooking::showFooter()) {
7443 VikBookingHelper::printFooter();
7444 }
7445 }
7446
7447 public function editcustomf() {
7448 VikBookingHelper::printHeader("16");
7449
7450 VikRequest::setVar('view', VikRequest::getCmd('view', 'managecustomf'));
7451
7452 parent::display();
7453
7454 if (VikBooking::showFooter()) {
7455 VikBookingHelper::printFooter();
7456 }
7457 }
7458
7459 public function createcustomf()
7460 {
7461 if (!JSession::checkToken()) {
7462 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
7463 }
7464
7465 if (!JFactory::getUser()->authorise('core.create', 'com_vikbooking')) {
7466 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
7467 }
7468
7469 $pname = VikRequest::getString('name', '', 'request', VIKREQUEST_ALLOWHTML);
7470 $ptype = VikRequest::getString('type', '', 'request');
7471 $pchoose = VikRequest::getVar('choose', array(0));
7472 $prequired = VikRequest::getString('required', '', 'request');
7473 $prequired = $prequired == "1" ? 1 : 0;
7474 $pflag = VikRequest::getString('flag', '', 'request');
7475 $pisemail = $pflag == 'isemail' ? 1 : 0;
7476 $pisnominative = $pflag == 'isnominative' && $ptype == 'text' ? 1 : 0;
7477 $pisphone = $pflag == 'isphone' && $ptype == 'text' ? 1 : 0;
7478 $pisaddress = $pflag == 'isaddress' && $ptype == 'text' ? 1 : 0;
7479 $piscity = $pflag == 'iscity' && $ptype == 'text' ? 1 : 0;
7480 $piszip = $pflag == 'iszip' && $ptype == 'text' ? 1 : 0;
7481 $piscompany = $pflag == 'iscompany' && $ptype == 'text' ? 1 : 0;
7482 $pisvat = $pflag == 'isvat' && $ptype == 'text' ? 1 : 0;
7483 $pisfisccode = $pflag == 'isfisccode' && $ptype == 'text' ? 1 : 0;
7484 $pispec = $pflag == 'ispec' && $ptype == 'text' ? 1 : 0;
7485 $pisrecipcode = $pflag == 'isrecipcode' && $ptype == 'text' ? 1 : 0;
7486 $fieldflag = '';
7487 if ($pisaddress == 1) {
7488 $fieldflag = 'address';
7489 } elseif ($piscity == 1) {
7490 $fieldflag = 'city';
7491 } elseif ($piszip == 1) {
7492 $fieldflag = 'zip';
7493 } elseif ($piscompany == 1) {
7494 $fieldflag = 'company';
7495 } elseif ($pisvat == 1) {
7496 $fieldflag = 'vat';
7497 } elseif ($pisfisccode == 1) {
7498 $fieldflag = 'fisccode';
7499 } elseif ($pispec == 1) {
7500 $fieldflag = 'pec';
7501 } elseif ($pisrecipcode == 1) {
7502 $fieldflag = 'recipcode';
7503 }
7504 $ppoplink = VikRequest::getString('poplink', '', 'request');
7505 $choosestr = "";
7506 if (is_array($pchoose)) {
7507 foreach ($pchoose as $ch) {
7508 if (!empty($ch)) {
7509 $choosestr .= $ch.";;__;;";
7510 }
7511 }
7512 }
7513 $defvalue = VikRequest::getString('defvalue', '', 'request');
7514
7515 $dbo = JFactory::getDbo();
7516
7517 $q = "SELECT `ordering` FROM `#__vikbooking_custfields` ORDER BY `#__vikbooking_custfields`.`ordering` DESC LIMIT 1;";
7518 $dbo->setQuery($q);
7519 $dbo->execute();
7520 if ($dbo->getNumRows() == 1) {
7521 $getlast = $dbo->loadResult();
7522 $newsortnum = $getlast + 1;
7523 } else {
7524 $newsortnum = 1;
7525 }
7526 $q = "INSERT INTO `#__vikbooking_custfields` (`name`,`type`,`choose`,`required`,`ordering`,`isemail`,`poplink`,`isnominative`,`isphone`,`flag`,`defvalue`) VALUES(".$dbo->quote($pname).", ".$dbo->quote($ptype).", ".$dbo->quote($choosestr).", ".$dbo->quote($prequired).", ".$dbo->quote($newsortnum).", ".$dbo->quote($pisemail).", ".$dbo->quote($ppoplink).", ".$pisnominative.", ".$pisphone.", ".$dbo->quote($fieldflag).", ".$dbo->quote($defvalue).");";
7527 $dbo->setQuery($q);
7528 $dbo->execute();
7529 $mainframe = JFactory::getApplication();
7530 $mainframe->redirect("index.php?option=com_vikbooking&task=customf");
7531 }
7532
7533 public function updatecustomf()
7534 {
7535 if (!JSession::checkToken()) {
7536 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
7537 }
7538
7539 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
7540 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
7541 }
7542
7543 $pname = VikRequest::getString('name', '', 'request', VIKREQUEST_ALLOWHTML);
7544 $ptype = VikRequest::getString('type', '', 'request');
7545 $pchoose = VikRequest::getVar('choose', array(0));
7546 $prequired = VikRequest::getString('required', '', 'request');
7547 $prequired = $prequired == "1" ? 1 : 0;
7548 $pflag = VikRequest::getString('flag', '', 'request');
7549 $pisemail = $pflag == 'isemail' ? 1 : 0;
7550 $pisnominative = $pflag == 'isnominative' && $ptype == 'text' ? 1 : 0;
7551 $pisphone = $pflag == 'isphone' && $ptype == 'text' ? 1 : 0;
7552 $pisaddress = $pflag == 'isaddress' && $ptype == 'text' ? 1 : 0;
7553 $piscity = $pflag == 'iscity' && $ptype == 'text' ? 1 : 0;
7554 $piszip = $pflag == 'iszip' && $ptype == 'text' ? 1 : 0;
7555 $piscompany = $pflag == 'iscompany' && $ptype == 'text' ? 1 : 0;
7556 $pisvat = $pflag == 'isvat' && $ptype == 'text' ? 1 : 0;
7557 $pisfisccode = $pflag == 'isfisccode' && $ptype == 'text' ? 1 : 0;
7558 $pispec = $pflag == 'ispec' && $ptype == 'text' ? 1 : 0;
7559 $pisrecipcode = $pflag == 'isrecipcode' && $ptype == 'text' ? 1 : 0;
7560 $fieldflag = '';
7561 if ($pisaddress == 1) {
7562 $fieldflag = 'address';
7563 } elseif ($piscity == 1) {
7564 $fieldflag = 'city';
7565 } elseif ($piszip == 1) {
7566 $fieldflag = 'zip';
7567 } elseif ($piscompany == 1) {
7568 $fieldflag = 'company';
7569 } elseif ($pisvat == 1) {
7570 $fieldflag = 'vat';
7571 } elseif ($pisfisccode == 1) {
7572 $fieldflag = 'fisccode';
7573 } elseif ($pispec == 1) {
7574 $fieldflag = 'pec';
7575 } elseif ($pisrecipcode == 1) {
7576 $fieldflag = 'recipcode';
7577 }
7578 $ppoplink = VikRequest::getString('poplink', '', 'request');
7579 $pwhere = VikRequest::getInt('where', '', 'request');
7580 $choosestr = "";
7581 if (is_array($pchoose)) {
7582 foreach ($pchoose as $ch) {
7583 if (!empty($ch)) {
7584 $choosestr .= $ch.";;__;;";
7585 }
7586 }
7587 }
7588 $defvalue = VikRequest::getString('defvalue', '', 'request');
7589
7590 $dbo = JFactory::getDbo();
7591
7592 $q = "UPDATE `#__vikbooking_custfields` SET `name`=".$dbo->quote($pname).",`type`=".$dbo->quote($ptype).",`choose`=".$dbo->quote($choosestr).",`required`=".$dbo->quote($prequired).",`isemail`=".$dbo->quote($pisemail).",`poplink`=".$dbo->quote($ppoplink).",`isnominative`=".$pisnominative.",`isphone`=".$pisphone.",`flag`=".$dbo->quote($fieldflag).",`defvalue`=".$dbo->quote($defvalue)." WHERE `id`=".$dbo->quote($pwhere).";";
7593 $dbo->setQuery($q);
7594 $dbo->execute();
7595 $mainframe = JFactory::getApplication();
7596 $mainframe->redirect("index.php?option=com_vikbooking&task=customf");
7597 }
7598
7599 public function removecustomf()
7600 {
7601 if (!JSession::checkToken()) {
7602 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
7603 }
7604
7605 if (!JFactory::getUser()->authorise('core.delete', 'com_vikbooking')) {
7606 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
7607 }
7608
7609 $ids = VikRequest::getVar('cid', array(0));
7610 if ($ids) {
7611 $dbo = JFactory::getDBO();
7612 foreach ($ids as $d) {
7613 $q = "DELETE FROM `#__vikbooking_custfields` WHERE `id`=".$dbo->quote($d).";";
7614 $dbo->setQuery($q);
7615 $dbo->execute();
7616 }
7617 }
7618 $mainframe = JFactory::getApplication();
7619 $mainframe->redirect("index.php?option=com_vikbooking&task=customf");
7620 }
7621
7622 public function overv() {
7623 VikBookingHelper::printHeader("15");
7624
7625 VikRequest::setVar('view', VikRequest::getCmd('view', 'overv'));
7626
7627 parent::display();
7628
7629 if (VikBooking::showFooter()) {
7630 VikBookingHelper::printFooter();
7631 }
7632 }
7633
7634 public function translations() {
7635 VikBookingHelper::printHeader("21");
7636
7637 VikRequest::setVar('view', VikRequest::getCmd('view', 'translations'));
7638
7639 parent::display();
7640
7641 if (VikBooking::showFooter()) {
7642 VikBookingHelper::printFooter();
7643 }
7644 }
7645
7646 public function savetranslation() {
7647 if (!JSession::checkToken()) {
7648 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
7649 }
7650 $this->do_savetranslation();
7651 }
7652
7653 public function savetranslationstay() {
7654 if (!JSession::checkToken()) {
7655 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
7656 }
7657 $this->do_savetranslation(true);
7658 }
7659
7660 private function do_savetranslation($stay = false) {
7661 $dbo = JFactory::getDBO();
7662 $mainframe = JFactory::getApplication();
7663 $vbo_tn = VikBooking::getTranslator();
7664 $table = VikRequest::getString('vbo_table', '', 'request');
7665 $cur_langtab = VikRequest::getString('vbo_lang', '', 'request');
7666 $langs = $vbo_tn->getLanguagesList();
7667 $xml_tables = $vbo_tn->getTranslationTables();
7668 if (!empty($table) && array_key_exists($table, $xml_tables)) {
7669 $tn = VikRequest::getVar('tn', array(), 'request', 'array', VIKREQUEST_ALLOWRAW);
7670 $tn_saved = 0;
7671 $table_cols = $vbo_tn->getTableColumns($table);
7672 foreach ($langs as $ltag => $lang) {
7673 if ($ltag == $vbo_tn->default_lang) {
7674 continue;
7675 }
7676 if (array_key_exists($ltag, $tn) && count($tn[$ltag]) > 0) {
7677 foreach ($tn[$ltag] as $reference_id => $translation) {
7678 $lang_translation = array();
7679 foreach ($table_cols as $field => $fdetails) {
7680 if (!array_key_exists($field, $translation)) {
7681 continue;
7682 }
7683 $ftype = $fdetails['type'];
7684 if ($ftype == 'skip') {
7685 continue;
7686 }
7687
7688 if (is_array($translation[$field])) {
7689 foreach ($translation[$field] as $tn_field_k => $tn_field_v) {
7690 if (!is_string($tn_field_v)) {
7691 continue;
7692 }
7693 // replace any possible placeholder for special tags
7694 $translation[$field][$tn_field_k] = preg_replace_callback("/(<strong class=\"vbo-editor-hl-specialtag\">)([^<]+)(<\/strong>)/", function($match) {
7695 return $match[2];
7696 }, $translation[$field][$tn_field_k]);
7697 }
7698 } elseif (!empty($translation[$field])) {
7699 // replace any possible placeholder for special tags
7700 $translation[$field] = preg_replace_callback("/(<strong class=\"vbo-editor-hl-specialtag\">)([^<]+)(<\/strong>)/", function($match) {
7701 return $match[2];
7702 }, $translation[$field]);
7703 }
7704
7705 if ($ftype == 'json' && !is_scalar($translation[$field])) {
7706 $translation[$field] = json_encode($translation[$field]);
7707 }
7708 $lang_translation[$field] = $translation[$field];
7709 }
7710 if (count($lang_translation) > 0) {
7711 $q = "SELECT `id` FROM `#__vikbooking_translations` WHERE `table`=".$dbo->quote($table)." AND `lang`=".$dbo->quote($ltag)." AND `reference_id`=".$dbo->quote((int)$reference_id).";";
7712 $dbo->setQuery($q);
7713 $dbo->execute();
7714 if ($dbo->getNumRows() > 0) {
7715 $last_id = $dbo->loadResult();
7716 $q = "UPDATE `#__vikbooking_translations` SET `content`=".$dbo->quote(json_encode($lang_translation))." WHERE `id`=".(int)$last_id.";";
7717 } else {
7718 $q = "INSERT INTO `#__vikbooking_translations` (`table`,`lang`,`reference_id`,`content`) VALUES (".$dbo->quote($table).", ".$dbo->quote($ltag).", ".$dbo->quote((int)$reference_id).", ".$dbo->quote(json_encode($lang_translation)).");";
7719 }
7720 $dbo->setQuery($q);
7721 $dbo->execute();
7722 $tn_saved++;
7723 }
7724 }
7725 }
7726 }
7727 if ($tn_saved > 0) {
7728 $mainframe->enqueueMessage(JText::translate('VBOTRANSLSAVEDOK'));
7729 }
7730 } else {
7731 VikError::raiseWarning('', JText::translate('VBTRANSLATIONERRINVTABLE'));
7732 }
7733 $mainframe->redirect("index.php?option=com_vikbooking".($stay ? '&task=translations&vbo_table='.$vbo_tn->replacePrefix($table).'&vbo_lang='.$cur_langtab : '').'&limitstart='.$vbo_tn->lim0.'&limit='.$vbo_tn->lim);
7734 }
7735
7736 public function choosebusy() {
7737 VikBookingHelper::printHeader("8");
7738
7739 VikRequest::setVar('view', VikRequest::getCmd('view', 'choosebusy'));
7740
7741 parent::display();
7742
7743 if (VikBooking::showFooter()) {
7744 VikBookingHelper::printFooter();
7745 }
7746 }
7747
7748 public function orders() {
7749 VikBookingHelper::printHeader("8");
7750
7751 VikRequest::setVar('view', VikRequest::getCmd('view', 'orders'));
7752
7753 parent::display();
7754
7755 if (VikBooking::showFooter()) {
7756 VikBookingHelper::printFooter();
7757 }
7758 }
7759
7760 public function vieworders() {
7761 //alias method of orders() for backward compatibility with VCM
7762 $this->orders();
7763 }
7764
7765 public function editorder() {
7766 VikBookingHelper::printHeader("8");
7767
7768 VikRequest::setVar('view', VikRequest::getCmd('view', 'editorder'));
7769
7770 parent::display();
7771
7772 if (VikBooking::showFooter()) {
7773 VikBookingHelper::printFooter();
7774 }
7775 }
7776
7777 public function removeorders()
7778 {
7779 if (!JFactory::getUser()->authorise('core.delete', 'com_vikbooking')) {
7780 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
7781 }
7782
7783 $dbo = JFactory::getDbo();
7784 $app = JFactory::getApplication();
7785
7786 $ids = VikRequest::getVar('cid', array(0));
7787 $pgoto = VikRequest::getString('goto', '', 'request', VIKREQUEST_ALLOWRAW);
7788
7789 $user = JFactory::getUser();
7790 $config = VBOFactory::getConfig();
7791
7792 $prev_conf_ids = [];
7793 $purged = false;
7794
7795 $tot_cancs = 0;
7796
7797 if (is_array($ids) && count($ids)) {
7798 foreach ($ids as $d) {
7799 $q = "SELECT * FROM `#__vikbooking_orders` WHERE `id`=" . $dbo->quote($d);
7800 $dbo->setQuery($q, 0, 1);
7801 $row = $dbo->loadAssoc();
7802
7803 // check for any cancellation constraints
7804 $canc_denied = false;
7805 if ($row && class_exists('VCMFeesCancellation')) {
7806 // let VCM detect if there are any constraints for the cancellation
7807 $canc_denied = VCMFeesCancellation::getInstance($row, $anew = true)->isBookingConstrained();
7808 if ($canc_denied) {
7809 // set error message
7810 $canc_deny_error = VCMFeesCancellation::getInstance()->getError();
7811 if ($canc_deny_error) {
7812 $app->enqueueMessage($canc_deny_error, 'error');
7813 }
7814 }
7815 }
7816
7817 if ($row && !$canc_denied) {
7818 // increase counter
7819 $tot_cancs++;
7820
7821 // set status to cancelled
7822 if ($row['status'] != 'cancelled') {
7823 $q = "UPDATE `#__vikbooking_orders` SET `status`='cancelled' WHERE `id`=".(int)$row['id'].";";
7824 $dbo->setQuery($q);
7825 $dbo->execute();
7826 $q = "DELETE FROM `#__vikbooking_tmplock` WHERE `idorder`=" . intval($row['id']) . ";";
7827 $dbo->setQuery($q);
7828 $dbo->execute();
7829 if ($row['status'] == 'confirmed') {
7830 $prev_conf_ids[] = $row['id'];
7831 }
7832 // Booking History
7833 VikBooking::getBookingHistoryInstance()->setBid($row['id'])->store('CB', "({$user->name})");
7834 }
7835
7836 // free records up
7837 $q = "SELECT * FROM `#__vikbooking_ordersbusy` WHERE `idorder`=".(int)$row['id'].";";
7838 $dbo->setQuery($q);
7839 $ordbusy = $dbo->loadAssocList();
7840 if ($ordbusy) {
7841 foreach ($ordbusy as $ob) {
7842 $q = "DELETE FROM `#__vikbooking_busy` WHERE `id`='".$ob['idbusy']."';";
7843 $dbo->setQuery($q);
7844 $dbo->execute();
7845 }
7846 }
7847
7848 $q = "DELETE FROM `#__vikbooking_ordersbusy` WHERE `idorder`=".(int)$row['id'].";";
7849 $dbo->setQuery($q);
7850 $dbo->execute();
7851
7852 // check for purge removal
7853 if ($row['status'] == 'cancelled') {
7854 $q = "DELETE FROM `#__vikbooking_customers_orders` WHERE `idorder`=" . intval($row['id']) . ";";
7855 $dbo->setQuery($q);
7856 $dbo->execute();
7857 $q = "DELETE FROM `#__vikbooking_ordersrooms` WHERE `idorder`=".(int)$row['id'].";";
7858 $dbo->setQuery($q);
7859 $dbo->execute();
7860 $q = "DELETE FROM `#__vikbooking_orderhistory` WHERE `idorder`=".(int)$row['id'].";";
7861 $dbo->setQuery($q);
7862 $dbo->execute();
7863 $q = "DELETE FROM `#__vikbooking_orders` WHERE `id`=".(int)$row['id'].";";
7864 $dbo->setQuery($q);
7865 $dbo->execute();
7866 // in case of split stay booking, remove the transient
7867 if ($row['split_stay']) {
7868 $config->remove('split_stay_' . $row['id']);
7869 }
7870 // turn flag on
7871 $purged = true;
7872 }
7873 }
7874 }
7875
7876 if ($tot_cancs) {
7877 // enqueue system message
7878 $app->enqueueMessage(JText::translate('VBMESSDELBUSY'));
7879 }
7880 }
7881
7882 if ($prev_conf_ids) {
7883 $prev_conf_ids_str = '';
7884 foreach ($prev_conf_ids as $prev_id) {
7885 $prev_conf_ids_str .= '&cid[]='.$prev_id;
7886 }
7887 //Invoke Channel Manager
7888 $vcm_autosync = VikBooking::vcmAutoUpdate();
7889 if ($vcm_autosync > 0) {
7890 $vcm_obj = VikBooking::getVcmInvoker();
7891 $vcm_obj->setOids($prev_conf_ids)->setSyncType('cancel');
7892 $sync_result = $vcm_obj->doSync();
7893 if ($sync_result === false) {
7894 $vcm_err = $vcm_obj->getError();
7895 VikError::raiseWarning('', JText::translate('VBCHANNELMANAGERRESULTKO').' <a href="index.php?option=com_vikchannelmanager" target="_blank">'.JText::translate('VBCHANNELMANAGEROPEN').'</a> '.(strlen($vcm_err) > 0 ? '('.$vcm_err.')' : ''));
7896 }
7897 } elseif (file_exists(VCM_SITE_PATH . DIRECTORY_SEPARATOR . "helpers" . DIRECTORY_SEPARATOR . "synch.vikbooking.php")) {
7898 $vcm_sync_url = 'index.php?option=com_vikbooking&task=invoke_vcm&stype=cancel'.$prev_conf_ids_str.'&returl='.urlencode('index.php?option=com_vikbooking&task=orders');
7899 VikError::raiseNotice('', JText::translate('VBCHANNELMANAGERINVOKEASK').' <button type="button" class="btn btn-primary" onclick="document.location.href=\''.$vcm_sync_url.'\';">'.JText::translate('VBCHANNELMANAGERSENDRQ').'</button>');
7900 }
7901 //
7902 }
7903
7904 if (!empty($pgoto)) {
7905 if (is_numeric($pgoto) && is_array($ids) && count($ids) === 1) {
7906 if ($purged) {
7907 // go back to the bookings list page
7908 $app->redirect("index.php?option=com_vikbooking&task=orders");
7909 } else {
7910 // go back to the booking details page
7911 $app->redirect("index.php?option=com_vikbooking&task=editorder&cid[]=" . (int)$ids[0]);
7912 }
7913 exit;
7914 }
7915 // we expect the goto URL to be base64 encoded
7916 $app->redirect(base64_decode($pgoto));
7917 exit;
7918 }
7919
7920 // go back to the bookings list page
7921 $app->redirect("index.php?option=com_vikbooking&task=orders");
7922 }
7923
7924 public function config() {
7925 VikBookingHelper::printHeader("11");
7926
7927 VikRequest::setVar('view', VikRequest::getCmd('view', 'config'));
7928
7929 parent::display();
7930
7931 if (VikBooking::showFooter()) {
7932 VikBookingHelper::printFooter();
7933 }
7934 }
7935
7936 public function saveconfig()
7937 {
7938 if (!JSession::checkToken()) {
7939 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
7940 }
7941
7942 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking') || !JFactory::getUser()->authorise('core.vbo.global', 'com_vikbooking')) {
7943 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
7944 }
7945
7946 $dbo = JFactory::getDbo();
7947 $app = JFactory::getApplication();
7948
7949 $config = VBOFactory::getConfig();
7950
7951 $pallowbooking = VikRequest::getString('allowbooking', '', 'request');
7952 $pdisabledbookingmsg = VikRequest::getString('disabledbookingmsg', '', 'request', VIKREQUEST_ALLOWHTML);
7953 $ptimeopenstorefh = VikRequest::getString('timeopenstorefh', '', 'request');
7954 $ptimeopenstorefm = VikRequest::getString('timeopenstorefm', '', 'request');
7955 $ptimeopenstoreth = VikRequest::getString('timeopenstoreth', '', 'request');
7956 $ptimeopenstoretm = VikRequest::getString('timeopenstoretm', '', 'request');
7957 $phoursmorebookingback = VikRequest::getString('hoursmorebookingback', '', 'request');
7958 $pdateformat = VikRequest::getString('dateformat', '', 'request');
7959 $pdatesep = VikRequest::getString('datesep', '', 'request');
7960 $pdatesep = empty($pdatesep) ? "/" : $pdatesep;
7961 $presmodcanc = VikRequest::getInt('resmodcanc', 1, 'request');
7962 $presmodcancmin = VikRequest::getInt('resmodcancmin', 1, 'request');
7963 $pshowcategories = VikRequest::getString('showcategories', '', 'request');
7964 $pshowchildren = VikRequest::getString('showchildren', '', 'request');
7965 $psearchsuggestions = VikRequest::getInt('searchsuggestions', '', 'request');
7966 $ptokenform = VikRequest::getString('tokenform', '', 'request');
7967 $padminemail = VikRequest::getString('adminemail', '', 'request');
7968 $psenderemail = VikRequest::getString('senderemail', '', 'request');
7969 $pminuteslock = VikRequest::getString('minuteslock', '', 'request');
7970 $pminautoremove = VikRequest::getInt('minautoremove', '', 'request');
7971 $pfooterordmail = VikRequest::getString('footerordmail', '', 'request', VIKREQUEST_ALLOWHTML);
7972 $ptermsconds = VikRequest::getString('termsconds', '', 'request', VIKREQUEST_ALLOWHTML);
7973 $prequirelogin = VikRequest::getString('requirelogin', '', 'request');
7974 $pautoroomunit = VikRequest::getInt('autoroomunit', '', 'request');
7975 $ptodaybookings = VikRequest::getInt('todaybookings', '', 'request');
7976 $ptodaybookings = $ptodaybookings === 1 ? 1 : 0;
7977 $ploadbootstrap = VikRequest::getInt('loadbootstrap', '', 'request');
7978 $ploadbootstrap = $ploadbootstrap === 1 ? 1 : 0;
7979 $pusefa = VikRequest::getInt('usefa', '', 'request');
7980 $pusefa = $pusefa > 0 ? 1 : 0;
7981 $ploadjquery = VikRequest::getString('loadjquery', '', 'request');
7982 $ploadjquery = $ploadjquery == "yes" ? "1" : "0";
7983 $pcalendar = VikRequest::getString('calendar', '', 'request');
7984 $pcalendar = $pcalendar == "joomla" ? "joomla" : "jqueryui";
7985 $penablecoupons = VikRequest::getString('enablecoupons', '', 'request');
7986 $penablecoupons = $penablecoupons == "1" ? 1 : 0;
7987 $penablepin = VikRequest::getString('enablepin', '', 'request');
7988 $penablepin = $penablepin == "1" ? 1 : 0;
7989 $pmindaysadvance = VikRequest::getInt('mindaysadvance', '', 'request');
7990 $pmindaysadvance = $pmindaysadvance < 0 ? 0 : $pmindaysadvance;
7991 $pautodefcalnights = VikRequest::getInt('autodefcalnights', '', 'request');
7992 $pautodefcalnights = $pautodefcalnights >= 1 ? $pautodefcalnights : '1';
7993 $pnumrooms = VikRequest::getInt('numrooms', '', 'request');
7994 $pnumrooms = $pnumrooms > 0 ? $pnumrooms : '5';
7995 $pnumadultsfrom = VikRequest::getString('numadultsfrom', '', 'request');
7996 $pnumadultsfrom = intval($pnumadultsfrom) >= 0 ? $pnumadultsfrom : '1';
7997 $pnumadultsto = VikRequest::getString('numadultsto', '', 'request');
7998 $pnumadultsto = intval($pnumadultsto) > 0 ? $pnumadultsto : '10';
7999 if (intval($pnumadultsfrom) > intval($pnumadultsto)) {
8000 $pnumadultsfrom = '1';
8001 $pnumadultsto = '10';
8002 }
8003 $pnumchildrenfrom = VikRequest::getString('numchildrenfrom', '', 'request');
8004 $pnumchildrenfrom = intval($pnumchildrenfrom) >= 0 ? $pnumchildrenfrom : '1';
8005 $pnumchildrento = VikRequest::getString('numchildrento', '', 'request');
8006 $pnumchildrento = intval($pnumchildrento) > 0 ? $pnumchildrento : '4';
8007 if (intval($pnumchildrenfrom) > intval($pnumchildrento)) {
8008 $pnumadultsfrom = '1';
8009 $pnumadultsto = '4';
8010 }
8011 $confnumadults = $pnumadultsfrom.'-'.$pnumadultsto;
8012 $confnumchildren = $pnumchildrenfrom.'-'.$pnumchildrento;
8013 $pmaxdate = VikRequest::getString('maxdate', '', 'request');
8014 $pmaxdate = intval($pmaxdate) < 1 ? 2 : $pmaxdate;
8015 $pmaxdateinterval = VikRequest::getString('maxdateinterval', '', 'request');
8016 $pmaxdateinterval = !in_array($pmaxdateinterval, array('d', 'w', 'm', 'y')) ? 'y' : $pmaxdateinterval;
8017 $maxdate_str = '+'.$pmaxdate.$pmaxdateinterval;
8018 $pcronkey = VikRequest::getString('cronkey', '', 'request');
8019 $pcdsfrom = VikRequest::getVar('cdsfrom', array());
8020 $pcdsto = VikRequest::getVar('cdsto', array());
8021 $closing_dates = array();
8022 if (count($pcdsfrom)) {
8023 foreach ($pcdsfrom as $kcd => $vcdfrom) {
8024 if (!empty($vcdfrom) && array_key_exists($kcd, $pcdsto) && !empty($pcdsto[$kcd])) {
8025 $tscdfrom = VikBooking::getDateTimestamp($vcdfrom, '0', '0');
8026 $tscdto = VikBooking::getDateTimestamp($pcdsto[$kcd], '0', '0');
8027 if (!empty($tscdfrom) && !empty($tscdto) && $tscdto >= $tscdfrom) {
8028 $cdval = array('from' => $tscdfrom, 'to' => $tscdto);
8029 if (!in_array($cdval, $closing_dates)) {
8030 $closing_dates[] = $cdval;
8031 }
8032 }
8033 }
8034 }
8035 }
8036 $psmartsearch = VikRequest::getString('smartsearch', '', 'request');
8037 $psmartsearch = $psmartsearch == "dynamic" ? "dynamic" : "automatic";
8038 $pvbosef = VikRequest::getInt('vbosef', '', 'request');
8039 $vbosef = file_exists(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'router.php');
8040 if ($pvbosef === 1) {
8041 if (!$vbosef) {
8042 rename(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'_router.php', VBO_SITE_PATH.DIRECTORY_SEPARATOR.'router.php');
8043 }
8044 } else {
8045 if ($vbosef) {
8046 rename(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'router.php', VBO_SITE_PATH.DIRECTORY_SEPARATOR.'_router.php');
8047 }
8048 }
8049 $pmultilang = VikRequest::getString('multilang', '', 'request');
8050 $pmultilang = $pmultilang == "1" ? 1 : 0;
8051 $pvcmautoupd = VikRequest::getInt('vcmautoupd', '', 'request');
8052 $pvcmautoupd = $pvcmautoupd > 0 ? 1 : 0;
8053 /**
8054 * Chat params and configuration settings
8055 *
8056 * @since 1.12
8057 */
8058 $pchatenabled = VikRequest::getInt('chatenabled', 0, 'request');
8059 if (is_file(VCM_SITE_PATH.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'lib.vikchannelmanager.php')) {
8060 $config->set('chatenabled', $pchatenabled);
8061
8062 // chat params
8063 $pchat_res_status = explode(';', VikRequest::getString('chat_res_status', '', 'request'));
8064 $chat_res_status = array();
8065 foreach ($pchat_res_status as $chatrs) {
8066 if (!empty($chatrs)) {
8067 array_push($chat_res_status, $chatrs);
8068 }
8069 }
8070 $chatparams = new stdClass;
8071 $chatparams->res_status = $chat_res_status;
8072 $chatparams->av_type = VikRequest::getString('chat_av_type', '', 'request');
8073 $chatparams->av_days = VikRequest::getInt('chat_av_days', 0, 'request');
8074
8075 $config->set('chatparams', $chatparams);
8076 }
8077
8078 /**
8079 * Pre check-in configuration settings
8080 *
8081 * @since 1.12
8082 */
8083 $pprecheckinenabled = VikRequest::getInt('precheckinenabled', 0, 'request');
8084 $pprecheckinenabled = $pprecheckinenabled > 0 ? 1 : 0;
8085
8086 $config->set('precheckinenabled', $pprecheckinenabled);
8087 $config->set('precheckinminoffset', VikRequest::getInt('precheckinminoffset', 0, 'request'));
8088
8089 $pupsellingenabled = VikRequest::getInt('upsellingenabled', 0, 'request');
8090 $pupsellingenabled = $pupsellingenabled > 0 ? 1 : 0;
8091 $config->set('upselling', $pupsellingenabled);
8092
8093 $porphanscal = VikRequest::getString('orphanscal', 'next', 'request');
8094 $porphanscal = $porphanscal == 'prevnext' ? 'prevnext' : 'next';
8095 $config->set('orphanscalculation', $porphanscal);
8096
8097 $psrcrtpl = VikRequest::getString('srcrtpl', 'compact', 'request');
8098 $config->set('searchrestmpl', $psrcrtpl);
8099
8100 /**
8101 * Guest Reviews settings
8102 *
8103 * @since 1.13
8104 */
8105 $pgrenabled = VikRequest::getInt('grenabled', 0, 'request');
8106 $pgrminchars = VikRequest::getInt('grminchars', 0, 'request');
8107 $pgrappr = VikRequest::getString('grappr', 'auto', 'request');
8108 $pgrappr = $pgrappr == 'auto' ? 'auto' : 'manual';
8109 $pgrtype = VikRequest::getString('grtype', 'service', 'request');
8110 $pgrtype = $pgrtype == 'service' ? 'service' : 'global';
8111 $pgrsrv = VikRequest::getVar('grsrv', array(), 'request', 'array');
8112 $config->set('grenabled', $pgrenabled);
8113 $config->set('grminchars', $pgrminchars);
8114 $config->set('grappr', $pgrappr);
8115 $config->set('grtype', $pgrtype);
8116 try {
8117 // always truncate service names (this query may require special permissions)
8118 $q = "TRUNCATE TABLE `#__vikbooking_greview_service`;";
8119 $dbo->setQuery($q);
8120 $dbo->execute();
8121 } catch (Exception $e) {
8122 // do nothing
8123 }
8124 foreach ($pgrsrv as $srvname) {
8125 $q = "INSERT INTO `#__vikbooking_greview_service` (`service_name`) VALUES (" . $dbo->quote($srvname) . ");";
8126 $dbo->setQuery($q);
8127 $dbo->execute();
8128 }
8129
8130 /**
8131 * Preferred countries ordering, or custom countries.
8132 *
8133 * @since 1.14 (J) - 1.3.11 (WP)
8134 * @since 1.14.1 (J) - 1.4.1 (WP) we also support "cust_pref_countries"
8135 */
8136 $pref_countries = VikRequest::getVar('pref_countries', array());
8137 $cust_pref_countries = VikRequest::getString('cust_pref_countries', '', 'request');
8138 $pref_countries = !is_array($pref_countries) || empty($pref_countries[0]) ? VikBooking::preferredCountriesOrdering() : $pref_countries;
8139 if (!empty($cust_pref_countries)) {
8140 $all_custom_prefcountries = array();
8141 $cust_pref_countries = explode(',', $cust_pref_countries);
8142 foreach ($cust_pref_countries as $cust_pref_country) {
8143 $cust_pref_country = trim(strtolower($cust_pref_country));
8144 if (empty($cust_pref_country) || strlen($cust_pref_country) != 2) {
8145 continue;
8146 }
8147 array_push($all_custom_prefcountries, $cust_pref_country);
8148 }
8149 if (count($all_custom_prefcountries)) {
8150 $pref_countries = $all_custom_prefcountries;
8151 }
8152 }
8153 $config->set('preferred_countries', $pref_countries);
8154 //
8155
8156 $gmapskey = VikRequest::getString('gmapskey', '', 'request');
8157 $config->set('gmapskey', $gmapskey);
8158
8159 $pref_textcolor = VikRequest::getString('pref_textcolor', '', 'request');
8160 $pref_bgcolor = VikRequest::getString('pref_bgcolor', '', 'request');
8161 $pref_fontcolor = VikRequest::getString('pref_fontcolor', '', 'request');
8162 $pref_bgcolorhov = VikRequest::getString('pref_bgcolorhov', '', 'request');
8163 $pref_fontcolorhov = VikRequest::getString('pref_fontcolorhov', '', 'request');
8164 $pref_colors = array(
8165 'textcolor' => $pref_textcolor,
8166 'bgcolor' => $pref_bgcolor,
8167 'fontcolor' => $pref_fontcolor,
8168 'bgcolorhov' => $pref_bgcolorhov,
8169 'fontcolorhov' => $pref_fontcolorhov,
8170 );
8171 $config->set('pref_colors', $pref_colors);
8172
8173 $interactive_map = VikRequest::getInt('interactive_map', 0, 'request');
8174 $config->set('interactive_map', $interactive_map);
8175
8176 $noemptydecimals = VikRequest::getInt('noemptydecimals', 0, 'request');
8177 $config->set('noemptydecimals', $noemptydecimals);
8178
8179 /**
8180 * Appearance preferences (light, auto, dark mode).
8181 *
8182 * @since 1.15.0 (J) - 1.5.0 (WP)
8183 */
8184 $appearance_pref = VikRequest::getString('appearance_pref', '');
8185 $config->set('appearance_pref', $appearance_pref);
8186
8187 $res_backend_path = VBO_ADMIN_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR;
8188 $picon = "";
8189 if (intval($_FILES['sitelogo']['error']) == 0 && trim($_FILES['sitelogo']['name'])!="") {
8190 jimport('joomla.filesystem.file');
8191 if (@is_uploaded_file($_FILES['sitelogo']['tmp_name'])) {
8192 $safename = JFile::makeSafe(str_replace(" ", "_", strtolower($_FILES['sitelogo']['name'])));
8193 if (file_exists($res_backend_path.$safename)) {
8194 $j = 1;
8195 while (file_exists($res_backend_path.$j.$safename)) {
8196 $j++;
8197 }
8198 $pwhere = $res_backend_path.$j.$safename;
8199 } else {
8200 $j = "";
8201 $pwhere = $res_backend_path.$safename;
8202 }
8203 if (!getimagesize($_FILES['sitelogo']['tmp_name']) || !preg_match("/\.(a?png|jpe?g|bmp|gif|ico|webp)\z/i", $safename)) {
8204 @unlink($pwhere);
8205 $picon = "";
8206 } else {
8207 VikBooking::uploadFile($_FILES['sitelogo']['tmp_name'], $pwhere);
8208 @chmod($pwhere, 0644);
8209 $picon = $j.$safename;
8210 }
8211 }
8212 if (!empty($picon)) {
8213 $config->set('sitelogo', $picon);
8214 }
8215 }
8216 $pbackicon = "";
8217 if (intval($_FILES['backlogo']['error']) == 0 && trim($_FILES['backlogo']['name'])!="") {
8218 jimport('joomla.filesystem.file');
8219 if (@is_uploaded_file($_FILES['backlogo']['tmp_name'])) {
8220 $safename = JFile::makeSafe(str_replace(" ", "_", strtolower($_FILES['backlogo']['name'])));
8221 if (file_exists($res_backend_path.$safename)) {
8222 $j = 1;
8223 while (file_exists($res_backend_path.$j.$safename)) {
8224 $j++;
8225 }
8226 $pwhere = $res_backend_path.$j.$safename;
8227 } else {
8228 $j = "";
8229 $pwhere = $res_backend_path.$safename;
8230 }
8231 if (!getimagesize($_FILES['backlogo']['tmp_name']) || !preg_match("/\.(a?png|jpe?g|bmp|gif|ico|webp)\z/i", $safename)) {
8232 @unlink($pwhere);
8233 $pbackicon = "";
8234 } else {
8235 VikBooking::uploadFile($_FILES['backlogo']['tmp_name'], $pwhere);
8236 @chmod($pwhere, 0644);
8237 $pbackicon = $j.$safename;
8238 }
8239 }
8240 if (!empty($pbackicon)) {
8241 $config->set('backlogo', $pbackicon);
8242 }
8243 }
8244 $config->set('vcmautoupd', $pvcmautoupd);
8245 $config->set('allowbooking', empty($pallowbooking) || $pallowbooking != "1" ? 0 : 1);
8246 $config->set('showcategories', empty($pshowcategories) || $pshowcategories != "yes" ? 0 : 1);
8247 $config->set('showchildren', empty($pshowchildren) || $pshowchildren != "yes" ? 0 : 1);
8248 $config->set('searchsuggestions', $psearchsuggestions);
8249 $config->set('tokenform', empty($ptokenform) || $ptokenform != "yes" ? 0 : 1);
8250 $config->set('guests_label', $app->input->getString('guests_label', 'adults'));
8251
8252 // translatable text
8253 $q = "UPDATE `#__vikbooking_texts` SET `setting`=".$dbo->quote($pfooterordmail)." WHERE `param`='footerordmail';";
8254 $dbo->setQuery($q);
8255 $dbo->execute();
8256
8257 // translatable text
8258 $q = "UPDATE `#__vikbooking_texts` SET `setting`=".$dbo->quote($pdisabledbookingmsg)." WHERE `param`='disabledbookingmsg';";
8259 $dbo->setQuery($q);
8260 $dbo->execute();
8261
8262 // translatable text
8263 $q = "UPDATE `#__vikbooking_texts` SET `setting`=" . $dbo->q($app->input->getString('guests_allowed_policy', '', 'raw')) . " WHERE `param`='guests_allowed_policy';";
8264 $dbo->setQuery($q);
8265 $dbo->execute();
8266
8267 // terms and conditions
8268 $q = "SELECT `id`,`setting` FROM `#__vikbooking_texts` WHERE `param`='termsconds';";
8269 $dbo->setQuery($q);
8270 $dbo->execute();
8271 if ($dbo->getNumRows() > 0) {
8272 $q = "UPDATE `#__vikbooking_texts` SET `setting`=".$dbo->quote($ptermsconds)." WHERE `param`='termsconds';";
8273 $dbo->setQuery($q);
8274 $dbo->execute();
8275 } else {
8276 $q = "INSERT INTO `#__vikbooking_texts` (`param`,`exp`,`setting`) VALUES ('termsconds','Terms and Conditions',".$dbo->quote($ptermsconds).");";
8277 $dbo->setQuery($q);
8278 $dbo->execute();
8279 }
8280
8281 $config->set('adminemail', $padminemail);
8282 $config->set('senderemail', $psenderemail);
8283 $config->set('dateformat', empty($pdateformat) ? "%d/%m/%Y" : $pdateformat);
8284 $config->set('datesep', $pdatesep);
8285 $config->set('resmodcanc', $presmodcanc);
8286 $config->set('resmodcancmin', $presmodcancmin);
8287 $config->set('minuteslock', $pminuteslock);
8288 $config->set('minautoremove', $pminautoremove);
8289
8290 $openingh = $ptimeopenstorefh * 3600;
8291 $openingm = $ptimeopenstorefm * 60;
8292 $openingts = $openingh + $openingm;
8293 $closingh = $ptimeopenstoreth * 3600;
8294 $closingm = $ptimeopenstoretm * 60;
8295 $closingts = $closingh + $closingm;
8296 // check if the check-in/out times have changed and if there are future bookings with the old time to prevent availability errors
8297 $prevtimes = $config->get('timeopenstore', '');
8298 if ($prevtimes != $openingts . "-" . $closingts) {
8299 $q = "SELECT `id` FROM `#__vikbooking_orders` WHERE `checkout`>".time().";";
8300 $dbo->setQuery($q);
8301 $dbo->execute();
8302 if ($dbo->getNumRows() > 0) {
8303 VikError::raiseWarning('', JText::translate('VBOCONFIGWARNDIFFCHECKINOUT'));
8304 /**
8305 * VBO 1.10 Patch - we concatenate a button to unify the check-in/out times
8306 * for all reservations to avoid issues with the availability.
8307 *
8308 * @since August 29th 2018
8309 */
8310 VikError::raiseWarning('', '<br/><a href="index.php?option=com_vikbooking&task=unifycheckinout&fh='.$ptimeopenstorefh.'&fm='.$ptimeopenstorefm.'&th='.$ptimeopenstoreth.'&tm='.$ptimeopenstoretm.'" class="btn btn-large btn-warning">'.JText::translate('VBAPPLY').'</a>');
8311 //
8312 }
8313 }
8314 $config->set('timeopenstore', $openingts . "-" . $closingts);
8315
8316 // set the hours of extended gratuity period to the difference between checkin and checkout if checkout is later
8317 $phoursmorebookingback = "0";
8318 if ($closingts > $openingts) {
8319 $diffcheck = ($closingts - $openingts) / 3600;
8320 $phoursmorebookingback = ceil($diffcheck);
8321 }
8322 $config->set('hoursmorebookingback', $phoursmorebookingback);
8323 $config->set('hoursmoreroomavail', '0');
8324 $config->set('multilang', $pmultilang);
8325 $config->set('requirelogin', $prequirelogin == "1" ? 1 : 0);
8326 $config->set('autoroomunit', $pautoroomunit ? 1 : 0);
8327 $config->set('todaybookings', $ptodaybookings);
8328 $config->set('bootstrap', $ploadbootstrap);
8329 $config->set('usefa', $pusefa);
8330 $config->set('loadjquery', $ploadjquery);
8331 $config->set('calendar', $pcalendar);
8332 $config->set('enablecoupons', $penablecoupons);
8333 $config->set('enablepin', $penablepin);
8334 $config->set('mindaysadvance', $pmindaysadvance);
8335 $config->set('autodefcalnights', $pautodefcalnights);
8336 $config->set('numrooms', $pnumrooms);
8337 $config->set('numadults', $confnumadults);
8338 $config->set('numchildren', $confnumchildren);
8339 $config->set('closingdates', $closing_dates);
8340 $config->set('smartsearch', $psmartsearch);
8341 $config->set('maxdate', $maxdate_str);
8342 $config->set('cronkey', $pcronkey);
8343
8344 $pfronttitle = VikRequest::getString('fronttitle', '', 'request');
8345 $pfronttitletag = VikRequest::getString('fronttitletag', '', 'request');
8346 $pfronttitletagclass = VikRequest::getString('fronttitletagclass', '', 'request');
8347 $pshowfooter = VikRequest::getString('showfooter', '', 'request');
8348 $pintromain = VikRequest::getString('intromain', '', 'request', VIKREQUEST_ALLOWHTML);
8349 $pclosingmain = VikRequest::getString('closingmain', '', 'request', VIKREQUEST_ALLOWHTML);
8350 $pcurrencyname = VikRequest::getString('currencyname', '', 'request', VIKREQUEST_ALLOWHTML);
8351 $pcurrencysymb = VikRequest::getString('currencysymb', '', 'request', VIKREQUEST_ALLOWHTML);
8352 $pcurrencycodepp = VikRequest::getString('currencycodepp', '', 'request');
8353 $pnumdecimals = VikRequest::getString('numdecimals', '', 'request');
8354 $pnumdecimals = intval($pnumdecimals);
8355 $pdecseparator = VikRequest::getString('decseparator', '', 'request');
8356 $pdecseparator = empty($pdecseparator) ? '.' : $pdecseparator;
8357 $pthoseparator = VikRequest::getString('thoseparator', '', 'request');
8358 $numberformatstr = $pnumdecimals.':'.$pdecseparator.':'.$pthoseparator;
8359 $pshowpartlyreserved = VikRequest::getString('showpartlyreserved', '', 'request');
8360 $pshowpartlyreserved = $pshowpartlyreserved == "yes" ? 1 : 0;
8361 $pshowcheckinoutonly = VikRequest::getInt('showcheckinoutonly', '', 'request');
8362 $pshowcheckinoutonly = $pshowcheckinoutonly > 0 ? 1 : 0;
8363 $pnumcalendars = VikRequest::getInt('numcalendars', '', 'request');
8364 $pnumcalendars = $pnumcalendars > -1 ? $pnumcalendars : 3;
8365 $pthumbsize = VikRequest::getInt('thumbsize', 0, 'request');
8366 $pfirstwday = VikRequest::getString('firstwday', '', 'request');
8367 $pfirstwday = intval($pfirstwday) >= 0 && intval($pfirstwday) <= 6 ? $pfirstwday : '0';
8368 $pbctagname = VikRequest::getVar('bctagname', array());
8369 $pbctagcolor = VikRequest::getVar('bctagcolor', array());
8370 $pbctagrule = VikRequest::getVar('bctagrule', array());
8371 $bctags_arr = array();
8372 $bctags_rules = array();
8373 if (count($pbctagname) > 0) {
8374 foreach ($pbctagname as $bctk => $bctv) {
8375 if (!empty($bctv) && !empty($pbctagcolor[$bctk]) && strlen($pbctagrule[$bctk]) > 0) {
8376 if (intval($pbctagrule[$bctk]) == 0 || !in_array($pbctagrule[$bctk], $bctags_rules)) {
8377 $bctags_rules[] = $pbctagrule[$bctk];
8378 $bctags_arr[] = array('color' => $pbctagcolor[$bctk], 'name' => $bctv, 'rule' => $pbctagrule[$bctk]);
8379 }
8380 }
8381 }
8382 }
8383 //theme
8384 $ptheme = VikRequest::getString('theme', '', 'request');
8385 if (empty($ptheme) || $ptheme == 'default') {
8386 $ptheme = 'default';
8387 } else {
8388 $validtheme = false;
8389 $themes = glob(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'themes'.DIRECTORY_SEPARATOR.'*');
8390 if (count($themes) > 0) {
8391 $strip = VBO_SITE_PATH.DIRECTORY_SEPARATOR.'themes'.DIRECTORY_SEPARATOR;
8392 foreach ($themes as $th) {
8393 if (is_dir($th)) {
8394 $tname = str_replace($strip, '', $th);
8395 if ($tname == $ptheme) {
8396 $validtheme = true;
8397 break;
8398 }
8399 }
8400 }
8401 }
8402 if ($validtheme == false) {
8403 $ptheme = 'default';
8404 }
8405 }
8406 $config->set('theme', $ptheme);
8407 //
8408 $config->set('showpartlyreserved', $pshowpartlyreserved);
8409 $config->set('showcheckinoutonly', $pshowcheckinoutonly);
8410 $config->set('numcalendars', $pnumcalendars);
8411
8412 // record may not be set
8413 $config->set('thumbsize', $pthumbsize);
8414
8415 $config->set('firstwday', $pfirstwday);
8416
8417 // translatable text
8418 $q = "UPDATE `#__vikbooking_texts` SET `setting`=".$dbo->quote($pfronttitle)." WHERE `param`='fronttitle';";
8419 $dbo->setQuery($q);
8420 $dbo->execute();
8421
8422 $config->set('fronttitletag', $pfronttitletag);
8423 $config->set('fronttitletagclass', $pfronttitletagclass);
8424 $config->set('showfooter', empty($pshowfooter) || $pshowfooter != "yes" ? 0 : 1);
8425
8426 // translatable texts
8427 $q = "UPDATE `#__vikbooking_texts` SET `setting`=".$dbo->quote($pintromain)." WHERE `param`='intromain';";
8428 $dbo->setQuery($q);
8429 $dbo->execute();
8430 $q = "UPDATE `#__vikbooking_texts` SET `setting`=".$dbo->quote($pclosingmain)." WHERE `param`='closingmain';";
8431 $dbo->setQuery($q);
8432 $dbo->execute();
8433
8434 $config->set('currencyname', $pcurrencyname);
8435 $config->set('currencysymb', $pcurrencysymb);
8436 $config->set('currencycodepp', $pcurrencycodepp);
8437 $config->set('numberformat', $numberformatstr);
8438 // bookings color tags
8439 $config->set('bookingsctags', $bctags_arr);
8440
8441 $pivainclusa = VikRequest::getString('ivainclusa', '', 'request');
8442 $ptaxsummary = VikRequest::getString('taxsummary', '', 'request');
8443 $ptaxsummary = empty($ptaxsummary) || $ptaxsummary != "yes" ? "0" : "1";
8444 $pccpaypal = VikRequest::getString('ccpaypal', '', 'request');
8445 $ppaytotal = VikRequest::getString('paytotal', '', 'request');
8446 $ppayaccpercent = VikRequest::getString('payaccpercent', '', 'request');
8447 $ptypedeposit = VikRequest::getString('typedeposit', '', 'request');
8448 $ptypedeposit = $ptypedeposit == 'fixed' ? 'fixed' : 'pcent';
8449 $pdepoverrides = VikRequest::getString('depoverrides', '', 'request');
8450 $ppaymentname = VikRequest::getString('paymentname', '', 'request');
8451 $pdisclaimer = VikRequest::getString('disclaimer', '', 'request', VIKREQUEST_ALLOWHTML);
8452 $pmultipay = VikRequest::getString('multipay', '', 'request');
8453 $pmultipay = $pmultipay == "yes" ? 1 : 0;
8454 $pdepifdaysadv = VikRequest::getInt('depifdaysadv', '', 'request');
8455 $pnodepnonrefund = VikRequest::getInt('nodepnonrefund', '', 'request');
8456 $pdepcustchoice = VikRequest::getString('depcustchoice', '', 'request');
8457 $pdepcustchoice = $pdepcustchoice == "yes" ? 1 : 0;
8458
8459 // translatable text
8460 $q = "UPDATE `#__vikbooking_texts` SET `setting`=" . $dbo->q($ppaymentname) . " WHERE `param`='paymentname';";
8461 $dbo->setQuery($q);
8462 $dbo->execute();
8463 $q = "UPDATE `#__vikbooking_texts` SET `setting`=" . $dbo->q($pdisclaimer) . " WHERE `param`='disclaimer';";
8464 $dbo->setQuery($q);
8465 $dbo->execute();
8466
8467 $config->set('ivainclusa', empty($pivainclusa) || $pivainclusa != "yes" ? 0 : 1);
8468 $config->set('taxsummary', $ptaxsummary);
8469 $config->set('paytotal', empty($ppaytotal) || $ppaytotal != "yes" ? 0 : 1);
8470
8471 $config->set('ccpaypal', $pccpaypal);
8472 $config->set('payaccpercent', $ppayaccpercent);
8473 $config->set('typedeposit', $ptypedeposit);
8474 $config->set('depoverrides', $pdepoverrides);
8475 $config->set('multipay', $pmultipay);
8476 $config->set('depifdaysadv', $pdepifdaysadv);
8477 $config->set('nodepnonrefund', $pnodepnonrefund);
8478 $config->set('depcustchoice', $pdepcustchoice);
8479
8480 $psendemailwhen = VikRequest::getInt('sendemailwhen', '', 'request');
8481 $psendemailwhen = $psendemailwhen > 1 ? 2 : 1;
8482 $pattachical = VikRequest::getInt('attachical', 0, 'request');
8483 $pattachical = $pattachical >= 0 && $pattachical <= 3 ? $pattachical : 1;
8484 $config->set('emailsendwhen', $psendemailwhen);
8485 $config->set('attachical', $pattachical);
8486
8487 // SMS APIs
8488 $psmsapi = VikRequest::getString('smsapi', '', 'request');
8489 $psmsautosend = VikRequest::getString('smsautosend', '', 'request');
8490 $psmsautosend = intval($psmsautosend) > 0 ? 1 : 0;
8491 $psmssendto = VikRequest::getVar('smssendto', array());
8492 $sms_sendto = array();
8493 foreach ($psmssendto as $sto) {
8494 if (in_array($sto, array('admin', 'customer'))) {
8495 $sms_sendto[] = $sto;
8496 }
8497 }
8498 $psmssendwhen = VikRequest::getInt('smssendwhen', '', 'request');
8499 $psmssendwhen = $psmssendwhen > 1 ? 2 : 1;
8500 $psmsadminphone = VikRequest::getString('smsadminphone', '', 'request');
8501 $psmsadmintpl = VikRequest::getString('smsadmintpl', '', 'request', VIKREQUEST_ALLOWRAW);
8502 $psmscustomertpl = VikRequest::getString('smscustomertpl', '', 'request', VIKREQUEST_ALLOWRAW);
8503 $psmsadmintplpend = VikRequest::getString('smsadmintplpend', '', 'request', VIKREQUEST_ALLOWRAW);
8504 $psmscustomertplpend = VikRequest::getString('smscustomertplpend', '', 'request', VIKREQUEST_ALLOWRAW);
8505 $psmsadmintplcanc = VikRequest::getString('smsadmintplcanc', '', 'request', VIKREQUEST_ALLOWRAW);
8506 $psmscustomertplcanc = VikRequest::getString('smscustomertplcanc', '', 'request', VIKREQUEST_ALLOWRAW);
8507 $viksmsparams = VikRequest::getVar('viksmsparams', array());
8508 $smsparamarr = array();
8509 if (count($viksmsparams) > 0) {
8510 foreach ($viksmsparams as $setting => $cont) {
8511 if (strlen($setting) > 0) {
8512 $smsparamarr[$setting] = $cont;
8513 }
8514 }
8515 }
8516 $config->set('smsapi', $psmsapi);
8517 $config->set('smsautosend', $psmsautosend);
8518 $config->set('smssendto', $sms_sendto);
8519 $config->set('smssendwhen', $psmssendwhen);
8520 $config->set('smsadminphone', $psmsadminphone);
8521 $config->set('smsparams', $smsparamarr);
8522
8523 // translatable texts
8524 $q = "UPDATE `#__vikbooking_texts` SET `setting`=".$dbo->quote($psmsadmintpl)." WHERE `param`='smsadmintpl';";
8525 $dbo->setQuery($q);
8526 $dbo->execute();
8527 $q = "UPDATE `#__vikbooking_texts` SET `setting`=".$dbo->quote($psmscustomertpl)." WHERE `param`='smscustomertpl';";
8528 $dbo->setQuery($q);
8529 $dbo->execute();
8530 $q = "UPDATE `#__vikbooking_texts` SET `setting`=".$dbo->quote($psmsadmintplpend)." WHERE `param`='smsadmintplpend';";
8531 $dbo->setQuery($q);
8532 $dbo->execute();
8533 $q = "UPDATE `#__vikbooking_texts` SET `setting`=".$dbo->quote($psmscustomertplpend)." WHERE `param`='smscustomertplpend';";
8534 $dbo->setQuery($q);
8535 $dbo->execute();
8536 $q = "UPDATE `#__vikbooking_texts` SET `setting`=".$dbo->quote($psmsadmintplcanc)." WHERE `param`='smsadmintplcanc';";
8537 $dbo->setQuery($q);
8538 $dbo->execute();
8539 $q = "UPDATE `#__vikbooking_texts` SET `setting`=".$dbo->quote($psmscustomertplcanc)." WHERE `param`='smscustomertplcanc';";
8540 $dbo->setQuery($q);
8541 $dbo->execute();
8542
8543 /**
8544 * Backup settings
8545 *
8546 * @since 1.15.0 (J) - 1.5.0 (WP)
8547 */
8548 $backup_type = $app->input->getString('backuptype', 'full');
8549 $backup_folder = $app->input->getString('backupfolder', '');
8550
8551 $tmp = $app->get('tmp_path');
8552
8553 if (!$backup_folder)
8554 {
8555 // path not specified, use temporary folder
8556 $backup_folder = $tmp;
8557 }
8558
8559 $current = $config->get('backupfolder');
8560
8561 if (!$current)
8562 {
8563 // path was missing, use temporary folder
8564 $current = $tmp;
8565 }
8566
8567 // check whether the backup folder has been moved
8568 if ($current && $backup_folder && rtrim($current, DIRECTORY_SEPARATOR) !== rtrim($backup_folder, DIRECTORY_SEPARATOR))
8569 {
8570 $backupModel = new VBOModelBackup();
8571
8572 // backup folder moved, try to copy all the existing overrides
8573 if (!$backupModel->moveArchives($backup_folder))
8574 {
8575 // iterate all errors and display them
8576 foreach ($backupModel->getErrors() as $error)
8577 {
8578 $app->enqueueMessage($error, 'warning');
8579 }
8580 }
8581 }
8582
8583 // save configuration
8584 $config->set('backuptype', $backup_type);
8585 $config->set('backupfolder', $backup_folder);
8586
8587 /**
8588 * Check-in data collection type.
8589 *
8590 * @since 1.15.0 (J) - 1.5.0 (WP)
8591 */
8592 $config->set('checkindata', VikRequest::getString('checkindata', 'basic', 'request'));
8593
8594 /**
8595 * Front-end appearance.
8596 *
8597 * @since 1.15.0 (J) - 1.5.0 (WP) (patch)
8598 */
8599 $config->set('appearance_front', VikRequest::getInt('appearance_front', 0, 'request'));
8600
8601 /**
8602 * Split stays.
8603 *
8604 * @since 1.16.0 (J) - 1.6.0 (WP)
8605 */
8606 $glob_split_stay = VikRequest::getInt('split_stay', 0, 'request');
8607 $split_stay_ratio = VikRequest::getFloat('split_stay_ratio', 0, 'request');
8608 $split_stay_ratio = $split_stay_ratio > 100 ? 100 : $split_stay_ratio;
8609 $config->set('split_stay_ratio', ($glob_split_stay && $split_stay_ratio > 0 ? $split_stay_ratio : 0));
8610
8611 /**
8612 * Re-build Web App manifest file to let the event trigger.
8613 *
8614 * @since 1.16.5 (J) - 1.6.5 (WP)
8615 */
8616 try {
8617 VBOWebappManifest::build();
8618 } catch (Exception $e) {
8619 // do nothing
8620 }
8621
8622 // redirect
8623 $app->enqueueMessage(JText::translate('VBSETTINGSAVED'));
8624 $app->redirect('index.php?option=com_vikbooking&task=config');
8625 $app->close();
8626 }
8627
8628 /**
8629 * Task to unify the check-in and check-out times for all reservations.
8630 */
8631 public function unifycheckinout()
8632 {
8633 $dbo = JFactory::getDbo();
8634 $app = JFactory::getApplication();
8635 $user = JFactory::getUser();
8636
8637 $fh = VikRequest::getInt('fh', 12, 'request');
8638 $fm = VikRequest::getInt('fm', 0, 'request');
8639 $th = VikRequest::getInt('th', 10, 'request');
8640 $tm = VikRequest::getInt('tm', 0, 'request');
8641
8642 $now = time();
8643 $totmod = 0;
8644 $totbookmod = 0;
8645
8646 // query all busy records
8647 $q = $dbo->getQuery(true)
8648 ->select('*')
8649 ->from($dbo->qn('#__vikbooking_busy'));
8650
8651 $dbo->setQuery($q);
8652 $records = $dbo->loadAssocList();
8653
8654 foreach ($records as $v) {
8655 $info_start = getdate($v['checkin']);
8656 $info_end = getdate($v['checkout']);
8657 $new_start = mktime($fh, $fm, 0, $info_start['mon'], $info_start['mday'], $info_start['year']);
8658 $new_end = mktime($th, $tm, 0, $info_end['mon'], $info_end['mday'], $info_end['year']);
8659
8660 $q = $dbo->getQuery(true)
8661 ->update($dbo->qn('#__vikbooking_busy'))
8662 ->set($dbo->qn('checkin') . ' = ' . $new_start)
8663 ->set($dbo->qn('checkout') . ' = ' . $new_end)
8664 ->set($dbo->qn('realback') . ' = ' . $new_end)
8665 ->where($dbo->qn('id') . ' = ' . (int)$v['id']);
8666
8667 $dbo->setQuery($q, 0, 1);
8668 $dbo->execute();
8669
8670 $totmod++;
8671 }
8672
8673 // query all bookings
8674 $q = $dbo->getQuery(true)
8675 ->select($dbo->qn([
8676 'id',
8677 'days',
8678 'checkin',
8679 'checkout',
8680 'total',
8681 ]))
8682 ->from($dbo->qn('#__vikbooking_orders'))
8683 ->order($dbo->qn('checkin') . ' DESC');
8684
8685 $dbo->setQuery($q);
8686 $records = $dbo->loadAssocList();
8687
8688 foreach ($records as $v) {
8689 $info_start = getdate($v['checkin']);
8690 $info_end = getdate($v['checkout']);
8691 $new_start = mktime($fh, $fm, 0, $info_start['mon'], $info_start['mday'], $info_start['year']);
8692 $new_end = mktime($th, $tm, 0, $info_end['mon'], $info_end['mday'], $info_end['year']);
8693
8694 $q = $dbo->getQuery(true)
8695 ->update($dbo->qn('#__vikbooking_orders'))
8696 ->set($dbo->qn('checkin') . ' = ' . $new_start)
8697 ->set($dbo->qn('checkout') . ' = ' . $new_end)
8698 ->where($dbo->qn('id') . ' = ' . (int)$v['id']);
8699
8700 $dbo->setQuery($q, 0, 1);
8701 $dbo->execute();
8702
8703 /**
8704 * In case the operation changed the check-in/check-out time for this booking,
8705 * store a new history record for a booking modification.
8706 *
8707 * @since 1.16.6 (J) - 1.6.6 (WP)
8708 */
8709 if ($v['checkout'] > $now && ($info_start['hours'] != $fh || $info_end['hours'] != $th)) {
8710 // Booking History
8711 VikBooking::getBookingHistoryInstance($v['id'])->store('MB', "({$user->name}) " . VikBooking::getLogBookingModification($v));
8712 }
8713
8714 $totbookmod++;
8715 }
8716
8717 $app->enqueueMessage('OK: ' . $totbookmod);
8718 $app->redirect("index.php?option=com_vikbooking&task=config");
8719 $app->close();
8720 }
8721
8722 public function savetmplfile() {
8723 if (!JSession::checkToken()) {
8724 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
8725 }
8726 $fpath = VikRequest::getString('path', '', 'request', VIKREQUEST_ALLOWRAW);
8727 $pcont = VikRequest::getString('cont', '', 'request', VIKREQUEST_ALLOWRAW);
8728 $mainframe = JFactory::getApplication();
8729 $exists = file_exists($fpath) ? true : false;
8730 if (!$exists) {
8731 $fpath = urldecode($fpath);
8732 }
8733 $fpath = file_exists($fpath) ? $fpath : '';
8734 if (!empty($fpath)) {
8735 $fp = fopen($fpath, 'wb');
8736 $byt = (int)fwrite($fp, $pcont);
8737 fclose($fp);
8738 if ($byt > 0) {
8739 $mainframe->enqueueMessage(JText::translate('VBOUPDTMPLFILEOK'));
8740
8741 if (VBOPlatformDetection::isWordPress()) {
8742 /**
8743 * @wponly call the UpdateManager Class to temporarily store modifications made to template files
8744 */
8745 VikBookingUpdateManager::storeTemplateContent($fpath, $pcont);
8746 }
8747 } else {
8748 VikError::raiseWarning('', JText::translate('VBOUPDTMPLFILENOBYTES'));
8749 }
8750 } else {
8751 VikError::raiseWarning('', JText::translate('VBOUPDTMPLFILEERR'));
8752 }
8753 $mainframe->redirect("index.php?option=com_vikbooking&task=edittmplfile&path=".$fpath."&tmpl=component");
8754
8755 exit;
8756 }
8757
8758 public function edittmplfile() {
8759 //modal box, so we do not set menu or footer
8760
8761 VikRequest::setVar('view', VikRequest::getCmd('view', 'edittmplfile'));
8762
8763 parent::display();
8764 }
8765
8766 public function tmplfileprew() {
8767 //modal box, so we do not set menu or footer
8768
8769 VikRequest::setVar('view', VikRequest::getCmd('view', 'tmplfileprew'));
8770
8771 parent::display();
8772 }
8773
8774 public function invoices() {
8775 VikBookingHelper::printHeader("invoices");
8776
8777 VikRequest::setVar('view', VikRequest::getCmd('view', 'invoices'));
8778
8779 parent::display();
8780
8781 if (VikBooking::showFooter()) {
8782 VikBookingHelper::printFooter();
8783 }
8784 }
8785
8786 public function newmaninvoice() {
8787 VikBookingHelper::printHeader("invoices");
8788
8789 VikRequest::setVar('view', VikRequest::getCmd('view', 'managemaninvoice'));
8790
8791 parent::display();
8792
8793 if (VikBooking::showFooter()) {
8794 VikBookingHelper::printFooter();
8795 }
8796 }
8797
8798 public function editmaninvoice() {
8799 VikBookingHelper::printHeader("invoices");
8800
8801 VikRequest::setVar('view', VikRequest::getCmd('view', 'managemaninvoice'));
8802
8803 parent::display();
8804
8805 if (VikBooking::showFooter()) {
8806 VikBookingHelper::printFooter();
8807 }
8808 }
8809
8810 public function savemaninvoice() {
8811 if (!JSession::checkToken()) {
8812 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
8813 }
8814 $this->do_storemaninvoice('save');
8815 $mainframe = JFactory::getApplication();
8816 $mainframe->enqueueMessage(JText::sprintf('VBOTOTINVOICESGEND', 1, 0));
8817 $pgoto = VikRequest::getString('goto', '', 'request', VIKREQUEST_ALLOWRAW);
8818 if (!empty($pgoto)) {
8819 $mainframe->redirect(base64_decode($pgoto));
8820 exit;
8821 }
8822 $mainframe->redirect("index.php?option=com_vikbooking&task=invoices");
8823 }
8824
8825 public function updatemaninvoice()
8826 {
8827 if (!JSession::checkToken()) {
8828 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
8829 }
8830
8831 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
8832 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
8833 }
8834
8835 $invid = VikRequest::getInt('whereup', 0, 'request');
8836 $this->do_storemaninvoice('update', $invid);
8837 $mainframe = JFactory::getApplication();
8838 $mainframe->enqueueMessage(JText::sprintf('VBOTOTINVOICESGEND', 1, 0));
8839 $pgoto = VikRequest::getString('goto', '', 'request', VIKREQUEST_ALLOWRAW);
8840 if (!empty($pgoto)) {
8841 $mainframe->redirect(base64_decode($pgoto));
8842 exit;
8843 }
8844 $mainframe->redirect("index.php?option=com_vikbooking&task=invoices");
8845 }
8846
8847 public function updatemaninvoicestay()
8848 {
8849 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
8850 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
8851 }
8852
8853 $invid = VikRequest::getInt('whereup', 0, 'request');
8854 $this->do_storemaninvoice('updatestay', $invid);
8855 $mainframe = JFactory::getApplication();
8856 $mainframe->enqueueMessage(JText::sprintf('VBOTOTINVOICESGEND', 1, 0));
8857 $pgoto = VikRequest::getString('goto', '', 'request', VIKREQUEST_ALLOWRAW);
8858 if (!empty($pgoto)) {
8859 $mainframe->redirect(base64_decode($pgoto));
8860 exit;
8861 }
8862 $mainframe->redirect("index.php?option=com_vikbooking&task=editmaninvoice&cid[]=".$invid);
8863 }
8864
8865 private function do_storemaninvoice($action, $invid = 0) {
8866 $dbo = JFactory::getDBO();
8867 $mainframe = JFactory::getApplication();
8868 $pinvoice_num = VikRequest::getInt('invoice_num', '', 'request');
8869 $pinvoice_num = $pinvoice_num <= 0 ? 1 : $pinvoice_num;
8870 $pinvoice_suff = VikRequest::getString('invoice_suff', '', 'request');
8871 $pcompany_info = VikRequest::getString('company_info', '', 'request', VIKREQUEST_ALLOWHTML);
8872 $pcompany_info = strpos($pcompany_info, '<') !== false ? $pcompany_info : nl2br($pcompany_info);
8873 $pinvoice_notes = VikRequest::getString('invoice_notes', '', 'request', VIKREQUEST_ALLOWHTML);
8874 $pinvoice_notes = strpos($pinvoice_notes, '<') !== false ? $pinvoice_notes : nl2br($pinvoice_notes);
8875 $pidcustomer = VikRequest::getInt('idcustomer', '', 'request');
8876 $error_uri = strpos($action, 'update') !== false && !empty($invid) ? 'index.php?option=com_vikbooking&task=editmaninvoice&cid[]='.$invid : 'index.php?option=com_vikbooking&task=newmaninvoice';
8877 if (empty($pidcustomer)) {
8878 VikError::raiseWarning('', JText::translate('VBNOCUSTOMERS'));
8879 $mainframe->redirect($error_uri);
8880 exit;
8881 }
8882 $services = VikRequest::getVar('service', array());
8883 $nets = VikRequest::getVar('net', array());
8884 $aliqs = VikRequest::getVar('aliq', array());
8885 $taxs = VikRequest::getVar('tax', array());
8886 $tots = VikRequest::getVar('tot', array());
8887 $ptotalnet = VikRequest::getFloat('totalnet', 0, 'request');
8888 $ptotaltax = VikRequest::getFloat('totaltax', 0, 'request');
8889 $ptotaltot = VikRequest::getFloat('totaltot', 0, 'request');
8890 if (!count($services) || count($services) != count($nets) || count($services) != count($taxs) || count($services) != count($tots)) {
8891 VikError::raiseWarning('', 'Missing data.');
8892 $mainframe->redirect($error_uri);
8893 exit;
8894 }
8895 $rawcont = array(
8896 'rows' => array(),
8897 'totalnet' => $ptotalnet,
8898 'totaltax' => $ptotaltax,
8899 'totaltot' => $ptotaltot,
8900 'notes' => $pinvoice_notes,
8901 );
8902 foreach ($services as $k => $service) {
8903 if (empty($service)) {
8904 continue;
8905 }
8906 array_push($rawcont['rows'], array(
8907 'service' => $service,
8908 'net' => (float)$nets[$k],
8909 'aliq' => (isset($aliqs[$k]) ? (float)$aliqs[$k] : 0),
8910 'tax' => (float)$taxs[$k],
8911 'tot' => (float)$tots[$k],
8912 ));
8913 }
8914 // store/update manual invoice
8915 $nowts = time();
8916 $retval = 0;
8917 if (strpos($action, 'save') !== false) {
8918 $pdffname = $nowts . '_' . rand() . '.pdf';
8919 $q = "INSERT INTO `#__vikbooking_invoices` (`number`,`file_name`,`idorder`,`idcustomer`,`created_on`,`for_date`,`rawcont`) VALUES (".$dbo->quote($pinvoice_num.$pinvoice_suff).", ".$dbo->quote($pdffname).", ".($pinvoice_num - ($pinvoice_num * 2)).", ".$dbo->quote($pidcustomer).", ".$nowts.", ".$nowts.", ".$dbo->quote(json_encode($rawcont)).");";
8920 $dbo->setQuery($q);
8921 $dbo->execute();
8922 $retval = $dbo->insertid();
8923 } else {
8924 // fetch old record
8925 $q = "SELECT * FROM `#__vikbooking_invoices` WHERE `id`=".(int)$invid.";";
8926 $dbo->setQuery($q);
8927 $dbo->execute();
8928 if (!$dbo->getNumRows()) {
8929 VikError::raiseWarning('', JText::translate('VBNOINVOICESFOUND'));
8930 $mainframe->redirect($error_uri);
8931 exit;
8932 }
8933 $previnvoice = $dbo->loadAssoc();
8934 //
8935 $q = "UPDATE `#__vikbooking_invoices` SET `number`=".$dbo->quote($pinvoice_num.$pinvoice_suff).",`file_name`=".$dbo->quote($previnvoice['file_name']).",`idorder`=".($pinvoice_num - ($pinvoice_num * 2)).",`idcustomer`=".$dbo->quote($pidcustomer).",`created_on`=".$nowts.",`rawcont`=".$dbo->quote(json_encode($rawcont))." WHERE `id`=".(int)$previnvoice['id'].";";
8936 $dbo->setQuery($q);
8937 $dbo->execute();
8938 $retval = $previnvoice['id'];
8939 }
8940 // update config values for the invoice
8941 $q = "UPDATE `#__vikbooking_config` SET `setting`=".$dbo->quote($pcompany_info)." WHERE `param`='invcompanyinfo';";
8942 $dbo->setQuery($q);
8943 $dbo->execute();
8944 // generate the custom invoice
8945 $result = VikBooking::generateCustomInvoice($retval);
8946 //
8947 $nextinv = VikBooking::getNextInvoiceNumber();
8948 $updatenum = ($pinvoice_num >= $nextinv);
8949 if ($updatenum) {
8950 /**
8951 * IMPORTANT: update the next invoice number after calling the e-Invocing drivers
8952 * to avoid conflicts with the drivers for the e-invoices generation.
8953 */
8954 $q = "UPDATE `#__vikbooking_config` SET `setting`=".$dbo->quote(($pinvoice_num - 1))." WHERE `param`='invoiceinum';";
8955 $dbo->setQuery($q);
8956 $dbo->execute();
8957 }
8958
8959 return $retval;
8960 }
8961
8962 public function downloadinvoices() {
8963 $ids = VikRequest::getVar('cid', array(0));
8964 if (@count($ids) > 0) {
8965 $dbo = JFactory::getDBO();
8966 $q = "SELECT * FROM `#__vikbooking_invoices` WHERE `id` IN (".implode(', ', $ids).");";
8967 $dbo->setQuery($q);
8968 $dbo->execute();
8969 if ($dbo->getNumRows() > 0) {
8970 $invoices = $dbo->loadAssocList();
8971 if (!(count($invoices) > 1)) {
8972 //Single Invoice Download
8973 if (file_exists(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'invoices'.DIRECTORY_SEPARATOR.'generated'.DIRECTORY_SEPARATOR.$invoices[0]['file_name'])) {
8974 header("Content-type:application/pdf");
8975 header("Content-Disposition:attachment;filename=".$invoices[0]['file_name']);
8976 readfile(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'invoices'.DIRECTORY_SEPARATOR.'generated'.DIRECTORY_SEPARATOR.$invoices[0]['file_name']);
8977 exit;
8978 }
8979 } else {
8980 //Multiple Invoices Download
8981 $to_zip = array();
8982 foreach ($invoices as $k => $invoice) {
8983 $to_zip[$k]['name'] = $invoice['file_name'];
8984 $to_zip[$k]['path'] = VBO_SITE_PATH.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'invoices'.DIRECTORY_SEPARATOR.'generated'.DIRECTORY_SEPARATOR.$invoice['file_name'];
8985 }
8986 if (class_exists('ZipArchive')) {
8987 $zip_path = VBO_SITE_PATH.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'invoices'.DIRECTORY_SEPARATOR.'generated'.DIRECTORY_SEPARATOR.date('Y-m-d').'-invoices.zip';
8988 $zip = new ZipArchive;
8989 $zip->open($zip_path, ZipArchive::CREATE);
8990 foreach ($to_zip as $k => $zipv) {
8991 $zip->addFile($zipv['path'], $zipv['name']);
8992 }
8993 $zip->close();
8994 header("Content-type:application/zip");
8995 header("Content-Disposition:attachment;filename=".date('Y-m-d').'-invoices.zip');
8996 header("Content-Length:".filesize($zip_path));
8997 readfile($zip_path);
8998 unlink($zip_path);
8999 exit;
9000 } else {
9001 //Class ZipArchive does not exist
9002 VikError::raiseWarning('', 'Class ZipArchive does not exist on your server. Download the files one by one.');
9003 }
9004 }
9005 }
9006 }
9007 $mainframe = JFactory::getApplication();
9008 $mainframe->redirect("index.php?option=com_vikbooking&task=invoices");
9009 }
9010
9011 public function resendinvoices() {
9012 $ids = VikRequest::getVar('cid', array(0));
9013 $mainframe = JFactory::getApplication();
9014 if (!(count($ids) > 0)) {
9015 $mainframe->redirect("index.php?option=com_vikbooking&task=invoices");
9016 exit;
9017 }
9018 $dbo = JFactory::getDBO();
9019 $invoices = array();
9020 $q = "SELECT `i`.*,`o`.`custmail`,`c`.`email` AS `customer_email`, CONCAT_WS(' ',`c`.`first_name`,`c`.`last_name`) AS `customer_name`,`c`.`country` AS `customer_country`,`nat`.`country_name` ".
9021 "FROM `#__vikbooking_invoices` AS `i` " .
9022 "LEFT JOIN `#__vikbooking_orders` `o` ON `o`.`id`=`i`.`idorder` " .
9023 "LEFT JOIN `#__vikbooking_customers` `c` ON `c`.`id`=`i`.`idcustomer` " .
9024 "LEFT JOIN `#__vikbooking_countries` `nat` ON `nat`.`country_3_code`=`c`.`country` " .
9025 "WHERE `i`.`id` IN (".implode(', ', $ids).") AND (`i`.`idorder` < 0 OR (`o`.`status`='confirmed' AND `o`.`total` > 0)) ORDER BY `o`.`id` ASC;";
9026 $dbo->setQuery($q);
9027 $dbo->execute();
9028 if ($dbo->getNumRows() > 0) {
9029 $invoices = $dbo->loadAssocList();
9030 }
9031 if (!(count($invoices) > 0)) {
9032 VikError::raiseWarning('', JText::translate('VBOGENINVERRNOBOOKINGS'));
9033 $mainframe->redirect("index.php?option=com_vikbooking&task=invoices");
9034 exit;
9035 }
9036 $tot_generated = 0;
9037 $tot_sent = 0;
9038 foreach ($invoices as $bkey => $invoice) {
9039 $invoice['custmail'] = empty($invoice['custmail']) && !empty($invoice['customer_email']) ? $invoice['customer_email'] : $invoice['custmail'];
9040 $invoices[$bkey] = $invoice;
9041 $send_res = VikBooking::sendBookingInvoice($invoice['id'], $invoice);
9042 if ($send_res !== false) {
9043 $tot_sent++;
9044 }
9045 }
9046 $mainframe->enqueueMessage(JText::sprintf('VBOTOTINVOICESGEND', $tot_generated, $tot_sent));
9047 $mainframe->redirect("index.php?option=com_vikbooking&task=invoices");
9048 }
9049
9050 public function removeinvoices()
9051 {
9052 if (!JFactory::getUser()->authorise('core.delete', 'com_vikbooking')) {
9053 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
9054 }
9055
9056 $ids = VikRequest::getVar('cid', array());
9057 $tot_removed = 0;
9058 $dbo = JFactory::getDbo();
9059
9060 foreach ($ids as $d) {
9061 $q = "SELECT * FROM `#__vikbooking_invoices` WHERE `id`=".(int)$d.";";
9062 $dbo->setQuery($q);
9063 $dbo->execute();
9064 if ($dbo->getNumRows() == 1) {
9065 $cur_invoice = $dbo->loadAssoc();
9066 if (file_exists(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'invoices'.DIRECTORY_SEPARATOR.'generated'.DIRECTORY_SEPARATOR.$cur_invoice['file_name'])) {
9067 unlink(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'invoices'.DIRECTORY_SEPARATOR.'generated'.DIRECTORY_SEPARATOR.$cur_invoice['file_name']);
9068 }
9069 $q = "DELETE FROM `#__vikbooking_invoices` WHERE `id`=".(int)$d.";";
9070 $dbo->setQuery($q);
9071 $dbo->execute();
9072 $tot_removed++;
9073 }
9074 }
9075
9076 $mainframe = JFactory::getApplication();
9077 $mainframe->enqueueMessage(JText::sprintf('VBOTOTINVOICESRMVD', $tot_removed));
9078 $mainframe->redirect("index.php?option=com_vikbooking&task=invoices");
9079 }
9080
9081 public function geninvoices()
9082 {
9083 $dbo = JFactory::getDbo();
9084 $app = JFactory::getApplication();
9085
9086 $ids = VikRequest::getVar('cid', array());
9087
9088 if (!$ids) {
9089 $app->redirect("index.php?option=com_vikbooking&task=orders");
9090 exit;
9091 }
9092
9093 $pinvoice_num = VikRequest::getInt('invoice_num', '', 'request');
9094 $pinvoice_num = $pinvoice_num <= 0 ? 1 : $pinvoice_num;
9095 $pinvoice_suff = VikRequest::getString('invoice_suff', '', 'request');
9096 $pinvoice_date = VikRequest::getString('invoice_date', '', 'request');
9097 $pcompany_info = VikRequest::getString('company_info', '', 'request', VIKREQUEST_ALLOWHTML);
9098 $pcompany_info = strpos($pcompany_info, '<') !== false ? $pcompany_info : nl2br($pcompany_info);
9099 $pinvoice_send = VikRequest::getInt('invoice_send', '', 'request');
9100 $pinvoice_send = $pinvoice_send > 0 ? true : false;
9101 $increment_inv = true;
9102 $pconfirmgen = VikRequest::getInt('confirmgen', '', 'request');
9103
9104 // if editing an invoice (re-creating an existing invoice for a booking), do not increment the invoice number
9105 if (count($ids) === 1) {
9106 $q = "SELECT `number` FROM `#__vikbooking_invoices` WHERE `idorder`=".(int)$ids[0].";";
9107 $dbo->setQuery($q);
9108 $dbo->execute();
9109 if ($dbo->getNumRows() == 1) {
9110 $increment_inv = false;
9111 }
9112 }
9113
9114 // get bookings
9115 $dbo->setQuery(
9116 $dbo->getQuery(true)
9117 ->select($dbo->qn('o') . '.*')
9118 ->select($dbo->qn('co.idcustomer'))
9119 ->select('CONCAT_WS(\' \', ' . $dbo->qn('c.first_name') . ', ' . $dbo->qn('c.last_name') . ') AS ' . $dbo->qn('customer_name'))
9120 ->select([
9121 $dbo->qn('c.pin', 'customer_pin'),
9122 $dbo->qn('nat.country_name'),
9123 ])
9124 ->from($dbo->qn('#__vikbooking_orders', 'o'))
9125 ->leftJoin($dbo->qn('#__vikbooking_customers_orders', 'co') . ' ON ' . $dbo->qn('co.idorder') . ' = ' . $dbo->qn('o.id'))
9126 ->leftJoin($dbo->qn('#__vikbooking_customers', 'c') . ' ON ' . $dbo->qn('c.id') . ' = ' . $dbo->qn('co.idcustomer'))
9127 ->leftJoin($dbo->qn('#__vikbooking_countries', 'nat') . ' ON ' . $dbo->qn('nat.country_3_code') . ' = ' . $dbo->qn('o.country'))
9128 ->where($dbo->qn('o.id') . ' IN (' . implode(', ', array_map('intval', $ids)) . ')')
9129 ->where($dbo->qn('o.status') . ' = ' . $dbo->q('confirmed'))
9130 ->where($dbo->qn('o.total') . ' > 0')
9131 ->order($dbo->qn('o.id') . ' ASC')
9132 );
9133
9134 $bookings = $dbo->loadAssocList();
9135
9136 if (!$bookings) {
9137 VikError::raiseWarning('', JText::translate('VBOGENINVERRNOBOOKINGS'));
9138 $app->redirect("index.php?option=com_vikbooking&task=orders");
9139 exit;
9140 }
9141
9142 $tot_generated = 0;
9143 $tot_sent = 0;
9144 foreach ($bookings as $bkey => $booking) {
9145 $gen_res = VikBooking::generateBookingInvoice($booking, $pinvoice_num, $pinvoice_suff, $pinvoice_date, $pcompany_info);
9146 if ($gen_res !== false && $gen_res > 0) {
9147 $tot_generated++;
9148 $pinvoice_num++;
9149 if ($pinvoice_send) {
9150 $send_res = VikBooking::sendBookingInvoice($gen_res, $booking);
9151 if ($send_res !== false) {
9152 $tot_sent++;
9153 }
9154 }
9155 } else {
9156 VikError::raiseWarning('', JText::sprintf('VBOGENINVERRBOOKING', $booking['id']));
9157 }
9158 }
9159
9160 if ($tot_generated > 0 && $increment_inv === true) {
9161 /**
9162 * IMPORTANT: update the next invoice number after calling generateBookingInvoice()
9163 * to avoid conflicts with the drivers for the e-invoices generation.
9164 */
9165 $q = "UPDATE `#__vikbooking_config` SET `setting`=".$dbo->quote(($pinvoice_num - 1))." WHERE `param`='invoiceinum';";
9166 $dbo->setQuery($q);
9167 $dbo->execute();
9168 }
9169
9170 $q = "UPDATE `#__vikbooking_config` SET `setting`=".$dbo->quote($pinvoice_suff)." WHERE `param`='invoicesuffix';";
9171 $dbo->setQuery($q);
9172 $dbo->execute();
9173
9174 $q = "UPDATE `#__vikbooking_config` SET `setting`=".$dbo->quote($pcompany_info)." WHERE `param`='invcompanyinfo';";
9175 $dbo->setQuery($q);
9176 $dbo->execute();
9177
9178 $app->enqueueMessage(JText::sprintf('VBOTOTINVOICESGEND', $tot_generated, $tot_sent));
9179
9180 if ($pconfirmgen > 0) {
9181 $app->redirect("index.php?option=com_vikbooking&task=invoices&show=".$pconfirmgen);
9182 } elseif (count($bookings) === 1) {
9183 // go to the back-end booking details page
9184 $app->redirect("index.php?option=com_vikbooking&task=editorder&cid[]=" . $bookings[0]['id']);
9185 } else {
9186 $app->redirect("index.php?option=com_vikbooking&task=orders");
9187 }
9188 }
9189
9190 public function optionals() {
9191 VikBookingHelper::printHeader("6");
9192
9193 VikRequest::setVar('view', VikRequest::getCmd('view', 'optionals'));
9194
9195 parent::display();
9196
9197 if (VikBooking::showFooter()) {
9198 VikBookingHelper::printFooter();
9199 }
9200 }
9201
9202 public function newoptionals() {
9203 VikBookingHelper::printHeader("6");
9204
9205 VikRequest::setVar('view', VikRequest::getCmd('view', 'manageoptional'));
9206
9207 parent::display();
9208
9209 if (VikBooking::showFooter()) {
9210 VikBookingHelper::printFooter();
9211 }
9212 }
9213
9214 public function editoptional() {
9215 VikBookingHelper::printHeader("6");
9216
9217 VikRequest::setVar('view', VikRequest::getCmd('view', 'manageoptional'));
9218
9219 parent::display();
9220
9221 if (VikBooking::showFooter()) {
9222 VikBookingHelper::printFooter();
9223 }
9224 }
9225
9226 public function updateoptional()
9227 {
9228 if (!JSession::checkToken()) {
9229 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
9230 }
9231
9232 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
9233 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
9234 }
9235
9236 $this->do_updateoptional();
9237 }
9238
9239 public function updateoptionalstay()
9240 {
9241 if (!JSession::checkToken()) {
9242 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
9243 }
9244
9245 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
9246 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
9247 }
9248
9249 $this->do_updateoptional(true);
9250 }
9251
9252 private function do_updateoptional($stay = false) {
9253 $dbo = JFactory::getDbo();
9254 $app = JFactory::getApplication();
9255 $poptname = VikRequest::getString('optname', '', 'request');
9256 $poptdescr = VikRequest::getString('optdescr', '', 'request', VIKREQUEST_ALLOWHTML);
9257 $poptcost = VikRequest::getFloat('optcost', '', 'request');
9258 $poptperday = VikRequest::getString('optperday', '', 'request');
9259 $poptperperson = VikRequest::getString('optperperson', '', 'request');
9260 $pmaxprice = VikRequest::getFloat('maxprice', '', 'request');
9261 $popthmany = VikRequest::getString('opthmany', '', 'request');
9262 $poptaliq = VikRequest::getInt('optaliq', '', 'request');
9263 $pwhereup = VikRequest::getString('whereup', '', 'request');
9264 $pautoresize = VikRequest::getString('autoresize', '', 'request');
9265 $presizeto = VikRequest::getString('resizeto', '', 'request');
9266 $pifchildren = VikRequest::getString('ifchildren', '', 'request');
9267 $pifchildren = $pifchildren == "1" ? 1 : 0;
9268 $pmaxquant = VikRequest::getString('maxquant', '', 'request');
9269 $pmaxquant = empty($pmaxquant) ? 0 : intval($pmaxquant);
9270 $pforcesel = VikRequest::getString('forcesel', '', 'request');
9271 $pforceval = VikRequest::getString('forceval', '', 'request');
9272 $pforcevalperday = VikRequest::getString('forcevalperday', '', 'request');
9273 $pforcevalperchild = VikRequest::getString('forcevalperchild', '', 'request');
9274 $pforcesummary = VikRequest::getString('forcesummary', '', 'request');
9275 $pforcesel = $pforcesel == "1" ? 1 : 0;
9276 $pis_citytax = VikRequest::getString('is_citytax', '', 'request');
9277 $pis_fee = VikRequest::getString('is_fee', '', 'request');
9278 $pis_citytax = $pis_citytax == "1" && $pis_fee != "1" ? 1 : 0;
9279 $pis_fee = $pis_fee == "1" && $pis_citytax == 0 ? 1 : 0;
9280 $pagefrom = VikRequest::getVar('agefrom', array());
9281 $pageto = VikRequest::getVar('ageto', array());
9282 $pagecost = VikRequest::getVar('agecost', array());
9283 $pagectype = VikRequest::getVar('agectype', array());
9284 $palwaysav = VikRequest::getInt('alwaysav', 0, 'request');
9285 $pavfrom = VikRequest::getString('avfrom', '', 'request');
9286 $pavto = VikRequest::getString('avto', '', 'request');
9287 $ppcentroom = VikRequest::getInt('pcentroom', 0, 'request');
9288 $pidrooms = VikRequest::getVar('idrooms', array());
9289 $optavstr = empty($palwaysav) && !empty($pavfrom) && !empty($pavto) ? VikBooking::getDateTimestamp($pavfrom, 0, 0, 0).';'.VikBooking::getDateTimestamp($pavto, 23, 59, 59) : '';
9290 if ($pforcesel == 1) {
9291 $strforceval = intval($pforceval)."-".($pforcevalperday == "1" ? "1" : "0")."-".($pforcevalperchild == "1" ? "1" : "0")."-".($pforcesummary == "1" ? "1" : "0");
9292 } else {
9293 $strforceval = "";
9294 }
9295 $minguestsnum = VikRequest::getInt('minguestsnum', 0, 'request');
9296 $mingueststype = VikRequest::getString('mingueststype', 'guests', 'request');
9297 $minguestsnum = $minguestsnum < 0 ? 0 : $minguestsnum;
9298 $mingueststype = !empty($mingueststype) && !in_array($mingueststype, array('adults', 'guests')) ? 'guests' : $mingueststype;
9299 $maxguestsnum = VikRequest::getInt('maxguestsnum', 0, 'request');
9300 $maxgueststype = VikRequest::getString('maxgueststype', 'guests', 'request');
9301 $maxguestsnum = $maxguestsnum < 0 ? 0 : $maxguestsnum;
9302 $maxgueststype = !empty($maxgueststype) && !in_array($maxgueststype, array('adults', 'guests')) ? 'guests' : $maxgueststype;
9303 $minguests = VikRequest::getInt('minguests', 0, 'request');
9304 $minguests_conflict = false;
9305 if ($minguests > 0 && $minguestsnum > 0 && $maxguestsnum > 0) {
9306 if ($minguestsnum >= $maxguestsnum) {
9307 $minguests_conflict = JText::translate('VBOMINMAXGUESTSOPTCONFL1');
9308 } elseif (($maxguestsnum - $minguestsnum) < 2) {
9309 $minguests_conflict = JText::translate('VBOMINMAXGUESTSOPTCONFL2');
9310 }
9311 }
9312 if (!$minguests || $minguests_conflict !== false) {
9313 $minguestsnum = 0;
9314 $maxguestsnum = 0;
9315 if ($minguests_conflict !== false) {
9316 // raise warning, but do not stop the process
9317 VikError::raiseWarning('', $minguests_conflict);
9318 }
9319 }
9320 $damagedep = VikRequest::getInt('damagedep', 0, 'request');
9321 $pet_fee = VikRequest::getInt('pet_fee', 0, 'request');
9322 $oparams = array(
9323 'minguestsnum' => $minguestsnum,
9324 'mingueststype' => $mingueststype,
9325 'maxguestsnum' => $maxguestsnum,
9326 'maxgueststype' => $maxgueststype,
9327 'damagedep' => $damagedep,
9328 'pet_fee' => $pet_fee,
9329 );
9330 /**
9331 * We fetch the previous params to merge them with the new ones
9332 * in case some properties have been set somewhere else.
9333 * For example, the damage deposit transmission to Booking.com.
9334 */
9335 $cur_oparams = array();
9336 $q = "SELECT `oparams` FROM `#__vikbooking_optionals` WHERE `id`=" . (int)$pwhereup . ";";
9337 $dbo->setQuery($q);
9338 $dbo->execute();
9339 if ($dbo->getNumRows()) {
9340 $cur_oparams = $dbo->loadResult();
9341 $cur_oparams = !empty($cur_oparams) ? json_decode($cur_oparams, true) : array();
9342 $cur_oparams = !is_array($cur_oparams) ? array() : $cur_oparams;
9343 // merge previous params with the new ones to get the new values
9344 $oparams = array_merge($cur_oparams, $oparams);
9345 }
9346 //
9347 if (!empty($poptname)) {
9348 if (intval($_FILES['optimg']['error']) == 0 && VikBooking::caniWrite(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR) && trim($_FILES['optimg']['name'])!="") {
9349 jimport('joomla.filesystem.file');
9350 $updpath = VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR;
9351 if (@is_uploaded_file($_FILES['optimg']['tmp_name'])) {
9352 $safename=JFile::makeSafe(str_replace(" ", "_", strtolower($_FILES['optimg']['name'])));
9353 if (file_exists($updpath.$safename)) {
9354 $j=1;
9355 while (file_exists($updpath.$j.$safename)) {
9356 $j++;
9357 }
9358 $pwhere=$updpath.$j.$safename;
9359 } else {
9360 $j="";
9361 $pwhere=$updpath.$safename;
9362 }
9363 if (!getimagesize($_FILES['optimg']['tmp_name']) || !preg_match("/\.(a?png|jpe?g|bmp|gif|ico|webp)\z/i", $safename)) {
9364 @unlink($pwhere);
9365 $picon="";
9366 } else {
9367 VikBooking::uploadFile($_FILES['optimg']['tmp_name'], $pwhere);
9368 @chmod($pwhere, 0644);
9369 $picon=$j.$safename;
9370 if ($pautoresize=="1" && !empty($presizeto)) {
9371 $eforj = new vikResizer();
9372 $origmod = $eforj->proportionalImage($pwhere, $updpath.'r_'.$j.$safename, $presizeto, $presizeto);
9373 if ($origmod) {
9374 @unlink($pwhere);
9375 $picon='r_'.$j.$safename;
9376 }
9377 }
9378 }
9379 } else {
9380 $picon="";
9381 }
9382 } else {
9383 $picon="";
9384 }
9385 ($poptperday=="each" ? $poptperday="1" : $poptperday="0");
9386 $poptperperson=($poptperperson=="each" ? "1" : "0");
9387 ($popthmany=="yes" ? $popthmany="1" : $popthmany="0");
9388 $ageintervalstr = '';
9389 if ($pifchildren == 1 && count($pagefrom) > 0 && count($pagecost) > 0 && count($pagefrom) == count($pagecost)) {
9390 foreach ($pagefrom as $kage => $vage) {
9391 $afrom = intval($vage);
9392 $ato = intval($pageto[$kage]);
9393 $acost = floatval($pagecost[$kage]);
9394 if (strlen($vage) > 0 && strlen($pagecost[$kage]) > 0) {
9395 if ($ato < $afrom) $ato = $afrom;
9396 $ageintervalstr .= $afrom.'_'.$ato.'_'.$acost.(array_key_exists($kage, $pagectype) && strpos($pagectype[$kage], '%') !== false ? '_%'.(strpos($pagectype[$kage], '%b') !== false ? 'b' : '') : '').';;';
9397 }
9398 }
9399 $ageintervalstr = rtrim($ageintervalstr, ';;');
9400 if (!empty($ageintervalstr)) {
9401 $pforcesel = 1;
9402 }
9403 }
9404 $q = "UPDATE `#__vikbooking_optionals` SET `name`=".$dbo->quote($poptname).",`descr`=".$dbo->quote($poptdescr).",`cost`=".$dbo->quote($poptcost).",`perday`=".$dbo->quote($poptperday).",`hmany`=".$dbo->quote($popthmany).",".(strlen($picon)>0 ? "`img`='".$picon."'," : "")."`idiva`=".$dbo->quote($poptaliq).", `maxprice`=".$dbo->quote($pmaxprice).", `forcesel`='".$pforcesel."', `forceval`='".$strforceval."', `perperson`='".$poptperperson."', `ifchildren`='".$pifchildren."', `maxquant`='".$pmaxquant."', `ageintervals`='".$ageintervalstr."',`is_citytax`=".$pis_citytax.",`is_fee`=".$pis_fee.",`alwaysav`=".$dbo->quote($optavstr).",`pcentroom`=".$dbo->quote($ppcentroom).",`oparams`=" . $dbo->quote(json_encode($oparams)) . " WHERE `id`=".$dbo->quote($pwhereup).";";
9405 $dbo->setQuery($q);
9406 $dbo->execute();
9407 $app->enqueueMessage(JText::translate('VBOSUCCUPDOPTION'));
9408
9409 // assign/unset option-rooms relations
9410 $rooms_with_opt = array();
9411 if (count($pidrooms)) {
9412 // assign this new option to the requested rooms
9413 foreach ($pidrooms as $idroom) {
9414 if (empty($idroom)) {
9415 continue;
9416 }
9417 $q = "SELECT `id`, `idopt` FROM `#__vikbooking_rooms` WHERE `id`=" . (int)$idroom . ";";
9418 $dbo->setQuery($q);
9419 $dbo->execute();
9420 if (!$dbo->getNumRows()) {
9421 continue;
9422 }
9423 $room_data = $dbo->loadAssoc();
9424 array_push($rooms_with_opt, $room_data['id']);
9425 $current_opts = empty($room_data['idopt']) ? array() : explode(';', rtrim($room_data['idopt'], ';'));
9426 if (in_array((string)$pwhereup, $current_opts)) {
9427 continue;
9428 }
9429 if (count($current_opts) === 1 && (string)$current_opts[0] == '0') {
9430 // make sure we do not concatenate a real ID to 0
9431 $current_opts = array();
9432 }
9433 array_push($current_opts, $pwhereup);
9434 $new_opts = implode(';', $current_opts) . ';';
9435 $q = "UPDATE `#__vikbooking_rooms` SET `idopt`=" . $dbo->quote($new_opts) . " WHERE `id`={$room_data['id']};";
9436 $dbo->setQuery($q);
9437 $dbo->execute();
9438 }
9439 }
9440 if (!count($rooms_with_opt)) {
9441 // get all rooms to unset this option (if previously set)
9442 array_push($rooms_with_opt, '0');
9443 }
9444 // unset the option from the other rooms that may have it
9445 $q = "SELECT `id`, `idopt` FROM `#__vikbooking_rooms` WHERE `id` NOT IN (" . implode(', ', $rooms_with_opt) . ");";
9446 $dbo->setQuery($q);
9447 $dbo->execute();
9448 if ($dbo->getNumRows()) {
9449 $unset_rooms_opt = $dbo->loadAssocList();
9450 foreach ($unset_rooms_opt as $room_data) {
9451 $current_opts = empty($room_data['idopt']) ? array() : explode(';', rtrim($room_data['idopt'], ';'));
9452 if (!in_array((string)$pwhereup, $current_opts)) {
9453 // this room is not using this option
9454 continue;
9455 }
9456 $optkey = array_search((string)$pwhereup, $current_opts);
9457 if ($optkey === false) {
9458 // key not found
9459 continue;
9460 }
9461 // unset this option ID from the string
9462 unset($current_opts[$optkey]);
9463 if (!count($current_opts)) {
9464 // a room with no options assigned will be listed as "0;"
9465 $current_opts = array(0);
9466 }
9467 $new_opts = implode(';', $current_opts) . ';';
9468 $q = "UPDATE `#__vikbooking_rooms` SET `idopt`=" . $dbo->quote($new_opts) . " WHERE `id`={$room_data['id']};";
9469 $dbo->setQuery($q);
9470 $dbo->execute();
9471 }
9472 }
9473 //
9474
9475 }
9476 $app->redirect("index.php?option=com_vikbooking&task=" . ($stay ? 'editoptional&cid[]=' . $pwhereup : 'optionals'));
9477 }
9478
9479 public function createoptionals()
9480 {
9481 if (!JSession::checkToken()) {
9482 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
9483 }
9484
9485 if (!JFactory::getUser()->authorise('core.create', 'com_vikbooking')) {
9486 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
9487 }
9488
9489 $this->do_createoptionals();
9490 }
9491
9492 public function createoptionalsstay()
9493 {
9494 if (!JSession::checkToken()) {
9495 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
9496 }
9497
9498 if (!JFactory::getUser()->authorise('core.create', 'com_vikbooking')) {
9499 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
9500 }
9501
9502 $this->do_createoptionals(true);
9503 }
9504
9505 private function do_createoptionals($stay = false) {
9506 $dbo = JFactory::getDbo();
9507 $poptname = VikRequest::getString('optname', '', 'request');
9508 $poptdescr = VikRequest::getString('optdescr', '', 'request', VIKREQUEST_ALLOWHTML);
9509 $poptcost = VikRequest::getFloat('optcost', '', 'request');
9510 $poptperday = VikRequest::getString('optperday', '', 'request');
9511 $poptperperson = VikRequest::getString('optperperson', '', 'request');
9512 $pmaxprice = VikRequest::getFloat('maxprice', '', 'request');
9513 $popthmany = VikRequest::getString('opthmany', '', 'request');
9514 $poptaliq = VikRequest::getInt('optaliq', '', 'request');
9515 $pautoresize = VikRequest::getString('autoresize', '', 'request');
9516 $presizeto = VikRequest::getString('resizeto', '', 'request');
9517 $pifchildren = VikRequest::getString('ifchildren', '', 'request');
9518 $pifchildren = $pifchildren == "1" ? 1 : 0;
9519 $pmaxquant = VikRequest::getString('maxquant', '', 'request');
9520 $pmaxquant = empty($pmaxquant) ? 0 : intval($pmaxquant);
9521 $pforcesel = VikRequest::getString('forcesel', '', 'request');
9522 $pforceval = VikRequest::getString('forceval', '', 'request');
9523 $pforcevalperday = VikRequest::getString('forcevalperday', '', 'request');
9524 $pforcevalperchild = VikRequest::getString('forcevalperchild', '', 'request');
9525 $pforcesummary = VikRequest::getString('forcesummary', '', 'request');
9526 $pforcesel = $pforcesel == "1" ? 1 : 0;
9527 $pis_citytax = VikRequest::getString('is_citytax', '', 'request');
9528 $pis_fee = VikRequest::getString('is_fee', '', 'request');
9529 $pis_citytax = $pis_citytax == "1" && $pis_fee != "1" ? 1 : 0;
9530 $pis_fee = $pis_fee == "1" && $pis_citytax == 0 ? 1 : 0;
9531 $pagefrom = VikRequest::getVar('agefrom', array());
9532 $pageto = VikRequest::getVar('ageto', array());
9533 $pagecost = VikRequest::getVar('agecost', array());
9534 $pagectype = VikRequest::getVar('agectype', array());
9535 $palwaysav = VikRequest::getInt('alwaysav', 0, 'request');
9536 $pavfrom = VikRequest::getString('avfrom', '', 'request');
9537 $pavto = VikRequest::getString('avto', '', 'request');
9538 $ppcentroom = VikRequest::getInt('pcentroom', 0, 'request');
9539 $pidrooms = VikRequest::getVar('idrooms', array());
9540 $optavstr = empty($palwaysav) && !empty($pavfrom) && !empty($pavto) ? VikBooking::getDateTimestamp($pavfrom, 0, 0, 0).';'.VikBooking::getDateTimestamp($pavto, 23, 59, 59) : '';
9541 if ($pforcesel == 1) {
9542 $strforceval = intval($pforceval)."-".($pforcevalperday == "1" ? "1" : "0")."-".($pforcevalperchild == "1" ? "1" : "0")."-".($pforcesummary == "1" ? "1" : "0");
9543 } else {
9544 $strforceval = "";
9545 }
9546 $minguestsnum = VikRequest::getInt('minguestsnum', 0, 'request');
9547 $mingueststype = VikRequest::getString('mingueststype', 'guests', 'request');
9548 $minguestsnum = $minguestsnum < 0 ? 0 : $minguestsnum;
9549 $mingueststype = !empty($mingueststype) && !in_array($mingueststype, array('adults', 'guests')) ? 'guests' : $mingueststype;
9550 $maxguestsnum = VikRequest::getInt('maxguestsnum', 0, 'request');
9551 $maxgueststype = VikRequest::getString('maxgueststype', 'guests', 'request');
9552 $maxguestsnum = $maxguestsnum < 0 ? 0 : $maxguestsnum;
9553 $maxgueststype = !empty($maxgueststype) && !in_array($maxgueststype, array('adults', 'guests')) ? 'guests' : $maxgueststype;
9554 $minguests = VikRequest::getInt('minguests', 0, 'request');
9555 $minguests_conflict = false;
9556 if ($minguests > 0 && $minguestsnum > 0 && $maxguestsnum > 0) {
9557 if ($minguestsnum >= $maxguestsnum) {
9558 $minguests_conflict = JText::translate('VBOMINMAXGUESTSOPTCONFL1');
9559 } elseif (($maxguestsnum - $minguestsnum) < 2) {
9560 $minguests_conflict = JText::translate('VBOMINMAXGUESTSOPTCONFL2');
9561 }
9562 }
9563 if (!$minguests || $minguests_conflict !== false) {
9564 $minguestsnum = 0;
9565 $maxguestsnum = 0;
9566 if ($minguests_conflict !== false) {
9567 // raise warning, but do not stop the process
9568 VikError::raiseWarning('', $minguests_conflict);
9569 }
9570 }
9571 $damagedep = VikRequest::getInt('damagedep', 0, 'request');
9572 $pet_fee = VikRequest::getInt('pet_fee', 0, 'request');
9573 $oparams = array(
9574 'minguestsnum' => $minguestsnum,
9575 'mingueststype' => $mingueststype,
9576 'maxguestsnum' => $maxguestsnum,
9577 'maxgueststype' => $maxgueststype,
9578 'damagedep' => $damagedep,
9579 'pet_fee' => $pet_fee,
9580 );
9581 if (!empty($poptname)) {
9582 if (intval($_FILES['optimg']['error']) == 0 && VikBooking::caniWrite(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR) && trim($_FILES['optimg']['name'])!="") {
9583 jimport('joomla.filesystem.file');
9584 $updpath = VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR;
9585 if (@is_uploaded_file($_FILES['optimg']['tmp_name'])) {
9586 $safename=JFile::makeSafe(str_replace(" ", "_", strtolower($_FILES['optimg']['name'])));
9587 if (file_exists($updpath.$safename)) {
9588 $j = 1;
9589 while (file_exists($updpath.$j.$safename)) {
9590 $j++;
9591 }
9592 $pwhere = $updpath.$j.$safename;
9593 } else {
9594 $j = "";
9595 $pwhere = $updpath.$safename;
9596 }
9597 if (!getimagesize($_FILES['optimg']['tmp_name']) || !preg_match("/\.(a?png|jpe?g|bmp|gif|ico|webp)\z/i", $safename)) {
9598 @unlink($pwhere);
9599 $picon = "";
9600 } else {
9601 VikBooking::uploadFile($_FILES['optimg']['tmp_name'], $pwhere);
9602 @chmod($pwhere, 0644);
9603 $picon = $j.$safename;
9604 if ($pautoresize == "1" && !empty($presizeto)) {
9605 $eforj = new vikResizer();
9606 $origmod = $eforj->proportionalImage($pwhere, $updpath.'r_'.$j.$safename, $presizeto, $presizeto);
9607 if ($origmod) {
9608 @unlink($pwhere);
9609 $picon = 'r_'.$j.$safename;
9610 }
9611 }
9612 }
9613 } else {
9614 $picon = "";
9615 }
9616 } else {
9617 $picon = "";
9618 }
9619 $poptperday = ($poptperday == "each" ? "1" : "0");
9620 $poptperperson = ($poptperperson == "each" ? "1" : "0");
9621 ($popthmany == "yes" ? $popthmany = "1" : $popthmany = "0");
9622 $ageintervalstr = '';
9623 if ($pifchildren == 1 && count($pagefrom) > 0 && count($pagecost) > 0 && count($pagefrom) == count($pagecost)) {
9624 foreach ($pagefrom as $kage => $vage) {
9625 $afrom = intval($vage);
9626 $ato = intval($pageto[$kage]);
9627 $acost = floatval($pagecost[$kage]);
9628 if (strlen($vage) > 0 && strlen($pagecost[$kage]) > 0) {
9629 if ($ato < $afrom) $ato = $afrom;
9630 $ageintervalstr .= $afrom.'_'.$ato.'_'.$acost.(array_key_exists($kage, $pagectype) && strpos($pagectype[$kage], '%') !== false ? '_%'.(strpos($pagectype[$kage], '%b') !== false ? 'b' : '') : '').';;';
9631 }
9632 }
9633 $ageintervalstr = rtrim($ageintervalstr, ';;');
9634 if (!empty($ageintervalstr)) {
9635 $pforcesel = 1;
9636 }
9637 }
9638 $q = "SELECT `ordering` FROM `#__vikbooking_optionals` ORDER BY `#__vikbooking_optionals`.`ordering` DESC LIMIT 1;";
9639 $dbo->setQuery($q);
9640 $dbo->execute();
9641 if ($dbo->getNumRows() == 1) {
9642 $getlast = $dbo->loadResult();
9643 $newsortnum = $getlast + 1;
9644 } else {
9645 $newsortnum = 1;
9646 }
9647 $q = "INSERT INTO `#__vikbooking_optionals` (`name`,`descr`,`cost`,`perday`,`hmany`,`img`,`idiva`,`maxprice`,`forcesel`,`forceval`,`perperson`,`ifchildren`,`maxquant`,`ordering`,`ageintervals`,`is_citytax`,`is_fee`,`alwaysav`,`pcentroom`,`oparams`) VALUES(".$dbo->quote($poptname).", ".$dbo->quote($poptdescr).", ".$dbo->quote($poptcost).", ".$dbo->quote($poptperday).", ".$dbo->quote($popthmany).", '".$picon."', ".$dbo->quote($poptaliq).", ".$dbo->quote($pmaxprice).", '".$pforcesel."', '".$strforceval."', '".$poptperperson."', '".$pifchildren."', '".$pmaxquant."', '".$newsortnum."', '".$ageintervalstr."', '".$pis_citytax."', '".$pis_fee."', ".$dbo->quote($optavstr).", ".$dbo->quote($ppcentroom).", " . $dbo->quote(json_encode($oparams)) . ");";
9648 $dbo->setQuery($q);
9649 $dbo->execute();
9650 $newoptid = $dbo->insertid();
9651
9652 if (!empty($newoptid)) {
9653 // assign/unset option-rooms relations
9654 $rooms_with_opt = array();
9655 if (count($pidrooms)) {
9656 // assign this new option to the requested rooms
9657 foreach ($pidrooms as $idroom) {
9658 if (empty($idroom)) {
9659 continue;
9660 }
9661 $q = "SELECT `id`, `idopt` FROM `#__vikbooking_rooms` WHERE `id`=" . (int)$idroom . ";";
9662 $dbo->setQuery($q);
9663 $dbo->execute();
9664 if (!$dbo->getNumRows()) {
9665 continue;
9666 }
9667 $room_data = $dbo->loadAssoc();
9668 array_push($rooms_with_opt, $room_data['id']);
9669 $current_opts = empty($room_data['idopt']) ? array() : explode(';', rtrim($room_data['idopt'], ';'));
9670 if (in_array((string)$newoptid, $current_opts)) {
9671 continue;
9672 }
9673 if (count($current_opts) === 1 && (string)$current_opts[0] == '0') {
9674 // make sure we do not concatenate a real ID to 0
9675 $current_opts = array();
9676 }
9677 array_push($current_opts, $newoptid);
9678 $new_opts = implode(';', $current_opts) . ';';
9679 $q = "UPDATE `#__vikbooking_rooms` SET `idopt`=" . $dbo->quote($new_opts) . " WHERE `id`={$room_data['id']};";
9680 $dbo->setQuery($q);
9681 $dbo->execute();
9682 }
9683 }
9684 if (!count($rooms_with_opt)) {
9685 // get all rooms to unset this option (if previously set)
9686 array_push($rooms_with_opt, '0');
9687 }
9688 // unset the option from the other rooms that may have it
9689 $q = "SELECT `id`, `idopt` FROM `#__vikbooking_rooms` WHERE `id` NOT IN (" . implode(', ', $rooms_with_opt) . ");";
9690 $dbo->setQuery($q);
9691 $dbo->execute();
9692 if ($dbo->getNumRows()) {
9693 $unset_rooms_opt = $dbo->loadAssocList();
9694 foreach ($unset_rooms_opt as $room_data) {
9695 $current_opts = empty($room_data['idopt']) ? array() : explode(';', rtrim($room_data['idopt'], ';'));
9696 if (!in_array((string)$newoptid, $current_opts)) {
9697 // this room is not using this option
9698 continue;
9699 }
9700 $optkey = array_search((string)$newoptid, $current_opts);
9701 if ($optkey === false) {
9702 // key not found
9703 continue;
9704 }
9705 // unset this option ID from the string
9706 unset($current_opts[$optkey]);
9707 if (!count($current_opts)) {
9708 // a room with no options assigned will be listed as "0;"
9709 $current_opts = array(0);
9710 }
9711 $new_opts = implode(';', $current_opts) . ';';
9712 $q = "UPDATE `#__vikbooking_rooms` SET `idopt`=" . $dbo->quote($new_opts) . " WHERE `id`={$room_data['id']};";
9713 $dbo->setQuery($q);
9714 $dbo->execute();
9715 }
9716 }
9717 //
9718 }
9719
9720 }
9721 $mainframe = JFactory::getApplication();
9722 $mainframe->redirect("index.php?option=com_vikbooking&task=" . ($stay && isset($newoptid) && !empty($newoptid) ? 'editoptional&cid[]=' . $newoptid : 'optionals'));
9723 }
9724
9725 public function removeoptionals()
9726 {
9727 if (!JSession::checkToken()) {
9728 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
9729 }
9730
9731 if (!JFactory::getUser()->authorise('core.delete', 'com_vikbooking')) {
9732 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
9733 }
9734
9735 $ids = VikRequest::getVar('cid', array(0));
9736 if ($ids) {
9737 $dbo = JFactory::getDbo();
9738 foreach ($ids as $d) {
9739 $q = "SELECT `img` FROM `#__vikbooking_optionals` WHERE `id`=".$dbo->quote($d).";";
9740 $dbo->setQuery($q);
9741 $dbo->execute();
9742 if ($dbo->getNumRows() == 1) {
9743 $rows = $dbo->loadAssocList();
9744 if (!empty($rows[0]['img']) && file_exists(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR.$rows[0]['img'])) {
9745 @unlink(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR.$rows[0]['img']);
9746 }
9747 }
9748 $q = "DELETE FROM `#__vikbooking_optionals` WHERE `id`=".$dbo->quote($d).";";
9749 $dbo->setQuery($q);
9750 $dbo->execute();
9751 }
9752 }
9753 $mainframe = JFactory::getApplication();
9754 $mainframe->redirect("index.php?option=com_vikbooking&task=optionals");
9755 }
9756
9757 public function sendcustomsms() {
9758 $mainframe = JFactory::getApplication();
9759 $pphone = VikRequest::getString('phone', '', 'request');
9760 $psmscont = VikRequest::getString('smscont', '', 'request');
9761 $pgoto = VikRequest::getString('goto', '', 'request', VIKREQUEST_ALLOWRAW);
9762 $pgoto = !empty($pgoto) ? urldecode($pgoto) : 'index.php?option=com_vikbooking';
9763 if (!empty($pphone) && !empty($psmscont)) {
9764 $sms_api = VikBooking::getSMSAPIClass();
9765 $sms_api_params = VikBooking::getSMSParams();
9766 if (!empty($sms_api) && file_exists(VBO_ADMIN_PATH.DIRECTORY_SEPARATOR.'smsapi'.DIRECTORY_SEPARATOR.$sms_api) && !empty($sms_api_params)) {
9767 require_once(VBO_ADMIN_PATH.DIRECTORY_SEPARATOR.'smsapi'.DIRECTORY_SEPARATOR.$sms_api);
9768 $sms_obj = new VikSmsApi(array(), $sms_api_params);
9769 $response_obj = $sms_obj->sendMessage($pphone, $psmscont);
9770 if ( !$sms_obj->validateResponse($response_obj) ) {
9771 VikError::raiseWarning('', $sms_obj->getLog());
9772 } else {
9773 $mainframe->enqueueMessage(JText::translate('VBSENDSMSOK'));
9774 }
9775 } else {
9776 VikError::raiseWarning('', JText::translate('VBSENDSMSERRMISSAPI'));
9777 }
9778 } else {
9779 VikError::raiseWarning('', JText::translate('VBSENDSMSERRMISSDATA'));
9780 }
9781 $mainframe->redirect($pgoto);
9782 }
9783
9784 public function sendcustomemail() {
9785 $dbo = JFactory::getDbo();
9786 $mainframe = JFactory::getApplication();
9787 $vbo_tn = VikBooking::getTranslator();
9788 $pbid = VikRequest::getInt('bid', '', 'request');
9789 $pemailsubj = VikRequest::getString('emailsubj', '', 'request');
9790 $pemail = VikRequest::getString('email', '', 'request');
9791 $pemailcont = VikRequest::getString('emailcont', '', 'request', VIKREQUEST_ALLOWRAW);
9792 $pemailfrom = VikRequest::getString('emailfrom', '', 'request');
9793 $pgoto = VikRequest::getString('goto', '', 'request', VIKREQUEST_ALLOWRAW);
9794 $pgoto = !empty($pgoto) ? urldecode($pgoto) : 'index.php?option=com_vikbooking';
9795 if (!empty($pemail) && !empty($pemailcont)) {
9796 $email_attach = null;
9797 jimport('joomla.filesystem.file');
9798 $pemailattch = VikRequest::getVar('emailattch', null, 'files', 'array');
9799 if (isset($pemailattch) && strlen(trim($pemailattch['name']))) {
9800 $filename = JFile::makeSafe(str_replace(" ", "_", strtolower($pemailattch['name'])));
9801 $src = $pemailattch['tmp_name'];
9802 $dest = VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR;
9803 $j = "";
9804 if (file_exists($dest.$filename)) {
9805 $j = rand(171, 1717);
9806 while (file_exists($dest.$j.$filename)) {
9807 $j++;
9808 }
9809 }
9810 $finaldest = $dest.$j.$filename;
9811 if (VikBooking::uploadFile($src, $finaldest)) {
9812 $email_attach = $finaldest;
9813 } else {
9814 VikError::raiseWarning('', 'Error uploading the attachment. Email not sent.');
9815 $mainframe->redirect($pgoto);
9816 exit;
9817 }
9818 }
9819 //VBO 1.10 - special tags for the custom email template files and messages
9820 $orig_mail_cont = $pemailcont;
9821 if (strpos($pemailcont, '{') !== false && strpos($pemailcont, '}') !== false) {
9822 // replace any possible placeholder for special tags
9823 $pemailcont = preg_replace_callback("/(<strong class=\"vbo-editor-hl-specialtag\">)([^<]+)(<\/strong>)/", function($match) {
9824 return $match[2];
9825 }, $pemailcont);
9826
9827 $booking = array();
9828 $q = "SELECT `o`.*,`co`.`idcustomer`,CONCAT_WS(' ',`c`.`first_name`,`c`.`last_name`) AS `customer_name`,`c`.`pin` AS `customer_pin`,`nat`.`country_name` FROM `#__vikbooking_orders` AS `o` LEFT JOIN `#__vikbooking_customers_orders` `co` ON `co`.`idorder`=`o`.`id` AND `co`.`idorder`=".(int)$pbid." LEFT JOIN `#__vikbooking_customers` `c` ON `c`.`id`=`co`.`idcustomer` LEFT JOIN `#__vikbooking_countries` `nat` ON `nat`.`country_3_code`=`o`.`country` WHERE `o`.`id`=".(int)$pbid.";";
9829 $dbo->setQuery($q);
9830 $dbo->execute();
9831 if ($dbo->getNumRows() > 0) {
9832 $booking = $dbo->loadAssoc();
9833 }
9834 $booking_rooms = array();
9835 $q = "SELECT `or`.*,`r`.`name` AS `room_name` FROM `#__vikbooking_ordersrooms` AS `or` LEFT JOIN `#__vikbooking_rooms` `r` ON `r`.`id`=`or`.`idroom` WHERE `or`.`idorder`=".(int)$pbid.";";
9836 $dbo->setQuery($q);
9837 $dbo->execute();
9838 if ($dbo->getNumRows() > 0) {
9839 $booking_rooms = $dbo->loadAssocList();
9840 if (!empty($booking['lang'])) {
9841 $vbo_tn->translateContents($booking_rooms, '#__vikbooking_rooms', array('id' => 'idroom', 'room_name' => 'name'), array(), $booking['lang']);
9842 }
9843 }
9844 //we use the same parsing function as the one for the Customer SMS Template
9845 $pemailcont = VikBooking::parseCustomerSMSTemplate($booking, $booking_rooms, null, $pemailcont);
9846 }
9847 //
9848 // allow the use of token {booking_id} in subject
9849 $pemailsubj = str_replace('{booking_id}', $pbid, $pemailsubj);
9850 //
9851 $is_html = (strpos($pemailcont, '<') !== false && strpos($pemailcont, '>') !== false);
9852 $pemailcont = $is_html ? nl2br($pemailcont) : $pemailcont;
9853 $vbo_app = VikBooking::getVboApplication();
9854 $vbo_app->sendMail($pemailfrom, $pemailfrom, $pemail, $pemailfrom, $pemailsubj, $pemailcont, $is_html, 'base64', $email_attach);
9855 $mainframe->enqueueMessage(JText::translate('VBSENDEMAILOK'));
9856 if ($email_attach !== null) {
9857 @unlink($email_attach);
9858 }
9859 //Booking History
9860 VikBooking::getBookingHistoryInstance()->setBid($pbid)->store('CE', nl2br($pemailsubj . "\n\n" . $pemailcont));
9861 //
9862 //Save email template for future sending
9863 $config_rec_exists = false;
9864 $emtpl = array(
9865 'emailsubj' => $pemailsubj,
9866 'emailcont' => $orig_mail_cont,
9867 'emailfrom' => $pemailfrom
9868 );
9869 $cur_emtpl = array();
9870 $q = "SELECT `setting` FROM `#__vikbooking_config` WHERE `param`='customemailtpls';";
9871 $dbo->setQuery($q);
9872 $dbo->execute();
9873 if ($dbo->getNumRows() > 0) {
9874 $config_rec_exists = true;
9875 $cur_emtpl = $dbo->loadResult();
9876 $cur_emtpl = empty($cur_emtpl) ? array() : json_decode($cur_emtpl, true);
9877 $cur_emtpl = is_array($cur_emtpl) ? $cur_emtpl : array();
9878 }
9879 if (count($cur_emtpl) > 0) {
9880 $existing_subj = false;
9881 foreach ($cur_emtpl as $emk => $emv) {
9882 if (array_key_exists('emailsubj', $emv) && $emv['emailsubj'] == $emtpl['emailsubj']) {
9883 $cur_emtpl[$emk] = $emtpl;
9884 $existing_subj = true;
9885 break;
9886 }
9887 }
9888 if ($existing_subj === false) {
9889 $cur_emtpl[] = $emtpl;
9890 }
9891 } else {
9892 $cur_emtpl[] = $emtpl;
9893 }
9894 if (count($cur_emtpl) > 10) {
9895 //Max 10 templates to avoid problems with the size of the field and truncated json strings
9896 $exceed = count($cur_emtpl) - 10;
9897 for ($tl=0; $tl < $exceed; $tl++) {
9898 unset($cur_emtpl[$tl]);
9899 }
9900 $cur_emtpl = array_values($cur_emtpl);
9901 }
9902 if ($config_rec_exists === true) {
9903 $q = "UPDATE `#__vikbooking_config` SET `setting`=".$dbo->quote(json_encode($cur_emtpl))." WHERE `param`='customemailtpls';";
9904 $dbo->setQuery($q);
9905 $dbo->execute();
9906 } else {
9907 $q = "INSERT INTO `#__vikbooking_config` (`param`,`setting`) VALUES ('customemailtpls', ".$dbo->quote(json_encode($cur_emtpl)).");";
9908 $dbo->setQuery($q);
9909 $dbo->execute();
9910 }
9911 //
9912 } else {
9913 VikError::raiseWarning('', JText::translate('VBSENDEMAILERRMISSDATA'));
9914 }
9915 $mainframe->redirect($pgoto);
9916 }
9917
9918 public function rmcustomemailtpl() {
9919 $cid = VikRequest::getVar('cid', array(0));
9920 $oid = $cid[0];
9921 $dbo = JFactory::getDBO();
9922 $mainframe = JFactory::getApplication();
9923 $tplind = VikRequest::getInt('tplind', '', 'request');
9924 if (empty($oid) || !(strlen($tplind) > 0)) {
9925 VikError::raiseWarning('', 'Missing Data.');
9926 $mainframe->redirect('index.php?option=com_vikbooking');
9927 exit;
9928 }
9929 $cur_emtpl = array();
9930 $q = "SELECT `setting` FROM `#__vikbooking_config` WHERE `param`='customemailtpls';";
9931 $dbo->setQuery($q);
9932 $dbo->execute();
9933 if ($dbo->getNumRows() > 0) {
9934 $cur_emtpl = $dbo->loadResult();
9935 $cur_emtpl = empty($cur_emtpl) ? array() : json_decode($cur_emtpl, true);
9936 $cur_emtpl = is_array($cur_emtpl) ? $cur_emtpl : array();
9937 } else {
9938 VikError::raiseWarning('', 'Missing Templates Record.');
9939 $mainframe->redirect('index.php?option=com_vikbooking');
9940 exit;
9941 }
9942 if (array_key_exists($tplind, $cur_emtpl)) {
9943 unset($cur_emtpl[$tplind]);
9944 $cur_emtpl = count($cur_emtpl) > 0 ? array_values($cur_emtpl) : array();
9945 $q = "UPDATE `#__vikbooking_config` SET `setting`=".$dbo->quote(json_encode($cur_emtpl))." WHERE `param`='customemailtpls';";
9946 $dbo->setQuery($q);
9947 $dbo->execute();
9948 }
9949 $mainframe->redirect('index.php?option=com_vikbooking&task=editorder&cid[]='.$oid.'&customemail=1');
9950 exit;
9951 }
9952
9953 public function exportcustomers() {
9954 //we do not set the menu for this view
9955
9956 VikRequest::setVar('view', VikRequest::getCmd('view', 'exportcustomers'));
9957
9958 parent::display();
9959
9960 if (VikBooking::showFooter()) {
9961 VikBookingHelper::printFooter();
9962 }
9963 }
9964
9965 public function csvexportprepare() {
9966 //modal box, so we do not set menu or footer
9967
9968 VikRequest::setVar('view', VikRequest::getCmd('view', 'csvexportprepare'));
9969
9970 parent::display();
9971 }
9972
9973 public function icsexportprepare() {
9974 //modal box, so we do not set menu or footer
9975
9976 VikRequest::setVar('view', VikRequest::getCmd('view', 'icsexportprepare'));
9977
9978 parent::display();
9979 }
9980
9981 public function bookingcheckin() {
9982 //modal box, so we do not set menu or footer
9983
9984 VikRequest::setVar('view', VikRequest::getCmd('view', 'bookingcheckin'));
9985
9986 parent::display();
9987 }
9988
9989 public function gencheckindoc() {
9990 //modal box, so we do not set menu or footer
9991
9992 VikRequest::setVar('view', VikRequest::getCmd('view', 'gencheckindoc'));
9993
9994 parent::display();
9995 }
9996
9997 public function checkversion() {
9998 //to be called via ajax
9999 $params = new stdClass;
10000 $params->version = VIKBOOKING_SOFTWARE_VERSION;
10001 $params->alias = 'com_vikbooking';
10002
10003 $result = array();
10004
10005 if (!count($result)) {
10006 $result = new stdClass;
10007 $result->status = 0;
10008 } else {
10009 $result = $result[0];
10010 }
10011
10012 echo json_encode($result);
10013 exit;
10014 }
10015
10016 public function updateprogram() {
10017 $params = new stdClass;
10018 $params->version = VIKBOOKING_SOFTWARE_VERSION;
10019 $params->alias = 'com_vikbooking';
10020
10021 $result = array();
10022
10023 if (!count($result) || !$result[0]) {
10024 if (class_exists('JEventDispatcher')) {
10025 $dispatcher = JEventDispatcher::getInstance();
10026 $result = $dispatcher->trigger('checkVersion', array(&$params));
10027 } else {
10028 $app = JFactory::getApplication();
10029 if (method_exists($app, 'triggerEvent')) {
10030 $result = $app->triggerEvent('checkVersion', array(&$params));
10031 }
10032 }
10033 }
10034
10035 if (!count($result) || !$result[0]->status || !$result[0]->response->status) {
10036 exit('Error, plugin disabled');
10037 }
10038
10039 JToolbarHelper::title(JText::translate('VBMAINTITLEUPDATEPROGRAM'));
10040
10041 VikBookingHelper::pUpdateProgram($result[0]->response);
10042 }
10043
10044 public function updateprogramlaunch() {
10045 $params = new stdClass;
10046 $params->version = VIKBOOKING_SOFTWARE_VERSION;
10047 $params->alias = 'com_vikbooking';
10048
10049 $json = new stdClass;
10050 $json->status = false;
10051
10052 echo json_encode($json);
10053 exit;
10054 }
10055
10056 public function invoke_vcm()
10057 {
10058 $app = JFactory::getApplication();
10059
10060 $oids = VikRequest::getVar('cid', []);
10061 $sync_type = VikRequest::getString('stype', 'new', 'request');
10062 $sync_type = !in_array($sync_type, ['new', 'modify', 'cancel']) ? 'new' : $sync_type;
10063 $original_booking_js = VikRequest::getString('origb', '', 'request', VIKREQUEST_ALLOWRAW);
10064 $return_url = VikRequest::getString('returl', '', 'request', VIKREQUEST_ALLOWRAW);
10065 $return_url = !empty($return_url) ? urldecode($return_url) : $return_url;
10066
10067 if (!$oids || !is_file(VCM_SITE_PATH . DIRECTORY_SEPARATOR . "helpers" . DIRECTORY_SEPARATOR . "synch.vikbooking.php")) {
10068 $app->redirect("index.php?option=com_vikbooking&task=orders");
10069 $app->close();
10070 }
10071
10072 $result = VikBooking::getVcmInvoker()
10073 ->setOids($oids)
10074 ->setSyncType($sync_type)
10075 ->setOriginalBooking($original_booking_js, true)
10076 ->doSync();
10077
10078 if ($result === true) {
10079 $app->enqueueMessage(JText::translate('VBCHANNELMANAGERRESULTOK'));
10080 } else {
10081 VikError::raiseWarning('', JText::translate('VBCHANNELMANAGERRESULTKO').' <a href="index.php?option=com_vikchannelmanager" target="_blank">'.JText::translate('VBCHANNELMANAGEROPEN').'</a>');
10082 }
10083
10084 if (!empty($return_url)) {
10085 $app->redirect($return_url);
10086 } else {
10087 $app->redirect("index.php?option=com_vikbooking&task=orders");
10088 }
10089
10090 $app->close();
10091 }
10092
10093 public function multiphotosupload() {
10094 jimport('joomla.filesystem.file');
10095
10096 $dbo = JFactory::getDBO();
10097 $proomid = VikRequest::getInt('roomid', '', 'request');
10098
10099 $resp = array('files' => array());
10100 $error_messages = array(
10101 1 => 'The uploaded file exceeds the upload_max_filesize directive in php.ini',
10102 2 => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form',
10103 3 => 'The uploaded file was only partially uploaded',
10104 4 => 'No file was uploaded',
10105 6 => 'Missing a temporary folder',
10106 7 => 'Failed to write file to disk',
10107 8 => 'A PHP extension stopped the file upload',
10108 'post_max_size' => 'The uploaded file exceeds the post_max_size directive in php.ini',
10109 'max_file_size' => 'File is too big',
10110 'min_file_size' => 'File is too small',
10111 'accept_file_types' => 'Filetype not allowed',
10112 'max_number_of_files' => 'Maximum number of files exceeded',
10113 'max_width' => 'Image exceeds maximum width',
10114 'min_width' => 'Image requires a minimum width',
10115 'max_height' => 'Image exceeds maximum height',
10116 'min_height' => 'Image requires a minimum height',
10117 'abort' => 'File upload aborted',
10118 'image_resize' => 'Failed to resize image',
10119 'vbo_type' => 'The file type cannot be accepted',
10120 'vbo_jupload' => 'The upload has failed. Check the Joomla Configuration',
10121 'vbo_perm' => 'Error moving the uploaded files. Check your permissions'
10122 );
10123
10124 $creativik = new vikResizer();
10125 $updpath = VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR;
10126 $bigsdest = $updpath;
10127 $thumbsdest = $updpath;
10128 $dest = $updpath;
10129 $moreimagestr = '';
10130 $cur_captions = json_encode(array());
10131
10132 $q = "SELECT `moreimgs`,`imgcaptions` FROM `#__vikbooking_rooms` WHERE `id`=".$proomid.";";
10133 $dbo->setQuery($q);
10134 $dbo->execute();
10135 if ($dbo->getNumRows() == 1) {
10136 $photo_data = $dbo->loadAssocList();
10137 $cur_captions = $photo_data[0]['imgcaptions'];
10138 $cur_photos = $photo_data[0]['moreimgs'];
10139 if (!empty($cur_photos)) {
10140 $moreimagestr .= $cur_photos;
10141 }
10142 }
10143
10144 $bulkphotos = VikRequest::getVar('bulkphotos', null, 'files', 'array');
10145
10146 if (is_array($bulkphotos) && count($bulkphotos) > 0 && array_key_exists('name', $bulkphotos) && count($bulkphotos['name']) > 0) {
10147 foreach ($bulkphotos['name'] as $updk => $photoname) {
10148 $uploaded_image = array();
10149 $filename = JFile::makeSafe(str_replace(" ", "_", strtolower($photoname)));
10150 $src = $bulkphotos['tmp_name'][$updk];
10151 $j = "";
10152 if (file_exists($dest.$filename)) {
10153 $j = rand(171, 1717);
10154 while (file_exists($dest.$j.$filename)) {
10155 $j++;
10156 }
10157 }
10158 $finaldest=$dest.$j.$filename;
10159 $is_error = false;
10160 $err_key = '';
10161 if (array_key_exists('error', $bulkphotos) && array_key_exists($updk, $bulkphotos['error']) && !empty($bulkphotos['error'][$updk])) {
10162 if (array_key_exists($bulkphotos['error'][$updk], $error_messages)) {
10163 $is_error = true;
10164 $err_key = $bulkphotos['error'][$updk];
10165 }
10166 }
10167 if (!$is_error) {
10168 $check = getimagesize($bulkphotos['tmp_name'][$updk]);
10169 if ($check[2] & imagetypes()) {
10170 if (VikBooking::uploadFile($src, $finaldest)) {
10171 $gimg = $j.$filename;
10172 //orig img
10173 $origmod = true;
10174 VikBooking::uploadFile($finaldest, $bigsdest.'big_'.$j.$filename, true);
10175 //thumb
10176 $thumbsize = VikBooking::getThumbSize();
10177 $thumb = $creativik->proportionalImage($finaldest, $thumbsdest.'thumb_'.$j.$filename, $thumbsize, $thumbsize);
10178 if (!$thumb || !$origmod) {
10179 if (file_exists($bigsdest.'big_'.$j.$filename)) @unlink($bigsdest.'big_'.$j.$filename);
10180 if (file_exists($thumbsdest.'thumb_'.$j.$filename)) @unlink($thumbsdest.'thumb_'.$j.$filename);
10181 $is_error = true;
10182 $err_key = 'vbo_perm';
10183 } else {
10184 $moreimagestr.=$j.$filename.";;";
10185 }
10186 @unlink($finaldest);
10187 } else {
10188 $is_error = true;
10189 $err_key = 'vbo_jupload';
10190 }
10191 } else {
10192 $is_error = true;
10193 $err_key = 'vbo_type';
10194 }
10195 }
10196 $img = new stdClass();
10197 if ($is_error) {
10198 $img->name = '';
10199 $img->size = '';
10200 $img->type = '';
10201 $img->url = '';
10202 $img->error = array_key_exists($err_key, $error_messages) ? $error_messages[$err_key] : 'Generic Error for Upload';
10203 } else {
10204 $img->name = $photoname;
10205 $img->size = $bulkphotos['size'][$updk];
10206 $img->type = $bulkphotos['type'][$updk];
10207 $img->url = VBO_SITE_URI.'resources/uploads/big_'.$j.$filename;
10208 }
10209 $resp['files'][] = $img;
10210 }
10211 } else {
10212 $res = new stdClass();
10213 $res->name = '';
10214 $res->size = '';
10215 $res->type = '';
10216 $res->url = '';
10217 $res->error = 'No images received for upload';
10218 $resp['files'][] = $res;
10219 }
10220 //Update current extra images string
10221 $q = "UPDATE `#__vikbooking_rooms` SET `moreimgs`=".$dbo->quote($moreimagestr)." WHERE `id`=".$proomid.";";
10222 $dbo->setQuery($q);
10223 $dbo->execute();
10224 $resp['actmoreimgs'] = $moreimagestr;
10225 //Update current extra images uploaded
10226 $cur_thumbs = '';
10227 $morei=explode(';;', $moreimagestr);
10228 if (@count($morei) > 0) {
10229 $imgcaptions = json_decode($cur_captions, true);
10230 $usecaptions = empty($imgcaptions) || is_null($imgcaptions) || !is_array($imgcaptions) || !(count($imgcaptions) > 0) ? false : true;
10231 $cur_thumbs .= '<ul class="vbo-sortable">';
10232 foreach ($morei as $ki => $mi) {
10233 if (!empty($mi)) {
10234 $cur_thumbs .= '<li class="vbo-editroom-currentphoto">';
10235 $cur_thumbs .= '<a href="'.VBO_SITE_URI.'resources/uploads/big_'.$mi.'" target="_blank" class="vbomodal"><img src="'.VBO_SITE_URI.'resources/uploads/thumb_'.$mi.'" class="maxfifty"/></a>';
10236 $cur_thumbs .= '<a class="vbo-toggle-imgcaption" href="javascript: void(0);" onclick="vbOpenImgDetails(\''.$ki.'\', this)"><i class="'.VikBookingIcons::i('cog').'"></i></a>';
10237 $cur_thumbs .= '<div id="vbimgdetbox'.$ki.'" class="vbimagedetbox" style="display: none;"><div class="captionlabel"><span>'.JText::translate('VBIMGCAPTION').'</span><input type="text" name="caption'.$ki.'" value="'.($usecaptions === true && isset($imgcaptions[$ki]) ? $imgcaptions[$ki] : "").'" size="40"/></div><input type="hidden" name="imgsorting[]" value="'.$mi.'"/><input class="captionsubmit" type="button" name="updcatpion" value="'.JText::translate('VBIMGUPDATE').'" onclick="javascript: updateCaptions();"/><div class="captionremoveimg"><a class="vbimgrm btn btn-danger" href="index.php?option=com_vikbooking&task=removemoreimgs&roomid='.$proomid.'&imgind='.$ki.'" title="'.JText::translate('VBREMOVEIMG').'"><i class="icon-remove"></i>'.JText::translate('VBREMOVEIMG').'</a></div></div>';
10238 $cur_thumbs .= '</li>';
10239 }
10240 }
10241 $cur_thumbs .= '</ul>';
10242 $cur_thumbs .= '<br clear="all"/>';
10243 }
10244 $resp['currentthumbs'] = $cur_thumbs;
10245
10246 echo json_encode($resp);
10247 exit;
10248 }
10249
10250 public function loadsmsbalance() {
10251 //to be called via ajax
10252 $html = 'Error1 [N/A]';
10253 $sms_api = VikBooking::getSMSAPIClass();
10254 if (file_exists(VBO_ADMIN_PATH.DIRECTORY_SEPARATOR.'smsapi'.DIRECTORY_SEPARATOR.$sms_api)) {
10255 require_once(VBO_ADMIN_PATH.DIRECTORY_SEPARATOR.'smsapi'.DIRECTORY_SEPARATOR.$sms_api);
10256 $sms_obj = new VikSmsApi(array(), VikBooking::getSMSParams());
10257 if (method_exists('VikSmsApi', 'estimate')) {
10258 $array_result = $sms_obj->estimate("+393711271611", "estimate credit");
10259 if ( $array_result->errorCode != 0 ) {
10260 $html = 'Error3 ['.$array_result->errorMsg.']';
10261 } else {
10262 $html = VikBooking::getCurrencySymb().' '.$array_result->userCredit;
10263 }
10264 } else {
10265 $html = 'Error2 [N/A]';
10266 }
10267 }
10268 echo $html;
10269 exit;
10270 }
10271
10272 public function loadsmsparams() {
10273 //to be called via ajax
10274 $html = '---------';
10275 $phpfile = VikRequest::getString('phpfile', '', 'request');
10276 if (!empty($phpfile)) {
10277 $sms_api = VikBooking::getSMSAPIClass();
10278 $sms_params = $sms_api == $phpfile ? VikBooking::getSMSParams(false) : '';
10279 $html = VikBooking::displaySMSParameters($phpfile, $sms_params);
10280 }
10281 echo $html;
10282 exit;
10283 }
10284
10285 public function loadcronparams() {
10286 //to be called via ajax
10287 $html = '---------';
10288 $phpfile = VikRequest::getString('phpfile', '', 'request');
10289 if (!empty($phpfile)) {
10290 $html = VikBooking::displayCronParameters($phpfile);
10291 }
10292 echo $html;
10293 exit;
10294 }
10295
10296 public function loadpaymentparams() {
10297 //to be called via ajax
10298 $html = '<p>---------</p>';
10299 $phpfile = VikRequest::getString('phpfile', '', 'request');
10300 if (!empty($phpfile)) {
10301 $html = VikBooking::displayPaymentParameters($phpfile);
10302 }
10303 echo $html;
10304 exit;
10305 }
10306
10307 public function setbookingtag() {
10308 //to be called via ajax
10309 $dbo = JFactory::getDBO();
10310 $pidorder = VikRequest::getInt('idorder', '', 'request');
10311 $ptagkey = VikRequest::getInt('tagkey', '', 'request');
10312 if (!empty($pidorder) && $ptagkey >= 0) {
10313 $all_tags = VikBooking::loadBookingsColorTags();
10314 if (array_key_exists($ptagkey, $all_tags)) {
10315 $q = "SELECT `id` FROM `#__vikbooking_orders` WHERE `id`=".(int)$pidorder.";";
10316 $dbo->setQuery($q);
10317 $dbo->execute();
10318 if ($dbo->getNumRows() > 0) {
10319 $newcolortag = json_encode($all_tags[$ptagkey]);
10320 $q = "UPDATE `#__vikbooking_orders` SET `colortag`=".$dbo->quote($newcolortag)." WHERE `id`=".(int)$pidorder.";";
10321 $dbo->setQuery($q);
10322 $dbo->execute();
10323 $newcolortag = $all_tags[$ptagkey];
10324 $newcolortag['name'] = JText::translate($newcolortag['name']);
10325 $newcolortag['fontcolor'] = VikBooking::getBestColorContrast($newcolortag['color']);
10326 echo json_encode($newcolortag);
10327 } else {
10328 echo 'e4j.error.Booking ('.$pidorder.') not found';
10329 }
10330 } else {
10331 echo 'e4j.error.Color Tag ('.$ptagkey.') not found';
10332 }
10333 } else {
10334 echo 'e4j.error.Missing Data';
10335 }
10336 exit;
10337 }
10338
10339 public function updatereceiptnum() {
10340 //to be called via ajax
10341 $pnewnum = VikRequest::getInt('newnum', '', 'request');
10342 $pnewnotes = VikRequest::getString('newnotes', '', 'request', VIKREQUEST_ALLOWRAW);
10343 $poid = VikRequest::getInt('oid', '', 'request');
10344 if ($pnewnum > 0) {
10345 VikBooking::getNextReceiptNumber($poid, $pnewnum);
10346 VikBooking::getReceiptNotes($pnewnotes);
10347 //Booking History
10348 VikBooking::getBookingHistoryInstance()->setBid($poid)->store('BR', JText::translate('VBOFISCRECEIPTNUM').': '.$pnewnum);
10349 //
10350 echo 'e4j.ok';
10351 exit;
10352 }
10353 echo 'e4j.error';
10354 exit;
10355 }
10356
10357 public function isroombookable() {
10358 //to be called via ajax
10359 $dbo = JFactory::getDBO();
10360 $res = array(
10361 'status' => 0,
10362 'err' => ''
10363 );
10364 $prid = VikRequest::getInt('rid', '', 'request');
10365 $pfdate = VikRequest::getString('fdate', '', 'request');
10366 $ptdate = VikRequest::getString('tdate', '', 'request');
10367 $room_info = array();
10368 $q = "SELECT * FROM `#__vikbooking_rooms` WHERE `id`=".(int)$prid.";";
10369 $dbo->setQuery($q);
10370 $dbo->execute();
10371 if ($dbo->getNumRows() > 0) {
10372 $room_info = $dbo->loadAssoc();
10373 }
10374 $pcheckinh = 0;
10375 $pcheckinm = 0;
10376 $pcheckouth = 0;
10377 $pcheckoutm = 0;
10378 $timeopst = VikBooking::getTimeOpenStore();
10379 if (is_array($timeopst)) {
10380 $opent = VikBooking::getHoursMinutes($timeopst[0]);
10381 $closet = VikBooking::getHoursMinutes($timeopst[1]);
10382 $pcheckinh = $opent[0];
10383 $pcheckinm = $opent[1];
10384 $pcheckouth = $closet[0];
10385 $pcheckoutm = $closet[1];
10386 }
10387 $from_ts = VikBooking::getDateTimestamp($pfdate, $pcheckinh, $pcheckinm);
10388 $to_ts = VikBooking::getDateTimestamp($ptdate, $pcheckouth, $pcheckoutm);
10389 if (
10390 count($room_info) > 0 &&
10391 (!empty($pfdate) && !empty($ptdate) && !empty($from_ts) && !empty($to_ts)) &&
10392 VikBooking::roomBookable($room_info['id'], $room_info['units'], $from_ts, $to_ts))
10393 {
10394 $res['status'] = 1;
10395 } else {
10396 if (!(count($room_info) > 0)) {
10397 $res['err'] = 'Room not found';
10398 } elseif (empty($pfdate) || empty($ptdate) || empty($from_ts) || empty($to_ts)) {
10399 $res['err'] = 'Invalid dates';
10400 } else {
10401 //not available
10402 $res['err'] = JText::sprintf('VBOBOOKADDROOMERR', $room_info['name'], $pfdate, $ptdate);
10403 }
10404 }
10405
10406 echo json_encode($res);
10407 exit;
10408 }
10409
10410 public function uploadsnapshot() {
10411 $snap_base_path = VBO_ADMIN_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'idscans';
10412 /**
10413 * We no longer access the uploaded file from php://input, we now retrieve it as a regular file upload.
10414 * The old snapshot collection script with Flash no longer works in 2021.
10415 *
10416 * @since 1.14 (J) - 1.4.0 (WP)
10417 */
10418 $result = null;
10419 try {
10420 $result = VikBooking::uploadFileFromRequest(VikRequest::getVar('snapshot', null, 'files', 'array'), $snap_base_path);
10421 } catch (RuntimeException $e) {
10422 echo "e4j.error.Error " . $e->getMessage();
10423 exit;
10424 }
10425
10426 if (!is_object($result)) {
10427 echo "e4j.error.Invalid upload response";
10428 exit;
10429 }
10430
10431 echo $result->filename;
10432 exit;
10433 }
10434
10435 public function checkvcmrateschanges() {
10436 //to be called via ajax
10437 $session = JFactory::getSession();
10438 $ret = array('changesCount' => 0, 'changesData' => '');
10439 $updforvcm = $session->get('vbVcmRatesUpd', '');
10440 if (!empty($updforvcm) && is_array($updforvcm) && count($updforvcm) > 0) {
10441 $ret['changesCount'] = $updforvcm['count'];
10442 $ret['changesData'] = $updforvcm;
10443 }
10444
10445 echo json_encode($ret);
10446 exit;
10447 }
10448
10449 /**
10450 * AJAX endpoint to load the details of one or more bookings.
10451 *
10452 * @return void
10453 *
10454 * @since 1.16.0 (J) - 1.6.0 (WP) the method was refactored.
10455 */
10456 public function getbookingsinfo()
10457 {
10458 //to be called via ajax
10459 $dbo = JFactory::getDbo();
10460
10461 $booking_infos = [];
10462 $bookings = [];
10463
10464 $pidorders = VikRequest::getString('idorders', '', 'request');
10465 $psubroom = VikRequest::getString('subroom', '', 'request');
10466 $pstatus = VikRequest::getString('status', '', 'request');
10467 $pstay_date = VikRequest::getString('stay_date', '', 'request');
10468 $pidroom = VikRequest::getInt('idroom', 0, 'request');
10469 $psharedcal = VikRequest::getInt('sharedcal', 0, 'request');
10470
10471 if (!empty($pidorders)) {
10472 $bookings = explode(',', $pidorders);
10473 foreach ($bookings as $k => $v) {
10474 $v = intval(str_replace('-', '', $v));
10475 if (empty($v)) {
10476 unset($bookings[$k]);
10477 continue;
10478 }
10479 $bookings[$k] = $v;
10480 }
10481 }
10482 $bookings = array_values($bookings);
10483
10484 if (!$bookings) {
10485 /**
10486 * AJAX requests made by the page availability overview may contain empty booking IDs
10487 * due to SQL errors that only occupied the room, but could not save the booking record.
10488 * Clean up busy records where the busy relations contain empty booking IDs.
10489 *
10490 * @since 1.14 (J) - 1.4.0 (WP)
10491 */
10492 $hanging_busy_ids = [];
10493
10494 $q = "SELECT `idbusy` FROM `#__vikbooking_ordersbusy` WHERE `idorder` = 0 OR `idorder` IS NULL;";
10495 $dbo->setQuery($q);
10496 $removelist = $dbo->loadAssocList();
10497 if ($removelist) {
10498 foreach ($removelist as $hanging_busy) {
10499 $hanging_busy_id = (int)$hanging_busy['idbusy'];
10500 if (!in_array($hanging_busy_id, $hanging_busy_ids)) {
10501 array_push($hanging_busy_ids, $hanging_busy_id);
10502 }
10503 }
10504 }
10505
10506 // let's check also for ghost records that only occupy the room
10507 $q = "SELECT `b`.*,`ob`.`idorder` FROM `#__vikbooking_busy` AS `b` LEFT JOIN `#__vikbooking_ordersbusy` AS `ob` ON `b`.`id`=`ob`.`idbusy` WHERE `b`.`checkout` >= " . time() . " AND (`ob`.`idorder` = 0 OR `ob`.`idorder` IS NULL);";
10508 $dbo->setQuery($q);
10509 $removelist = $dbo->loadAssocList();
10510 if ($removelist) {
10511 foreach ($removelist as $hanging_busy) {
10512 $hanging_busy_id = (int)$hanging_busy['id'];
10513 if (!in_array($hanging_busy_id, $hanging_busy_ids)) {
10514 array_push($hanging_busy_ids, $hanging_busy_id);
10515 }
10516 }
10517 }
10518
10519 if ($hanging_busy_ids) {
10520 $q = "DELETE FROM `#__vikbooking_busy` WHERE `id` IN (" . implode(', ', $hanging_busy_ids) . ");";
10521 $dbo->setQuery($q);
10522 $dbo->execute();
10523 }
10524 //
10525
10526 // output the error
10527 VBOHttpDocument::getInstance()->close(500, '1 - ' . JText::translate('VBOVWGETBKERRMISSDATA'));
10528 }
10529
10530 $nowdf = VikBooking::getDateFormat(true);
10531 if ($nowdf == "%d/%m/%Y") {
10532 $df = 'd/m/Y';
10533 } elseif ($nowdf == "%m/%d/%Y") {
10534 $df = 'm/d/Y';
10535 } else {
10536 $df = 'Y/m/d';
10537 }
10538 $datesep = VikBooking::getDateSeparator(true);
10539 $currencysymb = VikBooking::getCurrencySymb();
10540 $current_y = date('Y');
10541 $current_ts = time();
10542 $short_meal_enums = VBOMealplanManager::getInstance()->getShortMealPlans();
10543
10544 $query = $dbo->getQuery(true);
10545 $query->select('o.*');
10546 $query->from($dbo->qn('#__vikbooking_orders', 'o'));
10547 if (!empty($pstay_date) && !empty($pidroom) && $pstatus == 'any') {
10548 // include the requested booking IDs and the cancelled reservations for this stay date
10549 $stay_date_info = getdate(strtotime($pstay_date));
10550 $lim_ts_to = mktime(23, 59, 59, $stay_date_info['mon'], $stay_date_info['mday'], $stay_date_info['year']);
10551 $query->where('((' . $dbo->qn('o.checkin') . ' <= ' . $lim_ts_to . ' AND ' . $dbo->qn('o.checkout') . ' > ' . $lim_ts_to . ') OR ' . $dbo->qn('o.id') . ' IN (' . implode(', ', $bookings) . '))');
10552 // exclude the pending reservations
10553 $query->where($dbo->qn('o.status') . ' IN (' . $dbo->q('confirmed') . ', ' . $dbo->q('cancelled') . ')');
10554 } else {
10555 // include only the requested booking IDs
10556 $query->where($dbo->qn('o.id') . ' IN (' . implode(', ', $bookings) . ')');
10557 }
10558 if ($pstatus != 'any') {
10559 $query->where($dbo->qn('o.status') . ' != ' . $dbo->q('cancelled'));
10560 }
10561 if (!empty($pstay_date) && $pstatus == 'any') {
10562 // sort by confirmed status before cancelled status
10563 $query->order('CASE WHEN ' . $dbo->qn('o.status') . ' = ' . $dbo->q('confirmed') . ' THEN 1 ELSE 0 END DESC');
10564 $query->order($dbo->qn('o.id') . ' ASC');
10565 }
10566 $dbo->setQuery($query);
10567 $booking_infos = $dbo->loadAssocList();
10568
10569 foreach ($booking_infos as $k => $row) {
10570 // rooms, amounts and guests information
10571 $rooms = VikBooking::loadOrdersRoomsData($row['id']);
10572 $rids_involved = [];
10573 $room_names = [];
10574 $totadults = 0;
10575 $totchildren = 0;
10576 foreach ($rooms as $rr) {
10577 $rids_involved[] = $rr['idroom'];
10578 $totadults += $rr['adults'];
10579 $totchildren += $rr['children'];
10580 $room_names[] = $rr['room_name'];
10581 if ($row['split_stay']) {
10582 // do not sum guests in case of split stay booking
10583 $totadults = $rr['adults'];
10584 $totchildren = $rr['children'];
10585 }
10586 }
10587
10588 if (!empty($pstay_date) && !empty($pidroom) && $pstatus == 'any') {
10589 // make sure we have fetched a reservation for the correct room (in case of cancellations included)
10590 if (!in_array($pidroom, $rids_involved)) {
10591 $is_out_of_scope = true;
10592 if ($psharedcal && count($bookings) === 1) {
10593 $is_out_of_scope = ($row['id'] != $bookings[0]);
10594 }
10595 if ($is_out_of_scope) {
10596 // out of scope reservation, unset it and go to the next one
10597 unset($booking_infos[$k]);
10598 continue;
10599 }
10600 }
10601 }
10602
10603 // included meal plans to be displayed in case of single-room booking
10604 $included_meals = [];
10605 $rplan_name = '';
10606 if (count($rooms) === 1) {
10607 // rate plan name and ID, if any
10608 $active_rplan_id = 0;
10609 if (!empty($rooms[0]['otarplan'])) {
10610 $rplan_name = $rooms[0]['otarplan'];
10611 } else {
10612 list($rplan_name, $active_rplan_id) = VBOMealplanManager::getInstance()->getPriceData($rooms[0]['idtar']);
10613 }
10614
10615 // find the included meals
10616 if (!empty($rooms[0]['meals'])) {
10617 // display included meals defined at room-reservation record
10618 $included_meals = VBOMealplanManager::getInstance()->roomRateIncludedMeals($rooms[0]);
10619 } else {
10620 // fetch default included meals in the selected rate plan
10621 $included_meals = $active_rplan_id ? VBOMealplanManager::getInstance()->ratePlanIncludedMeals($active_rplan_id) : [];
10622 }
10623 if (!$included_meals && empty($row['meals']) && !empty($row['idorderota']) && !empty($row['channel']) && !empty($row['custdata'])) {
10624 // attempt to fetch the included meal plans from the raw customer data or OTA reservation and room
10625 $included_meals = VBOMealplanManager::getInstance()->otaDataIncludedMeals($row, $rooms[0]);
10626 }
10627 }
10628
10629 if ($included_meals) {
10630 $short_incl_meals = [];
10631 foreach ($included_meals as $meal_enum => $meal_name) {
10632 $short_incl_meals[] = $short_meal_enums[$meal_enum];
10633 }
10634 $booking_infos[$k]['meals_included'] = $short_incl_meals;
10635 }
10636
10637 $booking_infos[$k]['rateplan_name'] = $rplan_name;
10638 $booking_infos[$k]['currency_symb'] = $currencysymb;
10639 if ($row['status'] == 'confirmed') {
10640 $booking_infos[$k]['status_lbl'] = JText::translate('VBCONFIRMED');
10641 if ($row['checkout'] < $current_ts) {
10642 $booking_infos[$k]['status_lbl'] = JText::translate('VBOCHECKEDSTATUSOUT');
10643 } elseif ($row['checkin'] < $current_ts && $row['checkout'] > $current_ts) {
10644 if ($row['checked'] == 1) {
10645 $booking_infos[$k]['status_lbl'] = JText::translate('VBOCHECKEDSTATUSIN');
10646 } elseif ($row['checked'] == -1) {
10647 $booking_infos[$k]['status_lbl'] = JText::translate('VBOCHECKEDSTATUSNOS');
10648 }
10649 }
10650 } elseif ($row['status'] == 'standby') {
10651 $booking_infos[$k]['status_lbl'] = JText::translate('VBSTANDBY');
10652 } elseif ($row['status'] == 'cancelled') {
10653 $booking_infos[$k]['status_lbl'] = JText::translate('VBCANCELLED');
10654 } else {
10655 $booking_infos[$k]['status_lbl'] = $row['status'];
10656 }
10657 $booking_infos[$k]['colortag'] = VikBooking::applyBookingColorTag($row);
10658 if ($booking_infos[$k]['colortag']) {
10659 $booking_infos[$k]['colortag']['name'] = JText::translate($booking_infos[$k]['colortag']['name']);
10660 }
10661 $booking_infos[$k]['room_names'] = implode(', ', $room_names);
10662 $booking_infos[$k]['tot_adults'] = $totadults;
10663 $booking_infos[$k]['tot_children'] = $totchildren;
10664 $booking_infos[$k]['format_tot'] = VikBooking::numberFormat($row['total']);
10665 $booking_infos[$k]['format_totpaid'] = VikBooking::numberFormat($row['totpaid']);
10666
10667 // room indexes
10668 $rindexes = [];
10669 $av_room_indexes = [];
10670 $used_indexes_map = [];
10671 $sub_units_data = [];
10672 $optindexes = [];
10673 $subroomdata = !empty($psubroom) ? explode('-', $psubroom) : array();
10674 $missing_index = false;
10675 foreach ($rooms as $kor => $or) {
10676 if ($row['status'] != "confirmed" || $row['closure'] || empty($or['params'])) {
10677 // cannot build room indexes data
10678 continue;
10679 }
10680
10681 $room_params = json_decode($or['params'], true);
10682 if (!is_array($room_params) || empty($room_params['features']) || !is_array($room_params['features'])) {
10683 // no distinctive features information
10684 continue;
10685 }
10686
10687 if (!strlen($or['roomindex'])) {
10688 // turn flag on for missing index when room does support them
10689 $missing_index = true;
10690 // build array with available room indexes
10691 $av_indexes = [];
10692 $unavailable_indexes = VikBooking::getRoomUnitNumsUnavailable($row, $or['idroom']);
10693 foreach ($room_params['features'] as $rind => $rfeatures) {
10694 if (in_array($rind, $unavailable_indexes) || (isset($used_indexes_map[$or['idroom']]) && in_array($rind, $used_indexes_map[$or['idroom']]))) {
10695 continue;
10696 }
10697 foreach ($rfeatures as $fname => $fval) {
10698 if ($fval) {
10699 $av_indexes[$rind] = '#' . $rind . ' - ' . JText::translate($fname) . ': ' . $fval;
10700 break;
10701 }
10702 }
10703 }
10704 if ($av_indexes) {
10705 // push available indexes for this room
10706 $av_room_indexes[$kor] = [
10707 'rid' => $or['idroom'],
10708 'name' => $or['room_name'],
10709 'list' => $av_indexes,
10710 ];
10711 }
10712 // do not proceed any further
10713 continue;
10714 }
10715
10716 // parse distinctive features
10717 foreach ($room_params['features'] as $rind => $rfeatures) {
10718 if ($rind != $or['roomindex']) {
10719 continue;
10720 }
10721 $ind_str = '';
10722 $ind_str_short = '';
10723 foreach ($rfeatures as $fname => $fval) {
10724 if (strlen($fval)) {
10725 $ind_str = '#' . $rind . ' - ' . JText::translate($fname) . ': ' . $fval;
10726 $ind_str_short = $fval;
10727 break;
10728 }
10729 }
10730 if (!isset($rindexes[$or['room_name']])) {
10731 $rindexes[$or['room_name']] = $ind_str;
10732 $sub_units_data[$or['room_name']] = $ind_str_short;
10733 } else {
10734 $rindexes[$or['room_name']] .= ', ' . $ind_str;
10735 $sub_units_data[$or['room_name']] .= ', ' . $ind_str_short;
10736 }
10737 break;
10738 }
10739
10740 // build options to switch sub-unit index
10741 if (count($subroomdata) && !count($optindexes) && $or['idroom'] == (int)$subroomdata[0]) {
10742 // build the options for switching the room index for this room
10743 foreach ($room_params['features'] as $rind => $rfeatures) {
10744 foreach ($rfeatures as $fname => $fval) {
10745 if (strlen((string)$fval)) {
10746 $optindexes[] = '<option value="'.$rind.'"'.($rind == (int)$subroomdata[1] ? ' selected="selected"' : '').'>#'.$rind.' - '.JText::translate($fname).': '.$fval.'</option>';
10747 break;
10748 }
10749 }
10750 }
10751 }
10752 }
10753
10754 if ($rindexes) {
10755 $booking_infos[$k]['rindexes'] = $rindexes;
10756 $booking_infos[$k]['sub_units_data'] = $sub_units_data;
10757 }
10758
10759 if ($optindexes) {
10760 $booking_infos[$k]['optindexes'] = $optindexes;
10761 }
10762
10763 if ($missing_index && $av_room_indexes) {
10764 $booking_infos[$k]['av_room_indexes'] = $av_room_indexes;
10765 }
10766
10767 // include flag for missing room index
10768 $booking_infos[$k]['missing_index'] = $missing_index;
10769
10770 // channel provenience and small logo URL
10771 $ota_logo_img = JText::translate('VBORDFROMSITE');
10772 $booking_avatar_src = null;
10773 $booking_avatar_alt = null;
10774 if (!empty($row['channel'])) {
10775 $channelparts = explode('_', $row['channel']);
10776 $otachannel = array_key_exists(1, $channelparts) && strlen($channelparts[1]) > 0 ? $channelparts[1] : ucwords($channelparts[0]);
10777 $ota_logo_img = VikBooking::getVcmChannelsLogo($row['channel']);
10778 if ($ota_logo_img === false) {
10779 $ota_logo_img = $otachannel;
10780 } else {
10781 $ota_logo_img = '<img src="'.$ota_logo_img.'" class="vbo-channelimg-small"/>';
10782 }
10783 $logo_helper = VikBooking::getVcmChannelsLogo($row['channel'], $get_istance = true);
10784 if ($logo_helper !== false) {
10785 $booking_avatar_src = $logo_helper->getSmallLogoURL();
10786 $booking_avatar_alt = $logo_helper->provenience;
10787 }
10788 }
10789 $booking_infos[$k]['channelimg'] = $ota_logo_img;
10790 $booking_infos[$k]['avatar_src'] = $booking_avatar_src;
10791 $booking_infos[$k]['avatar_alt'] = $booking_avatar_alt;
10792
10793 // Customer Details
10794 $custdata = $row['custdata'];
10795 $custdata_parts = explode("\n", $row['custdata']);
10796 if (count($custdata_parts) > 2 && strpos($custdata_parts[0], ':') !== false && strpos($custdata_parts[1], ':') !== false) {
10797 //get the first two fields
10798 $custvalues = [];
10799 foreach ($custdata_parts as $custdet) {
10800 if (strlen($custdet) < 1) {
10801 continue;
10802 }
10803 $custdet_parts = explode(':', $custdet);
10804 if (count($custdet_parts) >= 2) {
10805 unset($custdet_parts[0]);
10806 array_push($custvalues, trim(implode(':', $custdet_parts)));
10807 }
10808 if (count($custvalues) > 1) {
10809 break;
10810 }
10811 }
10812 if (count($custvalues) > 1) {
10813 $custdata = implode(' ', $custvalues);
10814 }
10815 }
10816 if (strlen($custdata) > 45) {
10817 $custdata = (function_exists('mb_substr') ? mb_substr($custdata, 0, 45, 'UTF-8') : substr($custdata, 0, 45)) . " ...";
10818 }
10819
10820 // customer record details
10821 $customer = [];
10822 $q = "SELECT `c`.*,`co`.`idorder` FROM `#__vikbooking_customers` AS `c` LEFT JOIN `#__vikbooking_customers_orders` `co` ON `c`.`id`=`co`.`idcustomer` WHERE `co`.`idorder`=" . $row['id'];
10823 $dbo->setQuery($q, 0, 1);
10824 $dbo->execute();
10825 if ($dbo->getNumRows()) {
10826 $customer = $dbo->loadAssoc();
10827 if (!empty($customer['first_name'])) {
10828 $custdata = $customer['first_name'].' '.$customer['last_name'];
10829 if (!empty($customer['country'])) {
10830 if (file_exists(VBO_ADMIN_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'countries'.DIRECTORY_SEPARATOR.$customer['country'].'.png')) {
10831 $custdata .= '<img src="'.VBO_ADMIN_URI.'resources/countries/'.$customer['country'].'.png'.'" title="'.htmlspecialchars($customer['country']).'" class="vbo-country-flag vbo-country-flag-left"/>';
10832 }
10833 }
10834 }
10835 }
10836 $booking_infos[$k]['customer'] = $customer;
10837
10838 // check if a profile picture is available for the customer
10839 if (!empty($customer['pic'])) {
10840 $booking_avatar_src = strpos($customer['pic'], 'http') === 0 ? $customer['pic'] : VBO_SITE_URI . 'resources/uploads/' . $customer['pic'];
10841 $booking_avatar_alt = basename($booking_avatar_src);
10842 $booking_infos[$k]['avatar_src'] = $booking_avatar_src;
10843 $booking_infos[$k]['avatar_alt'] = $booking_avatar_alt;
10844 }
10845
10846 // whether this is a closure
10847 $booking_infos[$k]['closure'] = (int)$row['closure'];
10848 $booking_infos[$k]['closure_txt'] = $row['closure'] ? JText::translate('VBDBTEXTROOMCLOSED') : null;
10849
10850 // short customer information
10851 $custdata = JText::translate('VBDBTEXTROOMCLOSED') == $row['custdata'] ? '<span class="vbordersroomclosed">'.JText::translate('VBDBTEXTROOMCLOSED').'</span>' : $custdata;
10852 $booking_infos[$k]['cinfo'] = $custdata;
10853
10854 // formatted dates
10855 $booking_infos[$k]['ts'] = date(str_replace("/", $datesep, $df).' H:i', $row['ts']);
10856 $booking_infos[$k]['checkin'] = date(str_replace("/", $datesep, $df).' H:i', $row['checkin']);
10857 $booking_infos[$k]['checkout'] = date(str_replace("/", $datesep, $df).' H:i', $row['checkout']);
10858
10859 // short booking date, check-in, check-out date format
10860 $stay_info_in = getdate($row['checkin']);
10861 $stay_info_out = getdate($row['checkout']);
10862 $str_checkin = date('d', $row['checkin']);
10863 $str_checkin .= $stay_info_in['mon'] != $stay_info_out['mon'] ? ' ' . VikBooking::sayMonth($stay_info_in['mon'], $short = true) : '';
10864 $str_checkout = date('d', $row['checkout']) . ' ' . VikBooking::sayMonth($stay_info_out['mon'], $short = true);
10865 if ($stay_info_in['year'] != $stay_info_out['year'] || $stay_info_in['year'] != $current_y || $stay_info_out['year'] != $current_y) {
10866 $str_checkout .= ' ' . $stay_info_out['year'];
10867 }
10868 $booking_infos[$k]['checkin_short'] = $str_checkin;
10869 $booking_infos[$k]['checkout_short'] = $str_checkout;
10870 $booking_infos[$k]['book_date'] = date(str_replace("/", $datesep, $df), $row['ts']);
10871 $booking_infos[$k]['book_time'] = date('H:i', $row['ts']);
10872 }
10873
10874 if (!$booking_infos) {
10875 // output the error
10876 VBOHttpDocument::getInstance()->close(500, '2 - ' . JText::translate('VBOVWGETBKERRMISSDATA'));
10877 }
10878
10879 // output the JSON encoded response and exit
10880 VBOHttpDocument::getInstance()->json($booking_infos);
10881 }
10882
10883 public function switchRoomIndex() {
10884 //to be called via ajax
10885 $dbo = JFactory::getDBO();
10886 $bid = VikRequest::getInt('bid', '', 'request');
10887 $rid = VikRequest::getInt('rid', '', 'request');
10888 $old_rindex = VikRequest::getInt('old_rindex', '', 'request');
10889 $new_rindex = VikRequest::getInt('new_rindex', '', 'request');
10890 if (empty($bid) || empty($rid) || empty($old_rindex) || empty($new_rindex)) {
10891 echo 'e4j.error.#1 Missing Data';
10892 exit;
10893 }
10894 $q = "SELECT * FROM `#__vikbooking_ordersrooms` WHERE `idorder`=".$bid." AND `idroom`=".$rid." AND `roomindex`=".$old_rindex.";";
10895 $dbo->setQuery($q);
10896 $dbo->execute();
10897 if ($dbo->getNumRows() < 1) {
10898 echo 'e4j.error.#2 Record not found';
10899 exit;
10900 }
10901 $rows = $dbo->loadAssocList();
10902 $q = "UPDATE `#__vikbooking_ordersrooms` SET `roomindex`=".$new_rindex." WHERE `id`=".$rows[0]['id'].";";
10903 $dbo->setQuery($q);
10904 $dbo->execute();
10905 echo 'e4j.ok';
10906 exit;
10907 }
10908
10909 public function searchcustomer()
10910 {
10911 // to be called via ajax
10912 $dbo = JFactory::getDbo();
10913
10914 $kw = VikRequest::getString('kw', '', 'request');
10915 $nopin = VikRequest::getInt('nopin', '', 'request');
10916 $email = VikRequest::getInt('email', 0, 'request');
10917 $selector = VikRequest::getString('selector', 'vbo-custsearchres-entry', 'request');
10918 $no_script = VikRequest::getInt('no_script', 0, 'request');
10919
10920 if (!strlen($kw)) {
10921 VBOHttpDocument::getInstance()->close(200, '');
10922 }
10923
10924 if ($nopin > 0) {
10925 //page all bookings
10926 $q = "SELECT * FROM `#__vikbooking_customers` WHERE CONCAT_WS(' ', `first_name`, `last_name`) LIKE ".$dbo->quote("%".$kw."%")." OR `email` LIKE ".$dbo->quote("%".$kw."%")." ORDER BY `first_name` ASC LIMIT 30;";
10927 } elseif ($email > 0) {
10928 // page calendar for checking if an email exists
10929 $q = "SELECT `first_name`, `last_name`, `email` FROM `#__vikbooking_customers` WHERE `email`=".$dbo->quote($kw).";";
10930 } else {
10931 //page calendar
10932 $q = "SELECT * FROM `#__vikbooking_customers` WHERE CONCAT_WS(' ', `first_name`, `last_name`) LIKE ".$dbo->quote("%".$kw."%")." OR `email` LIKE ".$dbo->quote("%".$kw."%")." OR `pin` LIKE ".$dbo->quote("%".$kw."%")." ORDER BY `first_name` ASC;";
10933 }
10934 $dbo->setQuery($q);
10935 $customers = $dbo->loadAssocList();
10936
10937 if (!$customers) {
10938 VBOHttpDocument::getInstance()->close(200, '');
10939 }
10940
10941 if ($email > 0) {
10942 VBOHttpDocument::getInstance()->json($customers[0]);
10943 }
10944
10945 $cust_old_fields = array();
10946 $cstring_search = '<div class="vbo-custsearchres-inner">' . "\n";
10947 foreach ($customers as $k => $v) {
10948 $cstring_search .= '<div class="' . $selector . '" data-custid="'.$v['id'].'" data-email="'.$v['email'].'" data-phone="'.htmlspecialchars($v['phone']).'" data-country="'.$v['country'].'" data-pin="'.$v['pin'].'" data-firstname="'.htmlspecialchars($v['first_name']).'" data-lastname="'.htmlspecialchars($v['last_name']).'">'."\n";
10949 $cstring_search .= '<span class="vbo-custsearchres-cflag">';
10950 if (!empty($v['pic'])) {
10951 $cstring_search .= '<img src="' . (strpos($v['pic'], 'http') === 0 ? $v['pic'] : VBO_SITE_URI . 'resources/uploads/' . $v['pic']) . '" class="vbo-country-flag vbo-customer-avatar-flag"/>'."\n";
10952 } elseif (is_file(VBO_ADMIN_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'countries'.DIRECTORY_SEPARATOR.$v['country'].'.png')) {
10953 $cstring_search .= '<img src="'.VBO_ADMIN_URI.'resources/countries/'.$v['country'].'.png'.'" title="'.htmlspecialchars($v['country']).'" class="vbo-country-flag"/>'."\n";
10954 } else {
10955 $cstring_search .= '<i class="' . VikBookingIcons::i('globe') . '"></i>';
10956 }
10957 $cstring_search .= '</span>';
10958 $cstring_search .= '<span class="vbo-custsearchres-name" title="'.htmlspecialchars($v['email']).'">'.$v['first_name'].' '.$v['last_name'].'</span>'."\n";
10959 if (!($nopin > 0)) {
10960 $cstring_search .= '<span class="vbo-custsearchres-pin">'.$v['pin'].'</span>'."\n";
10961 }
10962 $cstring_search .= '</div>'."\n";
10963 if (!empty($v['cfields'])) {
10964 $oldfields = json_decode($v['cfields'], true);
10965 if (is_array($oldfields) && count($oldfields)) {
10966 $cust_old_fields[$v['id']] = $oldfields;
10967 }
10968 }
10969 }
10970 $cstring_search .= '</div>'."\n";
10971
10972 /**
10973 * Add the necessary JS code for the arrow navigation.
10974 */
10975 $cstring_search_js = '<script type="text/javascript">';
10976 $cstring_search_js .= '
10977 var vboCust = jQuery(".' . $selector . '");
10978 var vboCustSelected = null;
10979 jQuery(window).keydown(function(e) {
10980 if (e.which === 40) {
10981 if (vboCustSelected) {
10982 vboCustSelected.removeClass("' . $selector . '-highligthed");
10983 next = vboCustSelected.next();
10984 if (next.length > 0) {
10985 vboCustSelected = next.addClass("' . $selector . '-highligthed");
10986 } else {
10987 vboCustSelected = vboCust.eq(0).addClass("' . $selector . '-highligthed");
10988 }
10989 } else {
10990 vboCustSelected = vboCust.eq(0).addClass("' . $selector . '-highligthed");
10991 }
10992 } else if (e.which === 38) {
10993 if (vboCustSelected) {
10994 vboCustSelected.removeClass("' . $selector . '-highligthed");
10995 next = vboCustSelected.prev();
10996 if (next.length > 0) {
10997 vboCustSelected = next.addClass("' . $selector . '-highligthed");
10998 } else {
10999 vboCustSelected = vboCust.last().addClass("' . $selector . '-highligthed");
11000 }
11001 } else {
11002 vboCustSelected = vboCust.last().addClass("' . $selector . '-highligthed");
11003 }
11004 } else if (e.which === 13) {
11005 if (vboCustSelected) {
11006 vboCustSelected.trigger("click");
11007 }
11008 }
11009 });
11010 jQuery(".' . $selector . '").off("hover");
11011 jQuery(".' . $selector . '").hover(function() {
11012 if (vboCustSelected) {
11013 vboCustSelected.removeClass("' . $selector . '-highligthed");
11014 vboCustSelected = null;
11015 }
11016 vboCustSelected = jQuery(this).addClass("' . $selector . '-highligthed");
11017 }, function() {
11018 if (vboCustSelected) {
11019 vboCustSelected.removeClass("' . $selector . '-highligthed");
11020 vboCustSelected = null;
11021 }
11022 jQuery(this).removeClass("' . $selector . '-highligthed");
11023 });';
11024 $cstring_search_js .= '</script>';
11025
11026 if (!$no_script) {
11027 // append JS
11028 $cstring_search .= $cstring_search_js;
11029 }
11030
11031 VBOHttpDocument::getInstance()->json([($nopin > 0 ? '' : $cust_old_fields), $cstring_search]);
11032 }
11033
11034 public function sharesignaturelink() {
11035 //to be called via ajax
11036 $dbo = JFactory::getDBO();
11037 $response = array(
11038 'status' => 0,
11039 'error' => 'Generic Error'
11040 );
11041 $pbid = VikRequest::getInt('bid', '', 'request');
11042 $phow = VikRequest::getString('how', '', 'request');
11043 $pto = VikRequest::getString('to', '', 'request');
11044 $pcustomer = VikRequest::getInt('customer', '', 'request');
11045 $cpin = VikBooking::getCPinIstance();
11046 $customer_info = $cpin->getCustomerByID($pcustomer);
11047 if (!empty($pbid) && !empty($phow) && !empty($pto) && count($customer_info) > 0) {
11048 $q = "SELECT * FROM `#__vikbooking_orders` WHERE `id`=".(int)$pbid." AND `status`='confirmed' AND `checked` > 0;";
11049 $dbo->setQuery($q);
11050 $dbo->execute();
11051 if ($dbo->getNumRows() > 0) {
11052 $row = $dbo->loadAssoc();
11053
11054 $share_link = JUri::root() . 'index.php?option=com_vikbooking&task=signature&sid=' . (!empty($row['idorderota']) && !empty($row['channel']) ? $row['idorderota'] : $row['sid']) . '&ts=' . $row['ts'];
11055 if (VBOPlatformDetection::isWordPress()) {
11056 /**
11057 * @wponly Rewrite URI for front-end signature
11058 */
11059 $share_link = str_replace(JUri::root(), '', $share_link);
11060 $model = JModel::getInstance('vikbooking', 'shortcodes');
11061 $itemid = $model->all('post_id', $full = true);
11062 if (count($itemid)) {
11063 $share_link = JRoute::rewrite($share_link . "&Itemid={$itemid[0]->post_id}", false);
11064 }
11065 } else {
11066 /**
11067 * @joomlaonly
11068 */
11069 $best_menuitem_id = VikBooking::findProperItemIdType(['vikbooking', 'booking'], $row['lang']);
11070 if ($best_menuitem_id) {
11071 $share_base = str_replace(JUri::root(), '', $share_link);
11072 $share_link = VikBooking::externalroute($share_base, $xhtml = false, $best_menuitem_id);
11073 }
11074 }
11075
11076 $share_message = JText::sprintf('VBOSIGNSHAREMESSAGE', ltrim($customer_info['first_name'].' '.$customer_info['last_name']), $share_link, VikBooking::getFrontTitle());
11077 if ($phow == 'email') {
11078 $sender = VikBooking::getSenderMail();
11079 $vbo_app = VikBooking::getVboApplication();
11080 $vbo_app->sendMail($sender, $sender, $pto, $sender, JText::translate('VBOSIGNSHARESUBJECT'), $share_message, false);
11081 $response['status'] = 1;
11082 } elseif ($phow == 'sms') {
11083 $share_message = JText::sprintf('VBOSIGNSHAREMESSAGESMS', ltrim($customer_info['first_name'].' '.$customer_info['last_name']), $share_link, VikBooking::getFrontTitle());
11084 $sms_api = VikBooking::getSMSAPIClass();
11085 $sms_api_params = VikBooking::getSMSParams();
11086 if (!empty($sms_api) && file_exists(VBO_ADMIN_PATH.DIRECTORY_SEPARATOR.'smsapi'.DIRECTORY_SEPARATOR.$sms_api) && !empty($sms_api_params)) {
11087 require_once(VBO_ADMIN_PATH.DIRECTORY_SEPARATOR.'smsapi'.DIRECTORY_SEPARATOR.$sms_api);
11088 $sms_obj = new VikSmsApi(array(), $sms_api_params);
11089 $response_obj = $sms_obj->sendMessage($pto, $share_message);
11090 if ($sms_obj->validateResponse($response_obj)) {
11091 $response['status'] = 1;
11092 } else {
11093 $response['error'] = $sms_obj->getLog();
11094 }
11095 } else {
11096 $response['error'] = 'No SMS Provider Configured';
11097 }
11098 } else {
11099 $response['error'] = 'Invalid Sending Method';
11100 }
11101 } else {
11102 $response['error'] = 'Invalid Booking ID';
11103 }
11104 } else {
11105 $response['error'] = 'Empty values';
11106 }
11107
11108 echo json_encode($response);
11109 exit;
11110 }
11111
11112 public function dayselectioncount() {
11113 //to be called via ajax
11114 $tsinit = VikRequest::getString('dinit', '', 'request');
11115 $tsend = VikRequest::getString('dend', '', 'request');
11116 if (strlen($tsinit) > 0 && strlen($tsend) > 0) {
11117 $ptsinit=VikBooking::getDateTimestamp($tsinit, '0', '0');
11118 $ptsend=VikBooking::getDateTimestamp($tsend, '23', '59');
11119 $diff = $ptsend - $ptsinit;
11120 if ($diff >= 172800) {
11121 $datef = VikBooking::getDateFormat(true);
11122 if ($datef=="%d/%m/%Y") {
11123 $df = 'd-m-Y';
11124 } else {
11125 $df = 'Y-m-d';
11126 }
11127 //minimum 2 days for excluding some days
11128 $daysdiff = floor($diff / 86400);
11129 $infoinit = getdate($ptsinit);
11130 $select = '';
11131 $select .= '<div style="display: inline-block;"><select name="excludeday[]" multiple="multiple" size="'.($daysdiff > 8 ? 8 : $daysdiff).'" id="vboexclusion">';
11132 for($i = 0; $i <= $daysdiff; $i++) {
11133 $ts = $i > 0 ? mktime(0, 0, 0, $infoinit['mon'], ((int)$infoinit['mday'] + $i), $infoinit['year']) : $ptsinit;
11134 $infots = getdate($ts);
11135 $optval = $infots['mon'].'-'.$infots['mday'].'-'.$infots['year'];
11136 $select .= '<option value="'.$optval.'">'.date($df, $ts).'</option>';
11137 }
11138 $select .= '</select></div>';
11139 //excluded days of the week
11140 if ($daysdiff >= 14) {
11141 $select .= '<div style="display: inline-block; margin-left: 40px;"><select name="excludewdays[]" multiple="multiple" size="8" id="excludewdays" onchange="vboExcludeWDays();">';
11142 $select .= '<optgroup label="'.JText::translate('VBOEXCLWEEKD').'">';
11143 $select .= '<option value="0">'.JText::translate('VBSUNDAY').'</option><option value="1">'.JText::translate('VBMONDAY').'</option><option value="2">'.JText::translate('VBTUESDAY').'</option><option value="3">'.JText::translate('VBWEDNESDAY').'</option><option value="4">'.JText::translate('VBTHURSDAY').'</option><option value="5">'.JText::translate('VBFRIDAY').'</option><option value="6">'.JText::translate('VBSATURDAY').'</option>';
11144 $select .= '</optgroup>';
11145 $select .= '</select></div>';
11146 }
11147 //
11148 echo $select;
11149 } else {
11150 echo '';
11151 }
11152 } else {
11153 echo '';
11154 }
11155 exit;
11156 }
11157
11158 public function createcheckindoc()
11159 {
11160 if (!JFactory::getUser()->authorise('core.create', 'com_vikbooking')) {
11161 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
11162 }
11163
11164 $cid = VikRequest::getVar('cid', array(0));
11165 $id = $cid[0];
11166
11167 $dbo = JFactory::getDBO();
11168 $mainframe = JFactory::getApplication();
11169 $vbo_tn = VikBooking::getTranslator();
11170 $lang = JFactory::getLanguage();
11171 $ptmpl = VikRequest::getString('tmpl', '', 'request');
11172 $psignature = VikRequest::getString('signature', '', 'request', VIKREQUEST_ALLOWRAW);
11173 $ppad_width = VikRequest::getInt('pad_width', '', 'request');
11174 $ppad_ratio = VikRequest::getInt('pad_ratio', '', 'request');
11175 $q = "SELECT * FROM `#__vikbooking_orders` WHERE `id`=".(int)$id." AND `status`='confirmed' AND `checked` > 0;";
11176 $dbo->setQuery($q);
11177 $dbo->execute();
11178 if ($dbo->getNumRows() < 1) {
11179 $mainframe->redirect('index.php');
11180 exit;
11181 }
11182 $row = $dbo->loadAssoc();
11183 if (!empty($row['lang'])) {
11184 if ($lang->getTag() != $row['lang']) {
11185 if (VBOPlatformDetection::isWordPress()) {
11186 $lang->load('com_vikbooking', VIKBOOKING_LANG, $row['lang'], true);
11187 } else {
11188 $lang->load('com_vikbooking', JPATH_SITE, $row['lang'], true);
11189 $lang->load('com_vikbooking', JPATH_ADMINISTRATOR, $row['lang'], true);
11190 $lang->load('joomla', JPATH_SITE, $row['lang'], true);
11191 $lang->load('joomla', JPATH_ADMINISTRATOR, $row['lang'], true);
11192 }
11193 }
11194 if ($vbo_tn->getDefaultLang() != $row['lang']) {
11195 // force the translation to start because contents should be translated
11196 $vbo_tn::$force_tolang = $row['lang'];
11197 }
11198 }
11199 $customer = array();
11200 $q = "SELECT `c`.*,`co`.`idorder`,`co`.`signature`,`co`.`pax_data`,`co`.`comments`,`co`.`checkindoc` FROM `#__vikbooking_customers` AS `c` LEFT JOIN `#__vikbooking_customers_orders` `co` ON `c`.`id`=`co`.`idcustomer` WHERE `co`.`idorder`=".$row['id'].";";
11201 $dbo->setQuery($q);
11202 $dbo->execute();
11203 if ($dbo->getNumRows() > 0) {
11204 $customer = $dbo->loadAssoc();
11205 if (!empty($customer['country'])) {
11206 if (file_exists(VBO_ADMIN_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'countries'.DIRECTORY_SEPARATOR.$customer['country'].'.png')) {
11207 $customer['country_img'] = '<img src="'.VBO_ADMIN_URI.'resources/countries/'.$customer['country'].'.png'.'" title="'.htmlspecialchars($customer['country']).'" class="vbo-country-flag vbo-country-flag-left"/>';
11208 }
11209 }
11210 }
11211 if (!(count($customer) > 0)) {
11212 VikError::raiseWarning('', JText::translate('VBOCHECKINERRNOCUSTOMER'));
11213 $mainframe->redirect('index.php?option=com_vikbooking&task=newcustomer&checkin=1&bid='.$row['id'].($ptmpl == 'component' ? '&tmpl=component' : ''));
11214 exit;
11215 }
11216 $customer['pax_data'] = !empty($customer['pax_data']) ? json_decode($customer['pax_data'], true) : array();
11217 //check if the signature has been submitted
11218 $signature_data = '';
11219 $cont_type = '';
11220 if (!empty($psignature)) {
11221 //check whether the format is accepted
11222 if (strpos($psignature, 'image/png') !== false || strpos($psignature, 'image/jpeg') !== false || strpos($psignature, 'image/svg') !== false) {
11223 $parts = explode(';base64,', $psignature);
11224 $cont_type_parts = explode('image/', $parts[0]);
11225 $cont_type = $cont_type_parts[1];
11226 if (!empty($parts[1])) {
11227 $signature_data = base64_decode($parts[1]);
11228 }
11229 }
11230 }
11231 if (!empty($signature_data)) {
11232 //write file
11233 $sign_fname = $row['id'].'_'.$row['sid'].'_'.$customer['id'].'.'.$cont_type;
11234 $filepath = VBO_ADMIN_PATH . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR . 'idscans' . DIRECTORY_SEPARATOR . $sign_fname;
11235 $fp = fopen($filepath, 'w+');
11236 $bytes = fwrite($fp, $signature_data);
11237 fclose($fp);
11238 if ($bytes !== false && $bytes > 0) {
11239 //update the signature in the DB
11240 $q = "UPDATE `#__vikbooking_customers_orders` SET `signature`=".$dbo->quote($sign_fname)." WHERE `idorder`=".(int)$row['id'].";";
11241 $dbo->setQuery($q);
11242 $dbo->execute();
11243 $customer['signature'] = $sign_fname;
11244 //resize image for screens with high resolution
11245 if ($ppad_ratio > 1) {
11246 $new_width = floor(($ppad_width / 2));
11247 $creativik = new vikResizer();
11248 $creativik->proportionalImage($filepath, $filepath, $new_width, $new_width);
11249 } else {
11250 /**
11251 * @wponly - trigger files mirroring
11252 */
11253 VikBookingLoader::import('update.manager');
11254 VikBookingUpdateManager::triggerUploadBackup($filepath);
11255 //
11256 }
11257 //
11258 } else {
11259 VikError::raiseWarning('', JText::translate('VBOERRSTORESIGNFILE'));
11260 }
11261 }
11262 //
11263 //generate PDF for check-in document by parsing the apposite template file
11264 $booking_rooms = array();
11265 $q = "SELECT `or`.*,`r`.`name` AS `room_name`,`r`.`fromadult`,`r`.`toadult` FROM `#__vikbooking_ordersrooms` AS `or` LEFT JOIN `#__vikbooking_rooms` `r` ON `r`.`id`=`or`.`idroom` WHERE `or`.`idorder`=".(int)$row['id'].";";
11266 $dbo->setQuery($q);
11267 $dbo->execute();
11268 if ($dbo->getNumRows() > 0) {
11269 $booking_rooms = $dbo->loadAssocList();
11270 if (!empty($row['lang'])) {
11271 $vbo_tn->translateContents($booking_rooms, '#__vikbooking_rooms', array('id' => 'idroom', 'room_name' => 'name'), array(), $row['lang']);
11272 }
11273 }
11274 if (!class_exists('TCPDF')) {
11275 require_once(VBO_SITE_PATH . DIRECTORY_SEPARATOR . "helpers" . DIRECTORY_SEPARATOR . "tcpdf" . DIRECTORY_SEPARATOR . 'tcpdf.php');
11276 }
11277 $usepdffont = is_file(VBO_SITE_PATH . DIRECTORY_SEPARATOR . "helpers" . DIRECTORY_SEPARATOR . "tcpdf" . DIRECTORY_SEPARATOR . "fonts" . DIRECTORY_SEPARATOR . "dejavusans.php") ? 'dejavusans' : 'helvetica';
11278
11279 /**
11280 * Trigger event to allow third party plugins to return a specific font name.
11281 *
11282 * @since 1.16.0 (J) - 1.6.0 (WP)
11283 */
11284 $custom_pdf_font = VBOFactory::getPlatform()->getDispatcher()->filter('onGetPdfFontNameVikBooking', [$usepdffont]);
11285 if (is_array($custom_pdf_font) && !empty($custom_pdf_font[0])) {
11286 $usepdffont = $custom_pdf_font[0];
11287 }
11288
11289 list($checkintpl, $pdfparams) = VikBooking::loadCheckinDocTmpl($row, $booking_rooms, $customer);
11290 $checkin_body = VikBooking::parseCheckinDocTemplate($checkintpl, $row, $booking_rooms, $customer);
11291 $pdffname = $row['id'] . '_' . $row['sid'] . '.pdf';
11292 $pathpdf = VBO_SITE_PATH . DIRECTORY_SEPARATOR . "helpers" . DIRECTORY_SEPARATOR . "checkins" . DIRECTORY_SEPARATOR . "generated" . DIRECTORY_SEPARATOR . $pdffname;
11293 if (file_exists($pathpdf)) @unlink($pathpdf);
11294 $pdf_page_format = is_array($pdfparams['pdf_page_format']) ? $pdfparams['pdf_page_format'] : constant($pdfparams['pdf_page_format']);
11295 $pdf = new TCPDF(constant($pdfparams['pdf_page_orientation']), constant($pdfparams['pdf_unit']), $pdf_page_format, true, 'UTF-8', false);
11296 $pdf->SetTitle(JText::translate('VBOCHECKINDOCTITLE'));
11297 //Header for each page of the pdf
11298 if ($pdfparams['show_header'] == 1 && count($pdfparams['header_data']) > 0) {
11299 $pdf->SetHeaderData($pdfparams['header_data'][0], $pdfparams['header_data'][1], $pdfparams['header_data'][2], $pdfparams['header_data'][3], $pdfparams['header_data'][4], $pdfparams['header_data'][5]);
11300 }
11301 //header and footer fonts
11302 $pdf->setHeaderFont(array($usepdffont, '', $pdfparams['header_font_size']));
11303 $pdf->setFooterFont(array($usepdffont, '', $pdfparams['footer_font_size']));
11304 //margins
11305 $pdf->SetMargins(constant($pdfparams['pdf_margin_left']), constant($pdfparams['pdf_margin_top']), constant($pdfparams['pdf_margin_right']));
11306 $pdf->SetHeaderMargin(constant($pdfparams['pdf_margin_header']));
11307 $pdf->SetFooterMargin(constant($pdfparams['pdf_margin_footer']));
11308 //
11309 $pdf->SetAutoPageBreak(true, constant($pdfparams['pdf_margin_bottom']));
11310 $pdf->setImageScale(constant($pdfparams['pdf_image_scale_ratio']));
11311 $pdf->SetFont($usepdffont, '', (int)$pdfparams['body_font_size']);
11312 if ($pdfparams['show_header'] == 0 || !(count($pdfparams['header_data']) > 0)) {
11313 $pdf->SetPrintHeader(false);
11314 }
11315 if ($pdfparams['show_footer'] == 0) {
11316 $pdf->SetPrintFooter(false);
11317 }
11318 $pdf->AddPage();
11319 $pdf->writeHTML($checkin_body, true, false, true, false, '');
11320 $pdf->lastPage();
11321 $pdf->Output($pathpdf, 'F');
11322 if (!file_exists($pathpdf)) {
11323 VikError::raiseWarning('', JText::translate('VBOERRGENCHECKINDOC'));
11324 } else {
11325 $q = "UPDATE `#__vikbooking_customers_orders` SET `checkindoc`=".$dbo->quote($pdffname)." WHERE `idorder`=".(int)$row['id'].";";
11326 $dbo->setQuery($q);
11327 $dbo->execute();
11328 $mainframe->enqueueMessage(JText::translate('VBOGENCHECKINDOCSUCCESS'));
11329 /**
11330 * @wponly - trigger files mirroring
11331 */
11332 VikBookingLoader::import('update.manager');
11333 VikBookingUpdateManager::triggerUploadBackup($pathpdf);
11334 //
11335 }
11336 //
11337 /**
11338 * @wponly - this task is executed via Ajax for the Modal forms listener. We cannot redirect to tmpl=component
11339 */
11340 $mainframe->redirect('index.php?option=com_vikbooking&task=bookingcheckin&cid[]='.$row['id']);
11341 exit;
11342 }
11343
11344 public function updatebookingcheckin()
11345 {
11346 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
11347 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
11348 }
11349
11350 $cid = VikRequest::getVar('cid', array(0));
11351 $id = $cid[0];
11352
11353 $dbo = JFactory::getDbo();
11354 $app = JFactory::getApplication();
11355
11356 $ptmpl = VikRequest::getString('tmpl', '', 'request');
11357 $pnewtotpaid = VikRequest::getFloat('newtotpaid', 0, 'request');
11358 $pguests = VikRequest::getVar('guests', array());
11359 $pcomments = VikRequest::getString('comments', '', 'request', VIKREQUEST_ALLOWHTML);
11360 $pcheckin_action = VikRequest::getInt('checkin_action', '', 'request');
11361 $valid_actions = array(-1, 0, 1, 2);
11362 if (!in_array($pcheckin_action, $valid_actions)) {
11363 $app->redirect('index.php');
11364 exit;
11365 }
11366 $q = "SELECT * FROM `#__vikbooking_orders` WHERE `id`=".(int)$id." AND `status`='confirmed';";
11367 $dbo->setQuery($q);
11368 $dbo->execute();
11369 if ($dbo->getNumRows() < 1) {
11370 $app->redirect('index.php');
11371 exit;
11372 }
11373 $row = $dbo->loadAssoc();
11374 $q = "SELECT * FROM `#__vikbooking_customers_orders` WHERE `idorder`=".$row['id'].";";
11375 $dbo->setQuery($q);
11376 $dbo->execute();
11377 if ($dbo->getNumRows() < 1) {
11378 VikError::raiseWarning('', JText::translate('VBOCHECKINERRNOCUSTOMER'));
11379 $app->redirect('index.php?option=com_vikbooking&task=bookingcheckin&cid[]='.$row['id'].($ptmpl == 'component' ? '&tmpl=component' : ''));
11380 exit;
11381 }
11382 $custorder = $dbo->loadAssoc();
11383 //update checked status and new total paid
11384 $q = "UPDATE `#__vikbooking_orders` SET `checked`=".$pcheckin_action."".($pnewtotpaid > 0 ? ', `totpaid`='.$pnewtotpaid : '')." WHERE `id`=".$row['id'].";";
11385 $dbo->setQuery($q);
11386 $dbo->execute();
11387 // Booking History log for new amount paid (payment update)
11388 if ($pnewtotpaid > 0 && $pnewtotpaid > (float)$row['totpaid']) {
11389 $extra_data = new stdClass;
11390 $extra_data->amount_paid = ($pnewtotpaid - (float)$row['totpaid']);
11391 VikBooking::getBookingHistoryInstance()->setBid($row['id'])->setExtraData($extra_data)->store('PU', JText::sprintf('VBOPREVAMOUNTPAID', VikBooking::numberFormat((float)$row['totpaid'])));
11392 }
11393 //
11394 //Booking History
11395 $hist_type = 'A';
11396 if ($pcheckin_action < 0) {
11397 $hist_type = 'Z';
11398 } elseif ($pcheckin_action == 1) {
11399 $hist_type = 'B';
11400 } elseif ($pcheckin_action == 2) {
11401 $hist_type = 'C';
11402 }
11403 $user = JFactory::getUser();
11404 VikBooking::getBookingHistoryInstance()->setBid($row['id'])->store('R' . $hist_type, "({$user->name})");
11405 //
11406 //Guests Details
11407 $guests_details = array();
11408 list($pax_fields, $pax_fields_attributes) = VikBooking::getPaxFields();
11409 // grab also the fields for front-end pre check-in
11410 list($pre_pax_fields, $pre_pax_fields_attributes) = VikBooking::getPaxFields(true);
11411 //
11412 foreach ($pguests as $ind => $adults) {
11413 foreach ($adults as $aduind => $details) {
11414 foreach ($pax_fields as $key => $v) {
11415 if (isset($details[$key]) && ((is_scalar($details[$key]) && strlen($details[$key])) || !empty($details[$key]))) {
11416 if (!isset($guests_details[$ind])) {
11417 $guests_details[$ind] = array();
11418 }
11419 if (!isset($guests_details[$ind][$aduind])) {
11420 $guests_details[$ind][$aduind] = array();
11421 }
11422 $guests_details[$ind][$aduind][$key] = $details[$key];
11423 }
11424 }
11425 foreach ($pre_pax_fields as $key => $v) {
11426 if (isset($pax_fields[$key])) {
11427 // we must have parsed this back-end field already
11428 continue;
11429 }
11430 if (isset($details[$key]) && ((is_scalar($details[$key]) && strlen($details[$key])) || !empty($details[$key]))) {
11431 if (!isset($guests_details[$ind])) {
11432 $guests_details[$ind] = array();
11433 }
11434 if (!isset($guests_details[$ind][$aduind])) {
11435 $guests_details[$ind][$aduind] = array();
11436 }
11437 if (!isset($guests_details[$ind][$aduind][$key])) {
11438 $guests_details[$ind][$aduind][$key] = $details[$key];
11439 }
11440 }
11441 }
11442 }
11443 }
11444 if (count($guests_details)) {
11445 // current pax data may contain some extra information collected via front-end pre-checkin so we need to merge them
11446 $curpaxdata = json_decode($custorder['pax_data'], true);
11447 if (is_array($curpaxdata) && count($curpaxdata)) {
11448 foreach ($guests_details as $ind => $groom) {
11449 foreach ($groom as $aduind => $aduinfo) {
11450 if (isset($curpaxdata[$ind][$aduind])) {
11451 $guests_details[$ind][$aduind] = array_merge($curpaxdata[$ind][$aduind], $guests_details[$ind][$aduind]);
11452 // unset some default pax fields that were not specified now, or data cannot be deleted for guests
11453 foreach ($guests_details[$ind][$aduind] as $key => $det) {
11454 if (isset($pguests[$ind][$aduind][$key]) && empty($pguests[$ind][$aduind][$key])) {
11455 // this default pax field was specified as empty now, so we cannot merge it
11456 unset($guests_details[$ind][$aduind][$key]);
11457 }
11458 }
11459 }
11460 }
11461 }
11462 }
11463 //
11464 $q = "UPDATE `#__vikbooking_customers_orders` SET `pax_data`=".$dbo->quote(json_encode($guests_details))." WHERE `id`=".$custorder['id'].";";
11465 $dbo->setQuery($q);
11466 $dbo->execute();
11467 }
11468
11469 //'checked' status comments
11470 $q = "UPDATE `#__vikbooking_customers_orders` SET `comments`=".$dbo->quote($pcomments)." WHERE `id`=".$custorder['id'].";";
11471 $dbo->setQuery($q);
11472 $dbo->execute();
11473
11474 $app->enqueueMessage(JText::translate('VBOCHECKINSTATUSUPDATED'));
11475 $app->redirect('index.php?option=com_vikbooking&task=bookingcheckin&cid[]='.$row['id'].($pcheckin_action != $row['checked'] ? '&changed=1' : '').($ptmpl == 'component' ? '&tmpl=component' : ''));
11476 exit;
11477 }
11478
11479 public function alterbooking()
11480 {
11481 $dbo = JFactory::getDbo();
11482 $app = JFactory::getApplication();
11483 $user = JFactory::getUser();
11484
11485 $response = array(
11486 'esit' => 1,
11487 'message' => '',
11488 'vcm' => '',
11489 );
11490
11491 // must be a string as it may contain a dash
11492 $pidorder = VikRequest::getString('idorder', '', 'request');
11493 $pidorder = intval(str_replace('-', '', $pidorder));
11494
11495 $poldidroom = VikRequest::getInt('oldidroom', '', 'request');
11496 $pidroom = VikRequest::getInt('idroom', 0, 'request');
11497 $pfromdate = VikRequest::getString('fromdate', '', 'request');
11498 $ptodate = VikRequest::getString('todate', '', 'request');
11499 $pdebug = VikRequest::getInt('e4j_debug', 0, 'request');
11500 if ($pdebug == 1) {
11501 echo 'e4j.error.'.print_r($app->input->post->getArray(), true);
11502 exit;
11503 }
11504
11505 $nowdf = VikBooking::getDateFormat(true);
11506 if ($nowdf == "%d/%m/%Y") {
11507 $df = 'd/m/Y';
11508 } elseif ($nowdf == "%m/%d/%Y") {
11509 $df = 'm/d/Y';
11510 } else {
11511 $df = 'Y/m/d';
11512 }
11513 $pcheckinh = 0;
11514 $pcheckinm = 0;
11515 $pcheckouth = 0;
11516 $pcheckoutm = 0;
11517 $timeopst = VikBooking::getTimeOpenStore();
11518 if (is_array($timeopst)) {
11519 $opent = VikBooking::getHoursMinutes($timeopst[0]);
11520 $closet = VikBooking::getHoursMinutes($timeopst[1]);
11521 $pcheckinh = $opent[0];
11522 $pcheckinm = $opent[1];
11523 $pcheckouth = $closet[0];
11524 $pcheckoutm = $closet[1];
11525 }
11526 $info_tsto = getdate(strtotime($ptodate));
11527 $actualtsto = mktime(0, 0, 0, $info_tsto['mon'], ($info_tsto['mday'] + 1), $info_tsto['year']);
11528 $first = VikBooking::getDateTimestamp(date($df, strtotime($pfromdate)), $pcheckinh, $pcheckinm);
11529 $second = VikBooking::getDateTimestamp(date($df, $actualtsto), $pcheckouth, $pcheckoutm);
11530 $ptodate = date('Y-m-d', $second);
11531 if (!($second > $first)) {
11532 echo 'e4j.error.1 '.addslashes(JText::translate('VBOVWALTBKERRMISSDATA'));
11533 exit;
11534 }
11535 if (!($pidorder > 0) || !($pidroom > 0) || empty($pfromdate) || empty($ptodate)) {
11536 echo 'e4j.error.2 '.addslashes(JText::translate('VBOVWALTBKERRMISSDATA'));
11537 exit;
11538 }
11539
11540 $q = "SELECT * FROM `#__vikbooking_orders` WHERE `id`=" . $pidorder . " AND `status`='confirmed'";
11541 $dbo->setQuery($q, 0, 1);
11542 $dbo->execute();
11543 if (!$dbo->getNumRows()) {
11544 echo 'e4j.error.3 '.addslashes(JText::translate('VBOVWALTBKERRMISSDATA'));
11545 exit;
11546 }
11547 $ord = $dbo->loadAssoc();
11548
11549 $q = "SELECT `or`.*,`r`.`name`,`r`.`idopt`,`r`.`units`,`r`.`fromadult`,`r`.`toadult` FROM `#__vikbooking_ordersrooms` AS `or`,`#__vikbooking_rooms` AS `r` WHERE `or`.`idorder`=" . $ord['id'] . " AND `or`.`idroom`=`r`.`id` ORDER BY `or`.`id` ASC;";
11550 $dbo->setQuery($q);
11551 $dbo->execute();
11552 $ordersrooms = $dbo->loadAssocList();
11553
11554 // store for VCM the current rooms before the modification
11555 $ord['rooms_info'] = $ordersrooms;
11556
11557 // package or custom rate
11558 $is_package = !empty($ord['pkg']) ? true : false;
11559 $is_cust_cost = false;
11560 foreach ($ordersrooms as $kor => $or) {
11561 if ($is_package !== true && !empty($or['cust_cost']) && $or['cust_cost'] > 0.00) {
11562 $is_cust_cost = true;
11563 break;
11564 }
11565 }
11566
11567 // availability helper
11568 $av_helper = VikBooking::getAvailabilityInstance();
11569
11570 // room stay dates in case of split stay
11571 $room_stay_dates = [];
11572 if ($ord['split_stay']) {
11573 // no need to get the transient based on booking status, as the booking must be confirmed
11574 $room_stay_dates = $av_helper->loadSplitStayBusyRecords($ord['id']);
11575 // immediately count the number of nights of stay for each split room
11576 foreach ($room_stay_dates as $sps_r_k => $sps_r_v) {
11577 $room_stay_dates[$sps_r_k]['nights'] = $av_helper->countNightsOfStay($sps_r_v['checkin'], $sps_r_v['checkout']);
11578 }
11579 }
11580
11581 // determine if dates have changed
11582 $dates_changed = false;
11583 if (date('Y-m-d', $ord['checkin']) != $pfromdate || date('Y-m-d', $ord['checkout']) != $ptodate) {
11584 $dates_changed = true;
11585 }
11586
11587 $toswitch = array();
11588 $idbooked = array();
11589 $rooms_units = array();
11590 $q = "SELECT `id`,`name`,`units` FROM `#__vikbooking_rooms`;";
11591 $dbo->setQuery($q);
11592 $dbo->execute();
11593 $all_rooms = $dbo->loadAssocList();
11594 foreach ($all_rooms as $rr) {
11595 $rooms_units[$rr['id']]['name'] = $rr['name'];
11596 $rooms_units[$rr['id']]['units'] = $rr['units'];
11597 }
11598
11599 // switch room
11600 if ($poldidroom != $pidroom) {
11601 foreach ($ordersrooms as $ind => $or) {
11602 if ($poldidroom == $or['idroom'] && array_key_exists($pidroom, $rooms_units)) {
11603 if (!isset($idbooked[$or['idroom']])) {
11604 $idbooked[$or['idroom']] = 0;
11605 }
11606 // $idbooked is not really needed as switch is never made for the same room id
11607 $idbooked[$or['idroom']]++;
11608 //
11609 $orkey = count($toswitch);
11610 $toswitch[$orkey]['from'] = $or['idroom'];
11611 $toswitch[$orkey]['to'] = $pidroom;
11612 $toswitch[$orkey]['record'] = $or;
11613 $toswitch[$orkey]['record_ind'] = $ind;
11614 break;
11615 }
11616 }
11617 }
11618 if (count($toswitch)) {
11619 foreach ($toswitch as $ksw => $rsw) {
11620 $plusunit = array_key_exists($rsw['to'], $idbooked) ? $idbooked[$rsw['to']] : 0;
11621 $room_checkin = $ord['checkin'];
11622 $room_checkout = $ord['checkout'];
11623 if ($ord['split_stay'] && count($room_stay_dates) && isset($room_stay_dates[$rsw['record_ind']]) && $room_stay_dates[$rsw['record_ind']]['idroom'] == $rsw['from']) {
11624 $room_checkin = $room_stay_dates[$rsw['record_ind']]['checkin'];
11625 $room_checkout = $room_stay_dates[$rsw['record_ind']]['checkout'];
11626 }
11627 if (!VikBooking::roomBookable($rsw['to'], ($rooms_units[$rsw['to']]['units'] + $plusunit), $room_checkin, $room_checkout)) {
11628 // the room is not available
11629 unset($toswitch[$ksw]);
11630 echo 'e4j.error.'.JText::sprintf('VBSWITCHRERR', $rsw['record']['name'], $rooms_units[$rsw['to']]['name']);
11631 exit;
11632 }
11633 }
11634 if (count($toswitch)) {
11635 //reset first record rate so that rates can be set again (rates are unset only if the room is switched, if just the dates are different the rates are kept equal as the num nights is the same)
11636 reset($ordersrooms);
11637 $q = "UPDATE `#__vikbooking_ordersrooms` SET `idtar`=NULL,`roomindex`=NULL,`room_cost`=NULL WHERE `id`=".$ordersrooms[0]['id'].";";
11638 $dbo->setQuery($q);
11639 $dbo->execute();
11640 //
11641 foreach ($toswitch as $ksw => $rsw) {
11642 // update room reservation record
11643 $q = "UPDATE `#__vikbooking_ordersrooms` SET `idroom`=" . $rsw['to'] . ",`idtar`=NULL,`roomindex`=NULL,`room_cost`=NULL WHERE `id`=" . $rsw['record']['id'] . ";";
11644 $dbo->setQuery($q);
11645 $dbo->execute();
11646 $response['message'] .= JText::sprintf('VBOVWALTBKSWITCHROK', $rsw['record']['name'], $rooms_units[$rsw['to']]['name'])."\n";
11647
11648 // update Notes field for this booking to keep track of the previous room that was assigned
11649 $prev_room_name = array_key_exists($rsw['from'], $rooms_units) ? $rooms_units[$rsw['from']]['name'] : '';
11650 if (!empty($prev_room_name)) {
11651 $new_notes = JText::sprintf('VBOPREVROOMMOVED', $prev_room_name, date($df.' H:i:s'))."\n".$ord['adminnotes'];
11652 $q = "UPDATE `#__vikbooking_orders` SET `adminnotes`=".$dbo->quote($new_notes)." WHERE `id`=".(int)$ord['id'].";";
11653 $dbo->setQuery($q);
11654 $dbo->execute();
11655 }
11656
11657 if ($ord['status'] == 'confirmed') {
11658 // update room record in _busy
11659 if ($ord['split_stay'] && count($room_stay_dates) && isset($room_stay_dates[$rsw['record_ind']]) && $room_stay_dates[$rsw['record_ind']]['idroom'] == $rsw['from'] && !empty($room_stay_dates[$rsw['record_ind']]['id'])) {
11660 // in case of a split stay it is fundamental to update the exact busy record ID
11661 $q = "UPDATE `#__vikbooking_busy` SET `idroom`=" . $rsw['to'] . " WHERE `id`=" . (int)$room_stay_dates[$rsw['record_ind']]['id'];
11662 $dbo->setQuery($q);
11663 $dbo->execute();
11664 } else {
11665 // regular processing of a room ID for a reservation, no matter which one, we switch it
11666 $q = "SELECT `b`.`id`,`b`.`idroom`,`ob`.`idorder` FROM `#__vikbooking_busy` AS `b`,`#__vikbooking_ordersbusy` AS `ob` WHERE `b`.`idroom`=" . $rsw['from'] . " AND `b`.`id`=`ob`.`idbusy` AND `ob`.`idorder`=" . $ord['id'] . " LIMIT 1;";
11667 $dbo->setQuery($q);
11668 $dbo->execute();
11669 if ($dbo->getNumRows() == 1) {
11670 $cur_busy = $dbo->loadAssocList();
11671 $q = "UPDATE `#__vikbooking_busy` SET `idroom`=".$rsw['to']." WHERE `id`=".$cur_busy[0]['id']." AND `idroom`=".$cur_busy[0]['idroom']." LIMIT 1;";
11672 $dbo->setQuery($q);
11673 $dbo->execute();
11674 }
11675 }
11676
11677 // if automated updates enabled, keep $response['vcm'] empty
11678 // Invoke Channel Manager
11679 if (file_exists(VCM_SITE_PATH . DIRECTORY_SEPARATOR . "helpers" . DIRECTORY_SEPARATOR . "synch.vikbooking.php")) {
11680 $response['vcm'] = JText::translate('VBCHANNELMANAGERINVOKEASK').' <form action="index.php?option=com_vikbooking" method="post"><input type="hidden" name="option" value="com_vikbooking"/><input type="hidden" name="task" value="invoke_vcm"/><input type="hidden" name="stype" value="modify"/><input type="hidden" name="cid[]" value="'.$ord['id'].'"/><input type="hidden" name="origb" value="'.urlencode(json_encode($ord)).'"/><input type="hidden" name="returl" value="'.urlencode("index.php?option=com_vikbooking&task=overview").'"/><button type="submit" class="btn btn-primary">'.JText::translate('VBCHANNELMANAGERSENDRQ').'</button></form>';
11681 }
11682 } elseif ($ord['status'] == 'standby') {
11683 // remove record in _tmplock
11684 $q = "DELETE FROM `#__vikbooking_tmplock` WHERE `idorder`=" . intval($ord['id']) . ";";
11685 $dbo->setQuery($q);
11686 $dbo->execute();
11687 }
11688 }
11689
11690 // check if sub-units should be assigned again when switching room
11691 if (!$dates_changed && !$ord['split_stay'] && VikBooking::autoRoomUnit()) {
11692 $new_order_rooms = VikBooking::loadOrdersRoomsData($ord['id']);
11693 $room_indexes_usemap = [];
11694 foreach ($new_order_rooms as $kor => $or) {
11695 $num = $kor + 1;
11696 // assign room specific unit
11697 $room_indexes = VikBooking::getRoomUnitNumsAvailable($ord, $or['idroom']);
11698 $use_ind_key = 0;
11699 if ($room_indexes) {
11700 if (!array_key_exists($or['idroom'], $room_indexes_usemap)) {
11701 $room_indexes_usemap[$or['idroom']] = $use_ind_key;
11702 } else {
11703 $use_ind_key = $room_indexes_usemap[$or['idroom']];
11704 }
11705 $q = "UPDATE `#__vikbooking_ordersrooms` SET `roomindex`=".(int)$room_indexes[$use_ind_key]." WHERE `id`=".(int)$or['id'].";";
11706 $dbo->setQuery($q);
11707 $dbo->execute();
11708 $room_indexes_usemap[$or['idroom']]++;
11709 }
11710 }
11711 }
11712
11713 // do not terminate the process when there is a switch, proceed to check the dates.
11714 }
11715 }
11716
11717 // change dates
11718 if ($dates_changed) {
11719 if ($ord['split_stay']) {
11720 // we do not allow to drag and change dates for rooms in a split stay reservation
11721 echo 'e4j.error.' . JText::sprintf('VBO_BOOK_SPLIT_STAY_CANNOTDRAG', $ord['id']);
11722 exit;
11723 }
11724
11725 // total nights of stay
11726 $daysdiff = $ord['days'];
11727
11728 // re-read ordersrooms (as rooms may have been switched)
11729 $q = "SELECT `or`.*,`r`.`name`,`r`.`idopt`,`r`.`units`,`r`.`fromadult`,`r`.`toadult` FROM `#__vikbooking_ordersrooms` AS `or`,`#__vikbooking_rooms` AS `r` WHERE `or`.`idorder`=" . $ord['id'] . " AND `or`.`idroom`=`r`.`id` ORDER BY `or`.`id` ASC;";
11730 $dbo->setQuery($q);
11731 $dbo->execute();
11732 $ordersrooms = $dbo->loadAssocList();
11733
11734 $groupdays = VikBooking::getGroupDays($first, $second, $daysdiff);
11735 $opertwounits = true;
11736 $units_counter = array();
11737 foreach ($ordersrooms as $ind => $or) {
11738 if (!isset($units_counter[$or['idroom']])) {
11739 $units_counter[$or['idroom']] = -1;
11740 }
11741 $units_counter[$or['idroom']]++;
11742 }
11743
11744 foreach ($ordersrooms as $ind => $or) {
11745 $num = $ind + 1;
11746 $check = "SELECT `b`.`id`,`b`.`checkin`,`b`.`realback`,`ob`.`idorder` FROM `#__vikbooking_busy` AS `b`,`#__vikbooking_ordersbusy` AS `ob` WHERE `b`.`idroom`=" . $or['idroom'] . " AND `b`.`realback`>=" . $first . " AND `b`.`id`=`ob`.`idbusy` AND `ob`.`idorder`!=" . $ord['id'] . ";";
11747 $dbo->setQuery($check);
11748 $dbo->execute();
11749 if ($dbo->getNumRows() > 0) {
11750 $busy = $dbo->loadAssocList();
11751 foreach ($groupdays as $gday) {
11752 $bfound = 0;
11753 foreach ($busy as $bu) {
11754 if ($gday >= $bu['checkin'] && $gday <= $bu['realback']) {
11755 $bfound++;
11756 }
11757 }
11758 if ($bfound >= ($or['units'] - $units_counter[$or['idroom']]) || !VikBooking::roomNotLocked($or['idroom'], $or['units'], $first, $second)) {
11759 $opertwounits = false;
11760 break 2;
11761 }
11762 }
11763 }
11764 }
11765 if ($opertwounits !== true) {
11766 $response['esit'] = 0;
11767 $response['message'] = JText::translate('VBROOMNOTRIT')." ".date($df.' H:i', $first)." ".JText::translate('VBROOMNOTCONSTO')." ".date($df.' H:i', $second);
11768 echo json_encode($response);
11769 exit;
11770 }
11771
11772 // update dates and busy records
11773 $realback = VikBooking::getHoursRoomAvail() * 3600;
11774 $realback += $second;
11775 $q = "UPDATE `#__vikbooking_orders` SET `checkin`='".$first."', `checkout`='".$second."' WHERE `id`=".$ord['id'].";";
11776 $dbo->setQuery($q);
11777 $dbo->execute();
11778 if ($ord['status'] == 'confirmed') {
11779 $q = "SELECT `b`.`id` FROM `#__vikbooking_busy` AS `b`,`#__vikbooking_ordersbusy` AS `ob` WHERE `b`.`id`=`ob`.`idbusy` AND `ob`.`idorder`=".$ord['id'].";";
11780 $dbo->setQuery($q);
11781 $dbo->execute();
11782 $allbusy = $dbo->loadAssocList();
11783 foreach ($allbusy as $bb) {
11784 $q = "UPDATE `#__vikbooking_busy` SET `checkin`='".$first."', `checkout`='".$second."', `realback`='".$realback."' WHERE `id`='".$bb['id']."';";
11785 $dbo->setQuery($q);
11786 $dbo->execute();
11787 }
11788 // if automated updates enabled, keep $response['vcm'] empty
11789 // Invoke Channel Manager
11790 if (file_exists(VCM_SITE_PATH . DIRECTORY_SEPARATOR . "helpers" . DIRECTORY_SEPARATOR . "synch.vikbooking.php")) {
11791 $response['vcm'] = JText::translate('VBCHANNELMANAGERINVOKEASK').' <form action="index.php?option=com_vikbooking" method="post"><input type="hidden" name="option" value="com_vikbooking"/><input type="hidden" name="task" value="invoke_vcm"/><input type="hidden" name="stype" value="modify"/><input type="hidden" name="cid[]" value="'.$ord['id'].'"/><input type="hidden" name="origb" value="'.urlencode(json_encode($ord)).'"/><input type="hidden" name="returl" value="'.urlencode("index.php?option=com_vikbooking&task=overview").'"/><button type="submit" class="btn btn-primary">'.JText::translate('VBCHANNELMANAGERSENDRQ').'</button></form>';
11792 }
11793 }
11794 $response['message'] .= JText::translate('RESUPDATED')."\n";
11795 }
11796
11797 if (count($toswitch)) {
11798 /**
11799 * Rooms have changed so the new rates must be re-calculated.
11800 * Maybe they should be calculated in any case, even if just
11801 * the dates have changed. For the moment the rates are reset.
11802 */
11803 }
11804
11805 // unset any previously booked room due to calendar sharing
11806 VikBooking::cleanSharedCalendarsBusy($ord['id']);
11807 // check if some of the rooms booked have shared calendars
11808 VikBooking::updateSharedCalendars($ord['id']);
11809 //
11810
11811 //Booking History
11812 VikBooking::getBookingHistoryInstance()->setBid($ord['id'])->store('MB', "({$user->name}) " . VikBooking::getLogBookingModification($ord));
11813 //
11814
11815 $vcm_autosync = VikBooking::vcmAutoUpdate();
11816 if ($vcm_autosync > 0 && !empty($response['vcm'])) {
11817 //unset the vcm property as no buttons should be displayed when in auto-sync
11818 $response['vcm'] = '';
11819 $vcm_obj = VikBooking::getVcmInvoker();
11820 $vcm_obj->setOids(array($ord['id']))->setSyncType('modify')->setOriginalBooking($ord);
11821 $sync_result = $vcm_obj->doSync();
11822 if ($sync_result === false) {
11823 $response['message'] .= JText::translate('VBCHANNELMANAGERRESULTKO')." (".$vcm_obj->getError().")\n";
11824 }
11825 }
11826
11827 // in case of error but not empty VCM message, set an error that will be displayed after the mustReload
11828 if ($response['esit'] < 1 && !empty($response['vcm'])) {
11829 VikError::raiseNotice('', $response['vcm']);
11830 }
11831
11832 $response['message'] = nl2br($response['message']);
11833 echo json_encode($response);
11834 exit;
11835 }
11836
11837 public function modroomrateplans() {
11838 $dbo = JFactory::getDBO();
11839 $session = JFactory::getSession();
11840 $updforvcm = $session->get('vbVcmRatesUpd', '');
11841 $updforvcm = empty($updforvcm) || !is_array($updforvcm) ? array() : $updforvcm;
11842 $pid_room = VikRequest::getInt('id_room', '', 'request');
11843 $pid_price = VikRequest::getInt('id_price', '', 'request');
11844 $ptype = VikRequest::getString('type', '', 'request');
11845 $pfromdate = VikRequest::getString('fromdate', '', 'request');
11846 $ptodate = VikRequest::getString('todate', '', 'request');
11847 if (empty($pid_room) || empty($pid_price) || empty($ptype) || empty($pfromdate) || empty($ptodate) || !(strtotime($pfromdate) > 0) || !(strtotime($ptodate) > 0)) {
11848 echo 'e4j.error.'.addslashes(JText::translate('VBRATESOVWERRMODRPLANS'));
11849 exit;
11850 }
11851 $price_record = array();
11852 $q = "SELECT * FROM `#__vikbooking_prices` WHERE `id`=".$pid_price.";";
11853 $dbo->setQuery($q);
11854 $dbo->execute();
11855 if ($dbo->getNumRows() > 0) {
11856 $price_record = $dbo->loadAssoc();
11857 }
11858 if (!count($price_record) > 0) {
11859 echo 'e4j.error.'.addslashes(JText::translate('VBRATESOVWERRMODRPLANS')).'.';
11860 exit;
11861 }
11862 $current_closed = array();
11863 if (!empty($price_record['closingd'])) {
11864 $current_closed = json_decode($price_record['closingd'], true);
11865 }
11866 $current_closed = !is_array($current_closed) ? array() : $current_closed;
11867 $start_ts = strtotime($pfromdate);
11868 $end_ts = strtotime($ptodate);
11869 $infostart = getdate($start_ts);
11870 $all_days = array();
11871 $output = array();
11872 while ($infostart[0] > 0 && $infostart[0] <= $end_ts) {
11873 $all_days[] = date('Y-m-d', $infostart[0]);
11874 $indkey = $infostart['mday'].'-'.$infostart['mon'].'-'.$infostart['year'].'-'.$pid_price;
11875 $output[$indkey] = array();
11876 $infostart = getdate(mktime(0, 0, 0, $infostart['mon'], ($infostart['mday'] + 1), $infostart['year']));
11877 }
11878 if ($ptype == 'close') {
11879 if (!array_key_exists($pid_room, $current_closed)) {
11880 $current_closed[$pid_room] = array();
11881 }
11882 foreach ($all_days as $daymod) {
11883 if (!in_array($daymod, $current_closed[$pid_room])) {
11884 $current_closed[$pid_room][] = $daymod;
11885 }
11886 }
11887 } else {
11888 //open
11889 if (array_key_exists($pid_room, $current_closed)) {
11890 foreach ($all_days as $daymod) {
11891 if (in_array($daymod, $current_closed[$pid_room])) {
11892 foreach ($current_closed[$pid_room] as $ck => $cv) {
11893 if ($daymod == $cv) {
11894 unset($current_closed[$pid_room][$ck]);
11895 }
11896 }
11897 }
11898 }
11899 } else {
11900 $current_closed[$pid_room] = array();
11901 }
11902 }
11903 if (!count($current_closed[$pid_room]) > 0) {
11904 unset($current_closed[$pid_room]);
11905 }
11906 $q = "UPDATE `#__vikbooking_prices` SET `closingd`=".(count($current_closed) > 0 ? $dbo->quote(json_encode($current_closed)) : "NULL")." WHERE `id`=".(int)$pid_price.";";
11907 $dbo->setQuery($q);
11908 $dbo->execute();
11909 $oldcsscls = $ptype == 'close' ? 'vbo-roverw-rplan-on' : 'vbo-roverw-rplan-off';
11910 $newcsscls = $ptype == 'close' ? 'vbo-roverw-rplan-off' : 'vbo-roverw-rplan-on';
11911 foreach ($output as $ok => $ov) {
11912 $output[$ok] = array('oldcls' => $oldcsscls, 'newcls' => $newcsscls);
11913 }
11914 //update session values
11915 $updforvcm['count'] = array_key_exists('count', $updforvcm) && !empty($updforvcm['count']) ? ($updforvcm['count'] + 1) : 1;
11916 if (array_key_exists('dfrom', $updforvcm) && !empty($updforvcm['dfrom'])) {
11917 $updforvcm['dfrom'] = $updforvcm['dfrom'] > $start_ts ? $start_ts : $updforvcm['dfrom'];
11918 } else {
11919 $updforvcm['dfrom'] = $start_ts;
11920 }
11921 if (array_key_exists('dto', $updforvcm) && !empty($updforvcm['dto'])) {
11922 $updforvcm['dto'] = $updforvcm['dto'] < $end_ts ? $end_ts : $updforvcm['dto'];
11923 } else {
11924 $updforvcm['dto'] = $end_ts;
11925 }
11926 if (array_key_exists('rooms', $updforvcm) && is_array($updforvcm['rooms'])) {
11927 if (!in_array($pid_room, $updforvcm['rooms'])) {
11928 $updforvcm['rooms'][] = $pid_room;
11929 }
11930 } else {
11931 $updforvcm['rooms'] = array($pid_room);
11932 }
11933 if (array_key_exists('rplans', $updforvcm) && is_array($updforvcm['rplans'])) {
11934 if (array_key_exists($pid_room, $updforvcm['rplans'])) {
11935 if (!in_array($pid_price, $updforvcm['rplans'][$pid_room])) {
11936 $updforvcm['rplans'][$pid_room][] = $pid_price;
11937 }
11938 } else {
11939 $updforvcm['rplans'][$pid_room] = array($pid_price);
11940 }
11941 } else {
11942 $updforvcm['rplans'] = array($pid_room => array($pid_price));
11943 }
11944 $session->set('vbVcmRatesUpd', $updforvcm);
11945 //
11946 $pdebug = VikRequest::getInt('e4j_debug', '', 'request');
11947 if ($pdebug == 1) {
11948 echo "e4j.error.\n".print_r($current_closed, true)."\n";
11949 echo print_r($output, true)."\n\n";
11950 echo print_r($all_days, true)."\n";
11951 }
11952 echo json_encode($output);
11953 exit;
11954 }
11955
11956 public function icsexportlaunch() {
11957 $dbo = JFactory::getDBO();
11958 $pcheckindate = VikRequest::getString('checkindate', '', 'request');
11959 $pcheckoutdate = VikRequest::getString('checkoutdate', '', 'request');
11960 $pstatus = VikRequest::getString('status', '', 'request');
11961 $validstatus = array('confirmed', 'standby', 'cancelled');
11962 $filterstatus = '';
11963 $filterfirst = 0;
11964 $filtersecond = 0;
11965 $nowdf = VikBooking::getDateFormat(true);
11966 if ($nowdf == "%d/%m/%Y") {
11967 $df = 'd/m/Y';
11968 } elseif ($nowdf == "%m/%d/%Y") {
11969 $df = 'm/d/Y';
11970 } else {
11971 $df = 'Y/m/d';
11972 }
11973 $currencyname = VikBooking::getCurrencyName();
11974 if (!empty($pstatus) && in_array($pstatus, $validstatus)) {
11975 $filterstatus = $pstatus;
11976 }
11977 if (!empty($pcheckindate)) {
11978 if (VikBooking::dateIsValid($pcheckindate)) {
11979 $first=VikBooking::getDateTimestamp($pcheckindate, '0', '0');
11980 $filterfirst = $first;
11981 }
11982 }
11983 if (!empty($pcheckoutdate)) {
11984 if (VikBooking::dateIsValid($pcheckoutdate)) {
11985 $second=VikBooking::getDateTimestamp($pcheckoutdate, '23', '59');
11986 if ($second > $first) {
11987 $filtersecond = $second;
11988 }
11989 }
11990 }
11991 $clause = array();
11992 if ($filterfirst > 0) {
11993 $clause[] = "`o`.`checkin` >= ".$filterfirst;
11994 }
11995 if ($filtersecond > 0) {
11996 $clause[] = "`o`.`checkout` <= ".$filtersecond;
11997 }
11998 if (!empty($filterstatus)) {
11999 $clause[] = "`o`.`status` = '".$filterstatus."'";
12000 }
12001 $q = "SELECT `o`.*,`or`.`idroom`,`or`.`adults`,`or`.`children`,`r`.`name` FROM `#__vikbooking_orders` AS `o` LEFT JOIN `#__vikbooking_ordersrooms` `or` ON `or`.`idorder`=`o`.`id` LEFT JOIN `#__vikbooking_rooms` `r` ON `or`.`idroom`=`r`.`id` ".(count($clause) > 0 ? "WHERE ".implode(" AND ", $clause)." " : "")."ORDER BY `o`.`checkin` ASC;";
12002 $dbo->setQuery($q);
12003 $dbo->execute();
12004 if ($dbo->getNumRows() > 0) {
12005 $orders = $dbo->loadAssocList();
12006 $icscontent = "BEGIN:VCALENDAR\n";
12007 $icscontent .= "VERSION:2.0\n";
12008 $icscontent .= "PRODID:-//e4j//VikBooking//EN\n";
12009 $icscontent .= "CALSCALE:GREGORIAN\n";
12010 $str = "";
12011 foreach ($orders as $kord => $ord) {
12012 if (isset($orders[($kord + 1)]) && $orders[($kord + 1)]['id'] == $ord['id']) {
12013 continue;
12014 }
12015 $usecurrencyname = $currencyname;
12016 $usecurrencyname = !empty($ord['idorderota']) && !empty($ord['chcurrency']) ? $ord['chcurrency'] : $usecurrencyname;
12017 $statusstr = '';
12018 if ($ord['status'] == 'confirmed') {
12019 $statusstr = JText::translate('VBCSVSTATUSCONFIRMED');
12020 } elseif ($ord['status'] == 'standby') {
12021 $statusstr = JText::translate('VBCSVSTATUSSTANDBY');
12022 } elseif ($ord['status'] == 'cancelled') {
12023 $statusstr = JText::translate('VBCSVSTATUSCANCELLED');
12024 }
12025 $uri = JURI::root().'index.php?option=com_vikbooking&view=booking&sid='.$ord['sid'].'&ts='.$ord['ts'];
12026 /**
12027 * @wponly Rewrite URI for front-end
12028 */
12029 $uri = str_replace(JUri::root(), '', $uri);
12030 $model = JModel::getInstance('vikbooking', 'shortcodes');
12031 $itemid = $model->best('booking');
12032 if ($itemid) {
12033 $uri = JRoute::rewrite($uri . "&Itemid={$itemid}", false);
12034 }
12035 //
12036 $ordnumbstr = $ord['id'].(!empty($ord['confirmnumber']) ? ' - '.$ord['confirmnumber'] : '').(!empty($ord['idorderota']) ? ' ('.ucwords($ord['channel']).')' : '').' - '.$statusstr;
12037 $peoplestr = ($ord['adults'] + $ord['children']).($ord['children'] > 0 ? ' ('.JText::translate('VBCSVCHILDREN').': '.$ord['children'].')' : '');
12038 $totalstring = ($ord['total'] > 0 ? ($usecurrencyname.' '.VikBooking::numberFormat($ord['total'])) : '');
12039 $totalpaidstring = ($ord['totpaid'] > 0 ? (' ('.VikBooking::numberFormat($ord['totpaid']).')') : '');
12040 $description = JText::sprintf('VBICSEXPDESCRIPTION', $ordnumbstr."\\n", $peoplestr."\\n", $ord['days']."\\n", $totalstring.$totalpaidstring."\\n", "\\n".str_replace("\n", "\\n", trim($ord['custdata'])));
12041 $str .= "BEGIN:VEVENT\n";
12042 $str .= "DTEND:" . JFactory::getDate(date('Y-m-d H:i:s', $ord['checkout']), date_default_timezone_get())->format('Ymd\THis\Z') . "\n";
12043 $str .= "UID:" . uniqid() . "\n";
12044 $str .= "DTSTAMP:" . JFactory::getDate(date('Y-m-d H:i:s'), date_default_timezone_get())->format('Ymd\THis\Z') . "\n";
12045 $str .= ((strlen($description) > 0 ) ? "DESCRIPTION:".preg_replace('/([\,;])/','\\\$1', $description)."\n" : "");
12046 $str .= "URL;VALUE=URI:" . preg_replace('/([\,;])/','\\\$1', $uri) . "\n";
12047 $str .= "SUMMARY:" . JText::sprintf('VBICSEXPSUMMARY', date($df, $ord['checkin'])) . "\n";
12048 $str .= "DTSTART:" . JFactory::getDate(date('Y-m-d H:i:s', $ord['checkin']), date_default_timezone_get())->format('Ymd\THis\Z') . "\n";
12049 $str .= "END:VEVENT\n";
12050 }
12051 $icscontent .= $str;
12052 $icscontent .= "END:VCALENDAR\n";
12053 //download file from buffer
12054 header("Content-Type: application/octet-stream; ");
12055 header("Cache-Control: no-store, no-cache");
12056 header('Content-Disposition: attachment; filename="bookings_export.ics"');
12057 $f = fopen('php://output', "w");
12058 fwrite($f, $icscontent);
12059 fclose($f);
12060 exit;
12061 } else {
12062 VikError::raiseWarning('', JText::translate('VBICSEXPNORECORDS'));
12063 $mainframe = JFactory::getApplication();
12064 $mainframe->redirect("index.php?option=com_vikbooking&task=icsexportprepare&checkindate=".$pcheckindate."&checkoutdate=".$pcheckoutdate."&status=".$pstatus."&tmpl=component");
12065 }
12066 }
12067
12068 public function csvexportlaunch()
12069 {
12070 $dbo = JFactory::getDbo();
12071 $app = JFactory::getApplication();
12072
12073 $pdatefilt = VikRequest::getString('datefilt', '', 'request');
12074 $proomfilt = VikRequest::getString('roomfilt', '', 'request');
12075 $pchfilt = VikRequest::getString('chfilt', '', 'request');
12076 $ppayfilt = VikRequest::getString('payfilt', '', 'request');
12077 $pcheckindate = VikRequest::getString('checkindate', '', 'request');
12078 $pcheckoutdate = VikRequest::getString('checkoutdate', '', 'request');
12079 $pstatus = VikRequest::getString('status', '', 'request');
12080 $pcatfilt = VikRequest::getInt('catfilt', 0, 'request');
12081 $pformat = VikRequest::getString('format', 'csv', 'request');
12082
12083 // let the report class (a generic one) generate the CSV file in the proper format
12084 $report_obj = VikBooking::getReportInstance('revenue')->setExportCSVFormat($pformat);
12085
12086 $validstatus = array('confirmed', 'standby', 'cancelled');
12087 $validdates = array('ts', 'checkin', 'checkout');
12088
12089 $filterdate = '';
12090 $filterstatus = '';
12091 $first = 0;
12092 $filterfirst = 0;
12093 $filtersecond = 0;
12094 $nowdf = VikBooking::getDateFormat(true);
12095 if ($nowdf == "%d/%m/%Y") {
12096 $df = 'd/m/Y';
12097 } elseif ($nowdf == "%m/%d/%Y") {
12098 $df = 'm/d/Y';
12099 } else {
12100 $df = 'Y/m/d';
12101 }
12102 $datesep = VikBooking::getDateSeparator(true);
12103 $currencyname = VikBooking::getCurrencyName();
12104
12105 if (!empty($pstatus) && in_array($pstatus, $validstatus)) {
12106 $filterstatus = $pstatus;
12107 }
12108 if (!empty($pdatefilt) && in_array($pdatefilt, $validdates)) {
12109 $filterdate = $pdatefilt;
12110 }
12111 if (!empty($pcheckindate) && !empty($filterdate)) {
12112 if (VikBooking::dateIsValid($pcheckindate)) {
12113 $first = VikBooking::getDateTimestamp($pcheckindate, '0', '0');
12114 $filterfirst = $first;
12115 }
12116 }
12117 if (!empty($pcheckoutdate) && !empty($filterdate)) {
12118 if (VikBooking::dateIsValid($pcheckoutdate)) {
12119 $second = VikBooking::getDateTimestamp($pcheckoutdate, '23', '59');
12120 if ($second > $first) {
12121 $filtersecond = $second;
12122 }
12123 }
12124 }
12125 $clause = array();
12126 if ($filterfirst > 0) {
12127 $clause[] = "`o`.`".$filterdate."` >= ".$filterfirst;
12128 }
12129 if ($filtersecond > 0) {
12130 $clause[] = "`o`.`".$filterdate."` <= ".$filtersecond;
12131 }
12132 if (!empty($filterstatus)) {
12133 $clause[] = "`o`.`status` = '".$filterstatus."'";
12134 }
12135 if (!empty($pchfilt)) {
12136 $clause[] = "`o`.`channel` LIKE ".$dbo->quote("%".$pchfilt."%");
12137 }
12138 if (!empty($ppayfilt)) {
12139 $clause[] = "`o`.`idpayment` LIKE '".$ppayfilt."=%'";
12140 }
12141 if (!empty($proomfilt)) {
12142 $clause[] = "`or`.`idroom` = '".(int)$proomfilt."'";
12143 }
12144
12145 if (!empty($pcatfilt)) {
12146 $room_cat_ids = array();
12147 $q = "SELECT `id`,`idcat` FROM `#__vikbooking_rooms` WHERE `idcat` LIKE " . $dbo->quote("%$pcatfilt%");
12148 $dbo->setQuery($q);
12149 $dbo->execute();
12150 if ($dbo->getNumRows()) {
12151 $records = $dbo->loadAssocList();
12152 foreach ($records as $rcat) {
12153 $parts = explode(';', $rcat['idcat']);
12154 if (in_array($pcatfilt, $parts)) {
12155 $room_cat_ids[] = $rcat['id'];
12156 }
12157 }
12158 }
12159 if (count($room_cat_ids)) {
12160 $clause[] = "`or`.`idroom` IN (" . implode(', ', $room_cat_ids) . ")";
12161 }
12162 }
12163
12164 $q = "SELECT `o`.*,`or`.`idroom`,`or`.`adults`,`or`.`children`,`or`.`idtar`,`or`.`optionals`,`or`.`t_first_name`,`or`.`t_last_name`,`or`.`extracosts`,`or`.`cust_cost`,`or`.`cust_idiva`,`or`.`room_cost`,`r`.`name`,`d`.`idprice`,`p`.`idiva`,`t`.`aliq`,`t`.`breakdown` FROM `#__vikbooking_orders` AS `o` LEFT JOIN `#__vikbooking_ordersrooms` `or` ON `or`.`idorder`=`o`.`id` LEFT JOIN `#__vikbooking_rooms` `r` ON `or`.`idroom`=`r`.`id` LEFT JOIN `#__vikbooking_dispcost` `d` ON `or`.`idtar`=`d`.`id` LEFT JOIN `#__vikbooking_prices` `p` ON `d`.`idprice`=`p`.`id` LEFT JOIN `#__vikbooking_iva` `t` ON `p`.`idiva`=`t`.`id` ".(count($clause) > 0 ? "WHERE ".implode(" AND ", $clause)." " : "")."ORDER BY `o`.`checkin` ASC;";
12165 $dbo->setQuery($q);
12166 $orders = $dbo->loadAssocList();
12167 if (!$orders) {
12168 $app->enqueueMessage(JText::translate('VBCSVEXPNORECORDS'), 'error');
12169 $app->redirect("index.php?option=com_vikbooking&task=csvexportprepare&checkindate=".$pcheckindate."&checkoutdate=".$pcheckoutdate."&status=".$pstatus."&tmpl=component");
12170 $app->close();
12171 }
12172
12173 // options
12174 $all_options = array();
12175 $q = "SELECT * FROM `#__vikbooking_optionals` ORDER BY `#__vikbooking_optionals`.`ordering` ASC;";
12176 $dbo->setQuery($q);
12177 $options = $dbo->loadAssocList();
12178 if ($options) {
12179 foreach ($options as $ok => $ov) {
12180 $all_options[$ov['id']] = $ov;
12181 }
12182 }
12183
12184 // set CSV columns
12185 $report_obj->setReportCols([
12186 [
12187 'label' => JText::translate('VBDASHBOOKINGID'),
12188 ],
12189 [
12190 'label' => JText::translate('VBPVIEWORDERSONE'),
12191 ],
12192 [
12193 'label' => JText::translate('VBCSVCHECKIN'),
12194 ],
12195 [
12196 'label' => JText::translate('VBCSVCHECKOUT'),
12197 ],
12198 [
12199 'label' => JText::translate('VBCSVNIGHTS'),
12200 ],
12201 [
12202 'label' => JText::translate('VBCSVROOM'),
12203 ],
12204 [
12205 'label' => JText::translate('VBCSVPEOPLE'),
12206 ],
12207 [
12208 'label' => JText::translate('VBCSVCUSTINFO'),
12209 ],
12210 [
12211 'label' => JText::translate('ORDER_SPREQUESTS'),
12212 ],
12213 [
12214 'label' => JText::translate('ORDER_NOTES'),
12215 ],
12216 [
12217 'label' => JText::translate('VBCSVCREATEDBY'),
12218 ],
12219 [
12220 'label' => JText::translate('VBCSVCUSTMAIL'),
12221 ],
12222 [
12223 'label' => JText::translate('ORDER_PHONE'),
12224 ],
12225 [
12226 'label' => JText::translate('VBCSVOPTIONS'),
12227 ],
12228 [
12229 'label' => JText::translate('VBCSVPAYMENTMETHOD'),
12230 ],
12231 [
12232 'label' => JText::translate('VBCSVORDIDCONFNUMB'),
12233 ],
12234 [
12235 'label' => JText::translate('VBCSVEXPFILTBSTATUS'),
12236 ],
12237 [
12238 'label' => JText::translate('VBCSVTOTAL'),
12239 ],
12240 [
12241 'label' => JText::translate('VBCSVTOTPAID'),
12242 ],
12243 [
12244 'label' => JText::translate('VBCSVTOTTAXES'),
12245 ],
12246 ]);
12247
12248 // prepare the container for the CSV rows
12249 $orderscsv = [];
12250
12251 // availability helper
12252 $av_helper = VikBooking::getAvailabilityInstance();
12253
12254 $room_inds = [];
12255 $room_stay_dates = [];
12256 foreach ($orders as $kord => $ord) {
12257 // room index in this booking
12258 if (!isset($room_inds[$ord['id']])) {
12259 $room_inds[$ord['id']] = -1;
12260 }
12261 $room_inds[$ord['id']]++;
12262
12263 /**
12264 * Split stay reservation.
12265 *
12266 * @since 1.16.0 (J) - 1.6.0 (WP)
12267 */
12268 $room_stay_dates = $room_inds[$ord['id']] > 0 ? $room_stay_dates : [];
12269 if ($ord['split_stay']) {
12270 if ($ord['status'] == 'confirmed') {
12271 $room_stay_dates = $av_helper->loadSplitStayBusyRecords($ord['id']);
12272 } else {
12273 $room_stay_dates = VBOFactory::getConfig()->getArray('split_stay_' . $ord['id'], []);
12274 }
12275 // immediately count the number of nights of stay for each split room
12276 foreach ($room_stay_dates as $sps_r_k => $sps_r_v) {
12277 if (!empty($sps_r_v['checkin_ts']) && !empty($sps_r_v['checkout_ts'])) {
12278 // overwrite values for compatibility with non-confirmed bookings
12279 $sps_r_v['checkin'] = $sps_r_v['checkin_ts'];
12280 $sps_r_v['checkout'] = $sps_r_v['checkout_ts'];
12281 }
12282 $sps_r_v['nights'] = $av_helper->countNightsOfStay($sps_r_v['checkin'], $sps_r_v['checkout']);
12283 // overwrite the whole array
12284 $room_stay_dates[$sps_r_k] = $sps_r_v;
12285 }
12286 }
12287
12288 // determine nights and dates for this room booking
12289 $booking_nights = $ord['days'];
12290 $booking_checkin = $ord['checkin'];
12291 $booking_checkout = $ord['checkout'];
12292 if ($ord['split_stay'] && !empty($room_stay_dates) && isset($room_stay_dates[$room_inds[$ord['id']]]) && $room_stay_dates[$room_inds[$ord['id']]]['idroom'] == $ord['idroom']) {
12293 $booking_nights = $room_stay_dates[$room_inds[$ord['id']]]['nights'];
12294 $booking_checkin = $room_stay_dates[$room_inds[$ord['id']]]['checkin'];
12295 $booking_checkout = $room_stay_dates[$room_inds[$ord['id']]]['checkout'];
12296 }
12297
12298 $usecurrencyname = $currencyname;
12299 $usecurrencyname = !empty($ord['idorderota']) && !empty($ord['chcurrency']) ? $ord['chcurrency'] : $usecurrencyname;
12300 $peoplestr = ($ord['adults'] + $ord['children']).($ord['children'] > 0 ? ' ('.JText::translate('VBCSVCHILDREN').': '.$ord['children'].')' : '');
12301 $custinfostr = str_replace(",", " ", $ord['custdata']);
12302 $customer = VikBooking::getCPinIstance()->getCustomerFromBooking($ord['id']);
12303 if (count($customer)) {
12304 $custinfostr = $customer['first_name'] . ' ' . $customer['last_name'];
12305 }
12306 $special_requests = '';
12307 if (preg_match("/(?:special requests:\s*)(.*?)$/is", $ord['custdata'], $match)) {
12308 $special_requests = $match[1];
12309 } elseif (preg_match("/(?:special request:\s*)(.*?)$/is", $ord['custdata'], $match)) {
12310 $special_requests = $match[1];
12311 } elseif (preg_match("/(?:special request\s*)(.*?)$/is", $ord['custdata'], $match)) {
12312 $special_requests = $match[1];
12313 } elseif (preg_match("/(?:" . JText::translate('ORDER_SPREQUESTS') . ":\s*)(.*?)$/is", $ord['custdata'], $match)) {
12314 $special_requests = $match[1];
12315 }
12316 $paystr = '';
12317 if (!empty($ord['idpayment'])) {
12318 $payparts = explode('=', $ord['idpayment']);
12319 $paystr = $payparts[1];
12320 }
12321 $ordnumbstr = $ord['id'].' - '.$ord['confirmnumber'].(!empty($ord['idorderota']) ? ' ('.ucwords($ord['channel']).')' : '');
12322 $statusstr = '';
12323 if ($ord['status'] == 'confirmed') {
12324 $statusstr = JText::translate('VBCSVSTATUSCONFIRMED');
12325 } elseif ($ord['status'] == 'standby') {
12326 $statusstr = JText::translate('VBCSVSTATUSSTANDBY');
12327 } elseif ($ord['status'] == 'cancelled') {
12328 $statusstr = JText::translate('VBCSVSTATUSCANCELLED');
12329 }
12330 $totalstring = $usecurrencyname . ' ' . VikBooking::numberFormat($ord['total']);
12331 if ($ord['roomsnum'] > 1) {
12332 // take the cost for the individual room
12333 $totalstring = !empty($ord['cust_cost']) && $ord['cust_cost'] > 0 ? ($usecurrencyname . ' ' . VikBooking::numberFormat($ord['cust_cost'])) : ($usecurrencyname . ' ' . VikBooking::numberFormat($ord['room_cost']));
12334 }
12335 $totalpaidstring = $usecurrencyname . ' ' . VikBooking::numberFormat($ord['totpaid']);
12336 if (isset($orders[($kord + 1)]) && $orders[($kord + 1)]['id'] == $ord['id']) {
12337 // total paid will be printed only for the last room booked
12338 $totalpaidstring = '';
12339 }
12340 $options_str = '';
12341 if (!empty($ord['optionals'])) {
12342 $stepo = explode(";", $ord['optionals']);
12343 foreach ($stepo as $roptkey => $oo) {
12344 if (!empty($oo)) {
12345 $stept = explode(":", $oo);
12346 if (array_key_exists($stept[0], $all_options)) {
12347 $actopt = $all_options[$stept[0]];
12348 $optpcent = false;
12349 if (!empty($actopt['ageintervals']) && $ord['children'] > 0 && strstr($stept[1], '-') != false) {
12350 $optagenames = VikBooking::getOptionIntervalsAges($actopt['ageintervals']);
12351 $optagepcent = VikBooking::getOptionIntervalsPercentage($actopt['ageintervals']);
12352 $optageovrct = VikBooking::getOptionIntervalChildOverrides($actopt, $ord['adults'], $ord['children']);
12353 $child_num = VikBooking::getRoomOptionChildNumber($ord['optionals'], $actopt['id'], $roptkey, $ord['children']);
12354 $optagecosts = VikBooking::getOptionIntervalsCosts(isset($optageovrct['ageintervals_child' . ($child_num + 1)]) ? $optageovrct['ageintervals_child' . ($child_num + 1)] : $actopt['ageintervals']);
12355 $agestept = explode('-', $stept[1]);
12356 $stept[1] = $agestept[0];
12357 $chvar = $agestept[1];
12358 if (array_key_exists(($chvar - 1), $optagepcent) && $optagepcent[($chvar - 1)] > 0) {
12359 $optpcent = true;
12360 }
12361 $actopt['chageintv'] = $chvar;
12362 if (isset($optagenames[($chvar - 1)])) {
12363 $actopt['name'] .= ' ('.$optagenames[($chvar - 1)].')';
12364 }
12365 if (isset($optagecosts[($chvar - 1)])) {
12366 $realcost = (intval($actopt['perday']) == 1 ? (floatval($optagecosts[($chvar - 1)]) * $booking_nights * $stept[1]) : (floatval($optagecosts[($chvar - 1)]) * $stept[1]));
12367 } else {
12368 $realcost = 0;
12369 }
12370 } else {
12371 // VBO 1.11 - options percentage cost of the room total fee
12372 $optpcent = (int)$actopt['pcentroom'] ? true : $optpcent;
12373 //
12374 $realcost = (intval($actopt['perday']) == 1 ? ($actopt['cost'] * $booking_nights * $stept[1]) : ($actopt['cost'] * $stept[1]));
12375 }
12376 if ($actopt['maxprice'] > 0 && $realcost > $actopt['maxprice']) {
12377 $realcost=$actopt['maxprice'];
12378 if (intval($actopt['hmany']) == 1 && intval($stept[1]) > 1) {
12379 $realcost = $actopt['maxprice'] * $stept[1];
12380 }
12381 }
12382 $realcost = $actopt['perperson'] == 1 ? ($realcost * $ord['adults']) : $realcost;
12383 $tmpopr = VikBooking::sayOptionalsPlusIva($realcost, $actopt['idiva']);
12384 $options_str .= ($stept[1] > 1 ? $stept[1]." " : "").$actopt['name'].": ".(!$optpcent ? $currencyname : '')." ".VikBooking::numberFormat($tmpopr).($optpcent ? ' %' : '')." \r\n";
12385 }
12386 }
12387 }
12388 }
12389
12390 // custom extra costs
12391 if (!empty($ord['extracosts'])) {
12392 $cur_extra_costs = json_decode($ord['extracosts'], true);
12393 foreach ($cur_extra_costs as $eck => $ecv) {
12394 $ecplustax = !empty($ecv['idtax']) ? VikBooking::sayOptionalsPlusIva($ecv['cost'], $ecv['idtax']) : $ecv['cost'];
12395 $options_str .= $ecv['name'].": ".$currencyname." ".VikBooking::numberFormat($ecplustax)." \r\n";
12396 }
12397 }
12398
12399 // taxes
12400 $taxes_str = '';
12401 if ($ord['tot_taxes'] > 0.00) {
12402 $taxes_str .= $usecurrencyname.' '.VikBooking::numberFormat($ord['tot_taxes']);
12403 if (!empty($ord['aliq']) && !empty($ord['breakdown'])) {
12404 $tax_breakdown = json_decode($ord['breakdown'], true);
12405 $tax_breakdown = is_array($tax_breakdown) && count($tax_breakdown) > 0 ? $tax_breakdown : array();
12406 if (count($tax_breakdown)) {
12407 foreach ($tax_breakdown as $tbkk => $tbkv) {
12408 $tax_break_cost = $ord['tot_taxes'] * floatval($tbkv['aliq']) / $ord['aliq'];
12409 $taxes_str .= "\r\n".$tbkv['name'].": ".$usecurrencyname.' '.VikBooking::numberFormat($tax_break_cost);
12410 }
12411 }
12412 }
12413 }
12414 if (isset($orders[($kord + 1)]) && $orders[($kord + 1)]['id'] == $ord['id']) {
12415 // total taxes will be printed only for the last room booked
12416 $taxes_str = '';
12417 }
12418
12419 // created by
12420 $created_by = '';
12421 if (!empty($ord['ujid'])) {
12422 $creator = new JUser($ord['ujid']);
12423 if (property_exists($creator, 'name')) {
12424 $created_by = $creator->name.' ('.$creator->username.')';
12425 }
12426 }
12427 if (empty($created_by) && !empty($ord['t_first_name'])) {
12428 $created_by = $ord['t_first_name'].' '.$ord['t_last_name'];
12429 }
12430
12431 // push line for export
12432 $orderscsv[] = [
12433 [
12434 'value' => $ord['id'],
12435 ],
12436 [
12437 'value' => date(str_replace("/", $datesep, $df), $ord['ts']),
12438 ],
12439 [
12440 'value' => date(str_replace("/", $datesep, $df), $booking_checkin),
12441 ],
12442 [
12443 'value' => date(str_replace("/", $datesep, $df), $booking_checkout),
12444 ],
12445 [
12446 'value' => $booking_nights,
12447 ],
12448 [
12449 'value' => $ord['name'],
12450 ],
12451 [
12452 'value' => $peoplestr,
12453 ],
12454 [
12455 'value' => $custinfostr,
12456 ],
12457 [
12458 'value' => $special_requests,
12459 ],
12460 [
12461 'value' => $ord['adminnotes'],
12462 ],
12463 [
12464 'value' => $created_by,
12465 ],
12466 [
12467 'value' => $ord['custmail'],
12468 ],
12469 [
12470 'value' => $ord['phone'],
12471 ],
12472 [
12473 'value' => $options_str,
12474 ],
12475 [
12476 'value' => $paystr,
12477 ],
12478 [
12479 'value' => $ordnumbstr,
12480 ],
12481 [
12482 'value' => $statusstr,
12483 ],
12484 [
12485 'value' => $totalstring,
12486 ],
12487 [
12488 'value' => $totalpaidstring,
12489 ],
12490 [
12491 'value' => $taxes_str,
12492 ],
12493 ];
12494 }
12495
12496 // set CSV rows
12497 $report_obj->setReportRows($orderscsv);
12498
12499 // build lines to export
12500 $csvlines = $report_obj->getExportCSVLines($no_data = true);
12501
12502 // set export file name
12503 $report_obj->setExportCSVFileName('bookings_export_' . date('Y-m-d') . '.csv');
12504
12505 // force the download of the CSV file
12506 $report_obj->outputHeaders();
12507
12508 // send lines to output
12509 $report_obj->outputCSV($csvlines);
12510
12511 exit;
12512 }
12513
12514 public function exportcustomerslaunch() {
12515 $cid = VikRequest::getVar('cid', array(0));
12516 $dbo = JFactory::getDBO();
12517 $pnotes = VikRequest::getInt('notes', '', 'request');
12518 $pscanimg = VikRequest::getInt('scanimg', '', 'request');
12519 $ppin = VikRequest::getInt('pin', '', 'request');
12520 $pcountry = VikRequest::getString('country', '', 'request');
12521 $pfromdate = VikRequest::getString('fromdate', '', 'request');
12522 $ptodate = VikRequest::getString('todate', '', 'request');
12523 $pdatefilt = VikRequest::getInt('datefilt', '', 'request');
12524 $clauses = array();
12525 if (count($cid) > 0 && !empty($cid[0])) {
12526 $clauses[] = "`c`.`id` IN (".implode(', ', $cid).")";
12527 }
12528 if (!empty($pcountry)) {
12529 $clauses[] = "`c`.`country`=".$dbo->quote($pcountry);
12530 }
12531 $datescol = '`bk`.`ts`';
12532 if ($pdatefilt > 0) {
12533 if ($pdatefilt == 1) {
12534 $datescol = '`bk`.`ts`';
12535 } elseif ($pdatefilt == 2) {
12536 $datescol = '`bk`.`checkin`';
12537 } elseif ($pdatefilt == 3) {
12538 $datescol = '`bk`.`checkout`';
12539 }
12540 }
12541 if (!empty($pfromdate)) {
12542 $from_ts = VikBooking::getDateTimestamp($pfromdate, 0, 0);
12543 $clauses[] = $datescol.">=".$from_ts;
12544 }
12545 if (!empty($ptodate)) {
12546 $to_ts = VikBooking::getDateTimestamp($ptodate, 23, 59);
12547 $clauses[] = $datescol."<=".$to_ts;
12548 }
12549 //this query below is safe with the error #1055 when sql_mode=only_full_group_by
12550 $q = "SELECT `c`.`id`,`c`.`first_name`,`c`.`last_name`,`c`.`email`,`c`.`phone`,`c`.`country`,`c`.`cfields`,`c`.`pin`,`c`.`ujid`,`c`.`address`,`c`.`city`,`c`.`zip`,`c`.`doctype`,`c`.`docnum`,`c`.`docimg`,`c`.`notes`,`c`.`ischannel`,`c`.`chdata`,`c`.`company`,`c`.`vat`,`c`.`gender`,`c`.`bdate`,`c`.`pbirth`,".
12551 "(SELECT COUNT(*) FROM `#__vikbooking_customers_orders` AS `co` WHERE `co`.`idcustomer`=`c`.`id`) AS `tot_bookings`,".
12552 "`cy`.`country_3_code`,`cy`.`country_name` ".
12553 "FROM `#__vikbooking_customers` AS `c` LEFT JOIN `#__vikbooking_countries` `cy` ON `cy`.`country_3_code`=`c`.`country` ".
12554 "LEFT JOIN `#__vikbooking_customers_orders` `co` ON `co`.`idcustomer`=`c`.`id` ".
12555 "LEFT JOIN `#__vikbooking_orders` `bk` ON `bk`.`id`=`co`.`idorder`".
12556 (count($clauses) > 0 ? " WHERE ".implode(' AND ', $clauses) : "")."
12557 GROUP BY `c`.`id`,`c`.`first_name`,`c`.`last_name`,`c`.`email`,`c`.`phone`,`c`.`country`,`c`.`cfields`,`c`.`pin`,`c`.`ujid`,`c`.`address`,`c`.`city`,`c`.`zip`,`c`.`doctype`,`c`.`docnum`,`c`.`docimg`,`c`.`notes`,`c`.`ischannel`,`c`.`chdata`,`c`.`company`,`c`.`vat`,`c`.`gender`,`c`.`bdate`,`c`.`pbirth`,`cy`.`country_3_code`,`cy`.`country_name` ".
12558 "ORDER BY `c`.`last_name` ASC;";
12559 $dbo->setQuery($q);
12560 $dbo->execute();
12561 if (!($dbo->getNumRows() > 0)) {
12562 VikError::raiseWarning('', JText::translate('VBONORECORDSCSVCUSTOMERS'));
12563 $mainframe = JFactory::getApplication();
12564 $mainframe->redirect("index.php?option=com_vikbooking&task=customers");
12565 exit;
12566 }
12567 $customers = $dbo->loadAssocList();
12568 $csvlines = array();
12569 $csvheadline = array('ID', JText::translate('VBCUSTOMERLASTNAME'), JText::translate('VBCUSTOMERFIRSTNAME'), JText::translate('VBCUSTOMEREMAIL'), JText::translate('VBCUSTOMERPHONE'), JText::translate('VBCUSTOMERADDRESS'), JText::translate('VBCUSTOMERCITY'), JText::translate('VBCUSTOMERZIP'), JText::translate('VBCUSTOMERCOUNTRY'), JText::translate('VBCUSTOMERTOTBOOKINGS'));
12570 if ($ppin > 0) {
12571 $csvheadline[] = JText::translate('VBCUSTOMERPIN');
12572 }
12573 if ($pscanimg > 0) {
12574 $csvheadline[] = JText::translate('VBCUSTOMERDOCTYPE');
12575 $csvheadline[] = JText::translate('VBCUSTOMERDOCNUM');
12576 $csvheadline[] = JText::translate('VBCUSTOMERDOCIMG');
12577 }
12578 if ($pnotes > 0) {
12579 $csvheadline[] = JText::translate('VBCUSTOMERNOTES');
12580 }
12581 $csvlines[] = $csvheadline;
12582 foreach ($customers as $customer) {
12583 $csvcustomerline = array($customer['id'], $customer['last_name'], $customer['first_name'], $customer['email'], $customer['phone'], $customer['address'], $customer['city'], $customer['zip'], $customer['country_name'], $customer['tot_bookings']);
12584 if ($ppin > 0) {
12585 $csvcustomerline[] = $customer['pin'];
12586 }
12587 if ($pscanimg > 0) {
12588 $csvcustomerline[] = $customer['doctype'];
12589 $csvcustomerline[] = $customer['docnum'];
12590 $csvcustomerline[] = (!empty($customer['docimg']) ? VBO_ADMIN_URI.'resources/idscans/'.$customer['docimg'] : '');
12591 }
12592 if ($pnotes > 0) {
12593 $csvcustomerline[] = $customer['notes'];
12594 }
12595 $csvlines[] = $csvcustomerline;
12596 }
12597 header("Content-type: text/csv");
12598 header("Cache-Control: no-store, no-cache");
12599 header('Content-Disposition: attachment; filename="customers_export_'.(!empty($pcountry) ? strtolower($pcountry).'_' : '').date('Y-m-d').'.csv"');
12600 $outstream = fopen("php://output", 'w');
12601 foreach ($csvlines as $csvline) {
12602 fputcsv($outstream, $csvline);
12603 }
12604 fclose($outstream);
12605 exit;
12606 }
12607
12608 public function renewsession() {
12609 /*
12610 * @wponly
12611 * We just destroy the session
12612 */
12613 JSessionHandler::destroy();
12614 $mainframe = JFactory::getApplication();
12615 $mainframe->redirect("index.php?option=com_vikbooking&task=config");
12616 }
12617
12618 public function trackings() {
12619 VikBookingHelper::printHeader("trackings");
12620
12621 VikRequest::setVar('view', VikRequest::getCmd('view', 'trackings'));
12622
12623 parent::display();
12624
12625 if (VikBooking::showFooter()) {
12626 VikBookingHelper::printFooter();
12627 }
12628 }
12629
12630 public function trkconfig() {
12631 VikBookingHelper::printHeader("trackings");
12632
12633 VikRequest::setVar('view', VikRequest::getCmd('view', 'trkconfig'));
12634
12635 parent::display();
12636
12637 if (VikBooking::showFooter()) {
12638 VikBookingHelper::printFooter();
12639 }
12640 }
12641
12642 public function savetrkconfigstay() {
12643 if (!JSession::checkToken()) {
12644 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
12645 }
12646 $this->do_savetrkconfig(true);
12647 }
12648
12649 public function savetrkconfig() {
12650 if (!JSession::checkToken()) {
12651 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
12652 }
12653 $this->do_savetrkconfig();
12654 }
12655
12656 private function do_savetrkconfig($stay = false) {
12657 $dbo = JFactory::getDBO();
12658 $trkenabled = VikRequest::getInt('trkenabled', 0, 'request');
12659 $trkenabled = $trkenabled == 1 ? 1 : 0;
12660 $trkcookierfrdur = VikRequest::getFloat('trkcookierfrdur', 1, 'request');
12661 $trkcookierfrdur = $trkcookierfrdur < 0.1 ? 1 : $trkcookierfrdur;
12662 $trkcampname = VikRequest::getVar('trkcampname', array());
12663 $trkcampkey = VikRequest::getVar('trkcampkey', array());
12664 $trkcampval = VikRequest::getVar('trkcampval', array());
12665 $trkcampaigns = array();
12666 foreach ($trkcampname as $k => $v) {
12667 if (empty($trkcampkey[$k])) {
12668 continue;
12669 }
12670 $trkcampkey[$k] = str_replace(' ', '', trim($trkcampkey[$k]));
12671 $name = !empty($v) ? $v : date('Y-m-d').' '.(count($trkcampaigns) + 1);
12672 $trkcampaigns[$trkcampkey[$k]] = array(
12673 'key' => $trkcampkey[$k],
12674 'value' => $trkcampval[$k],
12675 'name' => $name,
12676 );
12677 }
12678
12679 $q = "UPDATE `#__vikbooking_config` SET `setting`=".$dbo->quote($trkenabled)." WHERE `param`='trkenabled';";
12680 $dbo->setQuery($q);
12681 $dbo->execute();
12682 $q = "UPDATE `#__vikbooking_config` SET `setting`=".$dbo->quote($trkcookierfrdur)." WHERE `param`='trkcookierfrdur';";
12683 $dbo->setQuery($q);
12684 $dbo->execute();
12685 $q = "UPDATE `#__vikbooking_config` SET `setting`=".$dbo->quote(json_encode($trkcampaigns))." WHERE `param`='trkcampaigns';";
12686 $dbo->setQuery($q);
12687 $dbo->execute();
12688
12689 $mainframe = JFactory::getApplication();
12690 $mainframe->redirect("index.php?option=com_vikbooking&task=".($stay ? 'trkconfig' : 'trackings'));
12691 }
12692
12693 public function modtracking() {
12694 $dbo = JFactory::getDbo();
12695 $cid = VikRequest::getVar('cid', array());
12696 foreach ($cid as $id) {
12697 if (!empty($id)) {
12698 $q = "SELECT `id`,`published` FROM `#__vikbooking_trackings` WHERE `id`=".(int)$id.";";
12699 $dbo->setQuery($q);
12700 $dbo->execute();
12701 if ($dbo->getNumRows()) {
12702 $data = $dbo->loadAssoc();
12703 $q = "UPDATE `#__vikbooking_trackings` SET `published`=".($data['published'] ? '0' : '1')." WHERE `id`=".(int)$data['id'].";";
12704 $dbo->setQuery($q);
12705 $dbo->execute();
12706 }
12707 }
12708 }
12709 $mainframe = JFactory::getApplication();
12710 $mainframe->redirect("index.php?option=com_vikbooking&task=trackings");
12711 }
12712
12713 public function removetrackings()
12714 {
12715 if (!JFactory::getUser()->authorise('core.delete', 'com_vikbooking')) {
12716 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
12717 }
12718
12719 $ids = VikRequest::getVar('cid', array());
12720 $dbo = JFactory::getDbo();
12721
12722 foreach ($ids as $d) {
12723 $q = "DELETE FROM `#__vikbooking_trackings` WHERE `id`=".(int)$d.";";
12724 $dbo->setQuery($q);
12725 $dbo->execute();
12726 $q = "DELETE FROM `#__vikbooking_tracking_infos` WHERE `idtracking`=".(int)$d.";";
12727 $dbo->setQuery($q);
12728 $dbo->execute();
12729 }
12730
12731 $mainframe = JFactory::getApplication();
12732 $mainframe->redirect("index.php?option=com_vikbooking&task=trackings");
12733 }
12734
12735 /**
12736 * Invokes the Tracker class to obtain
12737 * geo information about the IP addresses.
12738 * This task is called via ajax.
12739 *
12740 * @since 1.11
12741 */
12742 public function getgeoinfo() {
12743 $ips = VikRequest::getVar('ips', array());
12744 if (!count($ips)) {
12745 echo 'e4j.error.empty IPs';
12746 exit;
12747 }
12748
12749 // require the Tracker class without instantiating the object
12750 VikBooking::getTracker(true);
12751 $geo_info = VikBookingTracker::getIpGeoInfo($ips);
12752
12753 if ($geo_info === false) {
12754 echo 'e4j.error.Tracker error, could not get geo info from IPs';
12755 exit;
12756 }
12757
12758 // update db values and compose response
12759 $dbo = JFactory::getDbo();
12760 $resp = array();
12761 foreach ($geo_info as $id => $geo) {
12762 if (is_null($geo) || $geo === false) {
12763 continue;
12764 }
12765 // compose geo info string
12766 $geovals = array();
12767 if (!empty($geo['city'])) {
12768 array_push($geovals, $geo['city']);
12769 }
12770 if (!empty($geo['region'])) {
12771 array_push($geovals, $geo['region']);
12772 }
12773 $threecode = '';
12774 $cname = '';
12775 if (!empty($geo['country'])) {
12776 // returned country is a 2-char code, get the 3-char country code
12777 $q = "SELECT `country_3_code`,`country_name` FROM `#__vikbooking_countries` WHERE `country_2_code`=".$dbo->quote($geo['country']).";";
12778 $dbo->setQuery($q);
12779 $dbo->execute();
12780 if ($dbo->getNumRows()) {
12781 $cinfo = $dbo->loadAssoc();
12782 $threecode = $cinfo['country_3_code'];
12783 $cname = $cinfo['country_name'];
12784 }
12785 array_push($geovals, (empty($cname) ? $geo['country'] : $cname));
12786 }
12787
12788 // full geo information string
12789 $geoinfostr = implode(', ', $geovals);
12790
12791 // push data to the response pool
12792 $resp[$id] = array();
12793 $resp[$id]['geo'] = $geoinfostr;
12794 if (!empty($cname)) {
12795 $resp[$id]['country'] = $cname;
12796 }
12797 if (!empty($threecode)) {
12798 $resp[$id]['country3'] = $threecode;
12799 }
12800
12801 // update main tracking record
12802 $q = "UPDATE `#__vikbooking_trackings` SET `geo`=".$dbo->quote($geoinfostr).(!empty($threecode) ? ', `country`='.$dbo->quote($threecode) : '')." WHERE `id`=".(int)$id.";";
12803 $dbo->setQuery($q);
12804 $dbo->execute();
12805 }
12806
12807 // output the JSON response
12808 echo json_encode($resp);
12809 exit;
12810 }
12811
12812 /**
12813 * Counts the orphan dates for all published rooms
12814 * depending on their restrictions and booked dates.
12815 * By default, the task takes up to 3 months ahead.
12816 * It is possible to filter the request by rooms and months.
12817 * This task should be called via ajax.
12818 *
12819 * @since 1.11
12820 */
12821 public function orphanscount()
12822 {
12823 $dbo = JFactory::getDbo();
12824 $orphans = array();
12825
12826 $nowdf = VikBooking::getDateFormat();
12827 if ($nowdf == "%d/%m/%Y") {
12828 $df = 'd/m/Y';
12829 } elseif ($nowdf == "%m/%d/%Y") {
12830 $df = 'm/d/Y';
12831 } else {
12832 $df = 'Y/m/d';
12833 }
12834
12835 // global min los
12836 $glob_minlos = VikBooking::getDefaultNightsCalendar();
12837 $glob_minlos = $glob_minlos < 1 ? 1 : $glob_minlos;
12838
12839 // rooms and dates
12840 $roomids = VikRequest::getVar('roomids', array(), 'request', 'int');
12841 $months = VikRequest::getInt('months', 3, 'request');
12842 $from = VikRequest::getString('from', '', 'request');
12843 $today = strtotime(date('Y').'-'.date('m').'-'.date('d'));
12844 if (!empty($from)) {
12845 $fromts = VikBooking::getDateTimestamp($from, 0, 0);
12846 if (!empty($fromts)) {
12847 // custom starting date
12848 $today = $fromts;
12849 }
12850 }
12851 $until = strtotime("+{$months} months", $today);
12852
12853 // load all rooms
12854 $rooms = array();
12855 $q = "SELECT `id`,`name`,`units` FROM `#__vikbooking_rooms` WHERE `avail`=1".(count($roomids) ? ' AND `id` IN ('.implode(', ', $roomids).')' : '').";";
12856 $dbo->setQuery($q);
12857 $dbo->execute();
12858 if ($dbo->getNumRows()) {
12859 $allrooms = $dbo->loadAssocList();
12860 foreach ($allrooms as $r) {
12861 $rooms[$r['id']] = $r;
12862 }
12863 }
12864 if (!count($rooms)) {
12865 // no rooms found, exit
12866 echo json_encode($orphans);
12867 exit;
12868 }
12869
12870 // load availabilities
12871 $q = "SELECT `b`.*,`ob`.`idorder` FROM `#__vikbooking_busy` AS `b`,`#__vikbooking_ordersbusy` AS `ob` WHERE `b`.`idroom` IN (".implode(', ', array_keys($rooms)).") AND `b`.`id`=`ob`.`idbusy` AND (`b`.`checkin`>=".$today." OR `b`.`checkout`>=".$today.") AND (`b`.`checkin`<=".$until." OR `b`.`checkout`<=".$today.");";
12872 $dbo->setQuery($q);
12873 $dbo->execute();
12874 if (!$dbo->getNumRows()) {
12875 // no booked dates found, exit
12876 echo json_encode($orphans);
12877 exit;
12878 }
12879 $busy = $dbo->loadAssocList();
12880
12881 // sort booked dates by room id
12882 $rooms_busy = array();
12883 foreach ($busy as $b) {
12884 if (!isset($rooms_busy[$b['idroom']])) {
12885 $rooms_busy[$b['idroom']] = array();
12886 }
12887 array_push($rooms_busy[$b['idroom']], $b);
12888 }
12889
12890 // load restrictions
12891 $rooms_restr = array();
12892 foreach ($rooms as $rid => $r) {
12893 $restrictions = VikBooking::loadRestrictions(true, array($rid));
12894 if (count($restrictions)) {
12895 $rooms_restr[$rid] = $restrictions;
12896 }
12897 }
12898 if (!count($rooms_restr) && $glob_minlos < 2) {
12899 // no restrictions found and minlos=1, exit
12900 echo json_encode($orphans);
12901 exit;
12902 }
12903
12904 // count availability and minlos per day
12905 $rooms_data = array();
12906 foreach ($rooms as $rid => $r) {
12907 $rooms_data[$rid] = array(
12908 'avail' => array(),
12909 'restr' => array()
12910 );
12911 $nowts = getdate($today);
12912 while ($nowts[0] <= $until) {
12913 $dateind = date('Y-m-d', $nowts[0]);
12914
12915 // remaining availability
12916 if (!isset($rooms_busy[$rid])) {
12917 // no bookings for this room, set full availability for this day
12918 $rooms_data[$rid]['avail'][] = array(
12919 'dt' => $dateind,
12920 'units' => $r['units']
12921 );
12922 } else {
12923 // check remaining availability for this day
12924 $totfound = 0;
12925 foreach ($rooms_busy[$rid] as $b) {
12926 $tmpone = getdate($b['checkin']);
12927 $rit = ($tmpone['mon'] < 10 ? "0".$tmpone['mon'] : $tmpone['mon'])."/".($tmpone['mday'] < 10 ? "0".$tmpone['mday'] : $tmpone['mday'])."/".$tmpone['year'];
12928 $ritts = strtotime($rit);
12929 $tmptwo = getdate($b['checkout']);
12930 $con = ($tmptwo['mon'] < 10 ? "0".$tmptwo['mon'] : $tmptwo['mon'])."/".($tmptwo['mday'] < 10 ? "0".$tmptwo['mday'] : $tmptwo['mday'])."/".$tmptwo['year'];
12931 $conts = strtotime($con);
12932 if ($nowts[0] >= $ritts && $nowts[0] < $conts) {
12933 $totfound++;
12934 }
12935 }
12936 $totfound = $totfound > $r['units'] ? $r['units'] : $totfound;
12937 $rooms_data[$rid]['avail'][] = array(
12938 'dt' => $dateind,
12939 'units' => ($r['units'] - $totfound)
12940 );
12941 }
12942
12943 // restrictions
12944 if (!isset($rooms_restr[$rid])) {
12945 // no restrictions for this room, set global minlos for this day
12946 $rooms_data[$rid]['restr'][] = array(
12947 'dt' => $dateind,
12948 'minlos' => $glob_minlos
12949 );
12950 } else {
12951 // get restriction for this day
12952 $today_tsin = mktime(0, 0, 0, $nowts['mon'], $nowts['mday'], $nowts['year']);
12953 $today_tsout = mktime(0, 0, 0, $nowts['mon'], ($nowts['mday'] + 1), $nowts['year']);
12954
12955 $restr = VikBooking::parseSeasonRestrictions($today_tsin, $today_tsout, 1, $rooms_restr[$rid]);
12956 $minlos = count($restr) ? $restr['minlos'] : $glob_minlos;
12957
12958 $rooms_data[$rid]['restr'][] = array(
12959 'dt' => $dateind,
12960 'minlos' => $minlos
12961 );
12962 }
12963
12964 // next loop
12965 $dayts = mktime(0, 0, 0, $nowts['mon'], ($nowts['mday'] + 1), $nowts['year']);
12966 $nowts = getdate($dayts);
12967 }
12968 }
12969
12970 // week days and months labels
12971 $days_labels = array(
12972 JText::translate('VBSUNDAY'),
12973 JText::translate('VBMONDAY'),
12974 JText::translate('VBTUESDAY'),
12975 JText::translate('VBWEDNESDAY'),
12976 JText::translate('VBTHURSDAY'),
12977 JText::translate('VBFRIDAY'),
12978 JText::translate('VBSATURDAY')
12979 );
12980 $months_labels = array(
12981 JText::translate('VBMONTHONE'),
12982 JText::translate('VBMONTHTWO'),
12983 JText::translate('VBMONTHTHREE'),
12984 JText::translate('VBMONTHFOUR'),
12985 JText::translate('VBMONTHFIVE'),
12986 JText::translate('VBMONTHSIX'),
12987 JText::translate('VBMONTHSEVEN'),
12988 JText::translate('VBMONTHEIGHT'),
12989 JText::translate('VBMONTHNINE'),
12990 JText::translate('VBMONTHTEN'),
12991 JText::translate('VBMONTHELEVEN'),
12992 JText::translate('VBMONTHTWELVE')
12993 );
12994
12995 // orphan dates calculation method
12996 $calc_method = VikBooking::orphansCalculation();
12997
12998 // parse data and build orphans if any
12999 foreach ($rooms_data as $rid => $data) {
13000 foreach ($data['avail'] as $ind => $av) {
13001 if (!isset($data['restr'][$ind]) || $av['units'] < 1) {
13002 // continue, no restriction set or no availability for this day
13003 continue;
13004 }
13005 if ($data['restr'][$ind]['minlos'] < 2) {
13006 // continue, no min los > 1 set for this day
13007 continue;
13008 }
13009 // check if any night after today, until min los, is fully booked
13010 $hasorphans = false;
13011 $forward_count = 0;
13012 for ($i = 1; $i < $data['restr'][$ind]['minlos']; $i++) {
13013 if (!isset($data['avail'][($ind + $i)])) {
13014 // break loop, no info for this day after
13015 break;
13016 }
13017 if ($data['avail'][($ind + $i)]['units'] > 0) {
13018 // continue, availability found for tomorrow, we need a non available next-day
13019 continue;
13020 }
13021 // orphan found
13022 $hasorphans = true;
13023 $forward_count = $i;
13024 break;
13025 }
13026
13027 /**
13028 * Backward calculation method only if "prevnext".
13029 *
13030 * @since 1.3.0
13031 */
13032 $backward_count = 0;
13033 for ($i = 1; $i <= $data['restr'][$ind]['minlos']; $i++) {
13034 if (!isset($data['avail'][($ind - $i)])) {
13035 // break loop, no info for this prev day
13036 break;
13037 }
13038 if ($data['avail'][($ind - $i)]['units'] > 0) {
13039 // increase free nights going backward
13040 $backward_count++;
13041 }
13042 }
13043 if ($calc_method == 'prevnext' && $hasorphans && $backward_count > 0 && ($backward_count >= $data['restr'][$ind]['minlos'] || ($backward_count + $forward_count) >= $data['restr'][$ind]['minlos'])) {
13044 // this should not be an orphan date because of enough free days back, or enough free days in between
13045 $hasorphans = false;
13046 }
13047 //
13048
13049 if ($hasorphans) {
13050 // we pass the name of the room, the list of raw dates (Y-m-d), the list of readable dates, and the fist date with the VBO format
13051 if (!isset($orphans[$rid])) {
13052 $orphans[$rid] = array(
13053 'name' => $rooms[$rid]['name'],
13054 'dates' => array(),
13055 'rdates' => array(),
13056 'linkd' => date($df, strtotime($av['dt']))
13057 );
13058 }
13059 array_push($orphans[$rid]['dates'], $av['dt']);
13060 // build the value for the readable date
13061 $dtinfo = getdate(strtotime($av['dt']));
13062 $rdate = $days_labels[$dtinfo['wday']] . ', ' . $months_labels[($dtinfo['mon'] - 1)] . ' ' . $dtinfo['mday'] . ' ' . $dtinfo['year'];
13063 array_push($orphans[$rid]['rdates'], $rdate);
13064 }
13065 }
13066 }
13067
13068 // output response
13069 echo json_encode($orphans);
13070 exit;
13071 }
13072
13073 public function tableaux() {
13074 VikBookingHelper::printHeader("tableaux");
13075
13076 VikRequest::setVar('view', VikRequest::getCmd('view', 'tableaux'));
13077
13078 parent::display();
13079
13080 if (VikBooking::showFooter()) {
13081 VikBookingHelper::printFooter();
13082 }
13083 }
13084
13085 public function operators() {
13086 VikBookingHelper::printHeader("operators");
13087
13088 VikRequest::setVar('view', VikRequest::getCmd('view', 'operators'));
13089
13090 parent::display();
13091
13092 if (VikBooking::showFooter()) {
13093 VikBookingHelper::printFooter();
13094 }
13095 }
13096
13097 public function newoperator() {
13098 VikBookingHelper::printHeader("operators");
13099
13100 VikRequest::setVar('view', VikRequest::getCmd('view', 'manageoperator'));
13101
13102 parent::display();
13103
13104 if (VikBooking::showFooter()) {
13105 VikBookingHelper::printFooter();
13106 }
13107 }
13108
13109 public function editoperator() {
13110 VikBookingHelper::printHeader("operators");
13111
13112 VikRequest::setVar('view', VikRequest::getCmd('view', 'manageoperator'));
13113
13114 parent::display();
13115
13116 if (VikBooking::showFooter()) {
13117 VikBookingHelper::printFooter();
13118 }
13119 }
13120
13121 public function updateoperator()
13122 {
13123 if (!JSession::checkToken()) {
13124 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
13125 }
13126
13127 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
13128 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
13129 }
13130
13131 $this->do_updateoperator();
13132 }
13133
13134 public function updateoperatorstay()
13135 {
13136 if (!JSession::checkToken()) {
13137 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
13138 }
13139
13140 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
13141 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
13142 }
13143
13144 $this->do_updateoperator(true);
13145 }
13146
13147 private function do_updateoperator($stay = false) {
13148 $dbo = JFactory::getDBO();
13149 $mainframe = JFactory::getApplication();
13150 $pfirst_name = VikRequest::getString('first_name', '', 'request');
13151 $plast_name = VikRequest::getString('last_name', '', 'request');
13152 $pemail = VikRequest::getString('email', '', 'request');
13153 $pphone = VikRequest::getString('phone', '', 'request');
13154 $pcode = VikRequest::getString('code', '', 'request');
13155 $pujid = VikRequest::getInt('ujid', '', 'request');
13156 $pwhere = VikRequest::getInt('where', '', 'request');
13157 if (!empty($pfirst_name) && !empty($pemail) && (!empty($pcode) || !empty($pujid))) {
13158 $q = "SELECT * FROM `#__vikbooking_operators` WHERE `id`=".(int)$pwhere." LIMIT 1;";
13159 $dbo->setQuery($q);
13160 $dbo->execute();
13161 if ($dbo->getNumRows() == 1) {
13162 $customer = $dbo->loadAssoc();
13163 } else {
13164 $mainframe->redirect("index.php?option=com_vikbooking&task=operators");
13165 exit;
13166 }
13167 $q = "SELECT * FROM `#__vikbooking_operators` WHERE (`email`=".$dbo->quote($pemail)." OR ".(!empty($pcode) ? "`code`=".$dbo->quote($pcode) : "`ujid`=".$dbo->quote($pujid)).") AND `id`!=".(int)$pwhere." LIMIT 1;";
13168 $dbo->setQuery($q);
13169 $dbo->execute();
13170 if ($dbo->getNumRows() == 0) {
13171 // update fingerprint for the operator
13172 $fingpt = md5($pwhere.$pemail);
13173 //
13174 $q = "UPDATE `#__vikbooking_operators` SET `first_name`=".$dbo->quote($pfirst_name).",`last_name`=".$dbo->quote($plast_name).",`email`=".$dbo->quote($pemail).",`phone`=".$dbo->quote($pphone).",`code`=".$dbo->quote($pcode).",`ujid`=".$dbo->quote($pujid).",`fingpt`=".$dbo->quote($fingpt)." WHERE `id`=".(int)$pwhere.";";
13175 $dbo->setQuery($q);
13176 $dbo->execute();
13177 $mainframe->enqueueMessage(JText::translate('VBOPERATORSAVED'));
13178 } else {
13179 //email already exists
13180 $ex_operator = $dbo->loadAssoc();
13181 VikError::raiseWarning('', JText::translate('VBERROPERATOREXISTS').'<br/><a href="index.php?option=com_vikbooking&task=editoperator&cid[]='.$ex_operator['id'].'" target="_blank">'.$ex_operator['first_name'].' '.$ex_operator['last_name'].'</a>');
13182 $mainframe->redirect("index.php?option=com_vikbooking&task=editoperator&cid[]=".$pwhere);
13183 exit;
13184 }
13185 } else {
13186 VikError::raiseWarning('', JText::translate('VBERROPERATORDATA'));
13187 }
13188 if ($stay) {
13189 $mainframe->redirect("index.php?option=com_vikbooking&task=editoperator&cid[]=".$pwhere);
13190 } else {
13191 $mainframe->redirect("index.php?option=com_vikbooking&task=operators");
13192 }
13193 }
13194
13195 public function saveoperator() {
13196 if (!JSession::checkToken()) {
13197 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
13198 }
13199 $dbo = JFactory::getDbo();
13200 $mainframe = JFactory::getApplication();
13201 $pfirst_name = VikRequest::getString('first_name', '', 'request');
13202 $plast_name = VikRequest::getString('last_name', '', 'request');
13203 $pemail = VikRequest::getString('email', '', 'request');
13204 $pphone = VikRequest::getString('phone', '', 'request');
13205 $pcode = VikRequest::getString('code', '', 'request');
13206 $pujid = VikRequest::getInt('ujid', '', 'request');
13207 if (!empty($pfirst_name) && !empty($pemail) && (!empty($pcode) || !empty($pujid))) {
13208 $q = "SELECT * FROM `#__vikbooking_operators` WHERE `email`=".$dbo->quote($pemail)." OR ".(!empty($pcode) ? "`code`=".$dbo->quote($pcode) : "`ujid`=".$dbo->quote($pujid))." LIMIT 1;";
13209 $dbo->setQuery($q);
13210 $dbo->execute();
13211 if ($dbo->getNumRows() == 0) {
13212 $q = "INSERT INTO `#__vikbooking_operators` (`first_name`,`last_name`,`email`,`phone`,`code`,`ujid`) VALUES(".$dbo->quote($pfirst_name).", ".$dbo->quote($plast_name).", ".$dbo->quote($pemail).", ".$dbo->quote($pphone).", ".$dbo->quote($pcode).", ".$dbo->quote($pujid).");";
13213 $dbo->setQuery($q);
13214 $dbo->execute();
13215 $lid = $dbo->insertid();
13216 if (!empty($lid)) {
13217 $mainframe->enqueueMessage(JText::translate('VBOPERATORSAVED'));
13218 // generate fingerprint for the operator
13219 $q = "UPDATE `#__vikbooking_operators` SET `fingpt`=".$dbo->quote(md5($lid.$pemail))." WHERE `id`=".(int)$lid.";";
13220 $dbo->setQuery($q);
13221 $dbo->execute();
13222 //
13223 }
13224 } else {
13225 //email already exists
13226 $ex_operator = $dbo->loadAssoc();
13227 VikError::raiseWarning('', JText::translate('VBERROPERATOREXISTS').'<br/><a href="index.php?option=com_vikbooking&task=editoperator&cid[]='.$ex_operator['id'].'" target="_blank">'.$ex_operator['first_name'].' '.$ex_operator['last_name'].'</a>');
13228 }
13229 } else {
13230 VikError::raiseWarning('', JText::translate('VBERROPERATORDATA'));
13231 }
13232 $mainframe->redirect("index.php?option=com_vikbooking&task=operators");
13233 }
13234
13235 public function removeoperators()
13236 {
13237 if (!JSession::checkToken()) {
13238 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
13239 }
13240
13241 if (!JFactory::getUser()->authorise('core.delete', 'com_vikbooking')) {
13242 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
13243 }
13244
13245 $ids = VikRequest::getVar('cid', array(0));
13246 if ($ids) {
13247 $dbo = JFactory::getDBO();
13248 foreach ($ids as $d) {
13249 $q = "DELETE FROM `#__vikbooking_operators` WHERE `id`=".(int)$d.";";
13250 $dbo->setQuery($q);
13251 $dbo->execute();
13252 }
13253 }
13254 $mainframe = JFactory::getApplication();
13255 $mainframe->redirect("index.php?option=com_vikbooking&task=operators");
13256 }
13257
13258 public function operatorperms() {
13259 $dbo = JFactory::getDbo();
13260 $permtype = VikRequest::getString('permtype', 'tableaux', 'request');
13261 $permschanged = 0;
13262
13263 if ($permtype == 'tableaux') {
13264 $oper_id = VikRequest::getVar('oper_id', array());
13265 $oper_days = VikRequest::getVar('oper_days', array());
13266 $oper_rooms = VikRequest::getVar('oper_rooms', array());
13267 $oper_guestname = VikRequest::getVar('oper_guestname', array());
13268 $oper_roomextras = VikRequest::getVar('oper_roomextras', array());
13269 $oper_rm = VikRequest::getVar('oper_rm', array());
13270 if (count($oper_rm)) {
13271 // remove permissions first
13272 foreach ($oper_rm as $operatorid) {
13273 $q = "SELECT `id`,`perms` FROM `#__vikbooking_operators` WHERE `id`=".(int)$operatorid.";";
13274 $dbo->setQuery($q);
13275 $dbo->execute();
13276 if ($dbo->getNumRows()) {
13277 $current = $dbo->loadAssoc();
13278 $perms = !empty($current['perms']) ? json_decode($current['perms'], true) : array();
13279 $perms = !is_array($perms) ? array() : $perms;
13280 foreach ($perms as $kp => $perm) {
13281 if (isset($perm['type']) && $perm['type'] == $permtype) {
13282 unset($perms[$kp]);
13283 break;
13284 }
13285 }
13286 // update permissions for this operator
13287 $q = "UPDATE `#__vikbooking_operators` SET `perms`=".$dbo->quote(json_encode($perms))." WHERE `id`=".$current['id'].";";
13288 $dbo->setQuery($q);
13289 $dbo->execute();
13290 $permschanged++;
13291 }
13292 }
13293 }
13294 foreach ($oper_id as $k => $v) {
13295 if (empty($v) || !isset($oper_days[$k])) {
13296 // missing data
13297 continue;
13298 }
13299 // get operator
13300 $q = "SELECT `id`,`perms` FROM `#__vikbooking_operators` WHERE `id`=".(int)$v.";";
13301 $dbo->setQuery($q);
13302 $dbo->execute();
13303 if (!$dbo->getNumRows()) {
13304 continue;
13305 }
13306 $current = $dbo->loadAssoc();
13307 $perms = !empty($current['perms']) ? json_decode($current['perms'], true) : array();
13308 $perms = !is_array($perms) ? array() : $perms;
13309 foreach ($perms as $kp => $perm) {
13310 if (isset($perm['type']) && $perm['type'] == $permtype) {
13311 unset($perms[$kp]);
13312 break;
13313 }
13314 }
13315 // push new permission
13316 array_push($perms, array(
13317 'type' => $permtype,
13318 'perms' => array(
13319 'days' => (int)$oper_days[$k],
13320 'rooms' => (isset($oper_rooms[$k]) && is_array($oper_rooms[$k]) ? $oper_rooms[$k] : array()),
13321 'guestname' => (isset($oper_guestname[$k]) && (int)$oper_guestname[$k] > 0 ? 1 : 0),
13322 'roomextras' => (isset($oper_roomextras[$k]) && (int)$oper_roomextras[$k] > 0 ? 1 : 0),
13323 )
13324 ));
13325 // update permissions for this operator
13326 $q = "UPDATE `#__vikbooking_operators` SET `perms`=".$dbo->quote(json_encode($perms))." WHERE `id`=".$current['id'].";";
13327 $dbo->setQuery($q);
13328 $dbo->execute();
13329 $permschanged++;
13330 }
13331 }
13332
13333 $mainframe = JFactory::getApplication();
13334 if ($permschanged > 0) {
13335 $mainframe->enqueueMessage(JText::translate('VBOPERMSUPDOPEROK'));
13336 }
13337 $mainframe->redirect("index.php?option=com_vikbooking&task=".$permtype);
13338 }
13339
13340 public function canceloperator() {
13341 $mainframe = JFactory::getApplication();
13342 $mainframe->redirect("index.php?option=com_vikbooking&task=operators");
13343 }
13344
13345 public function cancelcrons() {
13346 $mainframe = JFactory::getApplication();
13347 $mainframe->redirect("index.php?option=com_vikbooking&task=crons");
13348 }
13349
13350 public function cancelpackages() {
13351 $mainframe = JFactory::getApplication();
13352 $mainframe->redirect("index.php?option=com_vikbooking&task=packages");
13353 }
13354
13355 public function cancelcustomer() {
13356 $mainframe = JFactory::getApplication();
13357 $pgoto = VikRequest::getString('goto', '', 'request', VIKREQUEST_ALLOWRAW);
13358 if (!empty($pgoto)) {
13359 $mainframe->redirect(base64_decode($pgoto));
13360 exit;
13361 }
13362 $mainframe->redirect("index.php?option=com_vikbooking&task=customers");
13363 }
13364
13365 public function cancelbusyvcm() {
13366 $mainframe = JFactory::getApplication();
13367 $mainframe->redirect("index.php?option=com_vikchannelmanager&task=oversight");
13368 }
13369
13370 public function cancelrestriction() {
13371 $mainframe = JFactory::getApplication();
13372 $mainframe->redirect("index.php?option=com_vikbooking&task=restrictions");
13373 }
13374
13375 public function cancelcoupon() {
13376 $mainframe = JFactory::getApplication();
13377 $mainframe->redirect("index.php?option=com_vikbooking&task=coupons");
13378 }
13379
13380 public function cancelcustomf() {
13381 $mainframe = JFactory::getApplication();
13382 $mainframe->redirect("index.php?option=com_vikbooking&task=customf");
13383 }
13384
13385 public function cancelpayment() {
13386 $mainframe = JFactory::getApplication();
13387 $mainframe->redirect("index.php?option=com_vikbooking&task=payments");
13388 }
13389
13390 public function cancelseason() {
13391 $mainframe = JFactory::getApplication();
13392 $mainframe->redirect("index.php?option=com_vikbooking&task=seasons");
13393 }
13394
13395 public function goconfig() {
13396 $mainframe = JFactory::getApplication();
13397 $mainframe->redirect("index.php?option=com_vikbooking&task=config");
13398 }
13399
13400 public function canceledorder() {
13401 $pgoto = VikRequest::getString('goto', 'orders', 'request');
13402 $mainframe = JFactory::getApplication();
13403 $mainframe->redirect("index.php?option=com_vikbooking&task=" . $pgoto);
13404 }
13405
13406 public function cancelbusy() {
13407 $pidorder = VikRequest::getString('idorder', '', 'request');
13408 $pgoto = VikRequest::getString('goto', '', 'request');
13409 $mainframe = JFactory::getApplication();
13410 $mainframe->redirect("index.php?option=com_vikbooking&task=editorder&cid[]=".$pidorder.($pgoto == 'overv' ? '&goto=overv' : ''));
13411 }
13412
13413 public function canceloverv() {
13414 $mainframe = JFactory::getApplication();
13415 $mainframe->redirect("index.php?option=com_vikbooking&task=overv");
13416 }
13417
13418 public function canceltableaux() {
13419 $mainframe = JFactory::getApplication();
13420 $mainframe->redirect("index.php?option=com_vikbooking&task=tableaux");
13421 }
13422
13423 public function cancelcalendar() {
13424 $pidroom = VikRequest::getString('idroom', '', 'request');
13425 $mainframe = JFactory::getApplication();
13426 $mainframe->redirect("index.php?option=com_vikbooking&task=calendar&cid[]=".$pidroom);
13427 }
13428
13429 public function canceloptionals() {
13430 $mainframe = JFactory::getApplication();
13431 $mainframe->redirect("index.php?option=com_vikbooking&task=optionals");
13432 }
13433
13434 public function cancel() {
13435 $mainframe = JFactory::getApplication();
13436 $mainframe->redirect("index.php?option=com_vikbooking&task=rooms");
13437 }
13438
13439 public function cancelcarat() {
13440 $mainframe = JFactory::getApplication();
13441 $mainframe->redirect("index.php?option=com_vikbooking&task=carat");
13442 }
13443
13444 public function cancelcat() {
13445 $mainframe = JFactory::getApplication();
13446 $mainframe->redirect("index.php?option=com_vikbooking&task=categories");
13447 }
13448
13449 public function cancelprice() {
13450 $mainframe = JFactory::getApplication();
13451 $mainframe->redirect("index.php?option=com_vikbooking&task=prices");
13452 }
13453
13454 public function canceliva() {
13455 $mainframe = JFactory::getApplication();
13456 $mainframe->redirect("index.php?option=com_vikbooking&task=iva");
13457 }
13458
13459 public function canceltrk() {
13460 $mainframe = JFactory::getApplication();
13461 $mainframe->redirect("index.php?option=com_vikbooking&task=trackings");
13462 }
13463
13464 public function canceldash() {
13465 $mainframe = JFactory::getApplication();
13466 $mainframe->redirect("index.php?option=com_vikbooking");
13467 }
13468
13469 public function cancelinvoice() {
13470 $mainframe = JFactory::getApplication();
13471 $pgoto = VikRequest::getString('goto', '', 'request', VIKREQUEST_ALLOWRAW);
13472 if (!empty($pgoto)) {
13473 $mainframe->redirect(base64_decode($pgoto));
13474 exit;
13475 }
13476 $mainframe->redirect("index.php?option=com_vikbooking&task=invoices");
13477 }
13478
13479 /**
13480 * AJAX upload the customer documents.
13481 *
13482 * @return void
13483 *
13484 * @throws Exception
13485 */
13486 public function upload_customer_document()
13487 {
13488 $input = JFactory::getApplication()->input;
13489 $dbo = JFactory::getDbo();
13490
13491 $customer_id = $input->getUint('customer', 0);
13492
13493 $result = new stdClass;
13494 $result->status = 0;
13495
13496 try
13497 {
13498 $q = $dbo->getQuery(true)
13499 ->select($dbo->qn(array(
13500 'id',
13501 'first_name',
13502 'last_name',
13503 'email',
13504 'docsfolder',
13505 )))
13506 ->from($dbo->qn('#__vikbooking_customers'))
13507 ->where($dbo->qn('id') . ' = ' . $customer_id);
13508
13509 $dbo->setQuery($q, 0, 1);
13510 $dbo->execute();
13511
13512 if (!$dbo->getNumRows())
13513 {
13514 throw new Exception(sprintf('Customer [%d] not found', $customer_id), 404);
13515 }
13516
13517 $customer = $dbo->loadObject();
13518
13519 // fetch documents folder path
13520 $dirpath = VBO_CUSTOMERS_PATH . DIRECTORY_SEPARATOR;
13521
13522 // check if we have a valid directory
13523 if (empty($customer->docsfolder) || !is_dir($dirpath . $customer->docsfolder))
13524 {
13525 // randomize string
13526 $customer->seed = uniqid();
13527
13528 // create blocks for hashed folder
13529 $parts = [
13530 $customer->first_name,
13531 $customer->last_name,
13532 md5(serialize($customer)),
13533 ];
13534
13535 // join fetched parts
13536 $customer->docsfolder = JFilterOutput::stringURLSafe(implode('-', array_filter($parts)));
13537
13538 if (strlen($customer->docsfolder) < 16)
13539 {
13540 throw new Exception('Possible security breach. Please specify the most details as possible.', 400);
13541 }
13542
13543 jimport('joomla.filesystem.folder');
13544
13545 // create a folder for this customer
13546 $created = JFolder::create($dirpath . $customer->docsfolder);
13547
13548 if (!$created)
13549 {
13550 throw new Exception(sprintf('Unable to create the folder [%s]', $dirpath . $customer->docsfolder), 403);
13551 }
13552
13553 unset($customer->seed);
13554
13555 // update docs folder
13556 $dbo->updateObject('#__vikbooking_customers', $customer, 'id');
13557 }
13558
13559 // get file from request
13560 $file = $input->files->get('file', array(), 'array');
13561
13562 // try to upload the file
13563 $result = VikBooking::uploadFileFromRequest($file, $dirpath . $customer->docsfolder, "/(image\/.+)|(application\/(zip|rar|pdf|msword|vnd.*?))|(text\/(plain|markdown|csv))$/i");
13564 $result->status = 1;
13565
13566 $result->size = JHtml::fetch('number.bytes', filesize($result->path), 'auto', 0);
13567 $result->url = str_replace(DIRECTORY_SEPARATOR, '/', str_replace(VBO_CUSTOMERS_PATH . DIRECTORY_SEPARATOR, VBO_CUSTOMERS_URI, $result->path));
13568 }
13569 catch (Exception $e)
13570 {
13571 $result->error = $e->getMessage();
13572 $result->code = $e->getCode();
13573 }
13574
13575 echo json_encode($result);
13576 exit;
13577 }
13578
13579 /**
13580 * AJAX delete the customer documents.
13581 *
13582 * @return void
13583 *
13584 * @throws Exception
13585 */
13586 public function delete_customer_document()
13587 {
13588 $input = JFactory::getApplication()->input;
13589 $dbo = JFactory::getDbo();
13590
13591 $customer_id = $input->getUint('customer', 0);
13592
13593 $result = new stdClass;
13594 $result->status = 0;
13595
13596 $q = $dbo->getQuery(true)
13597 ->select($dbo->qn('docsfolder'))
13598 ->from($dbo->qn('#__vikbooking_customers'))
13599 ->where($dbo->qn('id') . ' = ' . $customer_id);
13600
13601 $dbo->setQuery($q, 0, 1);
13602 $dbo->execute();
13603
13604 if (!$dbo->getNumRows())
13605 {
13606 throw new Exception(sprintf('Customer [%d] not found', $customer_id), 404);
13607 }
13608
13609 $folder = $dbo->loadResult();
13610
13611 if (!$folder)
13612 {
13613 throw new Exception('The customer does not have any documents', 500);
13614 }
13615
13616 $file = $input->getString('file');
13617
13618 if (!$file)
13619 {
13620 throw new Exception('File to remove not specified', 400);
13621 }
13622
13623 $path = implode(DIRECTORY_SEPARATOR, array(VBO_CUSTOMERS_PATH, $folder, $file));
13624
13625 if (!is_file($path))
13626 {
13627 throw new Exception(sprintf('File [%s] not found', $path), 404);
13628 }
13629
13630 jimport('joomla.filesystem.file');
13631
13632 $removed = JFile::delete($path);
13633
13634 echo json_encode(array('status' => (int) $removed));
13635 exit;
13636 }
13637
13638 /**
13639 * AJAX task to invoke a specific report and obtain information.
13640 *
13641 * @since 1.3.0
13642 */
13643 public function get_report_data()
13644 {
13645 $report_name = VikRequest::getString('report_name', '', 'request');
13646 $current_fest = VikRequest::getString('current_fest', '', 'request');
13647 $current_fromdate = VikRequest::getString('current_fromdate', '', 'request');
13648 $current_todate = VikRequest::getString('current_todate', '', 'request');
13649 $step = VikRequest::getString('step', 'weekend', 'request');
13650 $direction = VikRequest::getString('direction', 'load', 'request');
13651 $period = VikRequest::getString('period', 'full', 'request');
13652 $krsort = VikRequest::getString('krsort', 'occupancy', 'request');
13653 $krorder = VikRequest::getString('krorder', 'DESC', 'request');
13654 $chart_datatype = VikRequest::getVar('chart_datatype', array(), 'request');
13655 $chart_meta_data = VikRequest::getString('chart_meta_data', '', 'request', VIKREQUEST_ALLOWRAW);
13656 $chart_meta_data = !empty($chart_meta_data) ? json_decode($chart_meta_data, true) : array();
13657 // idroom can be an array of IDs or just one ID as int/string
13658 $idroom = VikRequest::getVar('idroom', null, 'request');
13659 //
13660
13661 if (empty($report_name) || empty($current_fromdate) || empty($current_todate)) {
13662 throw new Exception("Missing request data", 400);
13663 }
13664
13665 // get requested report instance
13666 $report = VikBooking::getReportInstance($report_name);
13667 if (!$report) {
13668 throw new Exception("Report not found", 404);
13669 }
13670
13671 // chart data
13672 if (empty($chart_datatype)) {
13673 $chart_datatype = array(
13674 'type' => 'doughnut',
13675 'depth' => 1,
13676 'keys' => array($krsort),
13677 );
13678 }
13679
13680 // website date format
13681 $df = $report->getDateFormat();
13682
13683 // prepare request params for the report
13684 $rparams = array(
13685 'fromdate' => $current_fromdate,
13686 'todate' => $current_todate,
13687 'period' => $period,
13688 'krsort' => $krsort,
13689 'krorder' => $krorder,
13690 'idroom' => $idroom,
13691 );
13692
13693 // starting dates info and timestamps
13694 $from_ts = VikBooking::getDateTimestamp($current_fromdate, 0, 0, 0);
13695 $to_ts = VikBooking::getDateTimestamp($current_todate, 23, 59, 59);
13696 $from_info = getdate($from_ts);
13697 $to_info = getdate($to_ts);
13698
13699 // the name of the period requested and whether it's a fest
13700 $period_name = '';
13701 $is_fest = null;
13702
13703 if ($direction == 'prev' || $direction == 'next') {
13704 // calculate prev or next dates
13705 if ($step == 'weekend') {
13706 $period_name = JText::translate('VBOWEEKND');
13707 if ($direction == 'next') {
13708 // next weekend from current end date
13709 $next_ts = strtotime("next friday", $to_ts);
13710 } else {
13711 // prev weekend from current start date
13712 $next_ts = strtotime("previous friday", $from_ts);
13713 }
13714 $next_info = getdate($next_ts);
13715 $new_from_ts = $next_ts;
13716 $new_to_ts = mktime(23, 59, 59, $next_info['mon'], ($next_info['mday'] + 1), $next_info['year']);
13717 $rparams['fromdate'] = date($df, $new_from_ts);
13718 $rparams['todate'] = date($df, $new_to_ts);
13719 } elseif ($step == 'week') {
13720 $period_name = JText::translate('VBOWEEK');
13721 if ($direction == 'next') {
13722 // start next week from the current end date
13723 $new_from_ts = $to_ts;
13724 $new_to_ts = mktime(23, 59, 59, $to_info['mon'], ($to_info['mday'] + 7), $to_info['year']);
13725 $rparams['fromdate'] = $rparams['todate'];
13726 $rparams['todate'] = date($df, $new_to_ts);
13727 } else {
13728 // end prev week from the current from date
13729 $new_from_ts = mktime(0, 0, 0, $from_info['mon'], ($from_info['mday'] - 7), $from_info['year']);
13730 $new_to_ts = $from_ts;
13731 $rparams['todate'] = $rparams['fromdate'];
13732 $rparams['fromdate'] = date($df, $new_from_ts);
13733 }
13734 } else {
13735 // month
13736 $period_name = JText::translate('VBPVIEWRESTRICTIONSTWO');
13737 if ($direction == 'next') {
13738 // next month from the current from date
13739 $nextmonts = mktime(0, 0, 0, ($from_info['mon'] + 1), 1, $from_info['year']);
13740 $new_from_ts = $nextmonts;
13741 $new_to_ts = mktime(23, 59, 59, ($from_info['mon'] + 1), date('t', $nextmonts), $from_info['year']);
13742 $rparams['fromdate'] = date($df, $new_from_ts);
13743 $rparams['todate'] = date($df, $new_to_ts);
13744 } else {
13745 // prev month from the current from date
13746 $nextmonts = mktime(0, 0, 0, ($from_info['mon'] - 1), 1, $from_info['year']);
13747 $new_from_ts = $nextmonts;
13748 $new_to_ts = mktime(23, 59, 59, ($from_info['mon'] - 1), date('t', $nextmonts), $from_info['year']);
13749 $rparams['fromdate'] = date($df, $new_from_ts);
13750 $rparams['todate'] = date($df, $new_to_ts);
13751 }
13752 }
13753
13754 // get the next festivities
13755 $fests = VikBooking::getFestivitiesInstance();
13756 $next_fests = $fests->loadFestDates();
13757 if (count($next_fests)) {
13758 // check whether a festivity should be displayed rather than the calculated period of dates
13759 foreach ($next_fests as $fest) {
13760 $fest_found = false;
13761 if ($direction == 'next' && $fest['festinfo'][0]->from_ts > $from_ts && $fest['festinfo'][0]->from_ts <= $new_to_ts) {
13762 $fest_found = true;
13763 } elseif ($direction == 'prev' && $fest['festinfo'][0]->from_ts < $to_ts && $fest['festinfo'][0]->from_ts >= $new_from_ts) {
13764 $fest_found = true;
13765 }
13766 if ($fest_found && (string)$fest['festinfo'][0]->next_ts != $current_fest) {
13767 // festivity found before next calculated period
13768 $is_fest = $fest['festinfo'][0]->next_ts;
13769 $period_name = $fest['festinfo'][0]->trans_name;
13770 $new_from_ts = $fest['festinfo'][0]->from_ts;
13771 $new_to_ts = $fest['festinfo'][0]->to_ts;
13772 $rparams['fromdate'] = date($df, $new_from_ts);
13773 $rparams['todate'] = date($df, $new_to_ts);
13774 break;
13775 }
13776 }
13777 }
13778 } else {
13779 // load requested dates by skipping the festivities
13780 $new_from_ts = $from_ts;
13781 $new_to_ts = $to_ts;
13782 }
13783
13784 // invoke report
13785 $report->injectParams($rparams);
13786 $report_values = $report->getReportValues(1);
13787 $report_cols = $report->getColumnsValues();
13788 $report_chart = null;
13789 $report_chart_metas = array();
13790 $chart_meta_data = array(
13791 'keys' => array(
13792 'occupancy',
13793 'tot_bookings',
13794 'nights_booked',
13795 ),
13796 );
13797 $error = null;
13798
13799 if (!count($report_values)) {
13800 $error = strlen($report->getError()) ? $report->getError() : JText::translate('VBNOTRACKINGS');
13801 } else {
13802 // get doughnut Chart for the requested key
13803 $report_chart = $report->getChart($chart_datatype);
13804
13805 // get Chart meta data
13806 $all_chart_metas = $report->getChartMetaData(null, $chart_meta_data);
13807 if (count($all_chart_metas)) {
13808 // merge all positions into one array
13809 foreach ($all_chart_metas as $pos_metas) {
13810 $report_chart_metas = array_merge($report_chart_metas, $pos_metas);
13811 }
13812 }
13813
13814 if (empty($period_name)) {
13815 $period_name = $report->getProperty('chartTitle');
13816 }
13817 }
13818
13819 // build response
13820 $response = new stdClass;
13821 $response->error = $error;
13822 $response->fromdate = $rparams['fromdate'];
13823 $response->todate = $rparams['todate'];
13824 $response->in_days = $report->countDaysTo($new_from_ts);
13825 $response->in_days_to = $report->countDaysTo($new_to_ts);
13826 $response->in_days_avg = $report->countAverageDays($response->in_days, $response->in_days_to);
13827 $response->period_name = $period_name;
13828 $response->period_date = count($report_values) && isset($report_values['day']) ? $report_values['day']['display_value'] : '';
13829 $response->is_fest = $is_fest;
13830 $response->report_chart = $report_chart;
13831 $response->report_cols = $report_cols;
13832 $response->report_values = $report_values;
13833 $response->report_script = $report->getScript();
13834 $response->chart_labels = $report->getProperty('chartJsLabels');
13835 $response->dataset_label = $report->getProperty('chartJsDataSetLabel');
13836 $response->chart_colors = $report->getProperty('chartJsColors');
13837 $response->chart_data = $report->getProperty('chartJsData');
13838 $response->report_chart_metas = $report_chart_metas;
13839
13840 echo json_encode($response);
13841 exit;
13842 }
13843
13844 /**
13845 * Go to the previous booking.
13846 *
13847 * @uses navigateToBooking()
13848 *
13849 * @since 1.3.0
13850 */
13851 public function prev_booking()
13852 {
13853 $this->navigateToBooking('prev');
13854 }
13855
13856 /**
13857 * Go to the next booking.
13858 *
13859 * @uses navigateToBooking()
13860 *
13861 * @since 1.3.0
13862 */
13863 public function next_booking()
13864 {
13865 $this->navigateToBooking('next');
13866 }
13867
13868 /**
13869 * Given the current booking ID in the request, we navigate
13870 * either to the next or to the previous reservation (if any).
13871 *
13872 * @param string $direction either next or prev.
13873 *
13874 * @return void
13875 *
13876 * @since 1.3.0
13877 */
13878 private function navigateToBooking($direction = 'next')
13879 {
13880 $bid = VikRequest::getInt('whereup', 0, 'request');
13881 if (empty($bid) || $bid < 1 || !in_array($direction, array('prev', 'next'))) {
13882 throw new Exception("Invalid request", 400);
13883 }
13884
13885 $dbo = JFactory::getDbo();
13886 $app = JFactory::getApplication();
13887
13888 $q = "SELECT `id` FROM `#__vikbooking_orders` WHERE `id`" . ($direction == 'next' ? '>' : '<') . "{$bid} ORDER BY `id` " . ($direction == 'next' ? 'ASC' : 'DESC');
13889 $dbo->setQuery($q, 0, 1);
13890 $dbo->execute();
13891 if (!$dbo->getNumRows()) {
13892 VikError::raiseWarning('', JText::translate('VBPEDITBUSYONE'));
13893 $app->redirect("index.php?option=com_vikbooking&task=orders");
13894 exit;
13895 }
13896
13897 $app->redirect("index.php?option=com_vikbooking&task=editorder&cid[]=" . $dbo->loadResult());
13898 exit;
13899 }
13900
13901 /**
13902 * AJAX request: from a list of reservation IDs, we return the ones
13903 * that have a review with the related review ID on VCM.
13904 *
13905 * @since 1.13
13906 */
13907 public function bookings_have_reviews()
13908 {
13909 $dbo = JFactory::getDbo();
13910 $bids = VikRequest::getVar('bids', array(), 'request', 'array');
13911 $vcm_installed = is_file(VCM_SITE_PATH . DIRECTORY_SEPARATOR . 'helpers' . DIRECTORY_SEPARATOR . 'lib.vikchannelmanager.php');
13912 $withreviews = array();
13913
13914 if ($vcm_installed && is_array($bids) && count($bids)) {
13915 try {
13916 $q = "SELECT `id`, `idorder` FROM `#__vikchannelmanager_otareviews` WHERE `idorder` IN (" . implode(', ', $bids) . ");";
13917 $dbo->setQuery($q);
13918 $dbo->execute();
13919 if ($dbo->getNumRows()) {
13920 $reviews = $dbo->loadAssocList();
13921 foreach ($reviews as $r) {
13922 $withreviews[$r['idorder']] = $r['id'];
13923 }
13924 }
13925 } catch (Exception $e) {
13926 // do nothing, outdated version
13927 }
13928 }
13929
13930 echo json_encode($withreviews);
13931 exit;
13932 }
13933
13934 /**
13935 * AJAX request for adding a new room-day note.
13936 *
13937 * @return void
13938 *
13939 * @since 1.13.5
13940 */
13941 public function add_roomdaynote()
13942 {
13943 $dt = VikRequest::getString('dt', '', 'request');
13944 $idroom = VikRequest::getInt('idroom', 0, 'request');
13945 $subunit = VikRequest::getInt('subunit', 0, 'request');
13946 $type = VikRequest::getString('type', '', 'request');
13947 $type = empty($type) ? 'custom' : $type;
13948 $name = VikRequest::getString('name', '', 'request');
13949 $descr = VikRequest::getString('descr', '', 'request');
13950 $cdays = VikRequest::getInt('cdays', 0, 'request');
13951 $cdays = $cdays < 0 ? 0 : $cdays;
13952 $cdays = $cdays > 365 ? 365 : $cdays;
13953 if (empty($idroom) || empty($dt) || !strtotime($dt)) {
13954 echo 'e4j.error.1';
13955 exit;
13956 }
13957
13958 // reload end date
13959 $end_date = $dt;
13960
13961 // build critical date object
13962 $new_note = array(
13963 'name' => $name,
13964 'type' => $type,
13965 'descr' => $descr,
13966 );
13967
13968 // get object
13969 $notes = VikBooking::getCriticalDatesInstance();
13970
13971 // store the notes for all consecutive dates
13972 for ($i = 0; $i <= $cdays; $i++) {
13973 $store_dt = $dt;
13974 if ($i > 0) {
13975 $dt_info = getdate(strtotime($store_dt));
13976 $store_dt = date('Y-m-d', mktime(0, 0, 0, $dt_info['mon'], ($dt_info['mday'] + $i), $dt_info['year']));
13977 $end_date = $store_dt;
13978 }
13979 $result = $notes->storeDayNote($new_note, $store_dt, $idroom, $subunit);
13980 if (!$result) {
13981 echo 'e4j.error.2';
13982 exit;
13983 }
13984 }
13985
13986 // reload all room day notes for this day for the AJAX response
13987 $all_notes = $notes->loadRoomDayNotes($dt, $end_date, $idroom, $subunit);
13988
13989 if (!$all_notes || !count($all_notes)) {
13990 // no notes found even after storing it
13991 echo 'e4j.error.3';
13992 exit;
13993 }
13994
13995 echo json_encode($all_notes);
13996 exit;
13997 }
13998
13999 /**
14000 * AJAX request for removing a room day note.
14001 *
14002 * @return void
14003 *
14004 * @since 1.13.5
14005 */
14006 public function remove_roomdaynote()
14007 {
14008 if (!JFactory::getUser()->authorise('core.delete', 'com_vikbooking')) {
14009 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
14010 }
14011
14012 $dt = VikRequest::getString('dt', '', 'request');
14013 $idroom = VikRequest::getInt('idroom', 0, 'request');
14014 $subunit = VikRequest::getInt('subunit', 0, 'request');
14015 $type = VikRequest::getString('type', '', 'request');
14016 $type = empty($type) ? 'custom' : $type;
14017 $ind = VikRequest::getInt('ind', 0, 'request');
14018 if (empty($dt) || !strtotime($dt)) {
14019 echo 'e4j.error.1';
14020 exit;
14021 }
14022
14023 $notes = VikBooking::getCriticalDatesInstance();
14024 $result = $notes->deleteDayNote($ind, $dt, $idroom, $subunit, $type);
14025 if (!$result) {
14026 echo 'e4j.error.2';
14027 exit;
14028 }
14029
14030 echo 'e4j.ok';
14031 exit;
14032 }
14033
14034 /**
14035 * AJAX request for storing an event for a booking.
14036 * Firstly developed for the VCM Reporting API - Guest Misconduct,
14037 * but it can be used for any other purpose.
14038 *
14039 * @return void
14040 *
14041 * @since 1.13.5
14042 */
14043 public function store_booking_history_event()
14044 {
14045 $bid = VikRequest::getInt('bid', 0, 'request');
14046 $event = VikRequest::getString('event', '', 'request');
14047 $descr = VikRequest::getString('descr', '', 'request');
14048
14049 if (empty($bid) || empty($event)) {
14050 throw new Exception("Missing required information", 500);
14051 }
14052
14053 // Booking History
14054 VikBooking::getBookingHistoryInstance()->setBid($bid)->store($event, $descr);
14055 //
14056
14057 echo 'e4j.ok';
14058 exit;
14059 }
14060
14061 /**
14062 * AJAX request for updating an option/extra service.
14063 * Firstly developed for the VCM Vacation Rentals Essentials API - Damage Deposit,
14064 * but it can be used for any other purpose.
14065 *
14066 * @return void
14067 *
14068 * @since 1.13.5
14069 */
14070 public function update_option_params()
14071 {
14072 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
14073 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
14074 }
14075
14076 $optid = VikRequest::getInt('optid', 0, 'request');
14077 $oparams = VikRequest::getVar('oparams', array(), 'request', 'array');
14078
14079 if (empty($optid) || !is_array($oparams) || empty($oparams)) {
14080 throw new Exception("Missing required information", 500);
14081 }
14082
14083 $dbo = JFactory::getDbo();
14084 $q = "SELECT `oparams` FROM `#__vikbooking_optionals` WHERE `id`=" . (int)$optid . ";";
14085 $dbo->setQuery($q);
14086 $dbo->execute();
14087 if (!$dbo->getNumRows()) {
14088 throw new Exception("Option not found", 404);
14089 }
14090 $cur_params = $dbo->loadResult();
14091 $cur_params = !empty($cur_params) ? json_decode($cur_params, true) : array();
14092 $cur_params = !is_array($cur_params) ? array() : $cur_params;
14093
14094 foreach ($oparams as $k => $v) {
14095 if (empty($k)) {
14096 continue;
14097 }
14098 $cur_params[$k] = $v;
14099 }
14100
14101 $q = "UPDATE `#__vikbooking_optionals` SET `oparams`=" . $dbo->quote(json_encode($cur_params)) ." WHERE `id`=" . (int)$optid . ";";
14102 $dbo->setQuery($q);
14103 $dbo->execute();
14104
14105 echo 'e4j.ok';
14106 exit;
14107 }
14108
14109 /**
14110 * Hidden task to clean up duplicate records in certain database tables
14111 * due to a double execution of the installation queries. Ghost records,
14112 * if any, are also removed to clean up issues with hanging records.
14113 *
14114 * @since November 4th 2020
14115 * @since 1.16.3 (J) - 1.6.3 (WP)
14116 */
14117 public function clean_duplicate_records()
14118 {
14119 $dbo = JFactory::getDbo();
14120
14121 $tables_with_duplicates = [
14122 '#__vikbooking_config' => [
14123 'id_key' => 'id',
14124 'compare_key' => 'param',
14125 ],
14126 '#__vikbooking_countries' => [
14127 'id_key' => 'id',
14128 'compare_key' => 'country_3_code',
14129 ],
14130 '#__vikbooking_custfields' => [
14131 'id_key' => 'id',
14132 'compare_key' => 'name',
14133 ],
14134 '#__vikbooking_texts' => [
14135 'id_key' => 'id',
14136 'compare_key' => 'param',
14137 ],
14138 ];
14139
14140 foreach ($tables_with_duplicates as $tblname => $data) {
14141 $doubles = [];
14142 $storage = [];
14143 $rmlist = [];
14144
14145 $q = "SELECT * FROM `{$tblname}` ORDER BY `{$data['id_key']}` DESC;";
14146 $dbo->setQuery($q);
14147 $rows = $dbo->loadAssocList();
14148 if (!$rows) {
14149 echo "<p>No records found in table {$tblname}</p>";
14150 continue;
14151 }
14152
14153 foreach ($rows as $row) {
14154 if (!isset($doubles[$row[$data['compare_key']]])) {
14155 $doubles[$row[$data['compare_key']]] = 0;
14156 }
14157 $doubles[$row[$data['compare_key']]]++;
14158 if (!isset($storage[$row[$data['compare_key']]])) {
14159 $storage[$row[$data['compare_key']]] = [];
14160 }
14161 array_push($storage[$row[$data['compare_key']]], $row[$data['id_key']]);
14162 }
14163
14164 foreach ($doubles as $paramkey => $paramcount) {
14165 if ($paramcount < 2 || !isset($storage[$paramkey]) || count($storage[$paramkey]) < 2 || $paramcount != count($storage[$paramkey])) {
14166 continue;
14167 }
14168 $exceeding = $paramcount - 1;
14169 for ($x = 0; $x < $exceeding; $x++) {
14170 array_push($rmlist, $storage[$paramkey][$x]);
14171 }
14172 }
14173
14174 echo "<p>Total records found in table {$tblname}: " . count($rows) . "</p>";
14175 echo '<p>Total records to remove: ' . count($rmlist) . '</p>';
14176 echo '<pre style="display: none;">'.print_r($rmlist, true).'</pre><br/>';
14177
14178 if (count($rmlist)) {
14179 $q = "DELETE FROM `{$tblname}` WHERE `{$data['id_key']}` IN (" . implode(', ', $rmlist) . ");";
14180 $dbo->setQuery($q);
14181 $dbo->execute();
14182 }
14183 }
14184
14185 /**
14186 * Clean up busy records where the busy relations contain empty booking IDs.
14187 */
14188 $hanging_busy_ids = [];
14189
14190 $q = "SELECT `idbusy` FROM `#__vikbooking_ordersbusy` WHERE `idorder` = 0 OR `idorder` IS NULL;";
14191 $dbo->setQuery($q);
14192 $removelist = $dbo->loadAssocList();
14193 if ($removelist) {
14194 foreach ($removelist as $hanging_busy) {
14195 $hanging_busy_id = (int)$hanging_busy['idbusy'];
14196 if (!in_array($hanging_busy_id, $hanging_busy_ids)) {
14197 array_push($hanging_busy_ids, $hanging_busy_id);
14198 }
14199 }
14200 }
14201
14202 // let's check also for ghost records that only occupy the room
14203 $q = "SELECT `b`.*,`ob`.`idorder` FROM `#__vikbooking_busy` AS `b` LEFT JOIN `#__vikbooking_ordersbusy` AS `ob` ON `b`.`id`=`ob`.`idbusy` WHERE `b`.`checkout` >= " . time() . " AND (`ob`.`idorder` = 0 OR `ob`.`idorder` IS NULL);";
14204 $dbo->setQuery($q);
14205 $removelist = $dbo->loadAssocList();
14206 if ($removelist) {
14207 foreach ($removelist as $hanging_busy) {
14208 $hanging_busy_id = (int)$hanging_busy['id'];
14209 if (!in_array($hanging_busy_id, $hanging_busy_ids)) {
14210 array_push($hanging_busy_ids, $hanging_busy_id);
14211 }
14212 }
14213 }
14214
14215 if ($hanging_busy_ids) {
14216 $q = "DELETE FROM `#__vikbooking_busy` WHERE `id` IN (" . implode(', ', $hanging_busy_ids) . ");";
14217 $dbo->setQuery($q);
14218 $dbo->execute();
14219 }
14220
14221 echo "<p>Total ghost records removed: " . count($hanging_busy_ids) . "</p>";
14222
14223 return;
14224 }
14225
14226 /**
14227 * Hidden task to scan all database tables of VikBooking and Vik Channel Manager
14228 * to ensure the column `id` is defined as a primary key and got an auto-increment
14229 * extra flag properly defined and set. We've noticed that some third-party plugins
14230 * used to migrate WP sites may break the primary keys, and so new records won't get an ID.
14231 *
14232 * @since 1.16.8 (J) - 1.6.8 (WP)
14233 */
14234 public function fix_autoincrement_tables()
14235 {
14236 $dbo = JFactory::getDbo();
14237
14238 // load all the installed database tables
14239 $tables = $dbo->getTableList();
14240
14241 // get current database prefix
14242 $prefix = $dbo->getPrefix();
14243
14244 // replace prefix with placeholder
14245 $tables = array_map(function($table) use ($prefix)
14246 {
14247 return preg_replace("/^{$prefix}/", '#__', $table);
14248 }, $tables);
14249
14250 // remove all the tables that do not belong to VikBooking/VCM
14251 $tables = array_values(array_filter($tables, function($table)
14252 {
14253 if (preg_match("/^#__vik(?:booking|channelmanager)_config$/", $table))
14254 {
14255 // exclude the configuration table, which will be handled in a different way
14256 return false;
14257 }
14258
14259 return preg_match("/^#__vik(?:booking|channelmanager)_/", $table);
14260 }));
14261
14262 foreach ($tables as $table) {
14263 $columns = $dbo->getTableColumns($table, false);
14264 if (!isset($columns['id']) || empty($columns['id']->Type) || !empty($columns['id']->Extra)) {
14265 continue;
14266 }
14267
14268 echo 'Fixing ' . $table. ' for missing auto-increment<br/><pre>' . print_r($columns['id'], true) . '</pre><br/>';
14269
14270 // set auto-increment and primary key
14271 $dbo->setQuery("ALTER TABLE `{$table}` MODIFY `id` " . $columns['id']->Type . " NOT NULL AUTO_INCREMENT PRIMARY KEY;");
14272 $dbo->execute();
14273
14274 // count next auto-increment
14275 $dbo->setQuery("SELECT MAX(`id`) FROM `{$table}`");
14276 $next_ai = (int) $dbo->loadResult() + 1;
14277
14278 // update next auto-increment value
14279 $dbo->setQuery("ALTER TABLE `{$table}` AUTO_INCREMENT = {$next_ai}");
14280 $dbo->execute();
14281 }
14282 }
14283
14284 /**
14285 * Loads a specific admin widget ID and executes the requested method.
14286 * Useful for loading a newly added widget, or to execute custom methods.
14287 *
14288 * @see this is an AJAX endpoint.
14289 *
14290 * @since 1.14 (J) - 1.4.0 (WP)
14291 * @since 1.15 (J) - 1.5.0 (WP) widget callback can return values rather than just echoing.
14292 * @since 1.16.5 (J) - 1.6.5 (WP) widgets are rendered within a try-catch statement.
14293 */
14294 public function exec_admin_widget()
14295 {
14296 if (!JSession::checkToken()) {
14297 // missing CSRF-proof token
14298 VBOHttpDocument::getInstance()->close(403, JText::translate('JINVALID_TOKEN'));
14299 }
14300
14301 $widget_id = VikRequest::getString('widget_id', '', 'request');
14302 $call = VikRequest::getString('call', '', 'request');
14303 $return = VikRequest::getInt('return', 0, 'request');
14304 $vbo_page = VikRequest::getString('vbo_page', '', 'request');
14305 $vbo_uri = VikRequest::getString('vbo_uri', '', 'request');
14306 $multitask = VikRequest::getInt('multitask', 0, 'request');
14307
14308 if (empty($widget_id)) {
14309 VBOHttpDocument::getInstance()->close(500, 'Empty Admin Widget ID');
14310 }
14311
14312 if (empty($call) || !is_string($call)) {
14313 VBOHttpDocument::getInstance()->close(500, 'Empty Admin Widget Callback');
14314 }
14315
14316 // invoke admin widgets helper
14317 $widgets_helper = VikBooking::getAdminWidgetsInstance();
14318 $widget = $widgets_helper->getWidget($widget_id);
14319
14320 if ($widget === false) {
14321 VBOHttpDocument::getInstance()->close(404, 'Requested Admin Widget not found');
14322 }
14323
14324 if (!method_exists($widget, $call) || !is_callable(array($widget, $call))) {
14325 VBOHttpDocument::getInstance()->close(403, 'Admin Widget Callback not found or not callable');
14326 }
14327
14328 // get the multitask parser object
14329 $parser = VBOMultitaskParser::getInstance($vbo_page, $vbo_uri);
14330
14331 // check if arguments should be passed
14332 $call_args = [];
14333 if ($multitask && $call === 'render') {
14334 // build the multitask data object and inject it to the args as the first index
14335 $call_args[] = $parser->getData();
14336
14337 // bind options within the widget, if any
14338 $widget->bindOptions($call_args[0]);
14339 } else {
14340 // always bind multitask options, if any
14341 $widget->bindOptions($parser->getOptions());
14342 }
14343
14344 try {
14345 if ($return) {
14346 // invoke the widget's method and get the value returned
14347 $widget_response = $call_args ? call_user_func_array([$widget, $call], $call_args) : $widget->{$call}();
14348 } else {
14349 // invoke the widget's method within a buffer
14350 ob_start();
14351 if ($call_args) {
14352 $res = call_user_func_array([$widget, $call], $call_args);
14353 } else {
14354 $widget->{$call}();
14355 }
14356 $widget_response = ob_get_contents();
14357 ob_end_clean();
14358 }
14359 } catch (Throwable $e) {
14360 VBOHttpDocument::getInstance()->close($e->getCode() ?: 500, $e->getMessage());
14361 } catch (Exception $e) {
14362 VBOHttpDocument::getInstance()->close($e->getCode(), $e->getMessage());
14363 }
14364
14365 // prepare response object with a property equal to the called method
14366 $response = new stdClass;
14367 $response->{$call} = $widget_response;
14368
14369 // output the JSON encoded response and exit
14370 VBOHttpDocument::getInstance()->json($response);
14371 }
14372
14373 /**
14374 * Updates the map of admin widgets.
14375 *
14376 * @throws Exception this is an AJAX endpoint.
14377 *
14378 * @since 1.4.0
14379 */
14380 public function save_admin_widgets()
14381 {
14382 if (!JSession::checkToken()) {
14383 // missing CSRF-proof token
14384 VBOHttpDocument::getInstance()->close(403, JText::translate('JINVALID_TOKEN'));
14385 }
14386
14387 // make sure permissions are sufficient
14388 if (!JFactory::getUser()->authorise('core.vbo.global', 'com_vikbooking')) {
14389 VBOHttpDocument::getInstance()->close(403, 'You are not authorized to modify the widgets.');
14390 }
14391
14392 $psections = VikRequest::getVar('sections', array(), 'request', 'array');
14393 if (!is_array($psections) || !count($psections)) {
14394 VBOHttpDocument::getInstance()->close(500, 'No sections found in map');
14395 }
14396
14397 // request values are all converted to arrays, so restore the object styling
14398 $psections = json_decode(json_encode($psections));
14399
14400 // update map
14401 $result = VikBooking::getAdminWidgetsInstance()->updateWidgetsMap($psections);
14402
14403 $response = new stdClass;
14404 $response->status = (int)$result;
14405
14406 // output the JSON encoded response and exit
14407 VBOHttpDocument::getInstance()->json($response);
14408 }
14409
14410 /**
14411 * Restores the default admin widgets map.
14412 *
14413 * @since 1.4.0
14414 */
14415 public function reset_admin_widgets()
14416 {
14417 // reset map and redirect to dashboard
14418 VikBooking::getAdminWidgetsInstance()->restoreDefaultWidgetsMap();
14419
14420 JFactory::getApplication()->redirect('index.php?option=com_vikbooking');
14421 exit;
14422 }
14423
14424 /**
14425 * Updates the welcome message status for the widget's customizer via AJAX.
14426 *
14427 * @since 1.4.0
14428 */
14429 public function admin_widgets_welcome()
14430 {
14431 if (!JSession::checkToken()) {
14432 // missing CSRF-proof token
14433 VBOHttpDocument::getInstance()->close(403, JText::translate('JINVALID_TOKEN'));
14434 }
14435
14436 $hide_welcome = VikRequest::getInt('hide_welcome', 0, 'request');
14437 // update configuration value
14438 VikBooking::getAdminWidgetsInstance()->updateWelcome($hide_welcome);
14439
14440 $response = new stdClass;
14441 $response->status = $hide_welcome;
14442
14443 // output the JSON encoded response and exit
14444 VBOHttpDocument::getInstance()->json($response);
14445 }
14446
14447 public function newcondtext()
14448 {
14449 VikBookingHelper::printHeader("11");
14450
14451 VikRequest::setVar('view', VikRequest::getCmd('view', 'managecondtext'));
14452
14453 parent::display();
14454
14455 if (VikBooking::showFooter()) {
14456 VikBookingHelper::printFooter();
14457 }
14458 }
14459
14460 public function editcondtext()
14461 {
14462 VikBookingHelper::printHeader("11");
14463
14464 VikRequest::setVar('view', VikRequest::getCmd('view', 'managecondtext'));
14465
14466 parent::display();
14467
14468 if (VikBooking::showFooter()) {
14469 VikBookingHelper::printFooter();
14470 }
14471 }
14472
14473 public function cancelcondtext()
14474 {
14475 JFactory::getApplication()->redirect('index.php?option=com_vikbooking&task=config&tab=7');
14476 }
14477
14478 public function createcondtext()
14479 {
14480 if (!JSession::checkToken()) {
14481 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
14482 }
14483
14484 if (!JFactory::getUser()->authorise('core.create', 'com_vikbooking')) {
14485 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
14486 }
14487
14488 $this->_doCreateCondText();
14489 }
14490
14491 public function createcondtextstay()
14492 {
14493 if (!JSession::checkToken()) {
14494 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
14495 }
14496
14497 if (!JFactory::getUser()->authorise('core.create', 'com_vikbooking')) {
14498 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
14499 }
14500
14501 $this->_doCreateCondText(true);
14502 }
14503
14504 private function _doCreateCondText($stay = false)
14505 {
14506 $dbo = JFactory::getDbo();
14507 $app = JFactory::getApplication();
14508 $rules_helper = VikBooking::getConditionalRulesInstance();
14509 $rules_list = $rules_helper->composeRulesParamsFromRequest();
14510
14511 $condtextname = VikRequest::getString('condtextname', '', 'request');
14512 $condtexttkn = VikRequest::getString('condtexttkn', '', 'request');
14513 $msg = VikRequest::getString('msg', '', 'request', VIKREQUEST_ALLOWRAW);
14514 $debug = VikRequest::getInt('debug', 0, 'request');
14515 if (empty($condtextname)) {
14516 $condtextname = date('Y-m-dHis');
14517 $condtexttkn = '{condition: ' . date('YmdHis') . '}';
14518 }
14519
14520 $existing_tokens = $rules_helper->getSpecialTags();
14521 if (count($existing_tokens) && isset($existing_tokens[$condtexttkn])) {
14522 VikError::raiseWarning('', 'Another conditional text with the same special tag already exists');
14523 $app->redirect('index.php?option=com_vikbooking&task=newcondtext');
14524 exit;
14525 }
14526
14527 $data = new stdClass;
14528 $data->name = $condtextname;
14529 $data->token = $condtexttkn;
14530 $data->rules = json_encode($rules_list);
14531 $data->msg = $msg;
14532 $data->lastupd = JDate::getInstance()->toSql();
14533 $data->debug = $debug;
14534
14535 $dbo->insertObject('#__vikbooking_condtexts', $data, 'id');
14536
14537 if (isset($data->id)) {
14538 $app->enqueueMessage(JText::translate('VBSEASONUPDATED'));
14539 }
14540
14541 if (!$stay || !isset($data->id)) {
14542 $this->cancelcondtext();
14543 exit;
14544 }
14545
14546 $app->redirect('index.php?option=com_vikbooking&task=editcondtext&cid[]=' . $data->id);
14547 }
14548
14549 public function updatecondtext()
14550 {
14551 if (!JSession::checkToken()) {
14552 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
14553 }
14554
14555 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
14556 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
14557 }
14558
14559 $this->_doUpdateCondText();
14560 }
14561
14562 public function updatecondtextstay()
14563 {
14564 if (!JSession::checkToken()) {
14565 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
14566 }
14567
14568 if (!JFactory::getUser()->authorise('core.edit', 'com_vikbooking')) {
14569 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
14570 }
14571
14572 $this->_doUpdateCondText(true);
14573 }
14574
14575 private function _doUpdateCondText($stay = false)
14576 {
14577 $dbo = JFactory::getDbo();
14578 $app = JFactory::getApplication();
14579 $rules_helper = VikBooking::getConditionalRulesInstance();
14580 $rules_list = $rules_helper->composeRulesParamsFromRequest();
14581
14582 $pwhere = VikRequest::getInt('where', '', 'request');
14583 $condtextname = VikRequest::getString('condtextname', '', 'request');
14584 $condtexttkn = VikRequest::getString('condtexttkn', '', 'request');
14585 $msg = VikRequest::getString('msg', '', 'request', VIKREQUEST_ALLOWRAW);
14586 $debug = VikRequest::getInt('debug', 0, 'request');
14587 if (empty($condtextname)) {
14588 $condtextname = date('Y-m-dHis');
14589 $condtexttkn = '{condition: ' . date('YmdHis') . '}';
14590 }
14591
14592 $existing_tokens = $rules_helper->getSpecialTags();
14593 if (count($existing_tokens) && isset($existing_tokens[$condtexttkn]) && ($existing_tokens[$condtexttkn]['id'] != $pwhere)) {
14594 VikError::raiseWarning('', 'Another conditional text with the same special tag already exists (' . $existing_tokens[$condtexttkn]['name'] . ')');
14595 $app->redirect('index.php?option=com_vikbooking&task=editcondtext&cid[]=' . $pwhere);
14596 exit;
14597 }
14598
14599 $data = new stdClass;
14600 $data->id = $pwhere;
14601 $data->name = $condtextname;
14602 $data->token = $condtexttkn;
14603 $data->rules = json_encode($rules_list);
14604 $data->msg = $msg;
14605 $data->lastupd = JDate::getInstance()->toSql();
14606 $data->debug = $debug;
14607
14608 $dbo->updateObject('#__vikbooking_condtexts', $data, 'id');
14609
14610 $app->enqueueMessage(JText::translate('VBSEASONUPDATED'));
14611
14612 if (!$stay) {
14613 $this->cancelcondtext();
14614 exit;
14615 }
14616
14617 $app->redirect('index.php?option=com_vikbooking&task=editcondtext&cid[]=' . $data->id);
14618 }
14619
14620 public function removecondtext()
14621 {
14622 if (!JFactory::getUser()->authorise('core.delete', 'com_vikbooking')) {
14623 VBOHttpDocument::getInstance()->close(403, JText::translate('JERROR_ALERTNOAUTHOR'));
14624 }
14625
14626 $dbo = JFactory::getDbo();
14627 $ids = VikRequest::getVar('cid', array());
14628
14629 VikBooking::getConditionalRulesInstance(true);
14630 $templates = VikBookingHelperConditionalRules::getTemplateFilesPaths();
14631
14632 foreach ($ids as $d) {
14633 $q = "SELECT `token` FROM `#__vikbooking_condtexts` WHERE `id`=" . (int)$d . ";";
14634 $dbo->setQuery($q);
14635 $dbo->execute();
14636 if (!$dbo->getNumRows()) {
14637 continue;
14638 }
14639 $special_tag = $dbo->loadResult();
14640
14641 // remove the token from each template file if it was used before
14642 if (!empty($special_tag)) {
14643 // remove token from all template files
14644 foreach ($templates as $tkey => $tpath) {
14645 // get requested file content
14646 $fcontent = VikBookingHelperConditionalRules::getTemplateFileCode($tkey);
14647 if (empty($fcontent) || !is_string($fcontent)) {
14648 break;
14649 }
14650 // remove tag from code content
14651 $fcontent = str_replace($special_tag, '', $fcontent);
14652 // update the file code
14653 VikBookingHelperConditionalRules::writeTemplateFileCode($tkey, $fcontent);
14654 }
14655 }
14656
14657 // delete the record
14658 $q = "DELETE FROM `#__vikbooking_condtexts` WHERE `id`=" . (int)$d . ";";
14659 $dbo->setQuery($q);
14660 $dbo->execute();
14661 }
14662
14663 $this->cancelcondtext();
14664 }
14665
14666 /**
14667 * AJAX endpoint to update one template file with the given tag or styles.
14668 * A JSON response will be echoed by exiting the process.
14669 */
14670 public function condtext_update_tmpl()
14671 {
14672 VikBooking::getConditionalRulesInstance(true);
14673
14674 $tagaction = VikRequest::getString('tagaction', '', 'request');
14675 $tag = VikRequest::getString('tag', '', 'request');
14676 $file = VikRequest::getString('file', '', 'request', VIKREQUEST_ALLOWRAW);
14677 $newcontent = VikRequest::getString('newcontent', '', 'request', VIKREQUEST_ALLOWRAW);
14678 $custom_classes = VikRequest::getVar('custom_classes', array(), 'request', 'array');
14679
14680 $allowed_actions = array(
14681 'add',
14682 'remove',
14683 'styles',
14684 'restore',
14685 );
14686
14687 if (empty($tagaction) || empty($file) || !in_array($tagaction, $allowed_actions)) {
14688 throw new Exception("Invalid request submitted", 500);
14689 }
14690
14691 if (in_array($tagaction, array('add', 'remove')) && empty($tag)) {
14692 throw new Exception("Invalid request submitted - missing tag", 500);
14693 }
14694
14695 if (in_array($tagaction, array('add', 'styles')) && empty($newcontent)) {
14696 throw new Exception("Invalid request submitted - missing new HTML content", 500);
14697 }
14698
14699 if ($tagaction == 'styles' && (!is_array($custom_classes) || !count($custom_classes))) {
14700 throw new Exception("No custom CSS classes to parse", 500);
14701 }
14702
14703 if ($tagaction == 'restore') {
14704 // immediately restore the requested file to avoid script interruptions
14705 VikBookingHelperConditionalRules::restoreTemplateFileCode($file);
14706 }
14707
14708 // get requested file content
14709 $fcontent = VikBookingHelperConditionalRules::getTemplateFileCode($file);
14710 if (empty($fcontent) || !is_string($fcontent)) {
14711 throw new Exception("File not found or its code is unreadable", 404);
14712 }
14713
14714 if ($tagaction == 'remove') {
14715 // remove tag from code content
14716 $fcontent = str_replace($tag, '', $fcontent);
14717 } elseif ($tagaction == 'add') {
14718 // add tag to code content in the same exact position
14719 $fcontent = VikBookingHelperConditionalRules::addTagByComparingSources($tag, $file, $newcontent, $fcontent);
14720 } elseif ($tagaction == 'styles') {
14721 // apply the same styling rules
14722 $fcontent = VikBookingHelperConditionalRules::addStylesByComparingSources($custom_classes, $file, $newcontent, $fcontent);
14723 }
14724
14725 // update the file code
14726 $res = VikBookingHelperConditionalRules::writeTemplateFileCode($file, $fcontent);
14727
14728 if (!$res) {
14729 throw new Exception("Could not update the source code of the template file", 500);
14730 }
14731
14732 // parse new HTML content
14733 $newhtmls = VikBookingHelperConditionalRules::getTemplateFilesContents($file);
14734 if (!is_array($newhtmls) || !isset($newhtmls[$file])) {
14735 throw new Exception("Could not parse new template file content", 404);
14736 }
14737
14738 // trigger backup/mirroring, if available
14739 if (VBOPlatformDetection::isWordPress()) {
14740 VikBookingUpdateManager::storeTemplateContent($file, $newhtmls[$file]);
14741 }
14742
14743 // build output
14744 $output = new stdClass;
14745 $output->newhtml = $newhtmls[$file];
14746 $output->log = VikBookingHelperConditionalRules::getEditingLog();
14747
14748 echo json_encode($output);
14749 exit;
14750 }
14751
14752 /**
14753 * AJAX endpoint to invoke methods of the geocoding helper.
14754 */
14755 public function geocoding_endpoint()
14756 {
14757 $geo = VikBooking::getGeocodingInstance();
14758 $callback = VikRequest::getString('callback', '', 'request');
14759
14760 if (empty($callback) || !method_exists($geo, $callback) || !is_callable(array($geo, $callback))) {
14761 throw new Exception("Callback not available", 403);
14762 }
14763
14764 // invoke requested method
14765 $res = $geo->{$callback}();
14766
14767 // prepare response
14768 $response = new stdClass;
14769 $response->{$callback} = $res;
14770
14771 echo json_encode($response);
14772 exit;
14773 }
14774
14775 public function refundtn()
14776 {
14777 //modal box, so we do not set menu or footer
14778
14779 VikRequest::setVar('view', VikRequest::getCmd('view', 'refundtn'));
14780
14781 parent::display();
14782 }
14783
14784 public function do_refundtn()
14785 {
14786 $dbo = JFactory::getDbo();
14787 $app = JFactory::getApplication();
14788
14789 $bid = VikRequest::getInt('bid', 0, 'request');
14790 $amount = VikRequest::getFloat('amount', 0, 'request');
14791 $refund_reason = VikRequest::getString('refund_reason', '', 'request');
14792 $tmpl = VikRequest::getString('tmpl', '', 'request');
14793 $nav_suffix = $tmpl == 'component' ? '&tmpl=component' : '';
14794
14795 $currencysymb = VikBooking::getCurrencySymb();
14796
14797 if (empty($bid) || $amount <= 0) {
14798 VikError::raiseWarning('', JText::translate('VBO_PLEASE_FILL_FIELDS'));
14799 $app->redirect('index.php?option=com_vikbooking');
14800 exit;
14801 }
14802
14803 $q = "SELECT * FROM `#__vikbooking_orders` WHERE `id`=" . $bid . " AND `status`!='standby';";
14804 $dbo->setQuery($q);
14805 $dbo->execute();
14806 if ($dbo->getNumRows() < 1) {
14807 VikError::raiseWarning('', 'Booking not found');
14808 $app->redirect('index.php?option=com_vikbooking');
14809 exit;
14810 }
14811 $row = $dbo->loadAssoc();
14812
14813 // get booking history instance
14814 $history_obj = VikBooking::getBookingHistoryInstance();
14815 $history_obj->setBid($row['id']);
14816
14817 // get payment information
14818 $payment = VikBooking::getPayment($row['idpayment']);
14819 $tn_driver = is_array($payment) ? $payment['file'] : null;
14820
14821 // transaction data validation callback
14822 $tn_data_callback = function($data) use ($tn_driver) {
14823 return (is_object($data) && isset($data->driver) && basename($data->driver, '.php') == basename($tn_driver, '.php'));
14824 };
14825 // get previous transactions
14826 $prev_tn_data = $history_obj->getEventsWithData(array('P0', 'PN'), $tn_data_callback);
14827
14828 if (!is_array($prev_tn_data) || !count($prev_tn_data)) {
14829 // no previous transactions found
14830 VikError::raiseWarning('', 'No previous transactions found, unable to issue the refund');
14831 $app->redirect('index.php?option=com_vikbooking&task=refundtn&cid[]=' . $row['id'] . $nav_suffix);
14832 exit;
14833 }
14834
14835 // push refund information for the payment gateway
14836 $row['total_to_refund'] = $amount;
14837 $row['transaction'] = $prev_tn_data;
14838 $row['refund_reason'] = $refund_reason;
14839
14840 // push the transaction currency information
14841 $row['transaction_currency'] = VikBooking::getCurrencyCodePp();
14842
14843 /**
14844 * @wponly The payment gateway is loaded
14845 * through the apposite dispatcher.
14846 */
14847 JLoader::import('adapter.payment.dispatcher');
14848 $obj = JPaymentDispatcher::getInstance('vikbooking', $payment['file'], $row, $payment['params']);
14849
14850 if (!method_exists($obj, 'isRefundSupported') || !$obj->isRefundSupported()) {
14851 // refund not supported
14852 VikError::raiseWarning('', 'The selected payment method does not support refunds');
14853 $app->redirect('index.php?option=com_vikbooking&task=refundtn&cid[]=' . $row['id'] . $nav_suffix);
14854 exit;
14855 }
14856
14857 // perform the refund transaction
14858 $array_result = $obj->refund();
14859
14860 if ($array_result['verified'] != 1) {
14861 // raise warning by getting the message
14862 if (!empty($array_result['log']) && is_string($array_result['log'])) {
14863 VikError::raiseWarning('', $array_result['log']);
14864 } else {
14865 VikError::raiseWarning('', 'Operation failed');
14866 }
14867 $app->redirect('index.php?option=com_vikbooking&task=refundtn&cid[]=' . $row['id'] . $nav_suffix);
14868 exit;
14869 }
14870
14871 /**
14872 * New payment plugins can return the total amount refunded ('tot_paid').
14873 *
14874 * @since 1.15.4 (J) - 1.5.10 (WP)
14875 */
14876 if (!empty($array_result['tot_paid'])) {
14877 // overwrite the requested amount with the returned one
14878 $amount = (float)$array_result['tot_paid'];
14879 }
14880
14881 // update total paid, total and refund columns for the booking
14882 $booking = new stdClass;
14883 $booking->id = $row['id'];
14884 if ($row['totpaid'] > 0) {
14885 $booking->totpaid = $row['totpaid'] - $amount;
14886 }
14887 if ($row['total'] > 0) {
14888 $booking->total = $row['total'] - $amount;
14889 }
14890 $booking->refund = (float)$row['refund'] + $amount;
14891 // update record in db
14892 $dbo->updateObject('#__vikbooking_orders', $booking, 'id');
14893
14894 // store the refund event
14895 $event_descr = array(
14896 '(' . $payment['name'] . ')',
14897 $refund_reason,
14898 $currencysymb . ' ' . VikBooking::numberFormat($amount),
14899 );
14900 $history_obj->store('RF', implode("\n", $event_descr));
14901
14902 // display success message and redirect
14903 $app->enqueueMessage(JText::translate('VBO_REFUND_SUCCESS'));
14904 $app->redirect('index.php?option=com_vikbooking&task=refundtn&cid[]=' . $row['id'] . '&success=1' . $nav_suffix);
14905 exit;
14906 }
14907
14908 /**
14909 * AJAX upload endpoint for media files.
14910 *
14911 * @return void
14912 *
14913 * @throws Exception
14914 *
14915 * @since 1.15.0 (J) - 1.5.0 (WP)
14916 */
14917 public function upload_media_file()
14918 {
14919 $input = JFactory::getApplication()->input;
14920
14921 // allowed types
14922 $type = $input->getString('type', '');
14923 $mask = "/(image\/.+)|(application\/(zip|rar|pdf|msword|vnd.*?))|(text\/(plain|markdown|csv))$/i";
14924 if ($type == 'image') {
14925 $mask = "/(image\/.+)$/i";
14926 }
14927
14928 // response object
14929 $result = new stdClass;
14930 $result->status = 0;
14931
14932 try
14933 {
14934 // get file from request
14935 $file = $input->files->get('file', array(), 'array');
14936
14937 // try to upload the file
14938 $result = VikBooking::uploadFileFromRequest($file, VBO_MEDIA_PATH, $mask);
14939 $result->status = 1;
14940
14941 $result->size = JHtml::fetch('number.bytes', filesize($result->path), 'auto', 0);
14942 $result->url = str_replace(DIRECTORY_SEPARATOR, '/', str_replace(VBO_MEDIA_PATH . DIRECTORY_SEPARATOR, VBO_MEDIA_URI, $result->path));
14943 }
14944 catch (Exception $e)
14945 {
14946 $result->error = $e->getMessage();
14947 $result->code = $e->getCode();
14948 }
14949
14950 echo json_encode($result);
14951 exit;
14952 }
14953
14954 /**
14955 * AJAX endpoint to invoke a report object's method.
14956 *
14957 * @return void
14958 *
14959 * @throws Exception
14960 *
14961 * @since 1.15.0 (J) - 1.5.0 (WP)
14962 */
14963 public function invoke_report()
14964 {
14965 $report_name = VikRequest::getString('report', '', 'request');
14966 $report_call = VikRequest::getString('call', '', 'request');
14967 $params = VikRequest::getVar('params', array(), 'request', 'array');
14968
14969 if (empty($report_name)) {
14970 VBOHttpDocument::getInstance()->close(400, 'Missing report name');
14971 }
14972
14973 if (empty($report_call)) {
14974 VBOHttpDocument::getInstance()->close(400, 'Missing report call');
14975 }
14976
14977 // get requested report instance
14978 $report = VikBooking::getReportInstance($report_name);
14979 if (!$report) {
14980 VBOHttpDocument::getInstance()->close(404, 'Report not found');
14981 }
14982
14983 if (!method_exists($report, $report_call) || !is_callable(array($report, $report_call))) {
14984 VBOHttpDocument::getInstance()->close(403, sprintf('Cannot call [%s] on report', $report_call));
14985 }
14986
14987 // call on report's method
14988 $result = $report->{$report_call}($params);
14989
14990 if (is_null($result)) {
14991 VBOHttpDocument::getInstance()->close(400, 'Null response');
14992 }
14993
14994 if (is_scalar($result)) {
14995 // wrap result within an array for a JSON encoded response
14996 VBOHttpDocument::getInstance()->json([$result]);
14997 }
14998
14999 // output the JSON encoded array/object returned
15000 VBOHttpDocument::getInstance()->json($result);
15001 }
15002
15003 /**
15004 * Handles requests for the multitask widgets panel.
15005 *
15006 * @see this is an AJAX endpoint.
15007 *
15008 * @since 1.15.0 (J) - 1.5.0 (WP)
15009 * @since 1.16.5 (J) - 1.6.5 (WP) widgets are rendered within a try-catch statement.
15010 */
15011 public function exec_multitask_widgets()
15012 {
15013 if (!JSession::checkToken()) {
15014 // missing CSRF-proof token
15015 VBOHttpDocument::getInstance()->close(403, JText::translate('JINVALID_TOKEN'));
15016 }
15017
15018 $call = VikRequest::getString('call', '', 'request');
15019 $call_args = VikRequest::getVar('call_args', array(), 'request', 'array');
15020
15021 if (empty($call)) {
15022 VBOHttpDocument::getInstance()->close(500, 'Empty Admin Widget Callback');
15023 }
15024
15025 // invoke admin widgets helper
15026 $widgets_helper = VikBooking::getAdminWidgetsInstance();
15027
15028 if (!method_exists($widgets_helper, $call) || !is_callable(array($widgets_helper, $call))) {
15029 VBOHttpDocument::getInstance()->close(403, 'Admin Widgets Callback not found or not callable');
15030 }
15031
15032 try {
15033 // invoke the helper's method and get the value returned
15034 if (is_array($call_args) && count($call_args)) {
15035 $result = call_user_func_array(array($widgets_helper, $call), $call_args);
15036 } else {
15037 $result = $widgets_helper->{$call}();
15038 }
15039 } catch (Throwable $e) {
15040 VBOHttpDocument::getInstance()->close($e->getCode() ?: 500, $e->getMessage());
15041 } catch (Exception $e) {
15042 VBOHttpDocument::getInstance()->close($e->getCode(), $e->getMessage());
15043 }
15044
15045 // prepare response object with a property equal to the called method
15046 $response = new stdClass;
15047 $response->result = $result;
15048
15049 // output the JSON response and exit
15050 VBOHttpDocument::getInstance()->json($response);
15051 }
15052
15053 /**
15054 * Handles requests for displaying a browser notification being dispatched.
15055 *
15056 * @see this is an AJAX endpoint.
15057 *
15058 * @since 1.15.0 (J) - 1.5.0 (WP)
15059 */
15060 public function notification_displayer()
15061 {
15062 $payload_str = VikRequest::getString('payload', '', 'request', VIKREQUEST_ALLOWRAW);
15063
15064 if (empty($payload_str)) {
15065 VBOHttpDocument::getInstance()->close(500, 'Empty notification payload');
15066 }
15067
15068 // attempt to decode the notification payload
15069 $payload = json_decode($payload_str);
15070
15071 if (!is_object($payload)) {
15072 VBOHttpDocument::getInstance()->close(500, 'Could not decode notification payload: ' . $payload_str);
15073 }
15074
15075 // get notification displayer for this type of notification
15076 $displayer = VBONotificationBuilder::getInstance($payload)->getDisplayer();
15077 if (!$displayer) {
15078 VBOHttpDocument::getInstance()->close(500, 'Could not build notification display data from payload: ' . $payload_str);
15079 }
15080
15081 // compose the notification display data object
15082 try {
15083 $notif_data = $displayer->getData();
15084 if (!$notif_data) {
15085 throw new Exception('Error building the notification display data', 500);
15086 }
15087 } catch (Exception $e) {
15088 VBOHttpDocument::getInstance()->close($e->getCode(), $e->getMessage());
15089 }
15090
15091 // output the JSON response and exit
15092 VBOHttpDocument::getInstance()->json($notif_data);
15093 }
15094
15095 /**
15096 * Handles requests for watching widgets data and getting
15097 * new events to trigger browser notifications.
15098 *
15099 * @see this is an AJAX endpoint.
15100 *
15101 * @since 1.15.0 (J) - 1.5.0 (WP)
15102 * @since 1.16.8 (J) - 1.6.8 (WP) introduced notification events.
15103 */
15104 public function widgets_watch_data()
15105 {
15106 if (!JSession::checkToken()) {
15107 // missing CSRF-proof token
15108 VBOHttpDocument::getInstance()->close(403, JText::translate('JINVALID_TOKEN'));
15109 }
15110
15111 $app = JFactory::getApplication();
15112
15113 $watch_data_str = $app->input->get('watch_data', '', 'raw');
15114 $pushed_data_str = $app->input->get('pushed_data', '[]', 'raw');
15115
15116 if (empty($watch_data_str)) {
15117 VBOHttpDocument::getInstance()->close(500, 'Empty watch-data payload');
15118 }
15119
15120 // attempt to decode the watch-data payload
15121 $watch_data = json_decode($watch_data_str, true);
15122
15123 if (!$watch_data) {
15124 VBOHttpDocument::getInstance()->close(500, 'Could not decode watch-data payload: ' . $watch_data_str);
15125 }
15126
15127 // check if any pushed data was set
15128 $pushed_data = (array)json_decode($pushed_data_str, true);
15129
15130 // container for new notifications
15131 $notifs_pool = [];
15132
15133 // container for the events data to dispatch
15134 $events_pool = [];
15135
15136 // get admin widgets helper
15137 $widgets_helper = VikBooking::getAdminWidgetsInstance();
15138
15139 foreach ($watch_data as $widget_id => $data) {
15140 // invoke admin widget (with no pre-loading)
15141 $widget_instance = $widgets_helper->getWidget($widget_id);
15142 if (!$widget_instance) {
15143 continue;
15144 }
15145
15146 // build the widget watch data object
15147 $widget_watch_data = VBONotificationWatchdata::getInstance($data)->setPushedData($pushed_data);
15148
15149 // check if the widget needs to emit browser notifications
15150 list($watch_next, $notifications) = $widget_instance->getNotifications($widget_watch_data);
15151
15152 // check if the widget needs to emit JavaScript events
15153 $events = $widget_instance->getNotificationEvents($widget_watch_data);
15154
15155 if ($watch_next) {
15156 // update next watch-data object for this widget
15157 $watch_data[$widget_id] = $watch_next;
15158 }
15159
15160 if (is_array($notifications) && $notifications) {
15161 // merge notifications
15162 $notifs_pool = array_merge($notifs_pool, $notifications);
15163 }
15164
15165 if (is_array($events) && $events) {
15166 // push notification events for this widget
15167 $events_pool[] = $events;
15168 }
15169 }
15170
15171 // build the response object
15172 $response = new stdClass;
15173 $response->watch_data = $watch_data;
15174 $response->notifications = $notifs_pool;
15175 $response->events = $events_pool;
15176
15177 // output the JSON response and exit
15178 VBOHttpDocument::getInstance()->json($response);
15179 }
15180
15181 /**
15182 * Outputs a list of CSS assets required to render the admin widgets
15183 * externally from Vik Booking. Useful i.e. to Vik Channel Manager.
15184 *
15185 * @see this is an AJAX endpoint.
15186 *
15187 * @since 1.16.0 (J) - 1.6.0 (WP)
15188 */
15189 public function widgets_get_assets()
15190 {
15191 // list of needed CSS asset details
15192 $assets_pool = [];
15193
15194 // appearance preference assets (one or none)
15195 $app_pref_asset = VikBooking::loadAppearancePreferenceAssets($get_info = true);
15196
15197 if (VBOPlatformDetection::isWordPress()) {
15198 // WordPress (main CSS)
15199 $assets_pool[] = [
15200 'rel' => 'stylesheet',
15201 'id' => 'vbo-style-css',
15202 'href' => VIKBOOKING_ADMIN_ASSETS_URI . 'vikbooking.css?ver=' . VIKBOOKING_SOFTWARE_VERSION,
15203 'media' => 'all',
15204 ];
15205
15206 if (is_array($app_pref_asset) && !empty($app_pref_asset['href'])) {
15207 // appearance preference CSS
15208 $assets_pool[] = [
15209 'rel' => 'stylesheet',
15210 'id' => (!empty($app_pref_asset['id']) ? $app_pref_asset['id'] : rand()),
15211 'href' => $app_pref_asset['href'] . '?ver=' . VIKBOOKING_SOFTWARE_VERSION,
15212 'media' => 'all',
15213 ];
15214 }
15215 } else {
15216 // Joomla (main CSS)
15217 $assets_pool[] = [
15218 'rel' => 'stylesheet',
15219 'id' => 'vbo-style-css',
15220 'href' => VBO_ADMIN_URI . 'vikbooking.css?' . VIKBOOKING_SOFTWARE_VERSION,
15221 'media' => 'all',
15222 ];
15223
15224 if (is_array($app_pref_asset) && !empty($app_pref_asset['href'])) {
15225 // appearance preference CSS
15226 $assets_pool[] = [
15227 'rel' => 'stylesheet',
15228 'id' => (!empty($app_pref_asset['id']) ? $app_pref_asset['id'] : rand()),
15229 'href' => $app_pref_asset['href'] . '?' . VIKBOOKING_SOFTWARE_VERSION,
15230 'media' => 'all',
15231 ];
15232 }
15233 }
15234
15235 // output the JSON response and exit
15236 VBOHttpDocument::getInstance()->json($assets_pool);
15237 }
15238 }
15239