PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.6.4
VikBooking Hotel Booking Engine & PMS v1.6.4
1.8.16 1.8.15 1.8.14 1.8.13 1.8.12 1.8.11 1.8.10 1.8.9 1.8.6 1.8.7 1.8.8 trunk 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 All 37 releases
vikbooking / admin / controller.php

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

14,540 lines 556.4 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 $dt = VikRequest::getString('dt', '', 'request');
233 $ind = VikRequest::getInt('ind', 0, 'request');
234 $type = VikRequest::getString('type', '', 'request');
235 $type = empty($type) ? 'custom' : $type;
236 if (empty($dt) || !strtotime($dt)) {
237 echo 'e4j.error.1';
238 exit;
239 }
240
241 $fests = VikBooking::getFestivitiesInstance();
242 $result = $fests->deleteFestivity($dt, $ind, $type);
243 if (!$result) {
244 echo 'e4j.error.2';
245 exit;
246 }
247
248 echo 'e4j.ok';
249 exit;
250 }
251
252 public function einvoicing() {
253 VikBookingHelper::printHeader("einvoicing");
254
255 VikRequest::setVar('view', VikRequest::getCmd('view', 'einvoicing'));
256
257 parent::display();
258
259 if (VikBooking::showFooter()) {
260 VikBookingHelper::printFooter();
261 }
262 }
263
264 public function pmsreports() {
265 VikBookingHelper::printHeader("pmsreports");
266
267 VikRequest::setVar('view', VikRequest::getCmd('view', 'pmsreports'));
268
269 parent::display();
270
271 if (VikBooking::showFooter()) {
272 VikBookingHelper::printFooter();
273 }
274 }
275
276 public function ratesoverv() {
277 VikBookingHelper::printHeader("20");
278
279 VikRequest::setVar('view', VikRequest::getCmd('view', 'ratesoverv'));
280
281 parent::display();
282
283 if (VikBooking::showFooter()) {
284 VikBookingHelper::printFooter();
285 }
286 }
287
288 public function stats() {
289 VikBookingHelper::printHeader("stats");
290
291 VikRequest::setVar('view', VikRequest::getCmd('view', 'stats'));
292
293 parent::display();
294
295 if (VikBooking::showFooter()) {
296 VikBookingHelper::printFooter();
297 }
298 }
299
300 /**
301 * AJAX endpoint to calculate the website rates.
302 *
303 * @return void
304 */
305 public function calc_rates()
306 {
307 $response = 'e4j.error.ErrorCode(1) Server is blocking the self-request';
308 $response_code = 0;
309
310 // availability helper
311 $av_helper = VikBooking::getAvailabilityInstance();
312
313 $currencysymb = VikBooking::getCurrencySymb();
314 $vbo_df = VikBooking::getDateFormat();
315 $df = $vbo_df == "%d/%m/%Y" ? 'd/m/Y' : ($vbo_df == "%m/%d/%Y" ? 'm/d/Y' : 'Y/m/d');
316 $id_room = VikRequest::getInt('id_room', '', 'request');
317 $checkin = VikRequest::getString('checkin', '', 'request');
318 $nights = VikRequest::getInt('num_nights', 1, 'request');
319 $adults = VikRequest::getInt('num_adults', 0, 'request');
320 $children = VikRequest::getInt('num_children', 0, 'request');
321 /**
322 * The page Calendar may call this task via AJAX to obtain information
323 * about the various rate plans and final costs associated.
324 *
325 * @since 1.13 (J) - 1.3.0 (WP)
326 */
327 $only_rates = VikRequest::getInt('only_rates', 0, 'request');
328 $units = VikRequest::getInt('units', 1, 'request');
329 $checkinfdate = VikRequest::getString('checkinfdate', '', 'request');
330 $checkoutfdate = VikRequest::getString('checkoutfdate', '', 'request');
331 if (!empty($checkinfdate) && empty($checkin)) {
332 $checkin = date('Y-m-d', VikBooking::getDateTimestamp($checkinfdate, 0, 0, 0));
333 }
334
335 $checkin_ts = strtotime($checkin);
336 if (empty($checkin_ts)) {
337 $checkin = date('Y-m-d');
338 $checkin_ts = strtotime($checkin);
339 }
340
341 if (!empty($checkoutfdate) && !empty($checkinfdate) && $nights < 2) {
342 // checkout date was given rather than number of nights
343 $checkout_ts = VikBooking::getDateTimestamp($checkoutfdate, 0, 0, 0);
344 $checkout = date('Y-m-d', $checkout_ts);
345 $nights = $av_helper->countNightsOfStay($checkin_ts, $checkout_ts);
346 } else {
347 // calculate checkout depending on number of nights of stay
348 $is_dst = date('I', $checkin_ts);
349 $checkout_ts = $checkin_ts;
350 for ($i = 1; $i <= $nights; $i++) {
351 $checkout_ts += 86400;
352 $is_now_dst = date('I', $checkout_ts);
353 if ($is_dst != $is_now_dst) {
354 if ((int)$is_dst == 1) {
355 $checkout_ts += 3600;
356 } else {
357 $checkout_ts -= 3600;
358 }
359 $is_dst = $is_now_dst;
360 }
361 }
362 $checkout = date('Y-m-d', $checkout_ts);
363 }
364
365 /**
366 * We got rid of the CURL request to the front-end task of VBO "tac_av_l"
367 * by replacing the call with the new helper class VikBookingAvailability.
368 *
369 * @since 1.15.0 (J) - 1.5.0 (WP)
370 */
371 $av_helper->setStayDates($checkin, $checkout);
372 $av_helper->setRoomParty($adults, $children);
373 // build extra params to obtain the necessary data
374 $params = array(
375 'hash' => md5('vbo.e4j.vbo'),
376 'req_type' => 'hotel_availability',
377 'nights' => $nights,
378 'num_rooms' => 1,
379 'only_rates' => $only_rates,
380 );
381 $arr_res = $av_helper->getRates($params);
382
383 // pricing pool
384 $price_details = array();
385
386 if (is_array($arr_res)) {
387 if (!strlen($av_helper->getError())) {
388 if (array_key_exists($id_room, $arr_res)) {
389 $response = '';
390 foreach ($arr_res[$id_room] as $rate) {
391 // build pricing object
392 $rplan_details = new stdClass;
393 $rplan_details->idprice = $rate['idprice'];
394 $rplan_details->name = $rate['pricename'];
395 $rplan_details->net = $rate['cost'];
396 $rplan_details->fnet = $currencysymb . ' ' . VikBooking::numberFormat($rate['cost']);
397 $rplan_details->tax = $rate['taxes'];
398 $rplan_details->ftax = $currencysymb . ' ' . VikBooking::numberFormat($rate['taxes']);
399 $rplan_details->tot = $rate['cost'] + $rate['taxes'];
400 $rplan_details->ftot = $currencysymb . ' ' . VikBooking::numberFormat(($rate['cost'] + $rate['taxes']));
401 array_push($price_details, $rplan_details);
402 //
403 $extra_response = '';
404 $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 . '">';
405 $response .= '<span class="vbo-calcrates-ratename">'.$rate['pricename'].'</span>';
406 $response .= '<span class="vbo-calcrates-pricedet vbo-calcrates-ratenet"><span>'.JText::translate('VBCALCRATESNET').'</span>'.$currencysymb.' '.VikBooking::numberFormat($rate['cost']).'</span>';
407 $response .= '<span class="vbo-calcrates-pricedet vbo-calcrates-ratetax"><span>'.JText::translate('VBCALCRATESTAX').'</span>'.$currencysymb.' '.VikBooking::numberFormat($rate['taxes']).'</span>';
408 if (!empty($rate['city_taxes'])) {
409 $response .= '<span class="vbo-calcrates-pricedet vbo-calcrates-ratecitytax"><span>'.JText::translate('VBCALCRATESCITYTAX').'</span>'.$currencysymb.' '.VikBooking::numberFormat($rate['city_taxes']).'</span>';
410 }
411 if (!empty($rate['fees'])) {
412 $response .= '<span class="vbo-calcrates-pricedet vbo-calcrates-ratefees"><span>'.JText::translate('VBCALCRATESFEES').'</span>'.$currencysymb.' '.VikBooking::numberFormat($rate['fees']).'</span>';
413 }
414 if (array_key_exists('affdays', $rate) && $rate['affdays'] > 0) {
415 $extra_response .= '<span class="vbo-calcrates-extrapricedet vbo-calcrates-ratespaffdays"><span>'.JText::translate('VBCALCRATESSPAFFDAYS').'</span>'.$rate['affdays'].'</span>';
416 }
417 if (array_key_exists('diffusagediscount', $rate) && count($rate['diffusagediscount']) > 0) {
418 foreach ($rate['diffusagediscount'] as $roomnumb => $disc) {
419 $extra_response .= '<span class="vbo-calcrates-extrapricedet vbo-calcrates-rateoccupancydisc"><span>'.JText::sprintf('VBCALCRATESADUOCCUPANCY', $rate['diffusage']).'</span>- '.$currencysymb.' '.VikBooking::numberFormat($disc).'</span>';
420 break;
421 }
422 } elseif (array_key_exists('diffusagecost', $rate) && count($rate['diffusagecost']) > 0) {
423 foreach ($rate['diffusagecost'] as $roomnumb => $charge) {
424 $extra_response .= '<span class="vbo-calcrates-extrapricedet vbo-calcrates-rateoccupancycharge"><span>'.JText::sprintf('VBCALCRATESADUOCCUPANCY', $rate['diffusage']).'</span>+ '.$currencysymb.' '.VikBooking::numberFormat($charge).'</span>';
425 break;
426 }
427 }
428 $tot = $rate['cost'] + $rate['taxes'] + $rate['city_taxes'] + $rate['fees'];
429 $tot = round($tot, 2);
430 $response .= '<span class="vbo-calcrates-ratetotal"><span>'.JText::translate('VBCALCRATESTOT').'</span>'.$currencysymb.' '.VikBooking::numberFormat($tot).'</span>';
431 if (!empty($extra_response)) {
432 $response .= '<div class="vbo-calcrates-info">'.$extra_response.'</div>';
433 }
434 $response .= '</div>';
435 }
436 } else {
437 $response = 'e4j.error.'.JText::sprintf('VBCALCRATESROOMNOTAVAILCOMBO', date($df, $checkin_ts), date($df, $checkout_ts));
438 /**
439 * Set a response code so that the View calendar can understand that the room is not available or has no rates.
440 *
441 * @since 1.14 (J) - 1.4.0 (WP)
442 */
443 if (isset($arr_res['fullybooked']) && in_array($id_room, $arr_res['fullybooked'])) {
444 $response_code = -1;
445 }
446 }
447 } else {
448 $response = 'e4j.error.' . $av_helper->getError();
449 /**
450 * Set a response code so that the View calendar can understand that the room is not available or has no rates.
451 *
452 * @since 1.14 (J) - 1.4.0 (WP)
453 */
454 if (isset($arr_res['fullybooked']) && in_array($id_room, $arr_res['fullybooked'])) {
455 $response_code = -1;
456 }
457 }
458 } else {
459 $response = 'e4j.error.' . $av_helper->getError();
460 }
461
462 if ($only_rates && strpos($response, 'e4j.error') === false) {
463 echo json_encode($price_details);
464 exit;
465 }
466
467 // do not do only echo trim($response); or the currency symbol will not be encoded on some servers
468 $safe_response = array(trim($response));
469 if ($only_rates && !empty($response_code)) {
470 array_push($safe_response, $response_code);
471 }
472
473 echo json_encode($safe_response);
474 exit;
475 }
476
477 /**
478 * This is an AJAX endpoint.
479 */
480 public function cron_exec()
481 {
482 ob_start();
483
484 VikRequest::setVar('view', VikRequest::getCmd('view', 'cronexec'));
485
486 parent::display();
487
488 $content = ob_get_contents();
489 ob_end_clean();
490
491 VBOHttpDocument::getInstance()->json([$content]);
492 }
493
494 public function downloadcron()
495 {
496 /**
497 * @wponly no more executable files need to be downloaded for WordPress.
498 */
499 VBOHttpDocument::getInstance()->close(406, 'Cron Jobs must be executed through WPCron');
500 }
501
502 /**
503 * This is an AJAX endpoint.
504 */
505 public function cronlogs()
506 {
507 $dbo = JFactory::getDBO();
508 $pcron_id = VikRequest::getInt('cron_id', '', 'request');
509
510 ob_start();
511
512 $q = "SELECT * FROM `#__vikbooking_cronjobs` WHERE `id`=".(int)$pcron_id.";";
513 $dbo->setQuery($q);
514 $dbo->execute();
515 if ($dbo->getNumRows() == 1) {
516 $cron_data = $dbo->loadAssoc();
517 $cron_data['logs'] = empty($cron_data['logs']) ? '--------' : $cron_data['logs'];
518 echo '<pre>'.print_r($cron_data['logs'], true).'</pre>';
519 }
520
521 $content = ob_get_contents();
522 ob_end_clean();
523
524 VBOHttpDocument::getInstance()->json([$content]);
525 }
526
527 public function packages() {
528 VikBookingHelper::printHeader("packages");
529
530 VikRequest::setVar('view', VikRequest::getCmd('view', 'packages'));
531
532 parent::display();
533
534 if (VikBooking::showFooter()) {
535 VikBookingHelper::printFooter();
536 }
537 }
538
539 public function newpackage() {
540 VikBookingHelper::printHeader("packages");
541
542 VikRequest::setVar('view', VikRequest::getCmd('view', 'managepackage'));
543
544 parent::display();
545
546 if (VikBooking::showFooter()) {
547 VikBookingHelper::printFooter();
548 }
549 }
550
551 public function editpackage() {
552 VikBookingHelper::printHeader("packages");
553
554 VikRequest::setVar('view', VikRequest::getCmd('view', 'managepackage'));
555
556 parent::display();
557
558 if (VikBooking::showFooter()) {
559 VikBookingHelper::printFooter();
560 }
561 }
562
563 public function createpackage() {
564 if (!JSession::checkToken()) {
565 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
566 }
567 $this->do_createpackage();
568 }
569
570 public function createpackagestay() {
571 if (!JSession::checkToken()) {
572 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
573 }
574 $this->do_createpackage(true);
575 }
576
577 private function do_createpackage($stay = false) {
578 $dbo = JFactory::getDBO();
579 $mainframe = JFactory::getApplication();
580 $pname = VikRequest::getString('name', '', 'request');
581 $palias = VikRequest::getString('alias', '', 'request');
582 $palias = empty($palias) ? $pname : $palias;
583 $palias = JFilterOutput::stringURLSafe($palias);
584 $pimg = VikRequest::getVar('img', null, 'files', 'array');
585 $pfrom = VikRequest::getString('from', '', 'request');
586 $pto = VikRequest::getString('to', '', 'request');
587 $pexcludeday = VikRequest::getVar('excludeday', array());
588 $strexcldates = array();
589 foreach ($pexcludeday as $exclday) {
590 if (!empty($exclday)) {
591 $strexcldates[] = $exclday;
592 }
593 }
594 $strexcldates = implode(';', $strexcldates);
595 $prooms = VikRequest::getVar('rooms', array());
596 $pminlos = VikRequest::getInt('minlos', '', 'request');
597 $pminlos = $pminlos < 1 ? 1 : $pminlos;
598 $pmaxlos = VikRequest::getInt('maxlos', '', 'request');
599 $pmaxlos = $pmaxlos < 0 ? 0 : $pmaxlos;
600 $pmaxlos = $pmaxlos < $pminlos ? 0 : $pmaxlos;
601 $pcost = VikRequest::getFloat('cost', '', 'request');
602 $paliq = VikRequest::getInt('aliq', '', 'request');
603 $ppernight_total = VikRequest::getInt('pernight_total', '', 'request');
604 $ppernight_total = $ppernight_total == 1 ? 1 : 2;
605 $pperperson = VikRequest::getInt('perperson', '', 'request');
606 $pperperson = $pperperson > 0 ? 1 : 0;
607 $pshowoptions = VikRequest::getInt('showoptions', '', 'request');
608 $pshowoptions = $pshowoptions >= 1 && $pshowoptions <= 3 ? $pshowoptions : 1;
609 $pdescr = VikRequest::getString('descr', '', 'request', VIKREQUEST_ALLOWRAW);
610 $pshortdescr = VikRequest::getString('shortdescr', '', 'request', VIKREQUEST_ALLOWHTML);
611 $pconditions = VikRequest::getString('conditions', '', 'request', VIKREQUEST_ALLOWRAW);
612 $pbenefits = VikRequest::getString('benefits', '', 'request', VIKREQUEST_ALLOWHTML);
613 $ptsinit = VikBooking::getDateTimestamp($pfrom, '0', '0');
614 $ptsend = VikBooking::getDateTimestamp($pto, '23', '59');
615 $ptsinit = empty($ptsinit) ? time() : $ptsinit;
616 $ptsend = empty($ptsend) || $ptsend < $ptsinit ? $ptsinit : $ptsend;
617 //file upload
618 jimport('joomla.filesystem.file');
619 $gimg = "";
620 if (isset($pimg) && strlen(trim($pimg['name']))) {
621 $pautoresize = VikRequest::getString('autoresize', '', 'request');
622 $presizeto = VikRequest::getInt('resizeto', '', 'request');
623 $creativik = new vikResizer();
624 $filename = JFile::makeSafe(str_replace(" ", "_", strtolower($pimg['name'])));
625 $src = $pimg['tmp_name'];
626 $dest = VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR;
627 $j = "";
628 if (file_exists($dest.$filename)) {
629 $j = rand(171, 1717);
630 while (file_exists($dest.$j.$filename)) {
631 $j++;
632 }
633 }
634 $finaldest = $dest.$j.$filename;
635 $check = getimagesize($pimg['tmp_name']);
636 if ($check[2] & imagetypes()) {
637 if (VikBooking::uploadFile($src, $finaldest)) {
638 $gimg = $j.$filename;
639 //orig img
640 $origmod = true;
641 if ($pautoresize == "1" && !empty($presizeto)) {
642 $origmod = $creativik->proportionalImage($finaldest, $dest.'big_'.$j.$filename, $presizeto, $presizeto);
643 } else {
644 VikBooking::uploadFile($finaldest, $dest.'big_'.$j.$filename, true);
645 }
646 //thumb
647 $thumbsize = VikBooking::getThumbSize();
648 $thumb = $creativik->proportionalImage($finaldest, $dest.'thumb_'.$j.$filename, $thumbsize, $thumbsize);
649 if (!$thumb || !$origmod) {
650 if (file_exists($dest.'big_'.$j.$filename)) @unlink($dest.'big_'.$j.$filename);
651 if (file_exists($dest.'thumb_'.$j.$filename)) @unlink($dest.'thumb_'.$j.$filename);
652 VikError::raiseWarning('', 'Error Uploading the File: '.$pimg['name']);
653 }
654 @unlink($finaldest);
655 } else {
656 VikError::raiseWarning('', 'Error while uploading image');
657 }
658 } else {
659 VikError::raiseWarning('', 'Uploaded file is not an Image');
660 }
661 }
662 //
663 $goto = "index.php?option=com_vikbooking&task=packages";
664 $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.");";
665 $dbo->setQuery($q);
666 $dbo->execute();
667 $lid = $dbo->insertid();
668 if (!empty($lid)) {
669 $mainframe->enqueueMessage(JText::translate('VBOPKGSAVED'));
670 if ($stay) {
671 $goto = "index.php?option=com_vikbooking&task=editpackage&cid[]=".$lid;
672 }
673 foreach ($prooms as $roomid) {
674 if (!empty($roomid)) {
675 $q = "INSERT INTO `#__vikbooking_packages_rooms` (`idpackage`,`idroom`) VALUES (".(int)$lid.", ".(int)$roomid.");";
676 $dbo->setQuery($q);
677 $dbo->execute();
678 }
679 }
680 }
681 $mainframe->redirect($goto);
682 }
683
684 public function updatepackage() {
685 if (!JSession::checkToken()) {
686 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
687 }
688 $this->do_updatepackage();
689 }
690
691 public function updatepackagestay() {
692 if (!JSession::checkToken()) {
693 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
694 }
695 $this->do_updatepackage(true);
696 }
697
698 private function do_updatepackage($stay = false) {
699 $dbo = JFactory::getDBO();
700 $mainframe = JFactory::getApplication();
701 $pwhereup = VikRequest::getInt('whereup', '', 'request');
702 $q = "SELECT * FROM `#__vikbooking_packages` WHERE `id`=".(int)$pwhereup.";";
703 $dbo->setQuery($q);
704 $dbo->execute();
705 if ($dbo->getNumRows() == 1) {
706 $pkg_data = $dbo->loadAssoc();
707 } else {
708 VikError::raiseWarning('', 'Not Found.');
709 $mainframe->redirect("index.php?option=com_vikbooking&task=packages");
710 exit;
711 }
712 $pname = VikRequest::getString('name', '', 'request');
713 $palias = VikRequest::getString('alias', '', 'request');
714 $palias = empty($palias) ? $pname : $palias;
715 $palias = JFilterOutput::stringURLSafe($palias);
716 $pimg = VikRequest::getVar('img', null, 'files', 'array');
717 $pfrom = VikRequest::getString('from', '', 'request');
718 $pto = VikRequest::getString('to', '', 'request');
719 $pexcludeday = VikRequest::getVar('excludeday', array());
720 $strexcldates = array();
721 foreach ($pexcludeday as $exclday) {
722 if (!empty($exclday)) {
723 $strexcldates[] = $exclday;
724 }
725 }
726 $strexcldates = implode(';', $strexcldates);
727 $prooms = VikRequest::getVar('rooms', array());
728 $pminlos = VikRequest::getInt('minlos', '', 'request');
729 $pminlos = $pminlos < 1 ? 1 : $pminlos;
730 $pmaxlos = VikRequest::getInt('maxlos', '', 'request');
731 $pmaxlos = $pmaxlos < 0 ? 0 : $pmaxlos;
732 $pmaxlos = $pmaxlos < $pminlos ? 0 : $pmaxlos;
733 $pcost = VikRequest::getFloat('cost', '', 'request');
734 $paliq = VikRequest::getInt('aliq', '', 'request');
735 $ppernight_total = VikRequest::getInt('pernight_total', '', 'request');
736 $ppernight_total = $ppernight_total == 1 ? 1 : 2;
737 $pperperson = VikRequest::getInt('perperson', '', 'request');
738 $pperperson = $pperperson > 0 ? 1 : 0;
739 $pshowoptions = VikRequest::getInt('showoptions', '', 'request');
740 $pshowoptions = $pshowoptions >= 1 && $pshowoptions <= 3 ? $pshowoptions : 1;
741 $pdescr = VikRequest::getString('descr', '', 'request', VIKREQUEST_ALLOWRAW);
742 $pshortdescr = VikRequest::getString('shortdescr', '', 'request', VIKREQUEST_ALLOWHTML);
743 $pconditions = VikRequest::getString('conditions', '', 'request', VIKREQUEST_ALLOWRAW);
744 $pbenefits = VikRequest::getString('benefits', '', 'request', VIKREQUEST_ALLOWHTML);
745 $ptsinit = VikBooking::getDateTimestamp($pfrom, '0', '0');
746 $ptsend = VikBooking::getDateTimestamp($pto, '23', '59');
747 $ptsinit = empty($ptsinit) ? time() : $ptsinit;
748 $ptsend = empty($ptsend) || $ptsend < $ptsinit ? $ptsinit : $ptsend;
749 //file upload
750 jimport('joomla.filesystem.file');
751 $gimg = "";
752 if (isset($pimg) && strlen(trim($pimg['name']))) {
753 $pautoresize = VikRequest::getString('autoresize', '', 'request');
754 $presizeto = VikRequest::getInt('resizeto', '', 'request');
755 $creativik = new vikResizer();
756 $filename = JFile::makeSafe(str_replace(" ", "_", strtolower($pimg['name'])));
757 $src = $pimg['tmp_name'];
758 $dest = VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR;
759 $j = "";
760 if (file_exists($dest.$filename)) {
761 $j = rand(171, 1717);
762 while (file_exists($dest.$j.$filename)) {
763 $j++;
764 }
765 }
766 $finaldest = $dest.$j.$filename;
767 $check = getimagesize($pimg['tmp_name']);
768 if ($check[2] & imagetypes()) {
769 if (VikBooking::uploadFile($src, $finaldest)) {
770 $gimg = $j.$filename;
771 //orig img
772 $origmod = true;
773 if ($pautoresize == "1" && !empty($presizeto)) {
774 $origmod = $creativik->proportionalImage($finaldest, $dest.'big_'.$j.$filename, $presizeto, $presizeto);
775 } else {
776 VikBooking::uploadFile($finaldest, $dest.'big_'.$j.$filename, true);
777 }
778 //thumb
779 $thumbsize = VikBooking::getThumbSize();
780 $thumb = $creativik->proportionalImage($finaldest, $dest.'thumb_'.$j.$filename, $thumbsize, $thumbsize);
781 if (!$thumb || !$origmod) {
782 if (file_exists($dest.'big_'.$j.$filename)) @unlink($dest.'big_'.$j.$filename);
783 if (file_exists($dest.'thumb_'.$j.$filename)) @unlink($dest.'thumb_'.$j.$filename);
784 VikError::raiseWarning('', 'Error Uploading the File: '.$pimg['name']);
785 }
786 @unlink($finaldest);
787 } else {
788 VikError::raiseWarning('', 'Error while uploading image');
789 }
790 } else {
791 VikError::raiseWarning('', 'Uploaded file is not an Image');
792 }
793 }
794 //
795 $goto = "index.php?option=com_vikbooking&task=packages";
796 $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.";";
797 $dbo->setQuery($q);
798 $dbo->execute();
799 $q = "DELETE FROM `#__vikbooking_packages_rooms` WHERE `idpackage`=".(int)$pwhereup.";";
800 $dbo->setQuery($q);
801 $dbo->execute();
802 foreach ($prooms as $roomid) {
803 if (!empty($roomid)) {
804 $q = "INSERT INTO `#__vikbooking_packages_rooms` (`idpackage`,`idroom`) VALUES (".(int)$pwhereup.", ".(int)$roomid.");";
805 $dbo->setQuery($q);
806 $dbo->execute();
807 }
808 }
809 $mainframe->enqueueMessage(JText::translate('VBOPKGUPDATED'));
810 if ($stay) {
811 $goto = "index.php?option=com_vikbooking&task=editpackage&cid[]=".$pwhereup;
812 }
813 $mainframe->redirect($goto);
814 }
815
816 public function removepackages() {
817 if (!JSession::checkToken()) {
818 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
819 }
820 $ids = VikRequest::getVar('cid', array());
821 $dbo = JFactory::getDbo();
822
823 foreach ($ids as $d) {
824 $q = "DELETE FROM `#__vikbooking_packages` WHERE `id`=".(int)$d.";";
825 $dbo->setQuery($q);
826 $dbo->execute();
827 $q = "DELETE FROM `#__vikbooking_packages_rooms` WHERE `idpackage`=".(int)$d.";";
828 $dbo->setQuery($q);
829 $dbo->execute();
830 }
831
832 $mainframe = JFactory::getApplication();
833 $mainframe->redirect("index.php?option=com_vikbooking&task=packages");
834 }
835
836 public function calendar() {
837 VikBookingHelper::printHeader("19");
838
839 VikRequest::setVar('view', VikRequest::getCmd('view', 'calendar'));
840
841 parent::display();
842
843 if (VikBooking::showFooter()) {
844 VikBookingHelper::printFooter();
845 }
846 }
847
848 public function rooms() {
849 VikBookingHelper::printHeader("7");
850
851 VikRequest::setVar('view', VikRequest::getCmd('view', 'rooms'));
852
853 parent::display();
854
855 if (VikBooking::showFooter()) {
856 VikBookingHelper::printFooter();
857 }
858 }
859
860 public function newroom() {
861 VikBookingHelper::printHeader("7");
862
863 VikRequest::setVar('view', VikRequest::getCmd('view', 'manageroom'));
864
865 parent::display();
866
867 if (VikBooking::showFooter()) {
868 VikBookingHelper::printFooter();
869 }
870 }
871
872 public function editroom() {
873 VikBookingHelper::printHeader("7");
874
875 VikRequest::setVar('view', VikRequest::getCmd('view', 'manageroom'));
876
877 parent::display();
878
879 if (VikBooking::showFooter()) {
880 VikBookingHelper::printFooter();
881 }
882 }
883
884 public function createroom() {
885 if (!JSession::checkToken()) {
886 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
887 }
888 $this->do_createroom();
889 }
890
891 public function createroomstay() {
892 if (!JSession::checkToken()) {
893 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
894 }
895 $this->do_createroom(true);
896 }
897
898 private function do_createroom($stay = false) {
899 $app = JFactory::getApplication();
900 $pcname = VikRequest::getString('cname', '', 'request');
901 $pccat = VikRequest::getVar('ccat', array(0));
902 $pcdescr = VikRequest::getString('cdescr', '', 'request', VIKREQUEST_ALLOWRAW);
903 $psmalldesc = VikRequest::getString('smalldesc', '', 'request', VIKREQUEST_ALLOWRAW);
904 $pccarat = VikRequest::getVar('ccarat', array(0));
905 $pcoptional = VikRequest::getVar('coptional', array(0));
906 $pcavail = VikRequest::getString('cavail', '', 'request');
907 $pautoresize = VikRequest::getString('autoresize', '', 'request');
908 $presizeto = VikRequest::getString('resizeto', '', 'request');
909 $pautoresizemore = VikRequest::getString('autoresizemore', '', 'request');
910 $presizetomore = VikRequest::getString('resizetomore', '', 'request');
911 $punits = VikRequest::getInt('units', '', 'request');
912 $pimages = VikRequest::getVar('cimgmore', null, 'files', 'array');
913 $pfromadult = VikRequest::getInt('fromadult', '', 'request');
914 $ptoadult = VikRequest::getInt('toadult', '', 'request');
915 $pfromchild = VikRequest::getInt('fromchild', '', 'request');
916 $ptochild = VikRequest::getInt('tochild', '', 'request');
917 $ptotpeople = VikRequest::getInt('totpeople', '', 'request');
918 $pmintotpeople = VikRequest::getInt('mintotpeople', '', 'request');
919 $pmintotpeople = $pmintotpeople < 1 ? 1 : $pmintotpeople;
920 $plastavail = VikRequest::getString('lastavail', '', 'request');
921 $plastavail = empty($plastavail) ? 0 : intval($plastavail);
922 $psuggocc = VikRequest::getInt('suggocc', 1, 'request');
923 $pcustprice = VikRequest::getString('custprice', '', 'request');
924 $pcustprice = empty($pcustprice) ? '' : floatval($pcustprice);
925 $pcustpricetxt = VikRequest::getString('custpricetxt', '', 'request', VIKREQUEST_ALLOWRAW);
926 $pcustpricesubtxt = VikRequest::getString('custpricesubtxt', '', 'request', VIKREQUEST_ALLOWRAW);
927 $preqinfo = VikRequest::getInt('reqinfo', '', 'request');
928 $ppricecal = VikRequest::getInt('pricecal', '', 'request');
929 $pdefcalcost = VikRequest::getString('defcalcost', '', 'request');
930 $pmaxminpeople = VikRequest::getString('maxminpeople', '', 'request');
931 $pcimgcaption = VikRequest::getVar('cimgcaption', array());
932 $pmaxminpeople = in_array($pmaxminpeople, array('0', '1', '2', '3', '4', '5')) ? $pmaxminpeople : '0';
933 $pseasoncal = VikRequest::getInt('seasoncal', 0, 'request');
934 $pseasoncal = $pseasoncal >= 0 || $pseasoncal <= 3 ? $pseasoncal : 0;
935 $pseasoncal_nights = VikRequest::getString('seasoncal_nights', '', 'request');
936 $pseasoncal_prices = VikRequest::getString('seasoncal_prices', '', 'request');
937 $pseasoncal_restr = VikRequest::getString('seasoncal_restr', '', 'request');
938 $pmulti_units = VikRequest::getInt('multi_units', '', 'request');
939 $pmulti_units = $punits > 1 ? $pmulti_units : 0;
940 $psefalias = VikRequest::getString('sefalias', '', 'request');
941 $psefalias = empty($psefalias) ? JFilterOutput::stringURLSafe($pcname) : JFilterOutput::stringURLSafe($psefalias);
942 $pcustptitle = VikRequest::getString('custptitle', '', 'request');
943 $pcustptitlew = VikRequest::getString('custptitlew', '', 'request');
944 $pcustptitlew = in_array($pcustptitlew, array('before', 'after', 'replace')) ? $pcustptitlew : 'before';
945 $pmetakeywords = VikRequest::getString('metakeywords', '', 'request');
946 $pmetadescription = VikRequest::getString('metadescription', '', 'request');
947 $pshare_with = VikRequest::getVar('share_with', array());
948 $scalnights_arr = array();
949 if (!empty($pseasoncal_nights)) {
950 $scalnights = explode(',', $pseasoncal_nights);
951 foreach ($scalnights as $scalnight) {
952 if (intval(trim($scalnight)) > 0) {
953 $scalnights_arr[] = intval(trim($scalnight));
954 }
955 }
956 }
957 if (count($scalnights_arr) > 0) {
958 $pseasoncal_nights = implode(', ', $scalnights_arr);
959 } else {
960 $pseasoncal_nights = '';
961 $pseasoncal = 0;
962 }
963 $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);
964 //distinctive features
965 $roomparams['features'] = array();
966 if ($punits > 0) {
967 for ($i=1; $i <= $punits; $i++) {
968 $distf_name = VikRequest::getVar('feature-name'.$i, array(0));
969 $distf_lang = VikRequest::getVar('feature-lang'.$i, array(0));
970 $distf_value = VikRequest::getVar('feature-value'.$i, array(0));
971 foreach ($distf_name as $distf_k => $distf) {
972 if (strlen($distf) > 0 && strlen($distf_value[$distf_k]) > 0) {
973 $use_key = strlen($distf_lang[$distf_k]) > 0 ? $distf_lang[$distf_k] : $distf;
974 $roomparams['features'][$i][$use_key] = $distf_value[$distf_k];
975 }
976 }
977 }
978 }
979
980 /**
981 * Store room geo params information.
982 *
983 * @since 1.14 (J) - 1.4.0 (WP)
984 */
985 $geo = VikBooking::getGeocodingInstance();
986 $geo_params = $geo->getRoomGeoTransient(0);
987 if ($geo_params !== false) {
988 // make sure the geocoding service was not turned off
989 $geo_enabled = VikRequest::getInt('geo_enabled', 0, 'request');
990 if (!$geo_enabled) {
991 $geo_params->enabled = 0;
992 }
993 //
994 $roomparams['geo'] = $geo_params;
995 }
996 //
997
998 $roomparamstr = json_encode($roomparams);
999
1000 if (empty($pcname)) {
1001 $app->enqueueMessage(JText::translate('VBO_PLEASE_FILL_FIELDS'), 'error');
1002 $app->redirect("index.php?option=com_vikbooking&task=rooms");
1003 $app->close();
1004 }
1005
1006 jimport('joomla.filesystem.file');
1007 $updpath = VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR;
1008
1009 if (intval($_FILES['cimg']['error']) == 0 && VikBooking::caniWrite($updpath) && trim($_FILES['cimg']['name'])!="") {
1010 if (@is_uploaded_file($_FILES['cimg']['tmp_name'])) {
1011 $safename = JFile::makeSafe(str_replace(" ", "_", strtolower($_FILES['cimg']['name'])));
1012 if (file_exists($updpath.$safename)) {
1013 $j = 1;
1014 while (file_exists($updpath.$j.$safename)) {
1015 $j++;
1016 }
1017 $pwhere = $updpath.$j.$safename;
1018 } else {
1019 $j = "";
1020 $pwhere = $updpath.$safename;
1021 }
1022 if (!getimagesize($_FILES['cimg']['tmp_name']) || !preg_match("/\.(a?png|jpe?g|bmp|gif|ico|webp)\z/i", $safename)) {
1023 @unlink($pwhere);
1024 $picon = "";
1025 } else {
1026 VikBooking::uploadFile($_FILES['cimg']['tmp_name'], $pwhere);
1027 @chmod($pwhere, 0644);
1028 $picon = $j.$safename;
1029 if ($pautoresize=="1" && !empty($presizeto)) {
1030 $eforj = new vikResizer();
1031 $origmod = $eforj->proportionalImage($pwhere, $updpath.'r_'.$j.$safename, $presizeto, $presizeto);
1032 if ($origmod) {
1033 @unlink($pwhere);
1034 $picon = 'r_'.$j.$safename;
1035 }
1036 }
1037 }
1038 } else {
1039 $picon = "";
1040 }
1041 } else {
1042 $picon = "";
1043 }
1044 //more images
1045 $creativik = new vikResizer();
1046 $bigsdest = $updpath;
1047 $thumbsdest = $updpath;
1048 $dest = $updpath;
1049 $moreimagestr = "";
1050 $arrimgs = array();
1051 $captiontexts = array();
1052 $imgcaptions = array();
1053 foreach ($pimages['name'] as $kk=>$ci) {
1054 if (!empty($ci)) {
1055 $arrimgs[] = $kk;
1056 $captiontexts[] = isset($pcimgcaption[$kk]) ? $pcimgcaption[$kk] : '';
1057 }
1058 }
1059 foreach ($arrimgs as $ki => $imgk) {
1060 if (strlen(trim($pimages['name'][$imgk]))) {
1061 $filename = JFile::makeSafe(str_replace(" ", "_", strtolower($pimages['name'][$imgk])));
1062 $src = $pimages['tmp_name'][$imgk];
1063 $j = "";
1064 if (file_exists($dest.$filename)) {
1065 $j = rand(171, 1717);
1066 while (file_exists($dest.$j.$filename)) {
1067 $j++;
1068 }
1069 }
1070 $finaldest = $dest.$j.$filename;
1071 $check = getimagesize($pimages['tmp_name'][$imgk]);
1072 if (($check[2] & imagetypes()) && preg_match("/\.(a?png|jpe?g|bmp|gif|ico|webp)\z/i", $filename)) {
1073 if (VikBooking::uploadFile($src, $finaldest)) {
1074 $gimg = $j.$filename;
1075 //orig img
1076 $origmod = true;
1077 if ($pautoresizemore == "1" && !empty($presizetomore)) {
1078 $origmod = $creativik->proportionalImage($finaldest, $bigsdest.'big_'.$j.$filename, $presizetomore, $presizetomore);
1079 } else {
1080 VikBooking::uploadFile($finaldest, $bigsdest.'big_'.$j.$filename, true);
1081 }
1082 //thumb
1083 $thumbsize = VikBooking::getThumbSize();
1084 $thumb = $creativik->proportionalImage($finaldest, $thumbsdest.'thumb_'.$j.$filename, $thumbsize, $thumbsize);
1085 if (!$thumb || !$origmod) {
1086 if (file_exists($bigsdest.'big_'.$j.$filename)) @unlink($bigsdest.'big_'.$j.$filename);
1087 if (file_exists($thumbsdest.'thumb_'.$j.$filename)) @unlink($thumbsdest.'thumb_'.$j.$filename);
1088 VikError::raiseWarning('', 'Error While Uploading the File: '.$pimages['name'][$imgk]);
1089 } else {
1090 $moreimagestr .= $j.$filename.";;";
1091 $imgcaptions[] = $captiontexts[$ki];
1092 }
1093 @unlink($finaldest);
1094 } else {
1095 VikError::raiseWarning('', 'Error While Uploading the File: '.$pimages['name'][$imgk]);
1096 }
1097 } else {
1098 VikError::raiseWarning('', 'Error While Uploading the File: '.$pimages['name'][$imgk]);
1099 }
1100 }
1101 }
1102 //end more images
1103 if (is_array($pccat) && count($pccat)) {
1104 $pccatdef="";
1105 foreach ($pccat as $ccat) {
1106 if (!empty($ccat)) {
1107 $pccatdef.=$ccat.";";
1108 }
1109 }
1110 } else {
1111 $pccatdef="";
1112 }
1113 if (is_array($pccarat) && count($pccarat)) {
1114 $pccaratdef="";
1115 foreach ($pccarat as $ccarat) {
1116 $pccaratdef.=$ccarat.";";
1117 }
1118 } else {
1119 $pccaratdef="";
1120 }
1121 if (is_array($pcoptional) && count($pcoptional)) {
1122 $pcoptionaldef="";
1123 foreach ($pcoptional as $coptional) {
1124 $pcoptionaldef.=$coptional.";";
1125 }
1126 } else {
1127 $pcoptionaldef="";
1128 }
1129 $pcavaildef=($pcavail=="yes" ? "1" : "0");
1130 if ($pfromadult > $ptoadult) {
1131 $pfromadult = 1;
1132 $ptoadult = 1;
1133 }
1134 if ($pfromchild > $ptochild) {
1135 $pfromchild = 1;
1136 $ptochild = 1;
1137 }
1138 $dbo = JFactory::getDbo();
1139 $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).");";
1140 $dbo->setQuery($q);
1141 $dbo->execute();
1142 $lid = $dbo->insertid();
1143 if (empty($lid)) {
1144 $app->enqueueMessage('Could not store the record on the database', 'error');
1145 $app->redirect("index.php?option=com_vikbooking&task=rooms");
1146 $app->close();
1147 }
1148
1149 /**
1150 * Share availability calendars with other rooms.
1151 *
1152 * @since 1.13
1153 */
1154 // always reset relations for this main room
1155 $q = "DELETE FROM `#__vikbooking_calendars_xref` WHERE `mainroom`={$lid};";
1156 $dbo->setQuery($q);
1157 $dbo->execute();
1158 $newxref = array();
1159 foreach ($pshare_with as $cldroom) {
1160 if (!empty($cldroom)) {
1161 array_push($newxref, (int)$cldroom);
1162 }
1163 }
1164 foreach ($newxref as $cldroom) {
1165 $q = "INSERT INTO `#__vikbooking_calendars_xref` (`mainroom`, `childroom`) VALUES ({$lid}, {$cldroom});";
1166 $dbo->setQuery($q);
1167 $dbo->execute();
1168 }
1169
1170 /**
1171 * Room upgrade options.
1172 *
1173 * @since 1.16.0 (J) - 1.6.0 (WP)
1174 */
1175 $config = VBOFactory::getConfig();
1176 $room_upgrade_options = [];
1177 $room_upgrade = VikRequest::getInt('room_upgrade', 0, 'request');
1178 $upgrade_rooms = VikRequest::getVar('upgrade_rooms', array());
1179 $upgrade_discount = VikRequest::getFloat('upgrade_discount', 0, 'request');
1180 if ($room_upgrade && is_array($upgrade_rooms) && count($upgrade_rooms)) {
1181 $upgrade_rooms = array_map(function($rid) {
1182 return (int)$rid;
1183 }, $upgrade_rooms);
1184
1185 $room_upgrade_options = [
1186 'rooms' => $upgrade_rooms,
1187 'discount' => $upgrade_discount,
1188 ];
1189 }
1190 $config->set('room_upgrade_options_' . $lid, json_encode($room_upgrade_options));
1191
1192 if ($stay === true) {
1193 $app->enqueueMessage(JText::translate('VBOROOMSAVEOK').' - <a href="index.php?option=com_vikbooking&task=tariffs&cid[]='.$lid.'">'.JText::translate('VBOGOTORATES').'</a>');
1194 $app->redirect("index.php?option=com_vikbooking&task=editroom&cid[]=".$lid);
1195 $app->close();
1196 }
1197
1198 $app->redirect("index.php?option=com_vikbooking&task=tariffs&cid[]=".$lid);
1199 $app->close();
1200 }
1201
1202 public function updateroom() {
1203 if (!JSession::checkToken()) {
1204 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
1205 }
1206 $this->do_updateroom();
1207 }
1208
1209 public function updateroomstay() {
1210 if (!JSession::checkToken()) {
1211 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
1212 }
1213 $this->do_updateroom(true);
1214 }
1215
1216 private function do_updateroom($stay = false)
1217 {
1218 $app = JFactory::getApplication();
1219 $config = VBOFactory::getConfig();
1220
1221 $pcname = VikRequest::getString('cname', '', 'request');
1222 $pccat = VikRequest::getVar('ccat', array(0));
1223 $pcdescr = VikRequest::getString('cdescr', '', 'request', VIKREQUEST_ALLOWRAW);
1224 $psmalldesc = VikRequest::getString('smalldesc', '', 'request', VIKREQUEST_ALLOWRAW);
1225 $pccarat = VikRequest::getVar('ccarat', array(0));
1226 $pcoptional = VikRequest::getVar('coptional', array(0));
1227 $pcavail = VikRequest::getString('cavail', '', 'request');
1228 $pwhereup = VikRequest::getInt('whereup', 0, 'request');
1229 $pautoresize = VikRequest::getString('autoresize', '', 'request');
1230 $presizeto = VikRequest::getString('resizeto', '', 'request');
1231 $pautoresizemore = VikRequest::getString('autoresizemore', '', 'request');
1232 $presizetomore = VikRequest::getString('resizetomore', '', 'request');
1233 $punits = VikRequest::getInt('units', '', 'request');
1234 $pimages = VikRequest::getVar('cimgmore', null, 'files', 'array');
1235 $pactmoreimgs = VikRequest::getString('actmoreimgs', '', 'request');
1236 $pfromadult = VikRequest::getInt('fromadult', '', 'request');
1237 $ptoadult = VikRequest::getInt('toadult', '', 'request');
1238 $pfromchild = VikRequest::getInt('fromchild', '', 'request');
1239 $ptochild = VikRequest::getInt('tochild', '', 'request');
1240 $padultsdiffchdisc = VikRequest::getVar('adultsdiffchdisc', array(0));
1241 $padultsdiffval = VikRequest::getVar('adultsdiffval', array(0));
1242 $padultsdiffnum = VikRequest::getVar('adultsdiffnum', array(0));
1243 $padultsdiffvalpcent = VikRequest::getVar('adultsdiffvalpcent', array(0));
1244 $padultsdiffpernight = VikRequest::getVar('adultsdiffpernight', array(0));
1245 $ptotpeople = VikRequest::getInt('totpeople', '', 'request');
1246 $pmintotpeople = VikRequest::getInt('mintotpeople', '', 'request');
1247 $pmintotpeople = $pmintotpeople < 1 ? 1 : $pmintotpeople;
1248 $plastavail = VikRequest::getString('lastavail', '', 'request');
1249 $plastavail = empty($plastavail) ? 0 : intval($plastavail);
1250 $psuggocc = VikRequest::getInt('suggocc', 1, 'request');
1251 $pcustprice = VikRequest::getString('custprice', '', 'request');
1252 $pcustprice = empty($pcustprice) ? '' : floatval($pcustprice);
1253 $pcustpricetxt = VikRequest::getString('custpricetxt', '', 'request', VIKREQUEST_ALLOWRAW);
1254 $pcustpricesubtxt = VikRequest::getString('custpricesubtxt', '', 'request', VIKREQUEST_ALLOWRAW);
1255 $preqinfo = VikRequest::getInt('reqinfo', '', 'request');
1256 $ppricecal = VikRequest::getInt('pricecal', '', 'request');
1257 $pdefcalcost = VikRequest::getString('defcalcost', '', 'request');
1258 $pdefrplan = VikRequest::getInt('defrplan', 0, 'request');
1259 $pmaxminpeople = VikRequest::getString('maxminpeople', '', 'request');
1260 $pcimgcaption = VikRequest::getVar('cimgcaption', array());
1261 $pimgsorting = VikRequest::getVar('imgsorting', array());
1262 $pupdatecaption = VikRequest::getInt('updatecaption', '', 'request');
1263 $pmaxminpeople = in_array($pmaxminpeople, array('0', '1', '2', '3', '4', '5')) ? $pmaxminpeople : '0';
1264 $pseasoncal = VikRequest::getInt('seasoncal', 0, 'request');
1265 $pseasoncal = $pseasoncal >= 0 || $pseasoncal <= 3 ? $pseasoncal : 0;
1266 $pseasoncal_nights = VikRequest::getString('seasoncal_nights', '', 'request');
1267 $pseasoncal_prices = VikRequest::getString('seasoncal_prices', '', 'request');
1268 $pseasoncal_restr = VikRequest::getString('seasoncal_restr', '', 'request');
1269 $pmulti_units = VikRequest::getInt('multi_units', '', 'request');
1270 $pmulti_units = $punits > 1 ? $pmulti_units : 0;
1271 $psefalias = VikRequest::getString('sefalias', '', 'request');
1272 $psefalias = empty($psefalias) ? JFilterOutput::stringURLSafe($pcname) : JFilterOutput::stringURLSafe($psefalias);
1273 $pcustptitle = VikRequest::getString('custptitle', '', 'request');
1274 $pcustptitlew = VikRequest::getString('custptitlew', '', 'request');
1275 $pcustptitlew = in_array($pcustptitlew, array('before', 'after', 'replace')) ? $pcustptitlew : 'before';
1276 $pmetakeywords = VikRequest::getString('metakeywords', '', 'request');
1277 $pmetadescription = VikRequest::getString('metadescription', '', 'request');
1278 $pshare_with = VikRequest::getVar('share_with', array());
1279 $scalnights_arr = array();
1280 if (!empty($pseasoncal_nights)) {
1281 $scalnights = explode(',', $pseasoncal_nights);
1282 foreach ($scalnights as $scalnight) {
1283 if (intval(trim($scalnight)) > 0) {
1284 $scalnights_arr[] = intval(trim($scalnight));
1285 }
1286 }
1287 }
1288 if (count($scalnights_arr) > 0) {
1289 $pseasoncal_nights = implode(', ', $scalnights_arr);
1290 } else {
1291 $pseasoncal_nights = '';
1292 $pseasoncal = 0;
1293 }
1294 $roomparams = [
1295 'lastavail' => $plastavail,
1296 'suggocc' => $psuggocc,
1297 'custprice' => $pcustprice,
1298 'custpricetxt' => $pcustpricetxt,
1299 'custpricesubtxt' => $pcustpricesubtxt,
1300 'reqinfo' => $preqinfo,
1301 'pricecal' => $ppricecal,
1302 'defcalcost' => floatval($pdefcalcost),
1303 'defrplan' => $pdefrplan,
1304 'maxminpeople' => $pmaxminpeople,
1305 'seasoncal' => $pseasoncal,
1306 'seasoncal_nights' => $pseasoncal_nights,
1307 'seasoncal_prices' => $pseasoncal_prices,
1308 'seasoncal_restr' => $pseasoncal_restr,
1309 'multi_units' => $pmulti_units,
1310 'custptitle' => $pcustptitle,
1311 'custptitlew' => $pcustptitlew,
1312 'metakeywords' => $pmetakeywords,
1313 'metadescription' => $pmetadescription,
1314 ];
1315 //distinctive features
1316 $roomparams['features'] = array();
1317 $newfeatures = array();
1318 if ($punits > 0) {
1319 for ($i=1; $i <= $punits; $i++) {
1320 $distf_name = VikRequest::getVar('feature-name'.$i, array(0));
1321 $distf_lang = VikRequest::getVar('feature-lang'.$i, array(0));
1322 $distf_value = VikRequest::getVar('feature-value'.$i, array(0));
1323 foreach ($distf_name as $distf_k => $distf) {
1324 if (strlen($distf) > 0 && strlen($distf_value[$distf_k]) > 0) {
1325 $use_key = strlen($distf_lang[$distf_k]) > 0 ? $distf_lang[$distf_k] : $distf;
1326 $roomparams['features'][$i][$use_key] = $distf_value[$distf_k];
1327 if ($distf_k < 1) {
1328 //check only the first feature
1329 $newfeatures[$i][$use_key] = $distf_value[$distf_k];
1330 }
1331 }
1332 }
1333 }
1334 }
1335
1336 /**
1337 * Store room geo params information.
1338 *
1339 * @since 1.14 (J) - 1.4.0 (WP)
1340 */
1341 $geo = VikBooking::getGeocodingInstance();
1342 $geo_params = $geo->getRoomGeoTransient($pwhereup);
1343 if ($geo_params !== false) {
1344 // make sure the geocoding service was not turned off
1345 $geo_enabled = VikRequest::getInt('geo_enabled', 0, 'request');
1346 if (!$geo_enabled) {
1347 $geo_params->enabled = 0;
1348 }
1349 //
1350 $roomparams['geo'] = $geo_params;
1351 }
1352 //
1353
1354 $roomparamstr = json_encode($roomparams);
1355
1356 jimport('joomla.filesystem.file');
1357 $updpath = VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR;
1358 if (!empty($pcname)) {
1359 if (intval($_FILES['cimg']['error']) == 0 && VikBooking::caniWrite($updpath) && trim($_FILES['cimg']['name'])!="") {
1360 if (@is_uploaded_file($_FILES['cimg']['tmp_name'])) {
1361 $safename = JFile::makeSafe(str_replace(" ", "_", strtolower($_FILES['cimg']['name'])));
1362 if (file_exists($updpath.$safename)) {
1363 $j = 1;
1364 while (file_exists($updpath.$j.$safename)) {
1365 $j++;
1366 }
1367 $pwhere = $updpath.$j.$safename;
1368 } else {
1369 $j = "";
1370 $pwhere = $updpath.$safename;
1371 }
1372 if (!getimagesize($_FILES['cimg']['tmp_name']) || !preg_match("/\.(a?png|jpe?g|bmp|gif|ico|webp)\z/i", $safename)) {
1373 @unlink($pwhere);
1374 $picon = "";
1375 } else {
1376 VikBooking::uploadFile($_FILES['cimg']['tmp_name'], $pwhere);
1377 @chmod($pwhere, 0644);
1378 $picon = $j.$safename;
1379 if ($pautoresize == "1" && !empty($presizeto)) {
1380 $eforj = new vikResizer();
1381 $origmod = $eforj->proportionalImage($pwhere, $updpath.'r_'.$j.$safename, $presizeto, $presizeto);
1382 if ($origmod) {
1383 @unlink($pwhere);
1384 $picon = 'r_'.$j.$safename;
1385 }
1386 }
1387 }
1388 } else {
1389 $picon = "";
1390 }
1391 } else {
1392 $picon = "";
1393 }
1394 //more images
1395 $creativik = new vikResizer();
1396 $bigsdest = $updpath;
1397 $thumbsdest = $updpath;
1398 $dest = $updpath;
1399 $moreimagestr = $pactmoreimgs;
1400 $arrimgs = array();
1401 $captiontexts = array();
1402 $imgcaptions = array();
1403 //captions of uploaded extra images
1404 if (!empty($pactmoreimgs)) {
1405 $sploimgs = explode(';;', $pactmoreimgs);
1406 foreach ($sploimgs as $ki => $oimg) {
1407 if (!empty($oimg)) {
1408 $oldcaption = VikRequest::getString('caption'.$ki, '', 'request', VIKREQUEST_ALLOWHTML);
1409 $imgcaptions[] = $oldcaption;
1410 }
1411 }
1412 }
1413 //
1414 foreach ($pimages['name'] as $kk=>$ci) {
1415 if (!empty($ci)) {
1416 $arrimgs[] = $kk;
1417 $captiontexts[] = isset($pcimgcaption[$kk]) ? $pcimgcaption[$kk] : '';
1418 }
1419 }
1420 foreach ($arrimgs as $ki => $imgk) {
1421 if (strlen(trim($pimages['name'][$imgk]))) {
1422 $filename = JFile::makeSafe(str_replace(" ", "_", strtolower($pimages['name'][$imgk])));
1423 $src = $pimages['tmp_name'][$imgk];
1424 $j = "";
1425 if (file_exists($dest.$filename)) {
1426 $j = rand(171, 1717);
1427 while (file_exists($dest.$j.$filename)) {
1428 $j++;
1429 }
1430 }
1431 $finaldest = $dest.$j.$filename;
1432 $check = getimagesize($pimages['tmp_name'][$imgk]);
1433 if (($check[2] & imagetypes()) && preg_match("/\.(a?png|jpe?g|bmp|gif|ico|webp)\z/i", $filename)) {
1434 if (VikBooking::uploadFile($src, $finaldest)) {
1435 $gimg = $j.$filename;
1436 //orig img
1437 $origmod = true;
1438 if ($pautoresizemore == "1" && !empty($presizetomore)) {
1439 $origmod = $creativik->proportionalImage($finaldest, $bigsdest.'big_'.$j.$filename, $presizetomore, $presizetomore);
1440 } else {
1441 VikBooking::uploadFile($finaldest, $bigsdest.'big_'.$j.$filename, true);
1442 }
1443 //thumb
1444 $thumbsize = VikBooking::getThumbSize();
1445 $thumb = $creativik->proportionalImage($finaldest, $thumbsdest.'thumb_'.$j.$filename, $thumbsize, $thumbsize);
1446 if (!$thumb || !$origmod) {
1447 if (file_exists($bigsdest.'big_'.$j.$filename)) @unlink($bigsdest.'big_'.$j.$filename);
1448 if (file_exists($thumbsdest.'thumb_'.$j.$filename)) @unlink($thumbsdest.'thumb_'.$j.$filename);
1449 VikError::raiseWarning('', 'Error While Uploading the File: '.$pimages['name'][$imgk]);
1450 } else {
1451 $moreimagestr .= $j.$filename.";;";
1452 $imgcaptions[] = $captiontexts[$ki];
1453 }
1454 @unlink($finaldest);
1455 } else {
1456 VikError::raiseWarning('', 'Error While Uploading the File: '.$pimages['name'][$imgk]);
1457 }
1458 } else {
1459 VikError::raiseWarning('', 'Error While Uploading the File: '.$pimages['name'][$imgk]);
1460 }
1461 }
1462 }
1463 //sorting of extra images
1464 $sorted_extraim = array();
1465 $sorted_captions = array();
1466 $extraim_parts = explode(';;', $moreimagestr);
1467 foreach ($pimgsorting as $k => $v) {
1468 $capkey = -1;
1469 if (isset($extraim_parts[$k])) {
1470 $sorted_extraim[] = $v;
1471 foreach ($extraim_parts as $oldk => $oldv) {
1472 if ($oldv == $v) {
1473 $capkey = $oldk;
1474 break;
1475 }
1476 }
1477 }
1478 if (isset($imgcaptions[$capkey])) {
1479 $sorted_captions[] = $imgcaptions[$capkey];
1480 }
1481 }
1482 $tot_sorted_im = count($sorted_extraim);
1483 if ($tot_sorted_im != count($extraim_parts)) {
1484 foreach ($extraim_parts as $k => $v) {
1485 if ($k <= ($tot_sorted_im - 1)) {
1486 continue;
1487 }
1488 $sorted_extraim[] = $v;
1489 if (isset($imgcaptions[$k])) {
1490 $sorted_captions[] = $imgcaptions[$k];
1491 }
1492 }
1493 }
1494 $moreimagestr = implode(';;', $sorted_extraim);
1495 $imgcaptions = $sorted_captions;
1496 //end more images
1497 if (is_array($pccat) && count($pccat)) {
1498 $pccatdef = "";
1499 foreach ($pccat as $ccat) {
1500 if (!empty($ccat)) {
1501 $pccatdef .= $ccat.";";
1502 }
1503 }
1504 } else {
1505 $pccatdef = "";
1506 }
1507 if (is_array($pccarat) && count($pccarat)) {
1508 $pccaratdef = "";
1509 foreach ($pccarat as $ccarat) {
1510 $pccaratdef .= $ccarat.";";
1511 }
1512 } else {
1513 $pccaratdef = "";
1514 }
1515 if (is_array($pcoptional) && count($pcoptional)) {
1516 $pcoptionaldef = "";
1517 foreach ($pcoptional as $coptional) {
1518 $pcoptionaldef .= $coptional.";";
1519 }
1520 } else {
1521 $pcoptionaldef = "";
1522 }
1523 $pcavaildef=($pcavail=="yes" ? "1" : "0");
1524 if ($pfromadult > $ptoadult) {
1525 $pfromadult = 1;
1526 $ptoadult = 1;
1527 }
1528 if ($pfromchild > $ptochild) {
1529 $pfromchild = 1;
1530 $ptochild = 1;
1531 }
1532 $dbo = JFactory::getDBO();
1533 //adults charges/discounts
1534 $adchdisctouch = false;
1535 $q = "SELECT * FROM `#__vikbooking_rooms` WHERE `id`='".$pwhereup."';";
1536 $dbo->setQuery($q);
1537 $dbo->execute();
1538 $oldroom = $dbo->loadAssocList();
1539 $oldroom = $oldroom[0];
1540 if ($oldroom['fromadult'] == $pfromadult && $oldroom['toadult'] == $ptoadult) {
1541 if ($oldroom['toadult'] > 1 && $oldroom['fromadult'] < $oldroom['toadult'] && @count($padultsdiffnum) > 0) {
1542 $startadind = $oldroom['fromadult'] > 0 ? $oldroom['fromadult'] : 1;
1543 for($adi = $startadind; $adi <= $oldroom['toadult']; $adi++) {
1544 foreach ($padultsdiffnum as $kad=>$vad) {
1545 if (intval($vad) == intval($adi) && strlen($padultsdiffval[$kad]) > 0) {
1546 $adchdisctouch = true;
1547 $inschdisc = intval($padultsdiffchdisc[$kad]) == 1 ? 1 : 2;
1548 $insvalpcent = intval($padultsdiffvalpcent[$kad]) == 1 ? 1 : 2;
1549 $inspernight = intval($padultsdiffpernight[$kad]) == 1 ? 1 : 0;
1550 $insvalue = floatval($padultsdiffval[$kad]);
1551 //check if it exists
1552 $q = "SELECT `id` FROM `#__vikbooking_adultsdiff` WHERE `idroom`='".$oldroom['id']."' AND `adults`='".$adi."';";
1553 $dbo->setQuery($q);
1554 $dbo->execute();
1555 if ($dbo->getNumRows() > 0) {
1556 if ($insvalue > 0) {
1557 //update
1558 $q = "UPDATE `#__vikbooking_adultsdiff` SET `chdisc`='".$inschdisc."', `valpcent`='".$insvalpcent."', `value`='".$insvalue."', `pernight`='".$inspernight."' WHERE `idroom`='".$oldroom['id']."' AND `adults`='".$adi."';";
1559 $dbo->setQuery($q);
1560 $dbo->execute();
1561 } else {
1562 //delete
1563 $q = "DELETE FROM `#__vikbooking_adultsdiff` WHERE `idroom`='".$oldroom['id']."' AND `adults`='".$adi."';";
1564 $dbo->setQuery($q);
1565 $dbo->execute();
1566 }
1567 } else {
1568 //insert
1569 $q = "INSERT INTO `#__vikbooking_adultsdiff` (`idroom`,`chdisc`,`valpcent`,`value`,`adults`,`pernight`) VALUES('".$oldroom['id']."', '".$inschdisc."', '".$insvalpcent."', '".$insvalue."', '".$adi."', '".$inspernight."');";
1570 $dbo->setQuery($q);
1571 $dbo->execute();
1572 }
1573 }
1574 }
1575 }
1576 }
1577 } else {
1578 //min and max adults num have changed, delete
1579 $q = "DELETE FROM `#__vikbooking_adultsdiff` WHERE `idroom`='".$oldroom['id']."';";
1580 $dbo->setQuery($q);
1581 $dbo->execute();
1582 }
1583 if ($adchdisctouch == true) {
1584 $app->enqueueMessage(JText::translate('VBUPDROOMADCHDISCSAVED'));
1585 }
1586 //
1587 //check distinctive features if there were any changes
1588 $old_rparams = json_decode($oldroom['params'], true);
1589 $old_rparams = is_array($old_rparams) ? $old_rparams : array();
1590 if (array_key_exists('features', $old_rparams)) {
1591 $oldfeatures = array();
1592 foreach ($old_rparams['features'] as $rnumunit => $oldfeat) {
1593 foreach ($oldfeat as $featname => $featval) {
1594 $oldfeatures[$rnumunit][$featname] = $featval;
1595 break;
1596 }
1597 }
1598 /**
1599 * We reset the sub-unit information to all bookings only in case the new
1600 * number of units is reduced. When we add new units or we modify the contents,
1601 * we keep everything as is for the past reservations.
1602 *
1603 * @since 1.15.2 (J) - 1.5.5 (WP)
1604 */
1605 if ($oldfeatures != $newfeatures && count($newfeatures) < count($oldfeatures)) {
1606 // changes were made to the first index (Room Number by default) of the distinctive features
1607 // set to NULL all the already set roomindexes in bookings
1608 $q = "UPDATE `#__vikbooking_ordersrooms` SET `roomindex`=NULL WHERE `idroom`=".(int)$oldroom['id'].";";
1609 $dbo->setQuery($q);
1610 $dbo->execute();
1611 }
1612 }
1613 //
1614 $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).";";
1615 $dbo->setQuery($q);
1616 $dbo->execute();
1617
1618 /**
1619 * Share availability calendars with other rooms.
1620 *
1621 * @since 1.13
1622 */
1623 // always reset relations for this main room
1624 $q = "DELETE FROM `#__vikbooking_calendars_xref` WHERE `mainroom`={$pwhereup};";
1625 $dbo->setQuery($q);
1626 $dbo->execute();
1627 $newxref = array();
1628 foreach ($pshare_with as $cldroom) {
1629 if (!empty($cldroom)) {
1630 array_push($newxref, (int)$cldroom);
1631 }
1632 }
1633 foreach ($newxref as $cldroom) {
1634 $q = "INSERT INTO `#__vikbooking_calendars_xref` (`mainroom`, `childroom`) VALUES ({$pwhereup}, {$cldroom});";
1635 $dbo->setQuery($q);
1636 $dbo->execute();
1637 }
1638
1639 /**
1640 * Room upgrade options.
1641 *
1642 * @since 1.16.0 (J) - 1.6.0 (WP)
1643 */
1644 $room_upgrade_options = [];
1645 $room_upgrade = VikRequest::getInt('room_upgrade', 0, 'request');
1646 $upgrade_rooms = VikRequest::getVar('upgrade_rooms', array());
1647 $upgrade_discount = VikRequest::getFloat('upgrade_discount', 0, 'request');
1648 if ($room_upgrade && is_array($upgrade_rooms) && count($upgrade_rooms)) {
1649 $upgrade_rooms = array_map(function($rid) {
1650 return (int)$rid;
1651 }, $upgrade_rooms);
1652
1653 $room_upgrade_options = [
1654 'rooms' => $upgrade_rooms,
1655 'discount' => $upgrade_discount,
1656 ];
1657 }
1658 $config->set('room_upgrade_options_' . $pwhereup, json_encode($room_upgrade_options));
1659
1660 /**
1661 * Maximum advance booking offset can be defined at room-level. TODO
1662 *
1663 * @since 1.16.3 (J) - 1.6.3 (WP)
1664 */
1665 $pmax_adv_notice_room = VikRequest::getInt('max_adv_notice_room', 0, 'request');
1666 $pmaxdate = VikRequest::getInt('maxdate', 0, 'request');
1667 $pmaxdateinterval = VikRequest::getString('maxdateinterval', '', 'request');
1668 $maxdate_str = '';
1669 if ($pmax_adv_notice_room && $pmaxdate > 0) {
1670 $pmaxdateinterval = !in_array($pmaxdateinterval, array('d', 'w', 'm', 'y')) ? 'y' : $pmaxdateinterval;
1671 $maxdate_str = '+' . $pmaxdate . $pmaxdateinterval;
1672 }
1673 $config->set("room_{$pwhereup}_max_adv_notice", $maxdate_str);
1674
1675 $app->enqueueMessage(JText::translate('VBUPDROOMOK'));
1676 }
1677
1678 if ($pupdatecaption == 1 || $stay === true) {
1679 $app->redirect("index.php?option=com_vikbooking&task=editroom&cid[]=".$pwhereup);
1680 } else {
1681 $app->redirect("index.php?option=com_vikbooking&task=rooms");
1682 }
1683 }
1684
1685 public function modavail() {
1686 if (!JSession::checkToken() && !JSession::checkToken('get')) {
1687 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
1688 }
1689 $cid = VikRequest::getVar('cid', array(0));
1690 $room = $cid[0];
1691 if (!empty($room)) {
1692 $dbo = JFactory::getDBO();
1693 $q = "SELECT `avail` FROM `#__vikbooking_rooms` WHERE `id`=".$dbo->quote($room).";";
1694 $dbo->setQuery($q);
1695 $dbo->execute();
1696 $get = $dbo->loadAssocList();
1697 $q = "UPDATE `#__vikbooking_rooms` SET `avail`='".(intval($get[0]['avail'])==1 ? 0 : 1)."' WHERE `id`=".$dbo->quote($room).";";
1698 $dbo->setQuery($q);
1699 $dbo->execute();
1700 }
1701 $mainframe = JFactory::getApplication();
1702 $mainframe->redirect("index.php?option=com_vikbooking&task=rooms");
1703 }
1704
1705 public function removeroom() {
1706 if (!JSession::checkToken()) {
1707 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
1708 }
1709 $ids = VikRequest::getVar('cid', array(0));
1710 if (@count($ids)) {
1711 $dbo = JFactory::getDBO();
1712 foreach ($ids as $d) {
1713 $q = "DELETE FROM `#__vikbooking_rooms` WHERE `id`=".$dbo->quote($d).";";
1714 $dbo->setQuery($q);
1715 $dbo->execute();
1716 $q = "DELETE FROM `#__vikbooking_dispcost` WHERE `idroom`=".$dbo->quote($d).";";
1717 $dbo->setQuery($q);
1718 $dbo->execute();
1719 }
1720 }
1721 $mainframe = JFactory::getApplication();
1722 $mainframe->redirect("index.php?option=com_vikbooking&task=rooms");
1723 }
1724
1725 public function tariffs() {
1726 VikBookingHelper::printHeader("fares");
1727
1728 VikRequest::setVar('view', VikRequest::getCmd('view', 'tariffs'));
1729
1730 parent::display();
1731
1732 if (VikBooking::showFooter()) {
1733 VikBookingHelper::printFooter();
1734 }
1735 }
1736
1737 public function removetariffs() {
1738 $ids = VikRequest::getVar('cid', array(0));
1739 $proomid = VikRequest::getInt('roomid', '', 'request');
1740 if (@count($ids)) {
1741 $dbo = JFactory::getDBO();
1742 foreach ($ids as $r) {
1743 $x=explode(";", $r);
1744 foreach ($x as $rm) {
1745 if (!empty($rm)) {
1746 $q = "DELETE FROM `#__vikbooking_dispcost` WHERE `id`=".$dbo->quote($rm).";";
1747 $dbo->setQuery($q);
1748 $dbo->execute();
1749 }
1750 }
1751 }
1752 }
1753 $mainframe = JFactory::getApplication();
1754 $mainframe->redirect("index.php?option=com_vikbooking&task=tariffs&cid[]=".$proomid);
1755 }
1756
1757 public function editbusy() {
1758 VikBookingHelper::printHeader("8");
1759
1760 VikRequest::setVar('view', VikRequest::getCmd('view', 'editbusy'));
1761
1762 parent::display();
1763
1764 if (VikBooking::showFooter()) {
1765 VikBookingHelper::printFooter();
1766 }
1767 }
1768
1769 public function updatebusy()
1770 {
1771 $this->do_updatebusy();
1772 }
1773
1774 public function updatebusydoinv()
1775 {
1776 $this->do_updatebusy('geninvoices');
1777 }
1778
1779 private function do_updatebusy($callback = '')
1780 {
1781 $pidorder = VikRequest::getInt('idorder', 0, 'request');
1782 $pcheckindate = VikRequest::getString('checkindate', '', 'request');
1783 $pcheckoutdate = VikRequest::getString('checkoutdate', '', 'request');
1784 $pcheckinh = VikRequest::getString('checkinh', '', 'request');
1785 $pcheckinm = VikRequest::getString('checkinm', '', 'request');
1786 $pcheckouth = VikRequest::getString('checkouth', '', 'request');
1787 $pcheckoutm = VikRequest::getString('checkoutm', '', 'request');
1788 $pcustdata = VikRequest::getString('custdata', '', 'request');
1789 $pareprices = VikRequest::getString('areprices', '', 'request');
1790 $ptotpaid = VikRequest::getString('totpaid', '', 'request');
1791 $prefund = VikRequest::getString('refund', '', 'request');
1792 $pfrominv = VikRequest::getInt('frominv', '', 'request');
1793 $pvcm = VikRequest::getInt('vcm', '', 'request');
1794 $pgoto = VikRequest::getString('goto', '', 'request');
1795 $pextracn = VikRequest::getVar('extracn', []);
1796 $pextracc = VikRequest::getVar('extracc', []);
1797 $pextractx = VikRequest::getVar('extractx', []);
1798 /**
1799 * This is a "foreign key" integer value useful for other Vik plugins
1800 * to store custom extra services within a VBO reservation. Another
1801 * custom value "extra foreign data" (extracdata) is added. We also
1802 * support a "type" string useful for VCM to determine the type of service.
1803 *
1804 * @since 1.16.0 (J) - 1.6.0 (WP)
1805 * @since 1.16.1 (J) - 1.6.1 (WP) added the "type" string.
1806 */
1807 $pextractype = VikRequest::getVar('extractype', []);
1808 $pextracfk = VikRequest::getVar('extracfk', []);
1809 $pextracdata = VikRequest::getVar('extracdata', [], 'request', 'array', VIKREQUEST_ALLOWRAW);
1810
1811 $dbo = JFactory::getDbo();
1812 $user = JFactory::getUser();
1813 $app = JFactory::getApplication();
1814
1815 // availability helper
1816 $av_helper = VikBooking::getAvailabilityInstance();
1817
1818 $actnow = time();
1819 $nowdf = VikBooking::getDateFormat(true);
1820 if ($nowdf == "%d/%m/%Y") {
1821 $df = 'd/m/Y';
1822 } elseif ($nowdf == "%m/%d/%Y") {
1823 $df = 'm/d/Y';
1824 } else {
1825 $df = 'Y/m/d';
1826 }
1827
1828 $q = "SELECT * FROM `#__vikbooking_orders` WHERE `id`=" . $pidorder;
1829 $dbo->setQuery($q, 0, 1);
1830 $dbo->execute();
1831 if (!$dbo->getNumRows()) {
1832 $app->redirect("index.php?option=com_vikbooking&task=rooms");
1833 exit;
1834 }
1835
1836 $ord = $dbo->loadAssoc();
1837
1838 $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;";
1839 $dbo->setQuery($q);
1840 $dbo->execute();
1841 $ordersrooms = $dbo->loadAssocList();
1842
1843 // do not touch this array property because it's used by VCM
1844 $ord['rooms_info'] = $ordersrooms;
1845
1846 // room stay dates in case of split stay
1847 $room_stay_dates = [];
1848 if ($ord['split_stay']) {
1849 if ($ord['status'] == 'confirmed') {
1850 $room_stay_dates = $av_helper->loadSplitStayBusyRecords($ord['id']);
1851 } else {
1852 $room_stay_dates = VBOFactory::getConfig()->getArray('split_stay_' . $ord['id'], []);
1853 }
1854 // immediately count the number of nights of stay for each split room
1855 foreach ($room_stay_dates as $sps_r_k => $sps_r_v) {
1856 if (!empty($sps_r_v['checkin_ts']) && !empty($sps_r_v['checkout_ts'])) {
1857 // overwrite values for compatibility with non-confirmed bookings
1858 $sps_r_v['checkin'] = $sps_r_v['checkin_ts'];
1859 $sps_r_v['checkout'] = $sps_r_v['checkout_ts'];
1860 }
1861 $sps_r_v['nights'] = $av_helper->countNightsOfStay($sps_r_v['checkin'], $sps_r_v['checkout']);
1862 // overwrite the whole array
1863 $room_stay_dates[$sps_r_k] = $sps_r_v;
1864 }
1865 }
1866
1867 // package or custom rate
1868 $is_package = !empty($ord['pkg']) ? true : false;
1869 $is_cust_cost = false;
1870 foreach ($ordersrooms as $kor => $or) {
1871 if ($is_package !== true && !empty($or['cust_cost']) && $or['cust_cost'] > 0.00) {
1872 $is_cust_cost = true;
1873 break;
1874 }
1875 }
1876
1877 // room switching
1878 $toswitch = array();
1879 $idbooked = array();
1880 $rooms_units = array();
1881
1882 $q = "SELECT `id`,`name`,`units` FROM `#__vikbooking_rooms`;";
1883 $dbo->setQuery($q);
1884 $dbo->execute();
1885 $all_rooms = $dbo->loadAssocList();
1886 foreach ($all_rooms as $rr) {
1887 $rooms_units[$rr['id']]['name'] = $rr['name'];
1888 $rooms_units[$rr['id']]['units'] = $rr['units'];
1889 }
1890
1891 foreach ($ordersrooms as $ind => $or) {
1892 $switch_command = VikRequest::getString('switch_'.$or['id'], '', 'request');
1893 if (!empty($switch_command) && intval($switch_command) != $or['idroom'] && array_key_exists(intval($switch_command), $rooms_units)) {
1894 if (!isset($idbooked[$or['idroom']])) {
1895 $idbooked[$or['idroom']] = 0;
1896 }
1897 $idbooked[$or['idroom']]++;
1898 $orkey = count($toswitch);
1899 $toswitch[$orkey]['from'] = $or['idroom'];
1900 $toswitch[$orkey]['to'] = intval($switch_command);
1901 $toswitch[$orkey]['record'] = $or;
1902 $toswitch[$orkey]['record_ind'] = $ind;
1903 }
1904 }
1905
1906 if (count($toswitch) && (!empty($ordersrooms[0]['idtar']) || $is_package || $is_cust_cost)) {
1907 foreach ($toswitch as $ksw => $rsw) {
1908 $plusunit = array_key_exists($rsw['to'], $idbooked) ? $idbooked[$rsw['to']] : 0;
1909 $room_checkin = $ord['checkin'];
1910 $room_checkout = $ord['checkout'];
1911 if ($ord['split_stay'] && count($room_stay_dates) && isset($room_stay_dates[$rsw['record_ind']]) && $room_stay_dates[$rsw['record_ind']]['idroom'] == $rsw['from']) {
1912 $room_checkin = $room_stay_dates[$rsw['record_ind']]['checkin'];
1913 $room_checkout = $room_stay_dates[$rsw['record_ind']]['checkout'];
1914 }
1915 if (!VikBooking::roomBookable($rsw['to'], ($rooms_units[$rsw['to']]['units'] + $plusunit), $room_checkin, $room_checkout)) {
1916 // the room is not available
1917 unset($toswitch[$ksw]);
1918 VikError::raiseWarning('', JText::sprintf('VBSWITCHRERR', $rsw['record']['name'], $rooms_units[$rsw['to']]['name']));
1919 }
1920 }
1921 if (count($toswitch)) {
1922 // reset first record rate
1923 reset($ordersrooms);
1924 $q = "UPDATE `#__vikbooking_ordersrooms` SET `idtar`=NULL,`roomindex`=NULL,`room_cost`=NULL WHERE `id`=".$ordersrooms[0]['id'].";";
1925 $dbo->setQuery($q);
1926 $dbo->execute();
1927
1928 // flag for invoking VCM at a proper time
1929 $vcm_should_run = false;
1930
1931 foreach ($toswitch as $ksw => $rsw) {
1932 // update room reservation record
1933 $q = "UPDATE `#__vikbooking_ordersrooms` SET `idroom`=".$rsw['to'].",`idtar`=NULL,`roomindex`=NULL,`room_cost`=NULL WHERE `id`=".$rsw['record']['id'].";";
1934 $dbo->setQuery($q);
1935 $dbo->execute();
1936 $app->enqueueMessage(JText::sprintf('VBSWITCHROK', $rsw['record']['name'], $rooms_units[$rsw['to']]['name']));
1937
1938 // update Notes field for this booking to keep track of the previous room that was assigned
1939 $prev_room_name = array_key_exists($rsw['from'], $rooms_units) ? $rooms_units[$rsw['from']]['name'] : '';
1940 if (!empty($prev_room_name)) {
1941 $new_notes = JText::sprintf('VBOPREVROOMMOVED', $prev_room_name, date($df.' H:i:s'))."\n".$ord['adminnotes'];
1942 $q = "UPDATE `#__vikbooking_orders` SET `adminnotes`=".$dbo->quote($new_notes)." WHERE `id`=".(int)$ord['id'].";";
1943 $dbo->setQuery($q);
1944 $dbo->execute();
1945 }
1946
1947 if ($ord['status'] == 'confirmed') {
1948 // update room record in _busy
1949 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'])) {
1950 // in case of a split stay it is fundamental to update the exact busy record ID
1951 $q = "UPDATE `#__vikbooking_busy` SET `idroom`=" . $rsw['to'] . " WHERE `id`=" . (int)$room_stay_dates[$rsw['record_ind']]['id'];
1952 $dbo->setQuery($q);
1953 $dbo->execute();
1954 } else {
1955 // regular processing of a room ID for a reservation, no matter which one, we switch it
1956 $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;";
1957 $dbo->setQuery($q);
1958 $dbo->execute();
1959 if ($dbo->getNumRows() == 1) {
1960 $cur_busy = $dbo->loadAssocList();
1961 $q = "UPDATE `#__vikbooking_busy` SET `idroom`=".$rsw['to']." WHERE `id`=".$cur_busy[0]['id']." AND `idroom`=".$cur_busy[0]['idroom']." LIMIT 1;";
1962 $dbo->setQuery($q);
1963 $dbo->execute();
1964 }
1965 }
1966
1967 /**
1968 * Make sure to take care of the shared calendars before invoking VCM.
1969 * Register the flag to run the Channel Manager and leave the booking
1970 * array unchanged to run just one update request.
1971 *
1972 * @since 1.16.0 (J) - 1.6.0 (WP)
1973 */
1974 $vcm_should_run = true;
1975
1976 } elseif ($ord['status'] == 'standby') {
1977 // remove record in _tmplock
1978 $q = "DELETE FROM `#__vikbooking_tmplock` WHERE `idorder`=" . intval($ord['id']) . ";";
1979 $dbo->setQuery($q);
1980 $dbo->execute();
1981 // check if it's a split stay
1982 if ($ord['split_stay'] && count($room_stay_dates) && isset($room_stay_dates[$rsw['record_ind']]) && $room_stay_dates[$rsw['record_ind']]['idroom'] == $rsw['from']) {
1983 // update room ID in split stay data
1984 $room_stay_dates[$rsw['record_ind']]['idroom'] = $rsw['to'];
1985 // update configuration record
1986 VBOFactory::getConfig()->set('split_stay_' . $ord['id'], json_encode($room_stay_dates));
1987 }
1988 }
1989 }
1990
1991 // unset any previously booked room due to calendar sharing
1992 VikBooking::cleanSharedCalendarsBusy($ord['id']);
1993 // check if some of the rooms booked have shared calendars
1994 VikBooking::updateSharedCalendars($ord['id']);
1995
1996 if ($vcm_should_run) {
1997 // we can now run the Channel Manager after having updated the shared calendars
1998 $vcm_autosync = VikBooking::vcmAutoUpdate();
1999 if ($vcm_autosync > 0) {
2000 $vcm_obj = VikBooking::getVcmInvoker();
2001 $vcm_obj->setOids(array($ord['id']))->setSyncType('modify')->setOriginalBooking($ord);
2002 $sync_result = $vcm_obj->doSync();
2003 if ($sync_result === false) {
2004 $vcm_err = $vcm_obj->getError();
2005 VikError::raiseWarning('', JText::translate('VBCHANNELMANAGERRESULTKO').' <a href="index.php?option=com_vikchannelmanager" target="_blank">'.JText::translate('VBCHANNELMANAGEROPEN').'</a> '.(strlen($vcm_err) > 0 ? '('.$vcm_err.')' : ''));
2006 }
2007 } elseif (file_exists(VCM_SITE_PATH . DIRECTORY_SEPARATOR . "helpers" . DIRECTORY_SEPARATOR . "synch.vikbooking.php")) {
2008 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>');
2009 }
2010 }
2011
2012 //Booking History
2013 VikBooking::getBookingHistoryInstance()->setBid($ord['id'])->store('MB', "({$user->name}) " . VikBooking::getLogBookingModification($ord));
2014 //
2015 $app->redirect("index.php?option=com_vikbooking&task=editbusy".($pvcm == 1 ? '&vcm=1' : '').($pfrominv == 1 ? '&frominv=1' : '')."&cid[]=".$ord['id'].($pgoto == 'overv' ? "&goto=overv" : ""));
2016 exit;
2017 }
2018 }
2019
2020 // update booking data
2021 $first = VikBooking::getDateTimestamp($pcheckindate, $pcheckinh, $pcheckinm);
2022 $second = VikBooking::getDateTimestamp($pcheckoutdate, $pcheckouth, $pcheckoutm);
2023 if ($second <= $first) {
2024 VikError::raiseWarning('', JText::translate('ERRPREV'));
2025 $app->redirect("index.php?option=com_vikbooking&task=editbusy".($pvcm == 1 ? '&vcm=1' : '').($pfrominv == 1 ? '&frominv=1' : '')."&cid[]=".$ord['id'].($pgoto == 'overv' ? "&goto=overv" : ""));
2026 exit;
2027 }
2028
2029 $secdiff = $second - $first;
2030 $daysdiff = $secdiff / 86400;
2031 if (is_int($daysdiff)) {
2032 if ($daysdiff < 1) {
2033 $daysdiff = 1;
2034 }
2035 } else {
2036 if ($daysdiff < 1) {
2037 $daysdiff = 1;
2038 } else {
2039 $sum = floor($daysdiff) * 86400;
2040 $newdiff = $secdiff - $sum;
2041 $maxhmore = VikBooking::getHoursMoreRb() * 3600;
2042 if ($maxhmore >= $newdiff) {
2043 $daysdiff = floor($daysdiff);
2044 } else {
2045 $daysdiff = ceil($daysdiff);
2046 }
2047 }
2048 }
2049
2050 $groupdays = VikBooking::getGroupDays($first, $second, $daysdiff);
2051 $opertwounits = true;
2052
2053 $units_counter = array();
2054 $prm_room_oid = VikRequest::getInt('rm_room_oid', 0, 'request');
2055 foreach ($ordersrooms as $ind => $or) {
2056 if (!isset($units_counter[$or['idroom']])) {
2057 $units_counter[$or['idroom']] = -1;
2058 }
2059 if ($prm_room_oid != $or['id']) {
2060 $units_counter[$or['idroom']]++;
2061 }
2062 }
2063
2064 /**
2065 * Split stay data for booking and rooms different stay dates.
2066 *
2067 * @since 1.16.0 (J) - 1.6.0 (WP)
2068 */
2069 $split_stay_data = VikRequest::getVar('split_stay_data', array());
2070 $room_modify_dates = VikRequest::getVar('room_modify_dates', array());
2071 $split_stay_checkins = [];
2072 $split_stay_checkouts = [];
2073
2074 if ($ord['split_stay'] && !empty($split_stay_data)) {
2075 // make sure the min/max split stay dates match the booking global dates
2076 foreach ($split_stay_data as $sps_k => $split_stay) {
2077 if (empty($split_stay['checkin']) || empty($split_stay['checkout'])) {
2078 continue;
2079 }
2080 $new_room_checkin = VikBooking::getDateTimestamp($split_stay['checkin'], $pcheckinh, $pcheckinm);
2081 $new_room_checkout = VikBooking::getDateTimestamp($split_stay['checkout'], $pcheckouth, $pcheckoutm);
2082 $split_stay_checkins[] = $new_room_checkin;
2083 $split_stay_checkouts[] = $new_room_checkout;
2084 if (isset($room_stay_dates[$sps_k])) {
2085 $room_stay_dates[$sps_k]['new_checkin'] = $new_room_checkin;
2086 $room_stay_dates[$sps_k]['new_checkout'] = $new_room_checkout;
2087 $room_stay_dates[$sps_k]['new_nights'] = $av_helper->countNightsOfStay($new_room_checkin, $new_room_checkout);
2088 }
2089 }
2090 if (empty($split_stay_checkins) || empty($split_stay_checkouts)) {
2091 // error
2092 VikError::raiseWarning('', 'Error, split stay rooms must have their own stay dates matching the booking check-in and check-out dates');
2093 $app->redirect("index.php?option=com_vikbooking&task=editbusy".($pvcm == 1 ? '&vcm=1' : '').($pfrominv == 1 ? '&frominv=1' : '')."&cid[]=".$ord['id'].($pgoto == 'overv' ? "&goto=overv" : ""));
2094 exit;
2095 }
2096 if (min($split_stay_checkins) != $first) {
2097 // error
2098 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)));
2099 $app->redirect("index.php?option=com_vikbooking&task=editbusy".($pvcm == 1 ? '&vcm=1' : '').($pfrominv == 1 ? '&frominv=1' : '')."&cid[]=".$ord['id'].($pgoto == 'overv' ? "&goto=overv" : ""));
2100 exit;
2101 }
2102 if (max($split_stay_checkouts) != $second) {
2103 // error
2104 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)));
2105 $app->redirect("index.php?option=com_vikbooking&task=editbusy".($pvcm == 1 ? '&vcm=1' : '').($pfrominv == 1 ? '&frominv=1' : '')."&cid[]=".$ord['id'].($pgoto == 'overv' ? "&goto=overv" : ""));
2106 exit;
2107 }
2108 }
2109
2110 /**
2111 * We need to make sure the sub-units of the rooms involved are not being overbooked.
2112 * In this case, we simply raise an error message by not stopping the process.
2113 *
2114 * @since 1.13.0 (J) - 1.3.0 (WP)
2115 */
2116 $subunits_involved_bids = array();
2117 //
2118
2119 foreach ($ordersrooms as $ind => $or) {
2120 $num = $ind + 1;
2121 $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'] . ";";
2122 $dbo->setQuery($check);
2123 $dbo->execute();
2124 if ($dbo->getNumRows() > 0) {
2125 $busy = $dbo->loadAssocList();
2126
2127 // determine the days to consider for the count of the availability
2128 $use_groupdays = $groupdays;
2129 $room_checkin = $first;
2130 $room_checkout = $second;
2131 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'])) {
2132 $use_groupdays = VikBooking::getGroupDays($room_stay_dates[$ind]['new_checkin'], $room_stay_dates[$ind]['new_checkout'], $room_stay_dates[$ind]['new_nights']);
2133 $room_checkin = $room_stay_dates[$ind]['new_checkin'];
2134 $room_checkout = $room_stay_dates[$ind]['new_checkout'];
2135 } elseif (!$ord['split_stay'] && !$ord['closure'] && $ord['roomsnum'] > 1 && $ord['days'] > 1 && $ord['status'] == 'confirmed' && VikRequest::getInt('room_modify_dates' . $ind, 0, 'request')) {
2136 // room may have individual stay dates
2137 if (isset($room_modify_dates[$ind]) && !empty($room_modify_dates[$ind]['checkin']) && !empty($room_modify_dates[$ind]['checkout'])) {
2138 // get new stay dates (if changed)
2139 $new_room_checkin = VikBooking::getDateTimestamp($room_modify_dates[$ind]['checkin'], $pcheckinh, $pcheckinm);
2140 $new_room_checkout = VikBooking::getDateTimestamp($room_modify_dates[$ind]['checkout'], $pcheckouth, $pcheckoutm);
2141 $use_groupdays = VikBooking::getGroupDays($new_room_checkin, $new_room_checkout, $av_helper->countNightsOfStay($new_room_checkin, $new_room_checkout));
2142 $room_checkin = $new_room_checkin;
2143 $room_checkout = $new_room_checkout;
2144 }
2145 }
2146
2147 foreach ($use_groupdays as $gday) {
2148 // count units booked for each stay timestamp
2149 $bfound = 0;
2150 foreach ($busy as $bu) {
2151 if ($gday >= $bu['checkin'] && $gday <= $bu['realback']) {
2152 // increase units booked found
2153 $bfound++;
2154 // keep track of the IDs involved to avoid overbooking for the sub-units
2155 if (!empty($or['roomindex'])) {
2156 if (!isset($subunits_involved_bids[$bu['idorder']])) {
2157 $subunits_involved_bids[$bu['idorder']] = array();
2158 }
2159 array_push($subunits_involved_bids[$bu['idorder']], array(
2160 'idroom' => $or['idroom'],
2161 'roomindex' => $or['roomindex'],
2162 ));
2163 }
2164 }
2165 }
2166
2167 // units booked must be greater than zero in case of split stays involving the same room multiple times
2168 $detract_multi_units = $units_counter[$or['idroom']];
2169 if ($ord['split_stay'] && count($room_stay_dates) && isset($room_stay_dates[$ind]) && $room_stay_dates[$ind]['idroom'] == $or['idroom']) {
2170 // split stay bookings never occupy the same room on the same dates
2171 $detract_multi_units = 0;
2172 }
2173 if ($bfound > 0 && $bfound >= ($or['units'] - $detract_multi_units)) {
2174 $opertwounits = false;
2175 break 2;
2176 }
2177
2178 // make sure the room is not temporarily locked while waiting to be paid/confirmed
2179 if ($ord['status'] == 'confirmed' && !VikBooking::roomNotLocked($or['idroom'], $or['units'], $room_checkin, $room_checkout)) {
2180 $opertwounits = false;
2181 break 2;
2182 }
2183 }
2184 }
2185 }
2186
2187 /**
2188 * Make sure no sub-units are overbooked even though the main room is available.
2189 *
2190 * @since 1.13.0 (J) - 1.3.0 (WP)
2191 */
2192 if ($opertwounits === true && count($subunits_involved_bids)) {
2193 $subunits_involved_bids = array_unique($subunits_involved_bids);
2194 // grab all the information about the bids involved and the related rooms/indexes
2195 $q = "SELECT `or`.`idorder`, `or`.`idroom`, `or`.`roomindex`, `o`.`checkin`, `o`.`checkout`, `r`.`name`, `r`.`params`
2196 FROM `#__vikbooking_ordersrooms` AS `or` LEFT JOIN `#__vikbooking_orders` AS `o` ON `or`.`idorder`=`o`.`id`
2197 LEFT JOIN `#__vikbooking_rooms` AS `r` ON `or`.`idroom`=`r`.`id`
2198 WHERE `or`.`idorder` IN (" . implode(', ', array_keys($subunits_involved_bids)) . ");";
2199 $dbo->setQuery($q);
2200 $dbo->execute();
2201 if ($dbo->getNumRows()) {
2202 $involved_data = $dbo->loadAssocList();
2203 foreach ($involved_data as $invb) {
2204 if (empty($invb['roomindex'])) {
2205 continue;
2206 }
2207 foreach ($subunits_involved_bids[$invb['idorder']] as $bookedindex) {
2208 if ($bookedindex['idroom'] == $invb['idroom'] && $bookedindex['roomindex'] == $invb['roomindex']) {
2209 // this same sub-unit is occupied by this booking ID: raise an error message to inform the administrator
2210 $subunit_name = $invb['roomindex'];
2211 $room_params = json_decode($invb['params'], true);
2212 if (is_array($room_params) && isset($room_params['features']) && @count($room_params['features'])) {
2213 foreach ($room_params['features'] as $rind => $rfeatures) {
2214 if ($rind == $invb['roomindex']) {
2215 foreach ($rfeatures as $fname => $fval) {
2216 if (strlen($fval)) {
2217 $subunit_name = '#' . $rind . ' - ' . JText::translate($fname) . ': ' . $fval;
2218 break;
2219 }
2220 }
2221 }
2222 }
2223 }
2224 $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>';
2225 VikError::raiseWarning('', JText::sprintf('VBOSUBUNITOVERBOOKEDERR', $subunit_name, $invb['name'], date($df, $invb['checkin']), date($df, $invb['checkout']), $invb['idorder']) . $adjust_link);
2226 }
2227 }
2228 }
2229 }
2230 }
2231
2232 $forcebooking = VikRequest::getInt('forcebooking', 0, 'request');
2233 if ($opertwounits === true || $forcebooking) {
2234 // update dates, customer information, amount paid and busy records before checking the rates
2235 $turnover_secs = VikBooking::getHoursRoomAvail() * 3600;
2236 $realback = $turnover_secs + $second;
2237
2238 $newtotalpaid = strlen($ptotpaid) > 0 ? floatval($ptotpaid) : "";
2239 $newrefund = strlen($prefund) > 0 ? floatval($prefund) : null;
2240 $roomsnum = $ord['roomsnum'];
2241
2242 // add room to existing booking
2243 $room_added = false;
2244 $padd_room_id = VikRequest::getInt('add_room_id', '', 'request');
2245 $padd_room_adults = VikRequest::getInt('add_room_adults', 2, 'request');
2246 $padd_room_children = VikRequest::getInt('add_room_children', 0, 'request');
2247 $padd_room_fname = VikRequest::getString('add_room_fname', '', 'request');
2248 $padd_room_lname = VikRequest::getString('add_room_lname', '', 'request');
2249 $padd_room_price = VikRequest::getFloat('add_room_price', 0, 'request');
2250 $paliq_add_room = VikRequest::getInt('aliq_add_room', 0, 'request');
2251 if ($padd_room_id > 0 && ($padd_room_adults + $padd_room_children) > 0) {
2252 // no need to re-validate the availability for this new room, as it was made via JS in the View.
2253 // increase the rooms number for later update, and insert the new room record
2254 $roomsnum++;
2255 $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').");";
2256 $dbo->setQuery($q);
2257 $dbo->execute();
2258 $room_added = true;
2259 }
2260
2261 // remove room from existing booking
2262 $room_removed = false;
2263 $room_removed_index = null;
2264 if ($prm_room_oid > 0 && $roomsnum > 1) {
2265 // check if the requested room record exists for removal
2266 $q = "SELECT * FROM `#__vikbooking_ordersrooms` WHERE `id`=".$prm_room_oid." AND `idorder`=".$ord['id'].";";
2267 $dbo->setQuery($q);
2268 $dbo->execute();
2269 if ($dbo->getNumRows() == 1) {
2270 $room_before_rm = $dbo->loadAssoc();
2271 // decrease the rooms number for later update, and remove the requested room record
2272 $roomsnum--;
2273 // find the index of this room in the current list before removal
2274 foreach ($ordersrooms as $kor => $or) {
2275 if ($or['id'] == $prm_room_oid) {
2276 $room_removed_index = $kor;
2277 break;
2278 }
2279 }
2280 // go ahead with the deletion of the room record
2281 $q = "DELETE FROM `#__vikbooking_ordersrooms` WHERE `id`=".$prm_room_oid." AND `idorder`=".$ord['id']." LIMIT 1;";
2282 $dbo->setQuery($q);
2283 $dbo->execute();
2284 $room_removed = $room_before_rm['idroom'];
2285 }
2286 }
2287
2288 if ($ord['split_stay'] && !empty($split_stay_data) && count($split_stay_checkins) && ($room_added !== false || $room_removed !== false)) {
2289 // split stay booking (even if only 1 room left) and one room was either added or removed: set new global stay dates
2290 if ($room_removed !== false && isset($room_removed_index) && isset($split_stay_checkins[$room_removed_index])) {
2291 // exclude the split stay dates of this room that was just removed
2292 unset($split_stay_checkins[$room_removed_index], $split_stay_checkouts[$room_removed_index]);
2293 }
2294 if (count($split_stay_checkins) && count($split_stay_checkouts)) {
2295 // if we still have rooms, and we should, update the booking global stay dates
2296 $first = min($split_stay_checkins);
2297 $second = max($split_stay_checkouts);
2298 $daysdiff = $av_helper->countNightsOfStay($first, $second);
2299 }
2300 }
2301
2302 // update booking's basic information (customer data, dates, tot paid, number of rooms, refund)
2303 $basic_booking = new stdClass;
2304 $basic_booking->id = $ord['id'];
2305 $basic_booking->custdata = $pcustdata;
2306 $basic_booking->days = (int)$daysdiff;
2307 $basic_booking->checkin = $first;
2308 $basic_booking->checkout = $second;
2309 if (strlen($newtotalpaid) > 0) {
2310 $basic_booking->totpaid = $newtotalpaid;
2311 }
2312 $basic_booking->roomsnum = (int)$roomsnum;
2313 if ($newrefund !== null) {
2314 $basic_booking->refund = $newrefund;
2315 }
2316 if ($ord['split_stay'] && $roomsnum < 2 && $room_removed !== false) {
2317 // there is no point in keep treating this reservation as a split stay
2318 $basic_booking->split_stay = 0;
2319 }
2320 $dbo->updateObject('#__vikbooking_orders', $basic_booking, 'id');
2321
2322 // Booking History log for new amount paid (payment update)
2323 if ($newtotalpaid > 0 && $newtotalpaid > (float)$ord['totpaid']) {
2324 $extra_data = new stdClass;
2325 $extra_data->amount_paid = ($newtotalpaid - (float)$ord['totpaid']);
2326 VikBooking::getBookingHistoryInstance()->setBid($ord['id'])->setExtraData($extra_data)->store('PU', JText::sprintf('VBOPREVAMOUNTPAID', VikBooking::numberFormat((float)$ord['totpaid'])));
2327 }
2328
2329 // booking history log for new refund amount
2330 if ($newrefund !== null && $newrefund != (float)$ord['refund']) {
2331 // update current refund value
2332 $ord['refund'] = $newrefund;
2333 // store event
2334 VikBooking::getBookingHistoryInstance()->setBid($ord['id'])->setExtraData(null)->store('RU', JText::sprintf('VBO_NEWREFUND_AMOUNT', VikBooking::numberFormat($ord['refund']), VikBooking::numberFormat($newrefund)));
2335 }
2336
2337 // update busy records
2338 if ($ord['status'] == 'confirmed') {
2339 $allbusy = [];
2340 if ($ord['split_stay'] && !empty($split_stay_data)) {
2341 // in case of split stay we need to update the busy records according to the nights selected
2342 foreach ($split_stay_data as $sps_k => $split_stay) {
2343 if (empty($split_stay['idbusy']) || empty($split_stay['checkin']) || empty($split_stay['checkout'])) {
2344 // missing data
2345 continue;
2346 }
2347 // get selected dates
2348 $room_checkin = VikBooking::getDateTimestamp($split_stay['checkin'], $pcheckinh, $pcheckinm);
2349 $room_checkout = VikBooking::getDateTimestamp($split_stay['checkout'], $pcheckouth, $pcheckoutm);
2350 $room_realback = $turnover_secs + $room_checkout;
2351 // update the exact record
2352 $q = "UPDATE `#__vikbooking_busy` SET `checkin`=" . $room_checkin . ", `checkout`=" . $room_checkout . ", `realback`=" . $room_realback . " WHERE `id`=" . (int)$split_stay['idbusy'] . ";";
2353 $dbo->setQuery($q);
2354 $dbo->execute();
2355 }
2356 } else {
2357 // regularly update busy records for all rooms involved
2358 $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'] . ";";
2359 $dbo->setQuery($q);
2360 $dbo->execute();
2361 $allbusy = $dbo->loadAssocList();
2362 foreach ($allbusy as $bb) {
2363 $q = "UPDATE `#__vikbooking_busy` SET `checkin`=" . $first . ", `checkout`=" . $second . ", `realback`=" . $realback . " WHERE `id`=" . $bb['id'] . ";";
2364 $dbo->setQuery($q);
2365 $dbo->execute();
2366 }
2367 }
2368
2369 /**
2370 * Check if some rooms have modified stay dates different than the booking stay dates.
2371 *
2372 * @since 1.16.0 (J) - 1.6.0 (WP)
2373 */
2374 if (!$ord['split_stay'] && !$ord['closure'] && $ord['roomsnum'] > 1 && $ord['days'] > 1) {
2375 // load the occupied stay dates for each room in case they were modified
2376 $room_stay_records = $av_helper->loadSplitStayBusyRecords($ord['id']);
2377 // loop over all rooms to check the requested operations
2378 foreach ($ordersrooms as $ind => $or) {
2379 if (!VikRequest::getInt('room_modify_dates' . $ind, 0, 'request') || !isset($room_stay_records[$ind]) || empty($room_stay_records[$ind]['id'])) {
2380 // toggle is disabled or data is missing
2381 continue;
2382 }
2383 if (isset($room_modify_dates[$ind]) && !empty($room_modify_dates[$ind]['checkin']) && !empty($room_modify_dates[$ind]['checkout'])) {
2384 // calculate the check-in and check-out timestamps, we expect them to be different from the global booking dates
2385 $room_checkin = VikBooking::getDateTimestamp($room_modify_dates[$ind]['checkin'], $pcheckinh, $pcheckinm);
2386 $room_checkout = VikBooking::getDateTimestamp($room_modify_dates[$ind]['checkout'], $pcheckouth, $pcheckoutm);
2387 $room_realback = $turnover_secs + $room_checkout;
2388 // we don't need to check if the dates are different, we just update the record
2389 $q = "UPDATE `#__vikbooking_busy` SET `checkin`=" . $room_checkin . ", `checkout`=" . $room_checkout . ", `realback`=" . $room_realback . " WHERE `id`=" . (int)$room_stay_records[$ind]['id'] . ";";
2390 $dbo->setQuery($q);
2391 $dbo->execute();
2392 }
2393 }
2394 }
2395
2396 // add room to existing (confirmed) booking
2397 if ($room_added === true) {
2398 // add busy record for the new room unit
2399 $q = "INSERT INTO `#__vikbooking_busy` (`idroom`,`checkin`,`checkout`,`realback`) VALUES(".$padd_room_id.", ".$dbo->quote($first).", ".$dbo->quote($second).", ".$dbo->quote($realback).");";
2400 $dbo->setQuery($q);
2401 $dbo->execute();
2402 $newbusyid = $dbo->insertid();
2403 $q = "INSERT INTO `#__vikbooking_ordersbusy` (`idorder`,`idbusy`) VALUES(".$ord['id'].", ".(int)$newbusyid.");";
2404 $dbo->setQuery($q);
2405 $dbo->execute();
2406 }
2407
2408 // remove room from existing (confirmed) booking
2409 if ($room_removed !== false) {
2410 // remove busy record for the removed room
2411 if ($ord['split_stay'] && !empty($split_stay_data) && !empty($room_removed_index)) {
2412 // in case of split stay we want to remove the exact dates of the previously booked room
2413 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'])) {
2414 // remove the exact records
2415 $q = "DELETE FROM `#__vikbooking_busy` WHERE `id`=" . $room_stay_dates[$room_removed_index]['id'] . " AND `idroom`=" . $room_removed . ";";
2416 $dbo->setQuery($q);
2417 $dbo->execute();
2418 $q = "DELETE FROM `#__vikbooking_ordersbusy` WHERE `idorder`=" . $ord['id'] . " AND `idbusy`=" . $room_stay_dates[$room_removed_index]['id'] . ";";
2419 $dbo->setQuery($q);
2420 $dbo->execute();
2421 }
2422 } else {
2423 // regularly remove the first matching room
2424 foreach ($allbusy as $bb) {
2425 if ($bb['idroom'] == $room_removed) {
2426 // remove the first room with this ID that was booked
2427 $q = "DELETE FROM `#__vikbooking_busy` WHERE `id`=".$bb['id']." AND `idroom`=".$room_removed.";";
2428 $dbo->setQuery($q);
2429 $dbo->execute();
2430 $q = "DELETE FROM `#__vikbooking_ordersbusy` WHERE `idorder`=".$ord['id']." AND `idbusy`=".$bb['id'].";";
2431 $dbo->setQuery($q);
2432 $dbo->execute();
2433 break;
2434 }
2435 }
2436 }
2437 }
2438
2439 if ($ord['checkin'] != $first || $ord['checkout'] != $second || $room_added === true || $room_removed !== false) {
2440 // unset any previously booked room due to calendar sharing
2441 VikBooking::cleanSharedCalendarsBusy($ord['id']);
2442 // check if some of the rooms booked have shared calendars
2443 VikBooking::updateSharedCalendars($ord['id'], array(), $first, $second);
2444
2445 // invoke Channel Manager
2446 $vcm_autosync = VikBooking::vcmAutoUpdate();
2447 if ($vcm_autosync > 0) {
2448 $vcm_obj = VikBooking::getVcmInvoker();
2449 $vcm_obj->setOids(array($ord['id']))->setSyncType('modify')->setOriginalBooking($ord);
2450 $sync_result = $vcm_obj->doSync();
2451 if ($sync_result === false) {
2452 $vcm_err = $vcm_obj->getError();
2453 VikError::raiseWarning('', JText::translate('VBCHANNELMANAGERRESULTKO').' <a href="index.php?option=com_vikchannelmanager" target="_blank">'.JText::translate('VBCHANNELMANAGEROPEN').'</a> '.(strlen($vcm_err) > 0 ? '('.$vcm_err.')' : ''));
2454 }
2455 } elseif (file_exists(VCM_SITE_PATH . DIRECTORY_SEPARATOR . "helpers" . DIRECTORY_SEPARATOR . "synch.vikbooking.php")) {
2456 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>');
2457 }
2458 //
2459 }
2460 }
2461
2462 $upd_esit = JText::translate('RESUPDATED');
2463
2464 // update the room rates
2465 $isdue = 0;
2466 $tot_taxes = 0;
2467 $tot_city_taxes = 0;
2468 $tot_fees = 0;
2469 $doup = true;
2470 $tars = array();
2471 $cust_costs = array();
2472 $rooms_costs_map = array();
2473 $arrpeople = array();
2474 foreach ($ordersrooms as $kor => $or) {
2475 // remove from existing booking
2476 if ($room_removed !== false) {
2477 if ($or['id'] == $prm_room_oid) {
2478 // do not consider this room for the calculation of the new total amount
2479 // we can unset this array for later use, because the channel manager has already been invoked.
2480 unset($ordersrooms[$kor]);
2481 continue;
2482 }
2483 }
2484
2485 // room index starting from 1
2486 $num = $kor + 1;
2487
2488 // default values to be considered
2489 $room_nights = $daysdiff;
2490 $room_checkin = $ord['checkin'];
2491 $room_checkout = $ord['checkout'];
2492 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'])) {
2493 $room_nights = $room_stay_dates[$kor]['new_nights'];
2494 $room_checkin = $room_stay_dates[$kor]['new_checkin'];
2495 $room_checkout = $room_stay_dates[$kor]['new_checkout'];
2496 }
2497
2498 $padults = VikRequest::getString('adults' . $num, '', 'request');
2499 $pchildren = VikRequest::getString('children' . $num, '', 'request');
2500 $ppets = VikRequest::getInt('pets' . $num, 0, 'request');
2501 if (strlen($padults) || strlen($pchildren)) {
2502 $arrpeople[$num]['adults'] = (int)$padults;
2503 $arrpeople[$num]['children'] = (int)$pchildren;
2504 $arrpeople[$num]['pets'] = $ppets;
2505 }
2506 $ppriceid = VikRequest::getString('priceid'.$num, '', 'request');
2507 $polderpriceid = VikRequest::getString('olderpriceid'.$num, '', 'request');
2508 $ppkgid = VikRequest::getString('pkgid'.$num, '', 'request');
2509 $pcust_cost = VikRequest::getString('cust_cost'.$num, '', 'request');
2510 $paliq = VikRequest::getString('aliq'.$num, '', 'request');
2511 if ($is_package === true && !empty($ppkgid)) {
2512 $pkg_cost = $or['cust_cost'];
2513 $pkg_idiva = $or['cust_idiva'];
2514 $pkg_info = VikBooking::getPackage($ppkgid);
2515 if (is_array($pkg_info) && count($pkg_info) > 0) {
2516 $use_adults = array_key_exists($num, $arrpeople) && array_key_exists('adults', $arrpeople[$num]) ? $arrpeople[$num]['adults'] : $or['adults'];
2517 $pkg_cost = $pkg_info['pernight_total'] == 1 ? ($pkg_info['cost'] * $room_nights) : $pkg_info['cost'];
2518 $pkg_cost = $pkg_info['perperson'] == 1 ? ($pkg_cost * ($use_adults > 0 ? $use_adults : 1)) : $pkg_cost;
2519 $pkg_cost = VikBooking::sayPackagePlusIva($pkg_cost, $pkg_info['idiva']);
2520 }
2521 $cust_costs[$num] = array('pkgid' => $ppkgid, 'cust_cost' => $pkg_cost, 'aliq' => $pkg_idiva);
2522 $isdue += $pkg_cost;
2523 $cost_minus_tax = VikBooking::sayPackageMinusIva($pkg_cost, $pkg_idiva);
2524 $tot_taxes += ($pkg_cost - $cost_minus_tax);
2525 continue;
2526 }
2527 if (empty($ppriceid) && !empty($pcust_cost) && floatval($pcust_cost) > 0) {
2528 $cust_costs[$num] = array('cust_cost' => $pcust_cost, 'aliq' => $paliq);
2529 $cost_after_tax = VikBooking::sayPackagePlusIva((float)$pcust_cost, (int)$paliq);
2530 $isdue += $cost_after_tax;
2531 $cost_minus_tax = VikBooking::sayPackageMinusIva((float)$pcust_cost, (int)$paliq);
2532 $tot_taxes += ($cost_after_tax - $cost_minus_tax);
2533 continue;
2534 }
2535
2536 // load room rates for the requested rate plan and nights
2537 $q = "SELECT * FROM `#__vikbooking_dispcost` WHERE `idroom`=" . (int)$or['idroom'] . " AND `days`=" . $room_nights . " AND `idprice`=" . (int)$ppriceid . ";";
2538 $dbo->setQuery($q);
2539 $dbo->execute();
2540 if (!$dbo->getNumRows()) {
2541 $doup = false;
2542 break;
2543 }
2544
2545 // load room tariffs
2546 $tar = $dbo->loadAssocList();
2547
2548 /**
2549 * The current price may be different from the price paid at the time of booking.
2550 * Check whether it has been asked to keep the old price of the time of booking.
2551 *
2552 * @since 1.13.0 (J) - 1.3.0 (WP)
2553 */
2554 $old_price_used = false;
2555 if (!empty($polderpriceid)) {
2556 $older_info = explode(':', $polderpriceid);
2557 if ((int)$older_info[0] == (int)$ppriceid) {
2558 $old_price = isset($older_info[1]) ? (float)$older_info[1] : 0;
2559 if ($old_price > 0) {
2560 // we override the 'cost' property of the tar array by taking the previous cost
2561 $old_price_used = true;
2562 $tar[0]['cost'] = $old_price;
2563 }
2564 }
2565 }
2566
2567 if (!$old_price_used) {
2568 // apply seasonal rates
2569 $tar = VikBooking::applySeasonsRoom($tar, $room_checkin, $room_checkout);
2570 }
2571
2572 // different usage
2573 if (!$old_price_used && $or['fromadult'] <= $or['adults'] && $or['toadult'] >= $or['adults']) {
2574 // apply OBP rules
2575 $tar = VBORoomHelper::getInstance()->applyOBPRules($tar, $or, $or['adults']);
2576 }
2577
2578 $cost_plus_tax = VikBooking::sayCostPlusIva($tar[0]['cost'], $tar[0]['idprice']);
2579 $isdue += $cost_plus_tax;
2580 if ($cost_plus_tax == $tar[0]['cost']) {
2581 $cost_minus_tax = VikBooking::sayCostMinusIva($tar[0]['cost'], $tar[0]['idprice']);
2582 $tot_taxes += ($tar[0]['cost'] - $cost_minus_tax);
2583 } else {
2584 $tot_taxes += ($cost_plus_tax - $tar[0]['cost']);
2585 }
2586 $tars[$num] = $tar;
2587 $rooms_costs_map[$num] = $tar[0]['cost'];
2588 }
2589
2590 if ($doup === true) {
2591 if ($room_added === true) {
2592 // add room to existing booking may require to increase the total amount, and taxes
2593 $padd_room_price = VikRequest::getFloat('add_room_price', 0, 'request');
2594 $paliq_add_room = VikRequest::getInt('aliq_add_room', 0, 'request');
2595 if (!empty($padd_room_price) && floatval($padd_room_price) > 0) {
2596 $isdue += (float)$padd_room_price;
2597 $cost_minus_tax = VikBooking::sayPackageMinusIva((float)$padd_room_price, (int)$paliq_add_room);
2598 $tot_taxes += ((float)$padd_room_price - $cost_minus_tax);
2599 }
2600 }
2601 $toptionals = '';
2602 $q = "SELECT * FROM `#__vikbooking_optionals` ORDER BY `#__vikbooking_optionals`.`ordering` ASC;";
2603 $dbo->setQuery($q);
2604 $dbo->execute();
2605 if ($dbo->getNumRows() > 0) {
2606 $toptionals = $dbo->loadAssocList();
2607 }
2608 foreach ($ordersrooms as $kor => $or) {
2609 $num = $kor + 1;
2610
2611 // default values to be considered
2612 $room_nights = $daysdiff;
2613 $room_checkin = $ord['checkin'];
2614 $room_checkout = $ord['checkout'];
2615 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'])) {
2616 $room_nights = $room_stay_dates[$kor]['new_nights'];
2617 $room_checkin = $room_stay_dates[$kor]['new_checkin'];
2618 $room_checkout = $room_stay_dates[$kor]['new_checkout'];
2619 }
2620
2621 $pt_first_name = VikRequest::getString('t_first_name'.$num, '', 'request');
2622 $pt_last_name = VikRequest::getString('t_last_name'.$num, '', 'request');
2623 $wop = "";
2624 if (is_array($toptionals)) {
2625 foreach ($toptionals as $opt) {
2626 if (!empty($opt['ageintervals']) && ($or['children'] > 0 || (array_key_exists($num, $arrpeople) && array_key_exists('children', $arrpeople[$num]))) ) {
2627 $tmpvar = VikRequest::getInt('optid'.$num.$opt['id'], []);
2628 if (is_array($tmpvar) && $tmpvar) {
2629 $opt['quan'] = 1;
2630 $optagenames = VikBooking::getOptionIntervalsAges($opt['ageintervals']);
2631 $optagepcent = VikBooking::getOptionIntervalsPercentage($opt['ageintervals']);
2632 $optageovrct = VikBooking::getOptionIntervalChildOverrides($opt, (isset($arrpeople[$num]) ? $arrpeople[$num]['adults'] : 0), (isset($arrpeople[$num]) ? $arrpeople[$num]['children'] : 0));
2633 $optorigname = $opt['name'];
2634 foreach ($tmpvar as $child_num => $chvar) {
2635 $ageintervals_child_string = isset($optageovrct['ageintervals_child' . ($child_num + 1)]) ? $optageovrct['ageintervals_child' . ($child_num + 1)] : $opt['ageintervals'];
2636 $optagecosts = VikBooking::getOptionIntervalsCosts($ageintervals_child_string);
2637 $optorigcost = $optagecosts[($chvar - 1)];
2638 if (array_key_exists(($chvar - 1), $optagepcent) && $optagepcent[($chvar - 1)] == 1) {
2639 //percentage value of the adults tariff
2640 if ($is_package !== true && array_key_exists($num, $tars)) {
2641 //type of price
2642 $optorigcost = $tars[$num][0]['cost'] * $optagecosts[($chvar - 1)] / 100;
2643 } elseif ($is_package === true && array_key_exists($num, $cust_costs)) {
2644 //package
2645 $optorigcost = $cust_costs[$num]['cust_cost'] * $optagecosts[($chvar - 1)] / 100;
2646 } elseif (array_key_exists($num, $cust_costs) && array_key_exists('cust_cost', $cust_costs[$num])) {
2647 //custom rate + custom tax rate
2648 $optorigcost = $cust_costs[$num]['cust_cost'] * $optagecosts[($chvar - 1)] / 100;
2649 }
2650 } elseif (array_key_exists(($chvar - 1), $optagepcent) && $optagepcent[($chvar - 1)] == 2) {
2651 //VBO 1.10 - percentage value of room base cost
2652 if ($is_package !== true && array_key_exists($num, $tars)) {
2653 //type of price
2654 $usecost = isset($tars[$num][0]['room_base_cost']) ? $tars[$num][0]['room_base_cost'] : $tars[$num][0]['cost'];
2655 $optorigcost = $usecost * $optagecosts[($chvar - 1)] / 100;
2656 } elseif ($is_package === true && array_key_exists($num, $cust_costs)) {
2657 //package
2658 $optorigcost = $cust_costs[$num]['cust_cost'] * $optagecosts[($chvar - 1)] / 100;
2659 } elseif (array_key_exists($num, $cust_costs) && array_key_exists('cust_cost', $cust_costs[$num])) {
2660 //custom rate + custom tax rate
2661 $optorigcost = $cust_costs[$num]['cust_cost'] * $optagecosts[($chvar - 1)] / 100;
2662 }
2663 }
2664 $opt['cost'] = $optorigcost;
2665 $opt['name'] = $optorigname.' ('.$optagenames[($chvar - 1)].')';
2666 $opt['chageintv'] = $chvar;
2667 $wop.=$opt['id'].":".$opt['quan']."-".$chvar.";";
2668 $realcost = (intval($opt['perday']) == 1 ? ($opt['cost'] * $room_nights * $opt['quan']) : ($opt['cost'] * $opt['quan']));
2669 if (!empty($opt['maxprice']) && $opt['maxprice'] > 0 && $realcost > $opt['maxprice']) {
2670 $realcost = $opt['maxprice'];
2671 }
2672 $tmpopr = VikBooking::sayOptionalsPlusIva($realcost, $opt['idiva']);
2673 if ($opt['is_citytax'] == 1) {
2674 $tot_city_taxes += $tmpopr;
2675 } elseif ($opt['is_fee'] == 1) {
2676 $tot_fees += $tmpopr;
2677 }
2678 // VBO 1.11 - always calculate the amount of tax no matter if this is already a tax or a fee
2679 if ($tmpopr == $realcost) {
2680 $opt_minus_iva = VikBooking::sayOptionalsMinusIva($realcost, $opt['idiva']);
2681 $tot_taxes += ($realcost - $opt_minus_iva);
2682 } else {
2683 $tot_taxes += ($tmpopr - $realcost);
2684 }
2685 //
2686 $isdue += $tmpopr;
2687 }
2688 }
2689 } else {
2690 $tmpvar = VikRequest::getString('optid'.$num.$opt['id'], '', 'request');
2691 //options forced per child fix, no age intervals, like children tourist taxes
2692 $forcedquan = 1;
2693 $forceperday = false;
2694 $forceperchild = false;
2695 if (intval($opt['forcesel']) == 1 && strlen($opt['forceval']) > 0 && strlen($tmpvar) > 0) {
2696 $forceparts = explode("-", $opt['forceval']);
2697 $forcedquan = intval($forceparts[0]);
2698 $forceperday = intval($forceparts[1]) == 1 ? true : false;
2699 $forceperchild = intval($forceparts[2]) == 1 ? true : false;
2700 $tmpvar = $forcedquan;
2701 $tmpvar = $forceperchild === true && array_key_exists($num, $arrpeople) && array_key_exists('children', $arrpeople[$num]) ? ($tmpvar * $arrpeople[$num]['children']) : $tmpvar;
2702 }
2703 //
2704 if (!empty($tmpvar)) {
2705 $wop .= $opt['id'].":".$tmpvar.";";
2706 // VBO 1.11 - options percentage cost of the room total fee
2707 if ($is_package !== true && array_key_exists($num, $tars)) {
2708 //type of price
2709 $deftar_basecosts = $tars[$num][0]['cost'];
2710 } elseif ($is_package === true && array_key_exists($num, $cust_costs)) {
2711 //package
2712 $deftar_basecosts = $cust_costs[$num]['cust_cost'];
2713 } elseif (array_key_exists($num, $cust_costs) && array_key_exists('cust_cost', $cust_costs[$num])) {
2714 //custom rate + custom tax rate
2715 $deftar_basecosts = $cust_costs[$num]['cust_cost'];
2716 }
2717 $opt['cost'] = (int)$opt['pcentroom'] ? ($deftar_basecosts * $opt['cost'] / 100) : $opt['cost'];
2718 //
2719 $realcost = (intval($opt['perday']) == 1 ? ($opt['cost'] * $room_nights * $tmpvar) : ($opt['cost'] * $tmpvar));
2720 if (!empty($opt['maxprice']) && $opt['maxprice'] > 0 && $realcost > $opt['maxprice']) {
2721 $realcost = $opt['maxprice'];
2722 if (intval($opt['hmany']) == 1 && intval($tmpvar) > 1) {
2723 $realcost = $opt['maxprice'] * $tmpvar;
2724 }
2725 }
2726 if ($opt['perperson'] == 1) {
2727 $num_adults = array_key_exists($num, $arrpeople) && array_key_exists('adults', $arrpeople[$num]) ? $arrpeople[$num]['adults'] : 1;
2728 $realcost = $realcost * $num_adults;
2729 }
2730 $tmpopr = VikBooking::sayOptionalsPlusIva($realcost, $opt['idiva']);
2731 if ($opt['is_citytax'] == 1) {
2732 $tot_city_taxes += $tmpopr;
2733 } elseif ($opt['is_fee'] == 1) {
2734 $tot_fees += $tmpopr;
2735 }
2736 // VBO 1.11 - always calculate the amount of tax no matter if this is already a tax or a fee
2737 if ($tmpopr == $realcost) {
2738 $opt_minus_iva = VikBooking::sayOptionalsMinusIva($realcost, $opt['idiva']);
2739 $tot_taxes += ($realcost - $opt_minus_iva);
2740 } else {
2741 $tot_taxes += ($tmpopr - $realcost);
2742 }
2743 //
2744 $isdue += $tmpopr;
2745 }
2746 }
2747 }
2748 }
2749
2750 $upd_fields = array();
2751 if ($is_package !== true && array_key_exists($num, $tars)) {
2752 //type of price
2753 $upd_fields[] = "`idtar`='".$tars[$num][0]['id']."'";
2754 $upd_fields[] = "`cust_cost`=NULL";
2755 $upd_fields[] = "`cust_idiva`=NULL";
2756 $upd_fields[] = "`room_cost`=".(array_key_exists($num, $rooms_costs_map) ? $dbo->quote($rooms_costs_map[$num]) : "NULL");
2757 } elseif ($is_package === true && array_key_exists($num, $cust_costs)) {
2758 //packages do not update name or cost, just set again the same package ID to avoid risks of empty upd_fields to update
2759 $upd_fields[] = "`idtar`=NULL";
2760 $upd_fields[] = "`pkg_id`='".$cust_costs[$num]['pkgid']."'";
2761 $upd_fields[] = "`cust_cost`='".$cust_costs[$num]['cust_cost']."'";
2762 $upd_fields[] = "`cust_idiva`='".$cust_costs[$num]['aliq']."'";
2763 $upd_fields[] = "`room_cost`=NULL";
2764 } elseif (array_key_exists($num, $cust_costs) && array_key_exists('cust_cost', $cust_costs[$num])) {
2765 //custom rate + custom tax rate
2766 $upd_fields[] = "`idtar`=NULL";
2767 $upd_fields[] = "`cust_cost`='".$cust_costs[$num]['cust_cost']."'";
2768 $upd_fields[] = "`cust_idiva`='".$cust_costs[$num]['aliq']."'";
2769 $upd_fields[] = "`room_cost`=NULL";
2770 }
2771 if (is_array($toptionals)) {
2772 $upd_fields[] = "`optionals`='".$wop."'";
2773 }
2774 if (!empty($pt_first_name) || !empty($pt_last_name)) {
2775 $upd_fields[] = "`t_first_name`=".$dbo->quote($pt_first_name);
2776 $upd_fields[] = "`t_last_name`=".$dbo->quote($pt_last_name);
2777 }
2778 if (array_key_exists($num, $arrpeople) && array_key_exists('adults', $arrpeople[$num])) {
2779 $upd_fields[] = "`adults`=".intval($arrpeople[$num]['adults']);
2780 $upd_fields[] = "`children`=".intval($arrpeople[$num]['children']);
2781 if (isset($arrpeople[$num]['pets'])) {
2782 $upd_fields[] = "`pets`=" . $arrpeople[$num]['pets'];
2783 }
2784 }
2785
2786 /**
2787 * Meal plans at room-reservation level.
2788 *
2789 * @since 1.16.1 (J) - 1.6.1 (WP)
2790 */
2791 $pmealplans = VikRequest::getVar('mealplan' . $num, []);
2792 $upd_fields[] = "`meals`=" . ($pmealplans ? $dbo->q(json_encode($pmealplans)) : 'NULL');
2793
2794 //calculate the extra costs and increase taxes + isdue
2795 $extracosts_arr = array();
2796 if (count($pextracn) && isset($pextracn[$num]) && count($pextracn[$num])) {
2797 foreach ($pextracn[$num] as $eck => $ecn) {
2798 if (strlen($ecn) > 0 && array_key_exists($eck, $pextracc[$num]) && is_numeric($pextracc[$num][$eck])) {
2799 $ecidtax = array_key_exists($eck, $pextractx[$num]) && intval($pextractx[$num][$eck]) > 0 ? (int)$pextractx[$num][$eck] : '';
2800 $extracosts_arr[] = array(
2801 'name' => $ecn,
2802 'cost' => (float)$pextracc[$num][$eck],
2803 'idtax' => $ecidtax,
2804 'type' => isset($pextractype[$num][$eck]) ? $pextractype[$num][$eck] : '',
2805 'fk' => isset($pextracfk[$num][$eck]) ? (string)$pextracfk[$num][$eck] : '',
2806 'data' => isset($pextracdata[$num][$eck]) ? json_decode($pextracdata[$num][$eck]) : null,
2807 );
2808 $ecplustax = !empty($ecidtax) ? VikBooking::sayOptionalsPlusIva((float)$pextracc[$num][$eck], $ecidtax) : (float)$pextracc[$num][$eck];
2809 $ecminustax = !empty($ecidtax) ? VikBooking::sayOptionalsMinusIva((float)$pextracc[$num][$eck], $ecidtax) : (float)$pextracc[$num][$eck];
2810 $ectottax = (float)$pextracc[$num][$eck] - $ecminustax;
2811 $isdue += $ecplustax;
2812 $tot_taxes += $ectottax;
2813 }
2814 }
2815 }
2816 if (count($extracosts_arr) > 0) {
2817 $upd_fields[] = "`extracosts`=".$dbo->quote(json_encode($extracosts_arr));
2818 } else {
2819 $upd_fields[] = "`extracosts`=NULL";
2820 }
2821 //end extra costs
2822 if (count($upd_fields) > 0) {
2823 $q = "UPDATE `#__vikbooking_ordersrooms` SET ".implode(', ', $upd_fields)." WHERE `idorder`=".$ord['id']." AND `idroom`='".$or['idroom']."' AND `id`='".$or['id']."';";
2824 $dbo->setQuery($q);
2825 $dbo->execute();
2826 }
2827 }
2828
2829 // update split stay transient record if not confirmed booking
2830 if ($ord['split_stay'] && $ord['status'] != 'confirmed' && !empty($room_stay_dates) && !empty($split_stay_data)) {
2831 /**
2832 * Important: if no rates have been selected for all rooms, we won't enter this inner statement.
2833 * It is necessary to select a rate plan for each room in order to update the split stay data.
2834 */
2835 $new_room_stay_dates = [];
2836 foreach ($room_stay_dates as $kor => $room_stay_info) {
2837 // clone the current information
2838 $clean_room_stay_info = $room_stay_info;
2839 // set new stay values
2840 if (!empty($clean_room_stay_info['checkin_ts'])) {
2841 $clean_room_stay_info['checkin_ts'] = $clean_room_stay_info['new_checkin'];
2842 $clean_room_stay_info['checkout_ts'] = $clean_room_stay_info['new_checkout'];
2843 } else {
2844 $clean_room_stay_info['checkin'] = $clean_room_stay_info['new_checkin'];
2845 $clean_room_stay_info['checkout'] = $clean_room_stay_info['new_checkout'];
2846 }
2847 $clean_room_stay_info['nights'] = $clean_room_stay_info['new_nights'];
2848 // clean up unnecessary keys
2849 unset($clean_room_stay_info['new_checkin'], $clean_room_stay_info['new_checkout'], $clean_room_stay_info['new_nights']);
2850 // push new array info
2851 $new_room_stay_dates[$kor] = $clean_room_stay_info;
2852 }
2853 // update configuration record
2854 VBOFactory::getConfig()->set('split_stay_' . $ord['id'], json_encode($new_room_stay_dates));
2855 }
2856
2857 // make sure to re-apply the discount with the coupon code
2858 if (strlen($ord['coupon']) > 0) {
2859 $expcoupon = explode(";", $ord['coupon']);
2860 $isdue -= $expcoupon[1];
2861 }
2862
2863 // make sure to apply any previously refunded amount
2864 if ($ord['refund'] > 0) {
2865 $isdue -= $ord['refund'];
2866 }
2867
2868 // update totals
2869 $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'].";";
2870 $dbo->setQuery($q);
2871 $dbo->execute();
2872 $upd_esit = JText::translate('VBORESRATESUPDATED');
2873
2874 // Customer Booking
2875 if ($ord['status'] == 'confirmed') {
2876 $q = "SELECT `idcustomer` FROM `#__vikbooking_customers_orders` WHERE `idorder`=".$ord['id'].";";
2877 $dbo->setQuery($q);
2878 $dbo->execute();
2879 if ($dbo->getNumRows() > 0) {
2880 $customer_id = $dbo->loadResult();
2881 $cpin = VikBooking::getCPinIstance();
2882 $cpin->is_admin = true;
2883 $cpin->updateBookingCommissions($ord['id'], $customer_id);
2884 }
2885 }
2886 }
2887 //Booking History
2888 $history_descr = "({$user->name}) " . VikBooking::getLogBookingModification($ord, $room_stay_dates);
2889 if (!$opertwounits && $forcebooking) {
2890 $history_descr .= "\n" . JText::translate('VBO_FORCED_BOOKDATES');
2891 }
2892 VikBooking::getBookingHistoryInstance()->setBid($ord['id'])->store('MB', $history_descr);
2893 //
2894 $app->enqueueMessage($upd_esit);
2895 } else {
2896 VikError::raiseWarning('', JText::translate('VBROOMNOTRIT')." ".date($df.' H:i', $first)." ".JText::translate('VBROOMNOTCONSTO')." ".date($df.' H:i', $second));
2897 $allow_force = 1;
2898 $app->enqueueMessage(JText::translate('VBO_BOOKING_SHOULDFORCE'), 'notice');
2899 }
2900
2901 if ($callback == 'geninvoices') {
2902 $app->redirect("index.php?option=com_vikbooking&task=orders&cid[]=".$ord['id']."&confirmgen=1");
2903 } else {
2904 $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" : ""));
2905 }
2906 }
2907
2908 public function removebusy()
2909 {
2910 $dbo = JFactory::getDbo();
2911 $app = JFactory::getApplication();
2912
2913 $config = VBOFactory::getConfig();
2914
2915 $prev_conf_ids = [];
2916 $pidorder = VikRequest::getInt('idorder', 0, 'request');
2917 $pgoto = VikRequest::getString('goto', '', 'request');
2918
2919 $purged = false;
2920
2921 $q = "SELECT * FROM `#__vikbooking_orders` WHERE `id`=" . $pidorder;
2922 $dbo->setQuery($q, 0, 1);
2923 $row = $dbo->loadAssoc();
2924
2925 // check for any cancellation constraints
2926 $canc_denied = false;
2927 if ($row && class_exists('VCMFeesCancellation')) {
2928 // let VCM detect if there are any constraints for the cancellation
2929 $canc_denied = VCMFeesCancellation::getInstance($row, $anew = true)->isBookingConstrained();
2930 if ($canc_denied) {
2931 // set error message
2932 $canc_deny_error = VCMFeesCancellation::getInstance()->getError();
2933 if ($canc_deny_error) {
2934 $app->enqueueMessage($canc_deny_error, 'error');
2935 }
2936 }
2937 }
2938
2939 if ($row && !$canc_denied) {
2940 // set status to cancelled
2941 if ($row['status'] != 'cancelled') {
2942 $q = "UPDATE `#__vikbooking_orders` SET `status`='cancelled' WHERE `id`=".(int)$row['id'].";";
2943 $dbo->setQuery($q);
2944 $dbo->execute();
2945 $q = "DELETE FROM `#__vikbooking_tmplock` WHERE `idorder`=" . intval($row['id']) . ";";
2946 $dbo->setQuery($q);
2947 $dbo->execute();
2948 if ($row['status'] == 'confirmed') {
2949 $prev_conf_ids[] = $row['id'];
2950 }
2951 // Booking History
2952 VikBooking::getBookingHistoryInstance()->setBid($row['id'])->store('CB');
2953 }
2954
2955 // free records up
2956 $q = "SELECT * FROM `#__vikbooking_ordersbusy` WHERE `idorder`=".(int)$row['id'].";";
2957 $dbo->setQuery($q);
2958 $ordbusy = $dbo->loadAssocList();
2959 if ($ordbusy) {
2960 foreach ($ordbusy as $ob) {
2961 $q = "DELETE FROM `#__vikbooking_busy` WHERE `id`='".$ob['idbusy']."';";
2962 $dbo->setQuery($q);
2963 $dbo->execute();
2964 }
2965 }
2966
2967 $q = "DELETE FROM `#__vikbooking_ordersbusy` WHERE `idorder`=".(int)$row['id'].";";
2968 $dbo->setQuery($q);
2969 $dbo->execute();
2970
2971 // check for purge removal
2972 if ($row['status'] == 'cancelled') {
2973 $q = "DELETE FROM `#__vikbooking_customers_orders` WHERE `idorder`=" . intval($row['id']) . ";";
2974 $dbo->setQuery($q);
2975 $dbo->execute();
2976 $q = "DELETE FROM `#__vikbooking_ordersrooms` WHERE `idorder`=".(int)$row['id'].";";
2977 $dbo->setQuery($q);
2978 $dbo->execute();
2979 $q = "DELETE FROM `#__vikbooking_orderhistory` WHERE `idorder`=".(int)$row['id'].";";
2980 $dbo->setQuery($q);
2981 $dbo->execute();
2982 $q = "DELETE FROM `#__vikbooking_orders` WHERE `id`=".(int)$row['id'].";";
2983 $dbo->setQuery($q);
2984 $dbo->execute();
2985 // in case of split stay booking, remove the transient
2986 if ($row['split_stay']) {
2987 $config->remove('split_stay_' . $row['id']);
2988 }
2989 // turn flag on
2990 $purged = true;
2991 }
2992
2993 // enqueue message
2994 $app->enqueueMessage(JText::translate('VBMESSDELBUSY'));
2995 }
2996
2997 if ($prev_conf_ids) {
2998 $prev_conf_ids_str = '';
2999 foreach ($prev_conf_ids as $prev_id) {
3000 $prev_conf_ids_str .= '&cid[]='.$prev_id;
3001 }
3002 //Invoke Channel Manager
3003 $vcm_autosync = VikBooking::vcmAutoUpdate();
3004 if ($vcm_autosync > 0) {
3005 $vcm_obj = VikBooking::getVcmInvoker();
3006 $vcm_obj->setOids($prev_conf_ids)->setSyncType('cancel');
3007 $sync_result = $vcm_obj->doSync();
3008 if ($sync_result === false) {
3009 $vcm_err = $vcm_obj->getError();
3010 VikError::raiseWarning('', JText::translate('VBCHANNELMANAGERRESULTKO').' <a href="index.php?option=com_vikchannelmanager" target="_blank">'.JText::translate('VBCHANNELMANAGEROPEN').'</a> '.(strlen($vcm_err) > 0 ? '('.$vcm_err.')' : ''));
3011 }
3012 } elseif (file_exists(VCM_SITE_PATH . DIRECTORY_SEPARATOR . "helpers" . DIRECTORY_SEPARATOR . "synch.vikbooking.php")) {
3013 $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');
3014 VikError::raiseNotice('', JText::translate('VBCHANNELMANAGERINVOKEASK').' <button type="button" class="btn btn-primary" onclick="document.location.href=\''.$vcm_sync_url.'\';">'.JText::translate('VBCHANNELMANAGERSENDRQ').'</button>');
3015 }
3016 //
3017 }
3018
3019 if ($pgoto == 'overv') {
3020 $app->redirect("index.php?option=com_vikbooking&task=overv");
3021 } elseif (!$purged) {
3022 $app->redirect("index.php?option=com_vikbooking&task=editorder&cid[]=" . $pidorder);
3023 } else {
3024 $app->redirect("index.php?option=com_vikbooking&task=orders");
3025 }
3026
3027 $app->close();
3028 }
3029
3030 public function unlockrecords() {
3031 $ids = VikRequest::getVar('cid', array(0));
3032 if (@count($ids)) {
3033 $dbo = JFactory::getDBO();
3034 foreach ($ids as $d) {
3035 $q = "DELETE FROM `#__vikbooking_tmplock` WHERE `id`=".$dbo->quote($d).";";
3036 $dbo->setQuery($q);
3037 $dbo->execute();
3038 }
3039 }
3040 $mainframe = JFactory::getApplication();
3041 $mainframe->redirect("index.php?option=com_vikbooking");
3042 }
3043
3044 public function sortoption() {
3045 if (!JSession::checkToken('get')) {
3046 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
3047 }
3048 $sortid = VikRequest::getVar('cid', array(0));
3049 $pmode = VikRequest::getString('mode', '', 'request');
3050 $dbo = JFactory::getDBO();
3051 $mainframe = JFactory::getApplication();
3052 if (!empty($pmode)) {
3053 $q = "SELECT `id`,`ordering` FROM `#__vikbooking_optionals` ORDER BY `#__vikbooking_optionals`.`ordering` ASC;";
3054 $dbo->setQuery($q);
3055 $dbo->execute();
3056 $totr = $dbo->getNumRows();
3057 if ($totr > 1) {
3058 $data = $dbo->loadAssocList();
3059 if ($pmode == "up") {
3060 foreach ($data as $v) {
3061 if ($v['id'] == $sortid[0]) {
3062 $y = $v['ordering'];
3063 }
3064 }
3065 if ($y && $y > 1) {
3066 $vik = $y - 1;
3067 $found = false;
3068 foreach ($data as $v) {
3069 if (intval($v['ordering']) == intval($vik)) {
3070 $found = true;
3071 $q = "UPDATE `#__vikbooking_optionals` SET `ordering`='".$y."' WHERE `id`='".$v['id']."' LIMIT 1;";
3072 $dbo->setQuery($q);
3073 $dbo->execute();
3074 $q = "UPDATE `#__vikbooking_optionals` SET `ordering`='".$vik."' WHERE `id`='".$sortid[0]."' LIMIT 1;";
3075 $dbo->setQuery($q);
3076 $dbo->execute();
3077 break;
3078 }
3079 }
3080 if (!$found) {
3081 $q = "UPDATE `#__vikbooking_optionals` SET `ordering`='".$vik."' WHERE `id`='".$sortid[0]."' LIMIT 1;";
3082 $dbo->setQuery($q);
3083 $dbo->execute();
3084 }
3085 }
3086 } elseif ($pmode == "down") {
3087 foreach ($data as $v) {
3088 if ($v['id'] == $sortid[0]) {
3089 $y = $v['ordering'];
3090 }
3091 }
3092 if ($y) {
3093 $vik = $y + 1;
3094 $found = false;
3095 foreach ($data as $v) {
3096 if (intval($v['ordering']) == intval($vik)) {
3097 $found = true;
3098 $q = "UPDATE `#__vikbooking_optionals` SET `ordering`='".$y."' WHERE `id`='".$v['id']."' LIMIT 1;";
3099 $dbo->setQuery($q);
3100 $dbo->execute();
3101 $q = "UPDATE `#__vikbooking_optionals` SET `ordering`='".$vik."' WHERE `id`='".$sortid[0]."' LIMIT 1;";
3102 $dbo->setQuery($q);
3103 $dbo->execute();
3104 break;
3105 }
3106 }
3107 if (!$found) {
3108 $q = "UPDATE `#__vikbooking_optionals` SET `ordering`='".$vik."' WHERE `id`='".$sortid[0]."' LIMIT 1;";
3109 $dbo->setQuery($q);
3110 $dbo->execute();
3111 }
3112 }
3113 }
3114 }
3115 $mainframe->redirect("index.php?option=com_vikbooking&task=optionals");
3116 } else {
3117 $mainframe->redirect("index.php?option=com_vikbooking");
3118 }
3119 }
3120
3121 public function sortpayment() {
3122 if (!JSession::checkToken('get')) {
3123 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
3124 }
3125 $cid = VikRequest::getVar('cid', array(0));
3126 $sortid = $cid[0];
3127 $dbo = JFactory::getDBO();
3128 $mainframe = JFactory::getApplication();
3129 $pmode = VikRequest::getString('mode', '', 'request');
3130 if (!empty($pmode) && !empty($sortid)) {
3131 $q = "SELECT `id`,`ordering` FROM `#__vikbooking_gpayments` ORDER BY `#__vikbooking_gpayments`.`ordering` ASC;";
3132 $dbo->setQuery($q);
3133 $dbo->execute();
3134 $totr=$dbo->getNumRows();
3135 if ($totr > 1) {
3136 $data = $dbo->loadAssocList();
3137 if ($pmode == "up") {
3138 foreach ($data as $v) {
3139 if ($v['id'] == $sortid) {
3140 $y = $v['ordering'];
3141 }
3142 }
3143 if ($y && $y > 1) {
3144 $vik = $y - 1;
3145 $found = false;
3146 foreach ($data as $v) {
3147 if (intval($v['ordering']) == intval($vik)) {
3148 $found = true;
3149 $q = "UPDATE `#__vikbooking_gpayments` SET `ordering`='".$y."' WHERE `id`='".$v['id']."' LIMIT 1;";
3150 $dbo->setQuery($q);
3151 $dbo->execute();
3152 $q = "UPDATE `#__vikbooking_gpayments` SET `ordering`='".$vik."' WHERE `id`='".$sortid."' LIMIT 1;";
3153 $dbo->setQuery($q);
3154 $dbo->execute();
3155 break;
3156 }
3157 }
3158 if (!$found) {
3159 $q = "UPDATE `#__vikbooking_gpayments` SET `ordering`='".$vik."' WHERE `id`='".$sortid."' LIMIT 1;";
3160 $dbo->setQuery($q);
3161 $dbo->execute();
3162 }
3163 }
3164 } elseif ($pmode == "down") {
3165 foreach ($data as $v) {
3166 if ($v['id'] == $sortid) {
3167 $y = $v['ordering'];
3168 }
3169 }
3170 if ($y) {
3171 $vik = $y + 1;
3172 $found = false;
3173 foreach ($data as $v) {
3174 if (intval($v['ordering']) == intval($vik)) {
3175 $found=true;
3176 $q = "UPDATE `#__vikbooking_gpayments` SET `ordering`='".$y."' WHERE `id`='".$v['id']."' LIMIT 1;";
3177 $dbo->setQuery($q);
3178 $dbo->execute();
3179 $q = "UPDATE `#__vikbooking_gpayments` SET `ordering`='".$vik."' WHERE `id`='".$sortid."' LIMIT 1;";
3180 $dbo->setQuery($q);
3181 $dbo->execute();
3182 break;
3183 }
3184 }
3185 if (!$found) {
3186 $q = "UPDATE `#__vikbooking_gpayments` SET `ordering`='".$vik."' WHERE `id`='".$sortid."' LIMIT 1;";
3187 $dbo->setQuery($q);
3188 $dbo->execute();
3189 }
3190 }
3191 }
3192 }
3193 $mainframe->redirect("index.php?option=com_vikbooking&task=payments");
3194 } else {
3195 $mainframe->redirect("index.php?option=com_vikbooking");
3196 }
3197 }
3198
3199 public function sortcarat() {
3200 if (!JSession::checkToken('get')) {
3201 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
3202 }
3203 $sortid = VikRequest::getVar('cid', array(0));
3204 $pmode = VikRequest::getString('mode', '', 'request');
3205 $dbo = JFactory::getDBO();
3206 $mainframe = JFactory::getApplication();
3207 if (!empty($pmode)) {
3208 $q = "SELECT `id`,`ordering` FROM `#__vikbooking_characteristics` ORDER BY `#__vikbooking_characteristics`.`ordering` ASC;";
3209 $dbo->setQuery($q);
3210 $dbo->execute();
3211 $totr = $dbo->getNumRows();
3212 if ($totr > 1) {
3213 $data = $dbo->loadAssocList();
3214 if ($pmode == "up") {
3215 foreach ($data as $v) {
3216 if ($v['id'] == $sortid[0]) {
3217 $y = $v['ordering'];
3218 }
3219 }
3220 if ($y && $y > 1) {
3221 $vik = $y - 1;
3222 $found = false;
3223 foreach ($data as $v) {
3224 if (intval($v['ordering']) == intval($vik)) {
3225 $found = true;
3226 $q = "UPDATE `#__vikbooking_characteristics` SET `ordering`='".$y."' WHERE `id`='".$v['id']."' LIMIT 1;";
3227 $dbo->setQuery($q);
3228 $dbo->execute();
3229 $q = "UPDATE `#__vikbooking_characteristics` SET `ordering`='".$vik."' WHERE `id`='".$sortid[0]."' LIMIT 1;";
3230 $dbo->setQuery($q);
3231 $dbo->execute();
3232 break;
3233 }
3234 }
3235 if (!$found) {
3236 $q = "UPDATE `#__vikbooking_characteristics` SET `ordering`='".$vik."' WHERE `id`='".$sortid[0]."' LIMIT 1;";
3237 $dbo->setQuery($q);
3238 $dbo->execute();
3239 }
3240 }
3241 } elseif ($pmode == "down") {
3242 foreach ($data as $v) {
3243 if ($v['id'] == $sortid[0]) {
3244 $y = $v['ordering'];
3245 }
3246 }
3247 if ($y) {
3248 $vik = $y + 1;
3249 $found = false;
3250 foreach ($data as $v) {
3251 if (intval($v['ordering']) == intval($vik)) {
3252 $found = true;
3253 $q = "UPDATE `#__vikbooking_characteristics` SET `ordering`='".$y."' WHERE `id`='".$v['id']."' LIMIT 1;";
3254 $dbo->setQuery($q);
3255 $dbo->execute();
3256 $q = "UPDATE `#__vikbooking_characteristics` SET `ordering`='".$vik."' WHERE `id`='".$sortid[0]."' LIMIT 1;";
3257 $dbo->setQuery($q);
3258 $dbo->execute();
3259 break;
3260 }
3261 }
3262 if (!$found) {
3263 $q = "UPDATE `#__vikbooking_characteristics` SET `ordering`='".$vik."' WHERE `id`='".$sortid[0]."' LIMIT 1;";
3264 $dbo->setQuery($q);
3265 $dbo->execute();
3266 }
3267 }
3268 }
3269 }
3270 $mainframe->redirect("index.php?option=com_vikbooking&task=carat");
3271 } else {
3272 $mainframe->redirect("index.php?option=com_vikbooking");
3273 }
3274 }
3275
3276 public function resendordemail() {
3277 $this->do_resendorderemail();
3278 }
3279
3280 public function sendcancordemail() {
3281 $this->do_resendorderemail(true);
3282 }
3283
3284 private function do_resendorderemail($cancellation = false)
3285 {
3286 $dbo = JFactory::getDbo();
3287 $app = JFactory::getApplication();
3288 $vbo_tn = VikBooking::getTranslator();
3289
3290 $cid = VikRequest::getVar('cid', array(0));
3291 $oid = (int)$cid[0];
3292
3293 $q = "SELECT * FROM `#__vikbooking_orders` WHERE `id`=" . $oid . ";";
3294 $dbo->setQuery($q);
3295 $dbo->execute();
3296 if (!$dbo->getNumRows()) {
3297 $app->redirect("index.php?option=com_vikbooking&task=orders");
3298 $app->close();
3299 }
3300 $order = $dbo->loadAssoc();
3301
3302 // check if the language in use is the same as the one used during the checkout
3303 if (!empty($order['lang'])) {
3304 $lang = JFactory::getLanguage();
3305 if ($lang->getTag() != $order['lang']) {
3306 $lang->load('com_vikbooking', (VBOPlatformDetection::isWordPress() ? VIKBOOKING_LANG : JPATH_ADMINISTRATOR), $order['lang'], true);
3307 if (defined('_JEXEC') && !defined('ABSPATH')) {
3308 $lang->load('joomla', JPATH_ADMINISTRATOR, $order['lang'], true);
3309 }
3310 }
3311 if ($vbo_tn->getDefaultLang() != $order['lang']) {
3312 // force the translation to start because contents should be translated
3313 $vbo_tn::$force_tolang = $order['lang'];
3314 }
3315 }
3316
3317 // availability helper
3318 $av_helper = VikBooking::getAvailabilityInstance();
3319
3320 /**
3321 * Split stay reservation.
3322 *
3323 * @since 1.16.0 (J) - 1.6.0 (WP)
3324 */
3325 $room_stay_dates = [];
3326 if ($order['split_stay']) {
3327 if ($order['status'] == 'confirmed') {
3328 $room_stay_dates = $av_helper->loadSplitStayBusyRecords($order['id']);
3329 } else {
3330 $room_stay_dates = VBOFactory::getConfig()->getArray('split_stay_' . $order['id'], []);
3331 }
3332 // immediately count the number of nights of stay for each split room
3333 foreach ($room_stay_dates as $sps_r_k => $sps_r_v) {
3334 if (!empty($sps_r_v['checkin_ts']) && !empty($sps_r_v['checkout_ts'])) {
3335 // overwrite values for compatibility with non-confirmed bookings
3336 $sps_r_v['checkin'] = $sps_r_v['checkin_ts'];
3337 $sps_r_v['checkout'] = $sps_r_v['checkout_ts'];
3338 }
3339 $sps_r_v['nights'] = $av_helper->countNightsOfStay($sps_r_v['checkin'], $sps_r_v['checkout']);
3340 // overwrite the whole array
3341 $room_stay_dates[$sps_r_k] = $sps_r_v;
3342 }
3343 }
3344
3345 // load rooms booked
3346 $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;";
3347 $dbo->setQuery($q);
3348 $dbo->execute();
3349 $ordersrooms = $dbo->loadAssocList();
3350 $vbo_tn->translateContents($ordersrooms, '#__vikbooking_rooms', array('id' => 'r_reference_id'));
3351
3352 $ftitle = VikBooking::getFrontTitle();
3353 $currencyname = VikBooking::getCurrencyName();
3354
3355 $turnover_secs = VikBooking::getHoursRoomAvail() * 3600;
3356 $realback = $turnover_secs + $order['checkout'];
3357
3358 $rooms = array();
3359 $tars = array();
3360 $arrpeople = array();
3361 $is_package = !empty($order['pkg']) ? true : false;
3362 $nowts = time();
3363 foreach ($ordersrooms as $kor => $or) {
3364 $num = $kor + 1;
3365 $rooms[$num] = $or;
3366 $arrpeople[$num]['adults'] = $or['adults'];
3367 $arrpeople[$num]['children'] = $or['children'];
3368 if ($is_package === true || (!empty($or['cust_cost']) && $or['cust_cost'] > 0.00)) {
3369 // package or custom cost set from the back-end
3370 continue;
3371 }
3372
3373 // determine the proper values for this room
3374 $room_nights = $order['days'];
3375 $room_checkin = $order['checkin'];
3376 $room_checkout = $order['checkout'];
3377 if ($order['split_stay'] && !empty($room_stay_dates) && isset($room_stay_dates[$kor]) && $room_stay_dates[$kor]['idroom'] == $or['idroom']) {
3378 $room_nights = $room_stay_dates[$kor]['nights'];
3379 $room_checkin = $room_stay_dates[$kor]['checkin'];
3380 $room_checkout = $room_stay_dates[$kor]['checkout'];
3381 }
3382
3383 // load tariff
3384 $q = "SELECT * FROM `#__vikbooking_dispcost` WHERE `id`=" . (int)$or['idtar'] . ";";
3385 $dbo->setQuery($q);
3386 $dbo->execute();
3387 if ($dbo->getNumRows() > 0) {
3388 $tar = $dbo->loadAssocList();
3389 $tar = VikBooking::applySeasonsRoom($tar, $room_checkin, $room_checkout);
3390
3391 // different usage
3392 $tar = VBORoomHelper::getInstance()->applyOBPRules($tar, $or, $or['adults']);
3393
3394 $tars[$num] = $tar[0];
3395 } else {
3396 VikError::raiseWarning('', JText::translate('VBERRNOFAREFOUND'));
3397 }
3398 }
3399
3400 $secdiff = $order['checkout'] - $order['checkin'];
3401 $daysdiff = $secdiff / 86400;
3402 if (is_int($daysdiff)) {
3403 if ($daysdiff < 1) {
3404 $daysdiff = 1;
3405 }
3406 } else {
3407 if ($daysdiff < 1) {
3408 $daysdiff = 1;
3409 } else {
3410 $sum = floor($daysdiff) * 86400;
3411 $newdiff = $secdiff - $sum;
3412 $maxhmore = VikBooking::getHoursMoreRb() * 3600;
3413 if ($maxhmore >= $newdiff) {
3414 $daysdiff = floor($daysdiff);
3415 } else {
3416 $daysdiff = ceil($daysdiff);
3417 }
3418 }
3419 }
3420
3421 $isdue = 0;
3422 $pricestr = array();
3423 $optstr = array();
3424 foreach ($ordersrooms as $kor => $or) {
3425 $num = $kor + 1;
3426
3427 // determine the proper values for this room
3428 $room_nights = $order['days'];
3429 $room_checkin = $order['checkin'];
3430 $room_checkout = $order['checkout'];
3431 if ($order['split_stay'] && !empty($room_stay_dates) && isset($room_stay_dates[$kor]) && $room_stay_dates[$kor]['idroom'] == $or['idroom']) {
3432 $room_nights = $room_stay_dates[$kor]['nights'];
3433 $room_checkin = $room_stay_dates[$kor]['checkin'];
3434 $room_checkout = $room_stay_dates[$kor]['checkout'];
3435 }
3436
3437 if ($is_package === true || (!empty($or['cust_cost']) && $or['cust_cost'] > 0.00)) {
3438 // package cost or cust_cost may not be inclusive of taxes if prices tax included is off
3439 $calctar = VikBooking::sayPackagePlusIva($or['cust_cost'], $or['cust_idiva']);
3440 $isdue += $calctar;
3441 $pricestr[$num] = (!empty($or['pkg_name']) ? $or['pkg_name'] : (!empty($or['otarplan']) ? ucwords($or['otarplan']) : JText::translate('VBOROOMCUSTRATEPLAN'))).": ".$calctar." ".$currencyname;
3442 } elseif (array_key_exists($num, $tars) && is_array($tars[$num])) {
3443 $display_rate = !empty($or['room_cost']) ? $or['room_cost'] : $tars[$num]['cost'];
3444 $calctar = VikBooking::sayCostPlusIva($display_rate, $tars[$num]['idprice']);
3445 $tars[$num]['calctar'] = $calctar;
3446 $isdue += $calctar;
3447 $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'] : "");
3448 }
3449 if (!empty($or['optionals'])) {
3450 $stepo = explode(";", $or['optionals']);
3451 foreach ($stepo as $roptkey => $oo) {
3452 if (empty($oo)) {
3453 continue;
3454 }
3455 $stept = explode(":", $oo);
3456 $q = "SELECT * FROM `#__vikbooking_optionals` WHERE `id`=" . $dbo->quote($stept[0]) . ";";
3457 $dbo->setQuery($q);
3458 $dbo->execute();
3459 if (!$dbo->getNumRows()) {
3460 continue;
3461 }
3462 $actopt = $dbo->loadAssocList();
3463 $vbo_tn->translateContents($actopt, '#__vikbooking_optionals', array(), array(), (!empty($order['lang']) ? $order['lang'] : null));
3464 $chvar = '';
3465 if (!empty($actopt[0]['ageintervals']) && $or['children'] > 0 && strstr($stept[1], '-') != false) {
3466 $optagenames = VikBooking::getOptionIntervalsAges($actopt[0]['ageintervals']);
3467 $optagepcent = VikBooking::getOptionIntervalsPercentage($actopt[0]['ageintervals']);
3468 $optageovrct = VikBooking::getOptionIntervalChildOverrides($actopt[0], $or['adults'], $or['children']);
3469 $child_num = VikBooking::getRoomOptionChildNumber($or['optionals'], $actopt[0]['id'], $roptkey, $or['children']);
3470 $optagecosts = VikBooking::getOptionIntervalsCosts(isset($optageovrct['ageintervals_child' . ($child_num + 1)]) ? $optageovrct['ageintervals_child' . ($child_num + 1)] : $actopt[0]['ageintervals']);
3471 $agestept = explode('-', $stept[1]);
3472 $stept[1] = $agestept[0];
3473 $chvar = $agestept[1];
3474 if (array_key_exists(($chvar - 1), $optagepcent) && $optagepcent[($chvar - 1)] == 1) {
3475 //percentage value of the adults tariff
3476 if ($is_package === true || (!empty($or['cust_cost']) && $or['cust_cost'] > 0.00)) {
3477 $optagecosts[($chvar - 1)] = $or['cust_cost'] * $optagecosts[($chvar - 1)] / 100;
3478 } else {
3479 $display_rate = !empty($or['room_cost']) ? $or['room_cost'] : $tars[$num]['cost'];
3480 $optagecosts[($chvar - 1)] = $display_rate * $optagecosts[($chvar - 1)] / 100;
3481 }
3482 } elseif (array_key_exists(($chvar - 1), $optagepcent) && $optagepcent[($chvar - 1)] == 2) {
3483 //VBO 1.10 - percentage value of room base cost
3484 if ($is_package === true || (!empty($or['cust_cost']) && $or['cust_cost'] > 0.00)) {
3485 $optagecosts[($chvar - 1)] = $or['cust_cost'] * $optagecosts[($chvar - 1)] / 100;
3486 } else {
3487 $display_rate = isset($tars[$num]['room_base_cost']) ? $tars[$num]['room_base_cost'] : (!empty($or['room_cost']) ? $or['room_cost'] : $tars[$num]['cost']);
3488 $optagecosts[($chvar - 1)] = $display_rate * $optagecosts[($chvar - 1)] / 100;
3489 }
3490 }
3491 $actopt[0]['chageintv'] = $chvar;
3492 $actopt[0]['name'] .= ' ('.$optagenames[($chvar - 1)].')';
3493 $actopt[0]['quan'] = $stept[1];
3494 $realcost = (intval($actopt[0]['perday']) == 1 ? (floatval($optagecosts[($chvar - 1)]) * $room_nights * $stept[1]) : (floatval($optagecosts[($chvar - 1)]) * $stept[1]));
3495 } else {
3496 $actopt[0]['quan'] = $stept[1];
3497 // VBO 1.11 - options percentage cost of the room total fee
3498 if ($is_package === true || (!empty($or['cust_cost']) && $or['cust_cost'] > 0.00)) {
3499 $deftar_basecosts = $or['cust_cost'];
3500 } else {
3501 $deftar_basecosts = !empty($or['room_cost']) ? $or['room_cost'] : $tars[$num]['cost'];
3502 }
3503 $actopt[0]['cost'] = (int)$actopt[0]['pcentroom'] ? ($deftar_basecosts * $actopt[0]['cost'] / 100) : $actopt[0]['cost'];
3504 //
3505 $realcost = (intval($actopt[0]['perday']) == 1 ? ($actopt[0]['cost'] * $room_nights * $stept[1]) : ($actopt[0]['cost'] * $stept[1]));
3506 }
3507 if (!empty($actopt[0]['maxprice']) && $actopt[0]['maxprice'] > 0 && $realcost > $actopt[0]['maxprice']) {
3508 $realcost = $actopt[0]['maxprice'];
3509 if (intval($actopt[0]['hmany']) == 1 && intval($stept[1]) > 1) {
3510 $realcost = $actopt[0]['maxprice'] * $stept[1];
3511 }
3512 }
3513 if ($actopt[0]['perperson'] == 1) {
3514 $realcost = $realcost * $or['adults'];
3515 }
3516 $tmpopr = VikBooking::sayOptionalsPlusIva($realcost, $actopt[0]['idiva']);
3517 $isdue += $tmpopr;
3518 $optstr[$num][] = ($stept[1] > 1 ? $stept[1] . " " : "") . $actopt[0]['name'] . ": " . $tmpopr . " " . $currencyname . "\n";
3519 }
3520 }
3521
3522 // custom extra costs
3523 if (!empty($or['extracosts'])) {
3524 $cur_extra_costs = json_decode($or['extracosts'], true);
3525 foreach ($cur_extra_costs as $eck => $ecv) {
3526 $ecplustax = !empty($ecv['idtax']) ? VikBooking::sayOptionalsPlusIva($ecv['cost'], $ecv['idtax']) : $ecv['cost'];
3527 $isdue += $ecplustax;
3528 $optstr[$num][] = $ecv['name'] . ": " . $ecplustax . " " . $currencyname."\n";
3529 }
3530 }
3531 }
3532
3533 // coupon
3534 $usedcoupon = false;
3535 $origisdue = $isdue;
3536 if (strlen($order['coupon']) > 0) {
3537 $usedcoupon = true;
3538 $expcoupon = explode(";", $order['coupon']);
3539 $isdue = $isdue - $expcoupon[1];
3540 }
3541
3542 // make sure to apply any previously refunded amount
3543 if ($order['refund'] > 0) {
3544 $isdue -= $order['refund'];
3545 }
3546
3547 // ConfirmationNumber
3548 $confirmnumber = $order['confirmnumber'];
3549
3550 $esit_mess = JText::sprintf('VBORDEREMAILRESENT', $order['custmail']);
3551 $status_str = JText::translate('VBCOMPLETED');
3552 if ($cancellation) {
3553 $confirmnumber = '';
3554 $esit_mess = JText::sprintf('VBCANCORDEREMAILSENT', $order['custmail']);
3555 $status_str = JText::translate('VBCANCELLED');
3556 } elseif ($order['status'] == 'standby') {
3557 $confirmnumber = '';
3558 $status_str = JText::translate('VBWAITINGFORPAYMENT');
3559 }
3560 $app->enqueueMessage($esit_mess);
3561
3562 // force the original total amount if rates have changed
3563 if (number_format($isdue, 2) != number_format($order['total'], 2)) {
3564 $isdue = $order['total'];
3565 }
3566
3567 // send email notification to guest (by ignoring the configuration settings)
3568 VikBooking::sendBookingEmail($order['id'], ['guest'], $send = true, $no_config = true);
3569
3570 if ($cancellation) {
3571 /**
3572 * If "send cancellation email", we log the event in the history.
3573 *
3574 * @since 1.14 (J) - 1.4.0 (WP)
3575 */
3576 VikBooking::getBookingHistoryInstance()->setBid($order['id'])->store('EC');
3577 } else {
3578 /**
3579 * Instead, we store an event log to remind that the email was re-sent to the guest
3580 *
3581 * @since 1.16.3 (J) - 1.6.3 (WP)
3582 */
3583 VikBooking::getBookingHistoryInstance()->setBid($order['id'])->store('ER', $esit_mess);
3584 }
3585
3586 $app->redirect("index.php?option=com_vikbooking&task=editorder&cid[]=".$oid);
3587 $app->close();
3588 }
3589
3590 public function setordconfirmed()
3591 {
3592 $dbo = JFactory::getDbo();
3593 $app = JFactory::getApplication();
3594
3595 $cid = VikRequest::getVar('cid', array(0));
3596 $oid = $cid[0];
3597
3598 $q = "SELECT * FROM `#__vikbooking_orders` WHERE `id`=" . (int)$oid . " AND `status` != 'confirmed';";
3599 $dbo->setQuery($q);
3600 $dbo->execute();
3601 if (!$dbo->getNumRows()) {
3602 $app->redirect("index.php?option=com_vikbooking&task=editorder&cid[]=" . $oid);
3603 exit;
3604 }
3605 $order = $dbo->loadAssoc();
3606
3607 /**
3608 * Memorize the original booking status for VCM in case of OTA booking.
3609 *
3610 * @since 1.14 (J) - 1.4.0 (WP)
3611 */
3612 $original_book_status = null;
3613 if (!empty($order['idorderota']) && !empty($order['channel'])) {
3614 $original_book_status = $order['status'];
3615 }
3616
3617 // availability helper
3618 $av_helper = VikBooking::getAvailabilityInstance();
3619
3620 // room stay dates in case of split stay
3621 $room_stay_dates = [];
3622 if ($order['split_stay']) {
3623 $room_stay_dates = VBOFactory::getConfig()->getArray('split_stay_' . $order['id'], []);
3624 }
3625
3626 $vbo_tn = VikBooking::getTranslator();
3627 // check if the language in use is the same as the one used during the checkout
3628 if (!empty($order['lang'])) {
3629 $lang = JFactory::getLanguage();
3630 if ($lang->getTag() != $order['lang']) {
3631 $lang->load('com_vikbooking', (VBOPlatformDetection::isWordPress() ? VIKBOOKING_LANG : JPATH_ADMINISTRATOR), $order['lang'], true);
3632 if (defined('_JEXEC') && !defined('ABSPATH')) {
3633 $lang->load('joomla', JPATH_ADMINISTRATOR, $order['lang'], true);
3634 }
3635 }
3636 if ($vbo_tn->getDefaultLang() != $order['lang']) {
3637 // force the translation to start because contents should be translated
3638 $vbo_tn::$force_tolang = $order['lang'];
3639 }
3640 }
3641
3642 // load order rooms
3643 $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;";
3644 $dbo->setQuery($q);
3645 $dbo->execute();
3646 $ordersrooms = $dbo->loadAssocList();
3647 $vbo_tn->translateContents($ordersrooms, '#__vikbooking_rooms', array('id' => 'r_reference_id'));
3648
3649 $currencyname = VikBooking::getCurrencyName();
3650 $turnover_secs = VikBooking::getHoursRoomAvail() * 3600;
3651 $realback = $turnover_secs + $order['checkout'];
3652 $allbook = true;
3653 $notavail = [];
3654
3655 /**
3656 * We need to calculate a minus operator for each room that was booked more than once.
3657 * In case we are confirming a booking for more than one unit of the same room, we need to
3658 * make sure the calculation is made properly, as only one unit of that room could be free.
3659 *
3660 * @since 1.13 (J) - 1.3.0 (WP)
3661 */
3662 $units_minus_oper = [];
3663 foreach ($ordersrooms as $ind => $or) {
3664 if (!isset($units_minus_oper[$or['idroom']])) {
3665 $units_minus_oper[$or['idroom']] = -1;
3666 }
3667 // increase counter
3668 $units_minus_oper[$or['idroom']]++;
3669 if (!empty($room_stay_dates)) {
3670 // split stay rooms never have the same stay dates, but they should also be different rooms
3671 $units_minus_oper[$or['idroom']] = 0;
3672 }
3673 }
3674
3675 foreach ($ordersrooms as $ind => $or) {
3676 // determine proper values for this room
3677 $room_stay_checkin = $order['checkin'];
3678 $room_stay_checkout = $order['checkout'];
3679 $room_stay_nights = $order['days'];
3680 if ($order['split_stay'] && count($room_stay_dates) && isset($room_stay_dates[$ind]) && $room_stay_dates[$ind]['idroom'] == $or['idroom']) {
3681 $room_stay_checkin = !empty($room_stay_dates[$ind]['checkin_ts']) ? $room_stay_dates[$ind]['checkin_ts'] : $room_stay_dates[$ind]['checkin'];
3682 $room_stay_checkout = !empty($room_stay_dates[$ind]['checkout_ts']) ? $room_stay_dates[$ind]['checkout_ts'] : $room_stay_dates[$ind]['checkout'];
3683 $room_stay_nights = $av_helper->countNightsOfStay($room_stay_checkin, $room_stay_checkout);
3684 // inject nights calculated for this room
3685 $room_stay_dates[$ind]['nights'] = $room_stay_nights;
3686 }
3687
3688 // check if the room is available
3689 if (!VikBooking::roomBookable($or['idroom'], ($or['units'] - $units_minus_oper[$or['idroom']]), $room_stay_checkin, $room_stay_checkout)) {
3690 $allbook = false;
3691 $notavail[] = $or['name']." (".JText::translate('VBMAILADULTS').": ".$or['adults'].($or['children'] > 0 ? " - ".JText::translate('VBMAILCHILDREN').": ".$or['children'] : "").")";
3692 }
3693 }
3694
3695 if (!$allbook) {
3696 VikError::raiseWarning('', JText::translate('VBERRCONFORDERNOTAVROOM').' '.implode(", ", $notavail).'<br/>'.JText::translate('VBUNABLESETRESCONF'));
3697 $app->redirect("index.php?option=com_vikbooking&task=editorder&cid[]=" . $oid);
3698 exit;
3699 }
3700
3701 $rooms = [];
3702 $tars = [];
3703 $arrpeople = [];
3704 $is_package = !empty($order['pkg']) ? true : false;
3705 $rooms_booked = [];
3706 foreach ($ordersrooms as $ind => $or) {
3707 // push room booked
3708 array_push($rooms_booked, (int)$or['idroom']);
3709
3710 // determine proper values for this room
3711 $room_stay_checkin = $order['checkin'];
3712 $room_stay_checkout = $order['checkout'];
3713 $room_stay_realback = $realback;
3714 if ($order['split_stay'] && count($room_stay_dates) && isset($room_stay_dates[$ind]) && $room_stay_dates[$ind]['idroom'] == $or['idroom']) {
3715 $room_stay_checkin = !empty($room_stay_dates[$ind]['checkin_ts']) ? $room_stay_dates[$ind]['checkin_ts'] : $room_stay_dates[$ind]['checkin'];
3716 $room_stay_checkout = !empty($room_stay_dates[$ind]['checkout_ts']) ? $room_stay_dates[$ind]['checkout_ts'] : $room_stay_dates[$ind]['checkout'];
3717 $room_stay_realback = $turnover_secs + $room_stay_checkout;
3718 }
3719
3720 $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 . ");";
3721 $dbo->setQuery($q);
3722 $dbo->execute();
3723 $lid = $dbo->insertid();
3724
3725 $q = "INSERT INTO `#__vikbooking_ordersbusy` (`idorder`,`idbusy`) VALUES(" . (int)$oid . ", " . (int)$lid . ");";
3726 $dbo->setQuery($q);
3727 $dbo->execute();
3728 }
3729
3730 // update status
3731 $q = "UPDATE `#__vikbooking_orders` SET `status`='confirmed' WHERE `id`=" . (int)$order['id'] . ";";
3732 $dbo->setQuery($q);
3733 $dbo->execute();
3734
3735 // remove any previous temporary locked record
3736 $q = "DELETE FROM `#__vikbooking_tmplock` WHERE `idorder`=" . (int)$order['id'] . ";";
3737 $dbo->setQuery($q);
3738 $dbo->execute();
3739
3740 // Booking History
3741 $now_user = JFactory::getUser();
3742 VikBooking::getBookingHistoryInstance()->setBid($order['id'])->store('TC', "({$now_user->name})");
3743
3744 // check if some of the rooms booked have shared calendars
3745 VikBooking::updateSharedCalendars($order['id'], $rooms_booked, $order['checkin'], $order['checkout']);
3746
3747 // send mail
3748 $ftitle = VikBooking::getFrontTitle();
3749 $nowts = time();
3750 // assign room specific unit
3751 $set_room_indexes = VikBooking::autoRoomUnit();
3752 $room_indexes_usemap = [];
3753
3754 foreach ($ordersrooms as $kor => $or) {
3755 $num = $kor + 1;
3756
3757 // determine proper values for this room
3758 $room_stay_checkin = $order['checkin'];
3759 $room_stay_checkout = $order['checkout'];
3760 $room_stay_nights = $order['days'];
3761 if ($order['split_stay'] && count($room_stay_dates) && isset($room_stay_dates[$kor]) && $room_stay_dates[$kor]['idroom'] == $or['idroom']) {
3762 $room_stay_checkin = !empty($room_stay_dates[$kor]['checkin_ts']) ? $room_stay_dates[$kor]['checkin_ts'] : $room_stay_dates[$kor]['checkin'];
3763 $room_stay_checkout = !empty($room_stay_dates[$kor]['checkout_ts']) ? $room_stay_dates[$kor]['checkout_ts'] : $room_stay_dates[$kor]['checkout'];
3764 $room_stay_nights = $room_stay_dates[$kor]['nights'];
3765 }
3766
3767 $rooms[$num] = $or;
3768 $arrpeople[$num]['adults'] = $or['adults'];
3769 $arrpeople[$num]['children'] = $or['children'];
3770
3771 // assign room specific unit
3772 if ($set_room_indexes === true) {
3773 $room_indexes = VikBooking::getRoomUnitNumsAvailable($order, $or['r_reference_id']);
3774 $use_ind_key = 0;
3775 if (count($room_indexes)) {
3776 if (!array_key_exists($or['r_reference_id'], $room_indexes_usemap)) {
3777 $room_indexes_usemap[$or['r_reference_id']] = $use_ind_key;
3778 } else {
3779 $use_ind_key = $room_indexes_usemap[$or['r_reference_id']];
3780 }
3781 $q = "UPDATE `#__vikbooking_ordersrooms` SET `roomindex`=".(int)$room_indexes[$use_ind_key]." WHERE `id`=".(int)$or['id'].";";
3782 $dbo->setQuery($q);
3783 $dbo->execute();
3784 // update rooms references for the customer email sending function
3785 $rooms[$num]['roomindex'] = (int)$room_indexes[$use_ind_key];
3786 //
3787 $room_indexes_usemap[$or['r_reference_id']]++;
3788 }
3789 }
3790
3791 if ($is_package === true || (!empty($or['cust_cost']) && $or['cust_cost'] > 0.00)) {
3792 // package or custom cost set from the back-end
3793 continue;
3794 }
3795
3796 $q = "SELECT * FROM `#__vikbooking_dispcost` WHERE `id`=" . (int)$or['idtar'] . ";";
3797 $dbo->setQuery($q);
3798 $dbo->execute();
3799 if ($dbo->getNumRows() > 0) {
3800 $tar = $dbo->loadAssocList();
3801 $tar = VikBooking::applySeasonsRoom($tar, $room_stay_checkin, $room_stay_checkout);
3802
3803 // different usage
3804 $tar = VBORoomHelper::getInstance()->applyOBPRules($tar, $or, $or['adults']);
3805
3806 $tars[$num] = $tar[0];
3807 } else {
3808 VikError::raiseWarning('', JText::translate('VBERRNOFAREFOUND'));
3809 }
3810 }
3811
3812 $pcheckin = $order['checkin'];
3813 $pcheckout = $order['checkout'];
3814 $secdiff = $pcheckout - $pcheckin;
3815 $daysdiff = $secdiff / 86400;
3816 if (is_int($daysdiff)) {
3817 if ($daysdiff < 1) {
3818 $daysdiff = 1;
3819 }
3820 } else {
3821 if ($daysdiff < 1) {
3822 $daysdiff = 1;
3823 } else {
3824 $sum = floor($daysdiff) * 86400;
3825 $newdiff = $secdiff - $sum;
3826 $maxhmore = VikBooking::getHoursMoreRb() * 3600;
3827 if ($maxhmore >= $newdiff) {
3828 $daysdiff = floor($daysdiff);
3829 } else {
3830 $daysdiff = ceil($daysdiff);
3831 }
3832 }
3833 }
3834
3835 $isdue = 0;
3836 $pricestr = [];
3837 $optstr = [];
3838 foreach ($ordersrooms as $kor => $or) {
3839 $num = $kor + 1;
3840
3841 // determine proper values for this room
3842 $room_stay_checkin = $order['checkin'];
3843 $room_stay_checkout = $order['checkout'];
3844 $room_stay_nights = $order['days'];
3845 if ($order['split_stay'] && count($room_stay_dates) && isset($room_stay_dates[$kor]) && $room_stay_dates[$kor]['idroom'] == $or['idroom']) {
3846 $room_stay_checkin = !empty($room_stay_dates[$kor]['checkin_ts']) ? $room_stay_dates[$kor]['checkin_ts'] : $room_stay_dates[$kor]['checkin'];
3847 $room_stay_checkout = !empty($room_stay_dates[$kor]['checkout_ts']) ? $room_stay_dates[$kor]['checkout_ts'] : $room_stay_dates[$kor]['checkout'];
3848 $room_stay_nights = $room_stay_dates[$kor]['nights'];
3849 }
3850
3851 if ($is_package === true || (!empty($or['cust_cost']) && $or['cust_cost'] > 0.00)) {
3852 // package cost or cust_cost may not be inclusive of taxes if prices tax included is off
3853 $calctar = VikBooking::sayPackagePlusIva($or['cust_cost'], $or['cust_idiva']);
3854 $isdue += $calctar;
3855 $pricestr[$num] = (!empty($or['pkg_name']) ? $or['pkg_name'] : (!empty($or['otarplan']) ? ucwords($or['otarplan']) : JText::translate('VBOROOMCUSTRATEPLAN'))).": ".$calctar." ".$currencyname;
3856 } elseif (array_key_exists($num, $tars) && is_array($tars[$num])) {
3857 $display_rate = !empty($or['room_cost']) ? $or['room_cost'] : $tars[$num]['cost'];
3858 $calctar = VikBooking::sayCostPlusIva($display_rate, $tars[$num]['idprice']);
3859 $tars[$num]['calctar'] = $calctar;
3860 $isdue += $calctar;
3861 $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'] : "");
3862 }
3863 if (!empty($or['optionals'])) {
3864 $stepo = explode(";", $or['optionals']);
3865 foreach ($stepo as $roptkey => $oo) {
3866 if (empty($oo)) {
3867 continue;
3868 }
3869 $stept = explode(":", $oo);
3870 $q = "SELECT * FROM `#__vikbooking_optionals` WHERE `id`=" . $dbo->quote($stept[0]) . ";";
3871 $dbo->setQuery($q);
3872 $dbo->execute();
3873 if (!$dbo->getNumRows()) {
3874 continue;
3875 }
3876 $actopt = $dbo->loadAssocList();
3877 $vbo_tn->translateContents($actopt, '#__vikbooking_optionals');
3878 $chvar = '';
3879 if (!empty($actopt[0]['ageintervals']) && $or['children'] > 0 && strstr($stept[1], '-') != false) {
3880 $optagenames = VikBooking::getOptionIntervalsAges($actopt[0]['ageintervals']);
3881 $optagepcent = VikBooking::getOptionIntervalsPercentage($actopt[0]['ageintervals']);
3882 $optageovrct = VikBooking::getOptionIntervalChildOverrides($actopt[0], $or['adults'], $or['children']);
3883 $child_num = VikBooking::getRoomOptionChildNumber($or['optionals'], $actopt[0]['id'], $roptkey, $or['children']);
3884 $optagecosts = VikBooking::getOptionIntervalsCosts(isset($optageovrct['ageintervals_child' . ($child_num + 1)]) ? $optageovrct['ageintervals_child' . ($child_num + 1)] : $actopt[0]['ageintervals']);
3885 $agestept = explode('-', $stept[1]);
3886 $stept[1] = $agestept[0];
3887 $chvar = $agestept[1];
3888 if (array_key_exists(($chvar - 1), $optagepcent) && $optagepcent[($chvar - 1)] == 1) {
3889 //percentage value of the adults tariff
3890 if ($is_package === true || (!empty($or['cust_cost']) && $or['cust_cost'] > 0.00)) {
3891 $optagecosts[($chvar - 1)] = $or['cust_cost'] * $optagecosts[($chvar - 1)] / 100;
3892 } else {
3893 $display_rate = !empty($or['room_cost']) ? $or['room_cost'] : $tars[$num]['cost'];
3894 $optagecosts[($chvar - 1)] = $display_rate * $optagecosts[($chvar - 1)] / 100;
3895 }
3896 } elseif (array_key_exists(($chvar - 1), $optagepcent) && $optagepcent[($chvar - 1)] == 2) {
3897 //VBO 1.10 - percentage value of room base cost
3898 if ($is_package === true || (!empty($or['cust_cost']) && $or['cust_cost'] > 0.00)) {
3899 $optagecosts[($chvar - 1)] = $or['cust_cost'] * $optagecosts[($chvar - 1)] / 100;
3900 } else {
3901 $display_rate = isset($tars[$num]['room_base_cost']) ? $tars[$num]['room_base_cost'] : (!empty($or['room_cost']) ? $or['room_cost'] : $tars[$num]['cost']);
3902 $optagecosts[($chvar - 1)] = $display_rate * $optagecosts[($chvar - 1)] / 100;
3903 }
3904 }
3905 $actopt[0]['chageintv'] = $chvar;
3906 $actopt[0]['name'] .= ' ('.$optagenames[($chvar - 1)].')';
3907 $actopt[0]['quan'] = $stept[1];
3908 $realcost = (intval($actopt[0]['perday']) == 1 ? (floatval($optagecosts[($chvar - 1)]) * $room_stay_nights * $stept[1]) : (floatval($optagecosts[($chvar - 1)]) * $stept[1]));
3909 } else {
3910 $actopt[0]['quan'] = $stept[1];
3911 // VBO 1.11 - options percentage cost of the room total fee
3912 if ($is_package === true || (!empty($or['cust_cost']) && $or['cust_cost'] > 0.00)) {
3913 $deftar_basecosts = $or['cust_cost'];
3914 } else {
3915 $deftar_basecosts = !empty($or['room_cost']) ? $or['room_cost'] : $tars[$num]['cost'];
3916 }
3917 $actopt[0]['cost'] = (int)$actopt[0]['pcentroom'] ? ($deftar_basecosts * $actopt[0]['cost'] / 100) : $actopt[0]['cost'];
3918 //
3919 $realcost = (intval($actopt[0]['perday']) == 1 ? ($actopt[0]['cost'] * $room_stay_nights * $stept[1]) : ($actopt[0]['cost'] * $stept[1]));
3920 }
3921 if (!empty($actopt[0]['maxprice']) && $actopt[0]['maxprice'] > 0 && $realcost > $actopt[0]['maxprice']) {
3922 $realcost = $actopt[0]['maxprice'];
3923 if (intval($actopt[0]['hmany']) == 1 && intval($stept[1]) > 1) {
3924 $realcost = $actopt[0]['maxprice'] * $stept[1];
3925 }
3926 }
3927 if ($actopt[0]['perperson'] == 1) {
3928 $realcost = $realcost * $or['adults'];
3929 }
3930 $tmpopr = VikBooking::sayOptionalsPlusIva($realcost, $actopt[0]['idiva']);
3931 $isdue += $tmpopr;
3932 $optstr[$num][] = ($stept[1] > 1 ? $stept[1] . " " : "") . $actopt[0]['name'] . ": " . $tmpopr . " " . $currencyname . "\n";
3933 }
3934 }
3935
3936 // custom extra costs
3937 if (!empty($or['extracosts'])) {
3938 $cur_extra_costs = json_decode($or['extracosts'], true);
3939 foreach ($cur_extra_costs as $eck => $ecv) {
3940 $ecplustax = !empty($ecv['idtax']) ? VikBooking::sayOptionalsPlusIva($ecv['cost'], $ecv['idtax']) : $ecv['cost'];
3941 $isdue += $ecplustax;
3942 $optstr[$num][] = $ecv['name'] . ": " . $ecplustax . " " . $currencyname."\n";
3943 }
3944 }
3945 }
3946
3947 // coupon
3948 $usedcoupon = false;
3949 $origisdue = $isdue;
3950 if (strlen($order['coupon']) > 0) {
3951 $usedcoupon = true;
3952 $expcoupon = explode(";", $order['coupon']);
3953 $isdue = $isdue - $expcoupon[1];
3954 }
3955
3956 // make sure to apply any previously refunded amount
3957 if ($order['refund'] > 0) {
3958 $isdue -= $order['refund'];
3959 }
3960
3961 // ConfirmationNumber
3962 $confirmnumber = VikBooking::generateConfirmNumber($order['id'], true);
3963
3964 $app->enqueueMessage(JText::translate('VBORDERSETASCONF'));
3965
3966 // notify the customer unless it was a re-confirmation
3967 $pskip = VikRequest::getInt('skip_notification', 0, 'request');
3968 if ($pskip < 1) {
3969 // send email notification to guest
3970 VikBooking::sendBookingEmail($order['id'], array('guest'));
3971
3972 // SMS skipping the administrator
3973 VikBooking::sendBookingSMS($order['id'], array('admin'));
3974 }
3975
3976 // Invoke Channel Manager
3977 $vcm_autosync = VikBooking::vcmAutoUpdate();
3978 if ($vcm_autosync > 0) {
3979 $vcm_obj = VikBooking::getVcmInvoker();
3980 $vcm_obj->setOids(array($order['id']))->setSyncType('new')->setOriginalStatuses(array($original_book_status));
3981 $sync_result = $vcm_obj->doSync();
3982 if ($sync_result === false) {
3983 $vcm_err = $vcm_obj->getError();
3984 VikError::raiseWarning('', JText::translate('VBCHANNELMANAGERRESULTKO').' <a href="index.php?option=com_vikchannelmanager" target="_blank">'.JText::translate('VBCHANNELMANAGEROPEN').'</a> '.(strlen($vcm_err) > 0 ? '('.$vcm_err.')' : ''));
3985 }
3986 } elseif (file_exists(VCM_SITE_PATH . DIRECTORY_SEPARATOR . "helpers" . DIRECTORY_SEPARATOR . "synch.vikbooking.php")) {
3987 $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']);
3988 VikError::raiseNotice('', JText::translate('VBCHANNELMANAGERINVOKEASK').' <button type="button" class="btn btn-primary" onclick="document.location.href=\''.$vcm_sync_url.'\';">'.JText::translate('VBCHANNELMANAGERSENDRQ').'</button>');
3989 }
3990
3991 $app->redirect("index.php?option=com_vikbooking&task=editorder&cid[]=" . $oid);
3992 }
3993
3994 public function payments() {
3995 VikBookingHelper::printHeader("14");
3996
3997 VikRequest::setVar('view', VikRequest::getCmd('view', 'payments'));
3998
3999 parent::display();
4000
4001 if (VikBooking::showFooter()) {
4002 VikBookingHelper::printFooter();
4003 }
4004 }
4005
4006 public function newpayment() {
4007 VikBookingHelper::printHeader("14");
4008
4009 VikRequest::setVar('view', VikRequest::getCmd('view', 'managepayment'));
4010
4011 parent::display();
4012
4013 if (VikBooking::showFooter()) {
4014 VikBookingHelper::printFooter();
4015 }
4016 }
4017
4018 public function editpayment() {
4019 VikBookingHelper::printHeader("14");
4020
4021 VikRequest::setVar('view', VikRequest::getCmd('view', 'managepayment'));
4022
4023 parent::display();
4024
4025 if (VikBooking::showFooter()) {
4026 VikBookingHelper::printFooter();
4027 }
4028 }
4029
4030 public function createpayment() {
4031 if (!JSession::checkToken()) {
4032 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
4033 }
4034 $mainframe = JFactory::getApplication();
4035 $pname = VikRequest::getString('name', '', 'request');
4036 $ppayment = VikRequest::getString('payment', '', 'request');
4037 $ppublished = VikRequest::getString('published', '', 'request');
4038 $pcharge = VikRequest::getFloat('charge', '', 'request');
4039 $psetconfirmed = VikRequest::getString('setconfirmed', '', 'request');
4040 $phidenonrefund = VikRequest::getInt('hidenonrefund', '', 'request');
4041 $ponlynonrefund = VikRequest::getInt('onlynonrefund', '', 'request');
4042 $pshownotealw = VikRequest::getString('shownotealw', '', 'request');
4043 $pnote = VikRequest::getString('note', '', 'request', VIKREQUEST_ALLOWHTML);
4044 $pval_pcent = VikRequest::getString('val_pcent', '', 'request');
4045 $pval_pcent = !in_array($pval_pcent, array('1', '2')) ? 1 : $pval_pcent;
4046 $pch_disc = VikRequest::getString('ch_disc', '', 'request');
4047 $pch_disc = !in_array($pch_disc, array('1', '2')) ? 1 : $pch_disc;
4048 $poutposition = VikRequest::getString('outposition', 'top', 'request');
4049 $plogo = VikRequest::getString('logo', '', 'request');
4050 $pall_rooms = VikRequest::getInt('all_rooms', 0, 'request');
4051 $pidrooms = VikRequest::getVar('idrooms', array());
4052 $vikpaymentparams = VikRequest::getVar('vikpaymentparams', array(0));
4053 $payparamarr = array();
4054 $payparamstr = '';
4055 if (count($vikpaymentparams) > 0) {
4056 foreach ($vikpaymentparams as $setting => $cont) {
4057 if (strlen($setting) > 0) {
4058 $payparamarr[$setting] = $cont;
4059 }
4060 }
4061 if (count($payparamarr) > 0) {
4062 $payparamstr = json_encode($payparamarr);
4063 }
4064 }
4065
4066 $dbo = JFactory::getDbo();
4067
4068 $set_idrooms = [];
4069 if (empty($pall_rooms) && !empty($pidrooms)) {
4070 $pidrooms = array_map(function($idroom) {
4071 return (int)$idroom;
4072 }, $pidrooms);
4073 foreach ($pidrooms as $idroom) {
4074 if (empty($idroom) || in_array($idroom, $set_idrooms)) {
4075 continue;
4076 }
4077 $set_idrooms[] = $idroom;
4078 }
4079 }
4080
4081 if (!empty($pname) && !empty($ppayment)) {
4082 $setpub = $ppublished == "1" ? 1 : 0;
4083 $psetconfirmed = $psetconfirmed == "1" ? 1 : 0;
4084 $pshownotealw = $pshownotealw == "1" ? 1 : 0;
4085 $q = "SELECT `id` FROM `#__vikbooking_gpayments` WHERE `file`=".$dbo->quote($ppayment).";";
4086 $dbo->setQuery($q);
4087 $dbo->execute();
4088 if ($dbo->getNumRows() >= 0) {
4089 $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') . ");";
4090 $dbo->setQuery($q);
4091 $dbo->execute();
4092 $mainframe->enqueueMessage(JText::translate('VBPAYMENTSAVED'));
4093 $mainframe->redirect("index.php?option=com_vikbooking&task=payments");
4094 } else {
4095 VikError::raiseWarning('', JText::translate('ERRINVFILEPAYMENT'));
4096 $mainframe->redirect("index.php?option=com_vikbooking&task=newpayment");
4097 }
4098 } else {
4099 $mainframe->redirect("index.php?option=com_vikbooking&task=newpayment");
4100 }
4101 }
4102
4103 public function updatepayment()
4104 {
4105 if (!JSession::checkToken()) {
4106 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
4107 }
4108
4109 $this->do_updatepayment($stay = false);
4110 }
4111
4112 public function updatepaymentstay()
4113 {
4114 if (!JSession::checkToken()) {
4115 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
4116 }
4117
4118 $this->do_updatepayment($stay = true);
4119 }
4120
4121 protected function do_updatepayment($stay = false)
4122 {
4123 $mainframe = JFactory::getApplication();
4124
4125 $pwhere = VikRequest::getString('where', '', 'request');
4126 $pname = VikRequest::getString('name', '', 'request');
4127 $ppayment = VikRequest::getString('payment', '', 'request');
4128 $ppublished = VikRequest::getString('published', '', 'request');
4129 $pcharge = VikRequest::getFloat('charge', '', 'request');
4130 $psetconfirmed = VikRequest::getString('setconfirmed', '', 'request');
4131 $phidenonrefund = VikRequest::getInt('hidenonrefund', '', 'request');
4132 $ponlynonrefund = VikRequest::getInt('onlynonrefund', '', 'request');
4133 $pshownotealw = VikRequest::getString('shownotealw', '', 'request');
4134 $pnote = VikRequest::getString('note', '', 'request', VIKREQUEST_ALLOWRAW);
4135 $pval_pcent = VikRequest::getString('val_pcent', '', 'request');
4136 $pval_pcent = !in_array($pval_pcent, array('1', '2')) ? 1 : $pval_pcent;
4137 $pch_disc = VikRequest::getString('ch_disc', '', 'request');
4138 $pch_disc = !in_array($pch_disc, array('1', '2')) ? 1 : $pch_disc;
4139 $poutposition = VikRequest::getString('outposition', 'top', 'request');
4140 $plogo = VikRequest::getString('logo', '', 'request');
4141 $pall_rooms = VikRequest::getInt('all_rooms', 0, 'request');
4142 $pidrooms = VikRequest::getVar('idrooms', array());
4143 $vikpaymentparams = VikRequest::getVar('vikpaymentparams', array(0));
4144 $payparamarr = array();
4145 $payparamstr = '';
4146 if (count($vikpaymentparams) > 0) {
4147 foreach ($vikpaymentparams as $setting => $cont) {
4148 if (strlen($setting) > 0) {
4149 $payparamarr[$setting] = $cont;
4150 }
4151 }
4152 if (count($payparamarr) > 0) {
4153 $payparamstr = json_encode($payparamarr);
4154 }
4155 }
4156
4157 $dbo = JFactory::getDbo();
4158
4159 $set_idrooms = [];
4160 if (empty($pall_rooms) && !empty($pidrooms)) {
4161 $pidrooms = array_map(function($idroom) {
4162 return (int)$idroom;
4163 }, $pidrooms);
4164 foreach ($pidrooms as $idroom) {
4165 if (empty($idroom) || in_array($idroom, $set_idrooms)) {
4166 continue;
4167 }
4168 $set_idrooms[] = $idroom;
4169 }
4170 }
4171
4172 if (!empty($pname) && !empty($ppayment) && !empty($pwhere)) {
4173 $setpub = $ppublished == "1" ? 1 : 0;
4174 $psetconfirmed = $psetconfirmed == "1" ? 1 : 0;
4175 $pshownotealw = $pshownotealw == "1" ? 1 : 0;
4176 $q = "SELECT `id` FROM `#__vikbooking_gpayments` WHERE `file`=".$dbo->quote($ppayment)." AND `id`!='".$pwhere."';";
4177 $dbo->setQuery($q);
4178 $dbo->execute();
4179 if ($dbo->getNumRows() >= 0) {
4180 $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).";";
4181 $dbo->setQuery($q);
4182 $dbo->execute();
4183
4184 $mainframe->enqueueMessage(JText::translate('VBPAYMENTUPDATED'));
4185 if ($stay) {
4186 $mainframe->redirect("index.php?option=com_vikbooking&task=editpayment&cid[]=".$pwhere);
4187 } else {
4188 $mainframe->redirect("index.php?option=com_vikbooking&task=payments");
4189 }
4190 } else {
4191 VikError::raiseWarning('', JText::translate('ERRINVFILEPAYMENT'));
4192 $mainframe->redirect("index.php?option=com_vikbooking&task=editpayment&cid[]=".$pwhere);
4193 }
4194 } else {
4195 $mainframe->redirect("index.php?option=com_vikbooking&task=editpayment&cid[]=".$pwhere);
4196 }
4197 }
4198
4199 public function removepayments() {
4200 if (!JSession::checkToken()) {
4201 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
4202 }
4203 $ids = VikRequest::getVar('cid', array(0));
4204 if (@count($ids)) {
4205 $dbo = JFactory::getDBO();
4206 foreach ($ids as $d) {
4207 $q = "DELETE FROM `#__vikbooking_gpayments` WHERE `id`=".$dbo->quote($d).";";
4208 $dbo->setQuery($q);
4209 $dbo->execute();
4210 }
4211 }
4212 $mainframe = JFactory::getApplication();
4213 $mainframe->redirect("index.php?option=com_vikbooking&task=payments");
4214 }
4215
4216 public function modavailpayment() {
4217 if (!JSession::checkToken('get')) {
4218 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
4219 }
4220 $cid = VikRequest::getVar('cid', array(0));
4221 $idp = $cid[0];
4222 if (!empty($idp)) {
4223 $dbo = JFactory::getDBO();
4224 $q = "SELECT `published` FROM `#__vikbooking_gpayments` WHERE `id`=".intval($idp).";";
4225 $dbo->setQuery($q);
4226 $dbo->execute();
4227 $get = $dbo->loadAssocList();
4228 $q = "UPDATE `#__vikbooking_gpayments` SET `published`=".(intval($get[0]['published']) == 1 ? '0' : '1')." WHERE `id`=".intval($idp).";";
4229 $dbo->setQuery($q);
4230 $dbo->execute();
4231 }
4232 $mainframe = JFactory::getApplication();
4233 $mainframe->redirect("index.php?option=com_vikbooking&task=payments");
4234 }
4235
4236 public function seasons() {
4237 VikBookingHelper::printHeader("13");
4238
4239 VikRequest::setVar('view', VikRequest::getCmd('view', 'seasons'));
4240
4241 parent::display();
4242
4243 if (VikBooking::showFooter()) {
4244 VikBookingHelper::printFooter();
4245 }
4246 }
4247
4248 public function newseason() {
4249 VikBookingHelper::printHeader("13");
4250
4251 VikRequest::setVar('view', VikRequest::getCmd('view', 'manageseason'));
4252
4253 parent::display();
4254
4255 if (VikBooking::showFooter()) {
4256 VikBookingHelper::printFooter();
4257 }
4258 }
4259
4260 public function editseason() {
4261 VikBookingHelper::printHeader("13");
4262
4263 VikRequest::setVar('view', VikRequest::getCmd('view', 'manageseason'));
4264
4265 parent::display();
4266
4267 if (VikBooking::showFooter()) {
4268 VikBookingHelper::printFooter();
4269 }
4270 }
4271
4272 public function updateseason()
4273 {
4274 if (!JSession::checkToken()) {
4275 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
4276 }
4277 $this->do_updateseason();
4278 }
4279
4280 public function updateseasonstay()
4281 {
4282 if (!JSession::checkToken()) {
4283 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
4284 }
4285 $this->do_updateseason(true);
4286 }
4287
4288 private function do_updateseason($stay = false)
4289 {
4290 $app = JFactory::getApplication();
4291 $dbo = JFactory::getDbo();
4292 $session = JFactory::getSession();
4293
4294 $pwhere = VikRequest::getInt('where', 0, 'request');
4295
4296 $pfrom = VikRequest::getString('from', '', 'request');
4297 $pto = VikRequest::getString('to', '', 'request');
4298 $ptype = VikRequest::getString('type', '', 'request');
4299 $pdiffcost = VikRequest::getFloat('diffcost', '', 'request');
4300 $pidrooms = VikRequest::getVar('idrooms', array());
4301 $pidprices = VikRequest::getVar('idprices', array());
4302 $pwdays = VikRequest::getVar('wdays', array());
4303 $pspname = VikRequest::getString('spname', '', 'request');
4304 $pcheckinincl = VikRequest::getString('checkinincl', '', 'request');
4305 $pcheckinincl = $pcheckinincl == 1 ? 1 : 0;
4306 $pyeartied = VikRequest::getString('yeartied', '', 'request');
4307 $pyeartied = $pyeartied == "1" ? 1 : 0;
4308 $tieyear = 0;
4309 $ppromo = VikRequest::getInt('promo', 0, 'request');
4310 $ppromo = $ppromo == 1 ? 1 : 0;
4311 $ppromodaysadv = VikRequest::getInt('promodaysadv', '', 'request');
4312 $ppromominlos = VikRequest::getInt('promominlos', '', 'request');
4313 $ppromotxt = VikRequest::getString('promotxt', '', 'request', VIKREQUEST_ALLOWHTML);
4314 $pval_pcent = VikRequest::getString('val_pcent', '', 'request');
4315 $pval_pcent = $pval_pcent == "1" ? 1 : 2;
4316 $proundmode = VikRequest::getString('roundmode', '', 'request');
4317 $proundmode = (!empty($proundmode) && in_array($proundmode, array('PHP_ROUND_HALF_UP', 'PHP_ROUND_HALF_DOWN')) ? $proundmode : '');
4318 $pnightsoverrides = VikRequest::getVar('nightsoverrides', array());
4319 $pvaluesoverrides = VikRequest::getVar('valuesoverrides', array());
4320 $pandmoreoverride = VikRequest::getVar('andmoreoverride', array());
4321 $padultsdiffchdisc = VikRequest::getVar('adultsdiffchdisc', array());
4322 $padultsdiffval = VikRequest::getVar('adultsdiffval', array());
4323 $padultsdiffvalpcent = VikRequest::getVar('adultsdiffvalpcent', array());
4324 $padultsdiffpernight = VikRequest::getVar('adultsdiffpernight', array());
4325 $ppromolastmind = VikRequest::getInt('promolastmind', 0, 'request');
4326 $ppromolastminh = VikRequest::getInt('promolastminh', 0, 'request');
4327 $promolastmin = ($ppromolastmind * 86400) + ($ppromolastminh * 3600);
4328 $ppromofinalprice = VikRequest::getInt('promofinalprice', 0, 'request');
4329 $ppromofinalprice = $ppromo ? $ppromofinalprice : 0;
4330 $occupancy_ovr = array();
4331 $losverridestr = "";
4332
4333 $updforvcm = $session->get('vbVcmRatesUpd', '');
4334 $updforvcm = empty($updforvcm) || !is_array($updforvcm) ? array() : $updforvcm;
4335
4336 // check null dates
4337 if ($dbo->getNullDate() == $pfrom) {
4338 $pfrom = '';
4339 }
4340 if ($dbo->getNullDate() == $pto) {
4341 $pto = '';
4342 }
4343
4344 if ((empty($pfrom) || empty($pto)) && !$pwdays) {
4345 VikError::raiseWarning('', JText::translate('ERRINVDATESEASON'));
4346 $app->redirect("index.php?option=com_vikbooking&task=editseason&cid[]=" . $pwhere);
4347 exit;
4348 }
4349
4350 $skipseason = false;
4351 if (empty($pfrom) || empty($pto)) {
4352 $skipseason = true;
4353 }
4354 $skipdays = false;
4355 $wdaystr = null;
4356 if (count($pwdays) == 0) {
4357 $skipdays = true;
4358 } else {
4359 $wdaystr = "";
4360 foreach ($pwdays as $wd) {
4361 $wdaystr .= $wd.';';
4362 }
4363 }
4364 $roomstr = "";
4365 $roomids = array();
4366 foreach ($pidrooms as $room) {
4367 if (empty($room)) {
4368 continue;
4369 }
4370 $roomstr .= "-".$room."-,";
4371 $roomids[] = (int)$room;
4372 }
4373 $pricestr = "";
4374 $priceids = array();
4375 foreach ($pidprices as $price) {
4376 if (empty($price)) {
4377 continue;
4378 }
4379 $pricestr .= "-".$price."-,";
4380 $priceids[] = (int)$price;
4381 }
4382 $valid = true;
4383 $double_records = array();
4384 $sfrom = null;
4385 $sto = null;
4386
4387 // value overrides
4388 if ($pnightsoverrides && $pvaluesoverrides) {
4389 foreach ($pnightsoverrides as $ko => $no) {
4390 if (!empty($no) && strlen(trim($pvaluesoverrides[$ko])) > 0) {
4391 $infiniteclause = intval($pandmoreoverride[$ko]) == 1 ? '-i' : '';
4392 $losverridestr .= intval($no).$infiniteclause.':'.trim($pvaluesoverrides[$ko]).'_';
4393 }
4394 }
4395 }
4396
4397 if (!$skipseason) {
4398 $first = VikBooking::getDateTimestamp($pfrom, 0, 0);
4399 $second = VikBooking::getDateTimestamp($pto, 0, 0);
4400
4401 if ($second > 0 && $second == $first) {
4402 $second += 86399;
4403 }
4404
4405 if (!($second > $first)) {
4406 VikError::raiseWarning('', JText::translate('ERRINVDATESEASON'));
4407 $app->redirect("index.php?option=com_vikbooking&task=editseason&cid[]=" . $pwhere);
4408 exit;
4409 }
4410
4411 $baseone = getdate($first);
4412 $basets = mktime(0, 0, 0, 1, 1, $baseone['year']);
4413 $sfrom = $baseone[0] - $basets;
4414 $basetwo = getdate($second);
4415 $basets = mktime(0, 0, 0, 1, 1, $basetwo['year']);
4416 $sto = $basetwo[0] - $basets;
4417
4418 // check leap year
4419 if ($baseone['year'] % 4 == 0 && ($baseone['year'] % 100 != 0 || $baseone['year'] % 400 == 0)) {
4420 $leapts = mktime(0, 0, 0, 2, 29, $baseone['year']);
4421 if ($baseone[0] > $leapts) {
4422 $sfrom -= 86400;
4423 /**
4424 * To avoid issue with leap years and dates near Feb 29th, we only reduce the seconds if these were reduced
4425 * for the from-date of the seasons. Doing it just for the to-date in 2019 for 2020 (leap) produced invalid results.
4426 *
4427 * @since July 2nd 2019
4428 */
4429 if ($basetwo['year'] % 4 == 0 && ($basetwo['year'] % 100 != 0 || $basetwo['year'] % 400 == 0)) {
4430 $leapts = mktime(0, 0, 0, 2, 29, $basetwo['year']);
4431 if ($basetwo[0] > $leapts) {
4432 $sto -= 86400;
4433 }
4434 }
4435 }
4436 }
4437
4438 // tied to the year
4439 if ($pyeartied == 1) {
4440 $tieyear = $baseone['year'];
4441 }
4442
4443 // Occupancy Override
4444 if (count($padultsdiffval) > 0) {
4445 foreach ($padultsdiffval as $rid => $valovr_arr) {
4446 if (!is_array($valovr_arr) || !is_array($padultsdiffchdisc[$rid]) || !is_array($padultsdiffvalpcent[$rid]) || !is_array($padultsdiffpernight[$rid])) {
4447 continue;
4448 }
4449 foreach ($valovr_arr as $occ => $valovr) {
4450 if (!(strlen($valovr) > 0) || !(strlen($padultsdiffchdisc[$rid][$occ]) > 0) || !(strlen($padultsdiffvalpcent[$rid][$occ]) > 0) || !(strlen($padultsdiffpernight[$rid][$occ]) > 0)) {
4451 continue;
4452 }
4453 if (!array_key_exists($rid, $occupancy_ovr)) {
4454 $occupancy_ovr[$rid] = array();
4455 }
4456 $occupancy_ovr[$rid][$occ] = array('chdisc' => (int)$padultsdiffchdisc[$rid][$occ], 'valpcent' => (int)$padultsdiffvalpcent[$rid][$occ], 'pernight' => (int)$padultsdiffpernight[$rid][$occ], 'value' => (float)$valovr);
4457 }
4458 }
4459 }
4460
4461 // check if seasons dates are valid
4462 $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").";";
4463 $dbo->setQuery($q);
4464 $similar = $dbo->loadAssocList();
4465 if ($similar) {
4466 $valid = false;
4467 foreach ($similar as $sim) {
4468 $double_records[] = $sim['spname'];
4469 }
4470 }
4471
4472 $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").";";
4473 $dbo->setQuery($q);
4474 $similar = $dbo->loadAssocList();
4475 if ($similar) {
4476 $valid = false;
4477 foreach ($similar as $sim) {
4478 $double_records[] = $sim['spname'];
4479 }
4480 }
4481
4482 $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").";";
4483 $dbo->setQuery($q);
4484 $dbo->execute();
4485 $similar = $dbo->loadAssocList();
4486 if ($similar) {
4487 $valid = false;
4488 foreach ($similar as $sim) {
4489 $double_records[] = $sim['spname'];
4490 }
4491 }
4492 }
4493
4494 // fetch previous record before the update
4495 $q = $dbo->getQuery(true)
4496 ->select('*')
4497 ->from($dbo->qn('#__vikbooking_seasons'))
4498 ->where($dbo->qn('id') . ' = ' . $pwhere);
4499 $dbo->setQuery($q, 0, 1);
4500 $prev_record = $dbo->loadAssoc();
4501
4502 if (!$valid || !$prev_record) {
4503 VikError::raiseWarning('', JText::translate('ERRINVDATEROOMSLOCSEASON').($double_records ? ' ('.implode(', ', array_unique($double_records)).')' : ''));
4504 $app->redirect("index.php?option=com_vikbooking&task=editseason&cid[]=" . $pwhere);
4505 exit;
4506 }
4507
4508 /**
4509 * Attempt to access the promotion handlers in advance to perform additional validations.
4510 *
4511 * @since 1.16.4 (J) - 1.6.4 (WP)
4512 */
4513 try {
4514 $promo_handlers = VikBooking::getPromotionHandlers();
4515 } catch (Exception $e) {
4516 // reset the value
4517 $promo_handlers = [];
4518 }
4519
4520 if (!$prev_record['promo'] && $ppromo && $promo_handlers) {
4521 // channels supporting promotions are available, and a regular special price is
4522 // being converted into a promotion - this is not allowed so we make it a non-promotion.
4523 $ppromo = 0;
4524 $app->enqueueMessage(JText::translate('VBO_NOPROMO_UPD_CHANNELS'), 'warning');
4525 }
4526
4527 // update record
4528 $upd_record = new stdClass;
4529 $upd_record->id = $prev_record['id'];
4530 $upd_record->type = $ptype == "1" ? 1 : 2;
4531 $upd_record->from = $sfrom;
4532 $upd_record->to = $sto;
4533 $upd_record->diffcost = $pdiffcost;
4534 $upd_record->idrooms = $roomstr;
4535 $upd_record->spname = $pspname;
4536 $upd_record->wdays = $wdaystr;
4537 $upd_record->checkinincl = $pcheckinincl;
4538 $upd_record->val_pcent = $pval_pcent;
4539 $upd_record->losoverride = $losverridestr;
4540 $upd_record->roundmode = !empty($proundmode) ? $proundmode : null;
4541 $upd_record->year = $pyeartied == 1 ? $tieyear : null;
4542 $upd_record->idprices = $pricestr;
4543 $upd_record->promo = $ppromo;
4544 $upd_record->promodaysadv = !empty($ppromodaysadv) ? $ppromodaysadv : null;
4545 $upd_record->promotxt = $ppromotxt;
4546 $upd_record->promominlos = !empty($ppromominlos) ? $ppromominlos : 0;
4547 $upd_record->occupancy_ovr = $occupancy_ovr ? json_encode($occupancy_ovr) : null;
4548 $upd_record->promolastmin = (int)$promolastmin;
4549 $upd_record->promofinalprice = $ppromofinalprice;
4550
4551 $dbo->updateObject('#__vikbooking_seasons', $upd_record, 'id');
4552
4553 $app->enqueueMessage(JText::translate('VBSEASONUPDATED'));
4554
4555 // update session values
4556 $updforvcm['count'] = array_key_exists('count', $updforvcm) && !empty($updforvcm['count']) ? ($updforvcm['count'] + 1) : 1;
4557 if (array_key_exists('dfrom', $updforvcm) && !empty($updforvcm['dfrom'])) {
4558 $updforvcm['dfrom'] = $updforvcm['dfrom'] > $first ? $first : $updforvcm['dfrom'];
4559 } else {
4560 $updforvcm['dfrom'] = $first;
4561 }
4562 if (array_key_exists('dto', $updforvcm) && !empty($updforvcm['dto'])) {
4563 $updforvcm['dto'] = $updforvcm['dto'] < $second ? $second : $updforvcm['dto'];
4564 } else {
4565 $updforvcm['dto'] = $second;
4566 }
4567 if (array_key_exists('rooms', $updforvcm) && is_array($updforvcm['rooms'])) {
4568 foreach ($roomids as $rid) {
4569 if (!in_array($rid, $updforvcm['rooms'])) {
4570 $updforvcm['rooms'][] = $rid;
4571 }
4572 }
4573 } else {
4574 $updforvcm['rooms'] = $roomids;
4575 }
4576 if (array_key_exists('rplans', $updforvcm) && is_array($updforvcm['rplans'])) {
4577 foreach ($roomids as $rid) {
4578 if (array_key_exists($rid, $updforvcm['rplans'])) {
4579 $updforvcm['rplans'][$rid] = $updforvcm['rplans'][$rid] + $priceids;
4580 } else {
4581 $updforvcm['rplans'][$rid] = $priceids;
4582 }
4583 }
4584 } else {
4585 $updforvcm['rplans'] = array();
4586 foreach ($roomids as $rid) {
4587 $updforvcm['rplans'][$rid] = $priceids;
4588 }
4589 }
4590 $session->set('vbVcmRatesUpd', $updforvcm);
4591
4592 /**
4593 * Query promotion handlers, if any, to trigger the update/delete promotion event.
4594 *
4595 * @since 1.15.0 (J) - 1.5.0 (WP)
4596 * @since 1.16.4 (J) - 1.6.4 (WP) added control to perform a delete operation.
4597 */
4598 $promo_update_type = $prev_record['promo'] && !$ppromo ? 'triggerDelete' : 'triggerUpdate';
4599 $promo_method_type = $prev_record['promo'] && !$ppromo ? 'delete' : 'update';
4600 try {
4601 if ($ppromo && is_array($promo_handlers) && $promo_handlers) {
4602 foreach ($promo_handlers as $promo_handler) {
4603 if (!isset($promo_handler->instance) || !is_object($promo_handler->instance) || !method_exists($promo_handler->instance, $promo_update_type)) {
4604 // outdated handler object
4605 continue;
4606 }
4607 if (!is_callable(array($promo_handler->instance, $promo_update_type)) || !$promo_handler->instance->{$promo_update_type}()) {
4608 // promotion handler does not support update/delete promotion event
4609 continue;
4610 }
4611 // invoke the update/delete promotion event for this handler
4612 $ch_result = $promo_handler->instance->createPromotion(['vbo_promo_id' => $pwhere], $promo_method_type);
4613 if (!$ch_result) {
4614 VikError::raiseWarning('', $promo_handler->instance->getName() . ': ' . $promo_handler->instance->getError());
4615 }
4616 }
4617 }
4618 } catch (Exception $e) {
4619 // do nothing
4620 }
4621
4622 if ($stay) {
4623 $app->redirect("index.php?option=com_vikbooking&task=editseason&cid[]=" . $pwhere);
4624 } else {
4625 $app->redirect("index.php?option=com_vikbooking&task=seasons");
4626 }
4627 $app->close();
4628 }
4629
4630 public function createseason()
4631 {
4632 if (!JSession::checkToken()) {
4633 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
4634 }
4635 $this->do_createseason();
4636 }
4637
4638 public function createseason_new()
4639 {
4640 if (!JSession::checkToken()) {
4641 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
4642 }
4643 $this->do_createseason(true);
4644 }
4645
4646 private function do_createseason($andnew = false)
4647 {
4648 $app = JFactory::getApplication();
4649 $dbo = JFactory::getDbo();
4650 $session = JFactory::getSession();
4651
4652 $pfrom = VikRequest::getString('from', '', 'request');
4653 $pto = VikRequest::getString('to', '', 'request');
4654 $ptype = VikRequest::getString('type', '', 'request');
4655 $pdiffcost = VikRequest::getFloat('diffcost', '', 'request');
4656 $pidrooms = VikRequest::getVar('idrooms', array());
4657 $pidprices = VikRequest::getVar('idprices', array());
4658 $pwdays = VikRequest::getVar('wdays', array());
4659 $pspname = VikRequest::getString('spname', '', 'request');
4660 $pcheckinincl = VikRequest::getString('checkinincl', '', 'request');
4661 $pcheckinincl = $pcheckinincl == 1 ? 1 : 0;
4662 $pyeartied = VikRequest::getString('yeartied', '', 'request');
4663 $pyeartied = $pyeartied == "1" ? 1 : 0;
4664 $tieyear = 0;
4665 $pval_pcent = VikRequest::getString('val_pcent', '', 'request');
4666 $pval_pcent = $pval_pcent == "1" ? 1 : 2;
4667 $proundmode = VikRequest::getString('roundmode', '', 'request');
4668 $proundmode = (!empty($proundmode) && in_array($proundmode, array('PHP_ROUND_HALF_UP', 'PHP_ROUND_HALF_DOWN')) ? $proundmode : '');
4669 $ppromo = VikRequest::getInt('promo', 0, 'request');
4670 $ppromodaysadv = VikRequest::getInt('promodaysadv', '', 'request');
4671 $ppromominlos = VikRequest::getInt('promominlos', '', 'request');
4672 $ppromotxt = VikRequest::getString('promotxt', '', 'request', VIKREQUEST_ALLOWHTML);
4673 $pnightsoverrides = VikRequest::getVar('nightsoverrides', array());
4674 $pvaluesoverrides = VikRequest::getVar('valuesoverrides', array());
4675 $pandmoreoverride = VikRequest::getVar('andmoreoverride', array());
4676 $padultsdiffchdisc = VikRequest::getVar('adultsdiffchdisc', array());
4677 $padultsdiffval = VikRequest::getVar('adultsdiffval', array());
4678 $padultsdiffvalpcent = VikRequest::getVar('adultsdiffvalpcent', array());
4679 $padultsdiffpernight = VikRequest::getVar('adultsdiffpernight', array());
4680 $ppromolastmind = VikRequest::getInt('promolastmind', 0, 'request');
4681 $ppromolastminh = VikRequest::getInt('promolastminh', 0, 'request');
4682 $promolastmin = ($ppromolastmind * 86400) + ($ppromolastminh * 3600);
4683 $ppromofinalprice = VikRequest::getInt('promofinalprice', 0, 'request');
4684 $ppromofinalprice = $ppromo ? $ppromofinalprice : 0;
4685 $pchannels = VikRequest::getVar('channels', array());
4686 $occupancy_ovr = array();
4687 $losverridestr = "";
4688
4689 $updforvcm = $session->get('vbVcmRatesUpd', '');
4690 $updforvcm = empty($updforvcm) || !is_array($updforvcm) ? array() : $updforvcm;
4691
4692 // check null dates
4693 if ($dbo->getNullDate() == $pfrom) {
4694 $pfrom = '';
4695 }
4696 if ($dbo->getNullDate() == $pto) {
4697 $pto = '';
4698 }
4699
4700 if ((empty($pfrom) || empty($pto)) && !$pwdays) {
4701 VikError::raiseWarning('', JText::translate('ERRINVDATESEASON'));
4702 $app->redirect("index.php?option=com_vikbooking&task=newseason");
4703 exit;
4704 }
4705
4706 $skipseason = false;
4707 if (empty($pfrom) || empty($pto)) {
4708 $skipseason = true;
4709 }
4710 $skipdays = false;
4711 $wdaystr = null;
4712 if (!$pwdays) {
4713 $skipdays = true;
4714 } else {
4715 $wdaystr = "";
4716 foreach ($pwdays as $wd) {
4717 $wdaystr .= $wd.';';
4718 }
4719 }
4720 $roomstr = "";
4721 $roomids = array();
4722 foreach ($pidrooms as $room) {
4723 if (empty($room)) {
4724 continue;
4725 }
4726 $roomstr .= "-".$room."-,";
4727 $roomids[] = (int)$room;
4728 }
4729 $pricestr = "";
4730 $priceids = array();
4731 foreach ($pidprices as $price) {
4732 if (empty($price)) {
4733 continue;
4734 }
4735 $pricestr .= "-".$price."-,";
4736 $priceids[] = (int)$price;
4737 }
4738 $valid = true;
4739 $double_records = array();
4740 $sfrom = null;
4741 $sto = null;
4742
4743 // value overrides
4744 if ($pnightsoverrides && $pvaluesoverrides) {
4745 foreach ($pnightsoverrides as $ko => $no) {
4746 if (!empty($no) && strlen(trim($pvaluesoverrides[$ko])) > 0) {
4747 $infiniteclause = intval($pandmoreoverride[$ko]) == 1 ? '-i' : '';
4748 $losverridestr .= intval($no).$infiniteclause.':'.trim($pvaluesoverrides[$ko]).'_';
4749 }
4750 }
4751 }
4752
4753 if (!$skipseason) {
4754 $first = VikBooking::getDateTimestamp($pfrom, 0, 0);
4755 $second = VikBooking::getDateTimestamp($pto, 0, 0);
4756
4757 if ($second > 0 && $second == $first) {
4758 $second += 86399;
4759 }
4760
4761 if (!($second > $first)) {
4762 VikError::raiseWarning('', JText::translate('ERRINVDATESEASON'));
4763 $app->redirect("index.php?option=com_vikbooking&task=newseason");
4764 exit;
4765 }
4766
4767 $baseone = getdate($first);
4768 $basets = mktime(0, 0, 0, 1, 1, $baseone['year']);
4769 $sfrom = $baseone[0] - $basets;
4770 $basetwo = getdate($second);
4771 $basets = mktime(0, 0, 0, 1, 1, $basetwo['year']);
4772 $sto = $basetwo[0] - $basets;
4773
4774 // check leap year
4775 if ($baseone['year'] % 4 == 0 && ($baseone['year'] % 100 != 0 || $baseone['year'] % 400 == 0)) {
4776 $leapts = mktime(0, 0, 0, 2, 29, $baseone['year']);
4777 if ($baseone[0] > $leapts) {
4778 $sfrom -= 86400;
4779 /**
4780 * To avoid issue with leap years and dates near Feb 29th, we only reduce the seconds if these were reduced
4781 * for the from-date of the seasons. Doing it just for the to-date in 2019 for 2020 (leap) produced invalid results.
4782 *
4783 * @since July 2nd 2019
4784 */
4785 if ($basetwo['year'] % 4 == 0 && ($basetwo['year'] % 100 != 0 || $basetwo['year'] % 400 == 0)) {
4786 $leapts = mktime(0, 0, 0, 2, 29, $basetwo['year']);
4787 if ($basetwo[0] > $leapts) {
4788 $sto -= 86400;
4789 }
4790 }
4791 }
4792 }
4793
4794 // tied to the year
4795 if ($pyeartied == 1) {
4796 $tieyear = $baseone['year'];
4797 }
4798
4799 // Occupancy Override
4800 if ($padultsdiffval) {
4801 foreach ($padultsdiffval as $rid => $valovr_arr) {
4802 if (!is_array($valovr_arr) || !is_array($padultsdiffchdisc[$rid]) || !is_array($padultsdiffvalpcent[$rid]) || !is_array($padultsdiffpernight[$rid])) {
4803 continue;
4804 }
4805 foreach ($valovr_arr as $occ => $valovr) {
4806 if (!(strlen($valovr) > 0) || !(strlen($padultsdiffchdisc[$rid][$occ]) > 0) || !(strlen($padultsdiffvalpcent[$rid][$occ]) > 0) || !(strlen($padultsdiffpernight[$rid][$occ]) > 0)) {
4807 continue;
4808 }
4809 if (!array_key_exists($rid, $occupancy_ovr)) {
4810 $occupancy_ovr[$rid] = array();
4811 }
4812 $occupancy_ovr[$rid][$occ] = array('chdisc' => (int)$padultsdiffchdisc[$rid][$occ], 'valpcent' => (int)$padultsdiffvalpcent[$rid][$occ], 'pernight' => (int)$padultsdiffpernight[$rid][$occ], 'value' => (float)$valovr);
4813 }
4814 }
4815 }
4816
4817 // check if seasons dates are valid
4818 $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").";";
4819 $dbo->setQuery($q);
4820 $similar = $dbo->loadAssocList();
4821 if ($similar) {
4822 $valid = false;
4823 foreach ($similar as $sim) {
4824 $double_records[] = $sim['spname'];
4825 }
4826 }
4827
4828 $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").";";
4829 $dbo->setQuery($q);
4830 $similar = $dbo->loadAssocList();
4831 if ($similar) {
4832 $valid = false;
4833 foreach ($similar as $sim) {
4834 $double_records[] = $sim['spname'];
4835 }
4836 }
4837
4838 $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").";";
4839 $dbo->setQuery($q);
4840 $similar = $dbo->loadAssocList();
4841 if ($similar) {
4842 $valid = false;
4843 foreach ($similar as $sim) {
4844 $double_records[] = $sim['spname'];
4845 }
4846 }
4847 }
4848
4849 if (!$valid && !$ppromo) {
4850 VikError::raiseWarning('', JText::translate('ERRINVDATEROOMSLOCSEASON').(count($double_records) ? ' ('.implode(', ', array_unique($double_records)).')' : ''));
4851 $app->redirect("index.php?option=com_vikbooking&task=newseason");
4852 exit;
4853 }
4854
4855 // insert new record
4856 $sea_record = new stdClass;
4857 $sea_record->type = $ptype == "1" ? 1 : 2;
4858 $sea_record->from = $sfrom;
4859 $sea_record->to = $sto;
4860 $sea_record->diffcost = $pdiffcost;
4861 $sea_record->idrooms = $roomstr;
4862 $sea_record->spname = $pspname;
4863 $sea_record->wdays = $wdaystr;
4864 $sea_record->checkinincl = $pcheckinincl;
4865 $sea_record->val_pcent = $pval_pcent;
4866 $sea_record->losoverride = $losverridestr;
4867 $sea_record->roundmode = !empty($proundmode) ? $proundmode : null;
4868 $sea_record->year = $pyeartied == 1 ? $tieyear : null;
4869 $sea_record->idprices = $pricestr;
4870 $sea_record->promo = $ppromo == 1 ? 1 : 0;
4871 $sea_record->promodaysadv = !empty($ppromodaysadv) ? $ppromodaysadv : null;
4872 $sea_record->promotxt = $ppromotxt;
4873 $sea_record->promominlos = !empty($ppromominlos) ? $ppromominlos : 0;
4874 $sea_record->occupancy_ovr = $occupancy_ovr ? json_encode($occupancy_ovr) : null;
4875 $sea_record->promolastmin = (int)$promolastmin;
4876 $sea_record->promofinalprice = $ppromofinalprice;
4877
4878 $dbo->insertObject('#__vikbooking_seasons', $sea_record, 'id');
4879
4880 $vbo_promo_id = $sea_record->id;
4881
4882 $app->enqueueMessage(JText::translate('VBSEASONSAVED'));
4883
4884 // update session values
4885 $updforvcm['count'] = array_key_exists('count', $updforvcm) && !empty($updforvcm['count']) ? ($updforvcm['count'] + 1) : 1;
4886 if (array_key_exists('dfrom', $updforvcm) && !empty($updforvcm['dfrom'])) {
4887 $updforvcm['dfrom'] = $updforvcm['dfrom'] > $first ? $first : $updforvcm['dfrom'];
4888 } else {
4889 $updforvcm['dfrom'] = $first;
4890 }
4891 if (array_key_exists('dto', $updforvcm) && !empty($updforvcm['dto'])) {
4892 $updforvcm['dto'] = $updforvcm['dto'] < $second ? $second : $updforvcm['dto'];
4893 } else {
4894 $updforvcm['dto'] = $second;
4895 }
4896 if (array_key_exists('rooms', $updforvcm) && is_array($updforvcm['rooms'])) {
4897 foreach ($roomids as $rid) {
4898 if (!in_array($rid, $updforvcm['rooms'])) {
4899 $updforvcm['rooms'][] = $rid;
4900 }
4901 }
4902 } else {
4903 $updforvcm['rooms'] = $roomids;
4904 }
4905 if (array_key_exists('rplans', $updforvcm) && is_array($updforvcm['rplans'])) {
4906 foreach ($roomids as $rid) {
4907 if (array_key_exists($rid, $updforvcm['rplans'])) {
4908 $updforvcm['rplans'][$rid] = $updforvcm['rplans'][$rid] + $priceids;
4909 } else {
4910 $updforvcm['rplans'][$rid] = $priceids;
4911 }
4912 }
4913 } else {
4914 $updforvcm['rplans'] = array();
4915 foreach ($roomids as $rid) {
4916 $updforvcm['rplans'][$rid] = $priceids;
4917 }
4918 }
4919 if (!$ppromo) {
4920 $session->set('vbVcmRatesUpd', $updforvcm);
4921 }
4922
4923 /**
4924 * Create the promotion also on the selected channels
4925 *
4926 * @since 1.13.0 (J) - 1.3.0 (WP)
4927 */
4928 if ($ppromo && $pchannels) {
4929 foreach ($pchannels as $channel_key) {
4930 $promo_obj = VikBooking::getPromotionHandlers($channel_key);
4931 if (!is_object($promo_obj)) {
4932 continue;
4933 }
4934 /**
4935 * We inject for VCM the ID of the newly created promotion in VBO.
4936 *
4937 * @since 1.15.0 (J) - 1.5.0 (WP)
4938 */
4939 $ch_result = $promo_obj->createPromotion(array('vbo_promo_id' => $vbo_promo_id), 'new');
4940 if (!$ch_result) {
4941 VikError::raiseWarning('', $promo_obj->getName() . ': ' . $promo_obj->getError());
4942 } else {
4943 $resp = $promo_obj->getResponse();
4944 $app->enqueueMessage($promo_obj->getName() . ': ' . JText::translate('VBOCHPROMOSUCCESS') . (!empty($resp) ? ' (' . str_replace('e4j.ok.', '', $resp) . ')' : ''));
4945 // in case of success, unset the current session values in VCM
4946 $session->set('vcmBPromo', '');
4947 }
4948 }
4949 }
4950
4951 $app->redirect("index.php?option=com_vikbooking&task=".($andnew ? 'newseason' : 'seasons'));
4952 $app->close();
4953 }
4954
4955 public function removeseasons()
4956 {
4957 if (!JSession::checkToken()) {
4958 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
4959 }
4960 $app = JFactory::getApplication();
4961 $dbo = JFactory::getDbo();
4962
4963 $ids = VikRequest::getVar('cid', array(0));
4964 $pidroom = VikRequest::getInt('idroom', '', 'request');
4965 $pwhere = VikRequest::getInt('where', '', 'request');
4966 if (!empty($pwhere)) {
4967 $ids[] = $pwhere;
4968 }
4969 $tot_removed = array();
4970 $prev_promos = array();
4971 foreach ($ids as $d) {
4972 if (empty($d)) {
4973 continue;
4974 }
4975 // check if it was a promotion
4976 $q = "SELECT `id` FROM `#__vikbooking_seasons` WHERE `id`=" . (int)$d . " AND `promo`=1;";
4977 $dbo->setQuery($q);
4978 $dbo->execute();
4979 if ($dbo->getNumRows()) {
4980 // push it as a previous promo
4981 array_push($prev_promos, $d);
4982 }
4983
4984 // delete the record
4985 $q = "DELETE FROM `#__vikbooking_seasons` WHERE `id`=".$dbo->quote($d).";";
4986 $dbo->setQuery($q);
4987 $dbo->execute();
4988 $tot_removed[] = $d;
4989 }
4990
4991 /**
4992 * Query promotion handlers, if any, to trigger the delete promotion event.
4993 *
4994 * @since 1.15.0 (J) - 1.5.0 (WP)
4995 */
4996 $promo_handlers = VikBooking::getPromotionHandlers();
4997 foreach ($prev_promos as $vbo_promo_id) {
4998 try {
4999 if (is_array($promo_handlers)) {
5000 foreach ($promo_handlers as $promo_handler) {
5001 if (!isset($promo_handler->instance) || !is_object($promo_handler->instance) || !method_exists($promo_handler->instance, 'triggerDelete')) {
5002 // outdated handler object
5003 continue;
5004 }
5005 if (!is_callable(array($promo_handler->instance, 'triggerDelete')) || !$promo_handler->instance->triggerDelete()) {
5006 // promotion handler does not support delete promotion event
5007 continue;
5008 }
5009 // invoke the delete promotion event for this handler
5010 $ch_result = $promo_handler->instance->createPromotion(array('vbo_promo_id' => $vbo_promo_id), 'delete');
5011 if (!$ch_result) {
5012 VikError::raiseWarning('', $promo_handler->instance->getName() . ': ' . $promo_handler->instance->getError());
5013 }
5014 }
5015 }
5016 } catch (Exception $e) {
5017 // do nothing
5018 }
5019 }
5020
5021 $app->enqueueMessage(JText::sprintf('VBRECORDSREMOVED', count($tot_removed)));
5022 $app->redirect("index.php?option=com_vikbooking&task=seasons".(!empty($pidroom) ? '&idroom='.$pidroom : ''));
5023 $app->close();
5024 }
5025
5026 public function updatecustomer() {
5027 if (!JSession::checkToken()) {
5028 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
5029 }
5030 $this->do_updatecustomer();
5031 }
5032
5033 public function updatecustomerstay() {
5034 if (!JSession::checkToken()) {
5035 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
5036 }
5037 $this->do_updatecustomer(true);
5038 }
5039
5040 private function do_updatecustomer($stay = false) {
5041 $dbo = JFactory::getDbo();
5042 $mainframe = JFactory::getApplication();
5043 $pfirst_name = VikRequest::getString('first_name', '', 'request');
5044 $plast_name = VikRequest::getString('last_name', '', 'request');
5045 $pcompany = VikRequest::getString('company', '', 'request');
5046 $pvat = VikRequest::getString('vat', '', 'request');
5047 $pemail = VikRequest::getString('email', '', 'request');
5048 $pphone = VikRequest::getString('phone', '', 'request');
5049 $pcountry = VikRequest::getString('country', '', 'request');
5050 $pstate = VikRequest::getString('state', '', 'request');
5051 $ppin = VikRequest::getString('pin', '', 'request');
5052 $pujid = VikRequest::getInt('ujid', '', 'request');
5053 $paddress = VikRequest::getString('address', '', 'request');
5054 $pcity = VikRequest::getString('city', '', 'request');
5055 $pzip = VikRequest::getString('zip', '', 'request');
5056 $pfisccode = VikRequest::getString('fisccode', '', 'request');
5057 $ppec = VikRequest::getString('pec', '', 'request');
5058 $precipcode = VikRequest::getString('recipcode', '', 'request');
5059 $pgender = VikRequest::getString('gender', '', 'request');
5060 $pgender = in_array($pgender, array('F', 'M')) ? $pgender : '';
5061 $pbdate = VikRequest::getString('bdate', '', 'request');
5062 $ppbirth = VikRequest::getString('pbirth', '', 'request');
5063 $pdoctype = VikRequest::getString('doctype', '', 'request');
5064 $pdocnum = VikRequest::getString('docnum', '', 'request');
5065 $pnotes = VikRequest::getString('notes', '', 'request');
5066 $pscandocimg = VikRequest::getString('scandocimg', '', 'request');
5067 $pischannel = VikRequest::getInt('ischannel', '', 'request');
5068 $pcommission = VikRequest::getFloat('commission', '', 'request');
5069 $pcalccmmon = VikRequest::getInt('calccmmon', '', 'request');
5070 $papplycmmon = VikRequest::getInt('applycmmon', '', 'request');
5071 $pchname = VikRequest::getString('chname', '', 'request');
5072 $pchcolor = VikRequest::getString('chcolor', '', 'request');
5073 $pwhere = VikRequest::getInt('where', '', 'request');
5074 $ptmpl = VikRequest::getString('tmpl', '', 'request');
5075 $pcheckin = VikRequest::getInt('checkin', '', 'request');
5076 $pbid = VikRequest::getInt('bid', '', 'request');
5077 $pgoto = VikRequest::getString('goto', '', 'request', VIKREQUEST_ALLOWRAW);
5078 if (!empty($pwhere) && !empty($pfirst_name) && !empty($plast_name) && !empty($pemail)) {
5079 $q = "SELECT * FROM `#__vikbooking_customers` WHERE `id`=".(int)$pwhere." LIMIT 1;";
5080 $dbo->setQuery($q);
5081 $dbo->execute();
5082 if ($dbo->getNumRows() == 1) {
5083 $customer = $dbo->loadAssoc();
5084 } else {
5085 $mainframe->redirect("index.php?option=com_vikbooking&task=customers");
5086 exit;
5087 }
5088 /**
5089 * Existing customers are recognized by equal first name, last name and email address.
5090 *
5091 * @since 1.3.0
5092 */
5093 $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;";
5094 $dbo->setQuery($q);
5095 $dbo->execute();
5096 if ($dbo->getNumRows() == 0) {
5097 $cpin = VikBooking::getCPinIstance();
5098 if (empty($ppin)) {
5099 $ppin = $customer['pin'];
5100 } elseif ($cpin->pinExists($ppin, $customer['pin'])) {
5101 $ppin = $cpin->generateUniquePin();
5102 }
5103 //file upload
5104 jimport('joomla.filesystem.file');
5105 $pimg = VikRequest::getVar('docimg', null, 'files', 'array');
5106 $gimg = "";
5107 if (isset($pimg) && strlen(trim($pimg['name']))) {
5108 $filename = JFile::makeSafe(rand(100, 9999).str_replace(" ", "_", strtolower($pimg['name'])));
5109 $src = $pimg['tmp_name'];
5110 $dest = VBO_ADMIN_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'idscans'.DIRECTORY_SEPARATOR;
5111 $j = "";
5112 if (file_exists($dest.$filename)) {
5113 $j = rand(171, 1717);
5114 while (file_exists($dest.$j.$filename)) {
5115 $j++;
5116 }
5117 }
5118 $finaldest = $dest.$j.$filename;
5119 $check = getimagesize($pimg['tmp_name']);
5120 if (($check[2] & imagetypes()) || preg_match("/application\/(zip|pdf)$/", $pimg['type'])) {
5121 if (VikBooking::uploadFile($src, $finaldest)) {
5122 $gimg = $j.$filename;
5123 } else {
5124 VikError::raiseWarning('', 'Error while uploading image');
5125 }
5126 } else {
5127 VikError::raiseWarning('', 'Uploaded file is not an Image');
5128 }
5129 } elseif (!empty($pscandocimg)) {
5130 $gimg = $pscandocimg;
5131 }
5132 //
5133 $pischannel = $pischannel > 0 ? 1 : 0;
5134 $pcalccmmon = $pcalccmmon > 0 ? 1 : 0;
5135 $papplycmmon = $papplycmmon > 0 ? 1 : 0;
5136 $pchname = str_replace(' ', '', trim($pchname));
5137 $pchname = strlen($pchname) <= 0 && $pischannel > 0 ? str_replace(' ', '', trim($pfirst_name.' '.$plast_name)) : $pchname;
5138 $chparams = array(
5139 'commission' => ($pcommission > 0.00 ? $pcommission : 0),
5140 'calccmmon' => $pcalccmmon,
5141 'applycmmon' => $papplycmmon,
5142 'chcolor' => $pchcolor,
5143 'chname' => $pchname
5144 );
5145
5146 /**
5147 * Customer profile picture (URL or uploaded file).
5148 *
5149 * @since 1.15.3 (J) - 1.5.5 (WP)
5150 */
5151 $customer_pic = VikRequest::getString('pic', '', 'request');
5152 $customer_pic_img = VikRequest::getVar('picimg', null, 'files', 'array');
5153 if (is_array($customer_pic_img) && !empty($customer_pic_img['name'])) {
5154 $filename = JFile::makeSafe(rand(100, 9999).str_replace(" ", "_", strtolower($customer_pic_img['name'])));
5155 $src = $customer_pic_img['tmp_name'];
5156 $dest = VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR;
5157 $j = "";
5158 if (is_file($dest.$filename)) {
5159 $j = rand(1, 99999);
5160 while (is_file($dest . $j .$filename)) {
5161 $j++;
5162 }
5163 }
5164 $finaldest = $dest . $j . $filename;
5165 $check = getimagesize($customer_pic_img['tmp_name']);
5166 if (($check[2] & imagetypes())) {
5167 if (VikBooking::uploadFile($src, $finaldest)) {
5168 $customer_pic = $j . $filename;
5169 } else {
5170 VikError::raiseWarning('', 'Error while uploading image');
5171 }
5172 } else {
5173 VikError::raiseWarning('', 'Uploaded file is not an Image');
5174 }
5175 }
5176
5177 // update customer object
5178 $new_customer = new stdClass;
5179 $new_customer->id = (int)$pwhere;
5180 $new_customer->first_name = $pfirst_name;
5181 $new_customer->last_name = $plast_name;
5182 $new_customer->email = $pemail;
5183 $new_customer->phone = $pphone;
5184 $new_customer->country = $pcountry;
5185 $new_customer->pin = $ppin;
5186 $new_customer->ujid = $pujid;
5187 $new_customer->address = $paddress;
5188 $new_customer->city = $pcity;
5189 $new_customer->zip = $pzip;
5190 $new_customer->state = $pstate;
5191 $new_customer->doctype = $pdoctype;
5192 $new_customer->docnum = $pdocnum;
5193 if (!empty($gimg)) {
5194 $new_customer->docimg = $gimg;
5195 }
5196 $new_customer->notes = $pnotes;
5197 $new_customer->ischannel = $pischannel;
5198 $new_customer->chdata = json_encode($chparams);
5199 $new_customer->company = $pcompany;
5200 $new_customer->vat = $pvat;
5201 $new_customer->gender = $pgender;
5202 $new_customer->bdate = $pbdate;
5203 $new_customer->pbirth = $ppbirth;
5204 $new_customer->fisccode = $pfisccode;
5205 $new_customer->pec = $ppec;
5206 $new_customer->recipcode = $precipcode;
5207 $new_customer->pic = $customer_pic;
5208 /**
5209 * We need to update the previous information stored through
5210 * the custom fields when making a reservation for/by this client.
5211 *
5212 * @since 1.13
5213 */
5214 $skip_prev_fields = array(
5215 'id',
5216 'ujid',
5217 'docimg',
5218 'ischannel',
5219 'chdata',
5220 'notes',
5221 );
5222 if (!empty($customer['cfields'])) {
5223 $custf_info = json_decode($customer['cfields'], true);
5224 foreach ($new_customer as $fname => $fnewval) {
5225 if (!isset($customer[$fname]) || in_array($fname, $skip_prev_fields)) {
5226 continue;
5227 }
5228 // seek for old value in custom fields submitted
5229 foreach ($custf_info as $k => $v) {
5230 if (!empty($customer[$fname]) && $v == $customer[$fname]) {
5231 // field found, replace it with the new value
5232 $custf_info[$k] = $fnewval;
5233 }
5234 }
5235 }
5236 // update record on db
5237 $new_customer->cfields = json_encode($custf_info);
5238 }
5239 //
5240
5241 $dbo->updateObject('#__vikbooking_customers', $new_customer, 'id');
5242
5243 $cpin->pluginCustomerSync($pwhere, 'update');
5244 //Update all the bookings affected by this Customer ID as a sales channel
5245 $source_name = 'customer'.$pwhere.'_'.$pchname;
5246 if ($pischannel > 0) {
5247 $oid_clause = '';
5248 if ($customer['ischannel'] < 1) {
5249 //Was not a sales channel but now it is, so update all his bookings
5250 $q = "SELECT `idorder` FROM `#__vikbooking_customers_orders` WHERE `idcustomer`=".$customer['id'].";";
5251 $dbo->setQuery($q);
5252 $dbo->execute();
5253 if ($dbo->getNumRows() > 0) {
5254 $all_bids = $dbo->loadAssocList();
5255 $bids = array();
5256 foreach ($all_bids as $bid) {
5257 if (!in_array($bid['idorder'], $bids)) {
5258 $bids[] = $bid['idorder'];
5259 }
5260 }
5261 $oid_clause = " OR `id` IN (".implode(',', $bids).")";
5262 }
5263 }
5264 $q = "UPDATE `#__vikbooking_orders` SET `channel`=".$dbo->quote($source_name)." WHERE `channel` LIKE 'customer".$pwhere."%'".$oid_clause.";";
5265 } else {
5266 $q = "UPDATE `#__vikbooking_orders` SET `channel`=NULL,`cmms`=NULL WHERE `channel` LIKE 'customer".$pwhere."%';";
5267 }
5268 $dbo->setQuery($q);
5269 $dbo->execute();
5270 //
5271 $mainframe->enqueueMessage(JText::translate('VBCUSTOMERSAVED'));
5272 } else {
5273 //email already exists
5274 $ex_customer = $dbo->loadAssoc();
5275 //check if coming from the Check-in view or not
5276 if (!empty($pcheckin) && !empty($pbid)) {
5277 VikError::raiseWarning('', JText::translate('VBERRCUSTOMEREMAILEXISTS').' ('.$ex_customer['first_name'].' '.$ex_customer['last_name'].')');
5278 /**
5279 * @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
5280 */
5281 $mainframe->redirect("index.php?option=com_vikbooking&task=editorder&cid[]=".$pbid);
5282 //
5283 exit;
5284 } elseif (!empty($pgoto)) {
5285 // check if coming from a specific task
5286 VikError::raiseWarning('', JText::translate('VBERRCUSTOMEREMAILEXISTS').' ('.$ex_customer['first_name'].' '.$ex_customer['last_name'].')');
5287 $mainframe->redirect(base64_decode($pgoto));
5288 exit;
5289 } else {
5290 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>');
5291 $mainframe->redirect("index.php?option=com_vikbooking&task=editcustomer&cid[]=".$pwhere);
5292 exit;
5293 }
5294 }
5295 }
5296
5297 //check if coming from the Check-in view
5298 if (!empty($pcheckin) && !empty($pbid)) {
5299 /**
5300 * @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
5301 */
5302 $mainframe->redirect("index.php?option=com_vikbooking&task=editorder&cid[]=" . $pbid);
5303 exit;
5304 }
5305
5306 if ($stay) {
5307 $mainframe->redirect("index.php?option=com_vikbooking&task=editcustomer&cid[]=" . $pwhere . (!empty($pgoto) ? '&goto=' . $pgoto : ''));
5308 exit;
5309 }
5310
5311 // check if coming from a specific task
5312 if (!empty($pgoto)) {
5313 $mainframe->redirect(base64_decode($pgoto));
5314 exit;
5315 }
5316
5317 $mainframe->redirect("index.php?option=com_vikbooking&task=customers");
5318 }
5319
5320 public function savecustomer() {
5321 if (!JSession::checkToken()) {
5322 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
5323 }
5324 $dbo = JFactory::getDbo();
5325 $mainframe = JFactory::getApplication();
5326 $pfirst_name = VikRequest::getString('first_name', '', 'request');
5327 $plast_name = VikRequest::getString('last_name', '', 'request');
5328 $pcompany = VikRequest::getString('company', '', 'request');
5329 $pvat = VikRequest::getString('vat', '', 'request');
5330 $pemail = VikRequest::getString('email', '', 'request');
5331 $pphone = VikRequest::getString('phone', '', 'request');
5332 $pcountry = VikRequest::getString('country', '', 'request');
5333 $pstate = VikRequest::getString('state', '', 'request');
5334 $ppin = VikRequest::getString('pin', '', 'request');
5335 $pujid = VikRequest::getInt('ujid', '', 'request');
5336 $paddress = VikRequest::getString('address', '', 'request');
5337 $pcity = VikRequest::getString('city', '', 'request');
5338 $pzip = VikRequest::getString('zip', '', 'request');
5339 $pfisccode = VikRequest::getString('fisccode', '', 'request');
5340 $ppec = VikRequest::getString('pec', '', 'request');
5341 $precipcode = VikRequest::getString('recipcode', '', 'request');
5342 $pgender = VikRequest::getString('gender', '', 'request');
5343 $pgender = in_array($pgender, array('F', 'M')) ? $pgender : '';
5344 $pbdate = VikRequest::getString('bdate', '', 'request');
5345 $ppbirth = VikRequest::getString('pbirth', '', 'request');
5346 $pdoctype = VikRequest::getString('doctype', '', 'request');
5347 $pdocnum = VikRequest::getString('docnum', '', 'request');
5348 $pnotes = VikRequest::getString('notes', '', 'request');
5349 $pscandocimg = VikRequest::getString('scandocimg', '', 'request');
5350 $pischannel = VikRequest::getInt('ischannel', '', 'request');
5351 $pcommission = VikRequest::getFloat('commission', '', 'request');
5352 $pcalccmmon = VikRequest::getInt('calccmmon', '', 'request');
5353 $papplycmmon = VikRequest::getInt('applycmmon', '', 'request');
5354 $pchname = VikRequest::getString('chname', '', 'request');
5355 $pchcolor = VikRequest::getString('chcolor', '', 'request');
5356 $ptmpl = VikRequest::getString('tmpl', '', 'request');
5357 $pcheckin = VikRequest::getInt('checkin', '', 'request');
5358 $pgoto = VikRequest::getString('goto', '', 'request', VIKREQUEST_ALLOWRAW);
5359 $pbid = VikRequest::getInt('bid', '', 'request');
5360 if (!empty($pfirst_name) && !empty($plast_name) && !empty($pemail)) {
5361 $cpin = VikBooking::getCPinIstance();
5362 /**
5363 * Existing customers are recognized by equal first name, last name and email address.
5364 *
5365 * @since 1.3.0
5366 */
5367 $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;";
5368 $dbo->setQuery($q);
5369 $dbo->execute();
5370 if ($dbo->getNumRows() == 0) {
5371 if (empty($ppin)) {
5372 $ppin = $cpin->generateUniquePin();
5373 } elseif ($cpin->pinExists($ppin)) {
5374 $ppin = $cpin->generateUniquePin();
5375 }
5376 //file upload
5377 jimport('joomla.filesystem.file');
5378 $pimg = VikRequest::getVar('docimg', null, 'files', 'array');
5379 $gimg = "";
5380 if (isset($pimg) && strlen(trim($pimg['name']))) {
5381 $filename = JFile::makeSafe(rand(100, 9999).str_replace(" ", "_", strtolower($pimg['name'])));
5382 $src = $pimg['tmp_name'];
5383 $dest = VBO_ADMIN_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'idscans'.DIRECTORY_SEPARATOR;
5384 $j = "";
5385 if (file_exists($dest.$filename)) {
5386 $j = rand(171, 1717);
5387 while (file_exists($dest.$j.$filename)) {
5388 $j++;
5389 }
5390 }
5391 $finaldest = $dest.$j.$filename;
5392 $check = getimagesize($pimg['tmp_name']);
5393 if (($check[2] & imagetypes()) || preg_match("/application\/(zip|pdf)$/", $pimg['type'])) {
5394 if (VikBooking::uploadFile($src, $finaldest)) {
5395 $gimg = $j.$filename;
5396 } else {
5397 VikError::raiseWarning('', 'Error while uploading image');
5398 }
5399 } else {
5400 VikError::raiseWarning('', 'Uploaded file is not an Image');
5401 }
5402 } elseif (!empty($pscandocimg)) {
5403 $gimg = $pscandocimg;
5404 }
5405 //
5406 $pischannel = $pischannel > 0 ? 1 : 0;
5407 $pcalccmmon = $pcalccmmon > 0 ? 1 : 0;
5408 $papplycmmon = $papplycmmon > 0 ? 1 : 0;
5409 $pchname = str_replace(' ', '', trim($pchname));
5410 $pchname = strlen($pchname) <= 0 && $pischannel > 0 ? str_replace(' ', '', trim($pfirst_name.' '.$plast_name)) : $pchname;
5411 $chparams = array(
5412 'commission' => ($pcommission > 0.00 ? $pcommission : 0),
5413 'calccmmon' => $pcalccmmon,
5414 'applycmmon' => $papplycmmon,
5415 'chcolor' => $pchcolor,
5416 'chname' => $pchname
5417 );
5418
5419 /**
5420 * Customer profile picture (URL or uploaded file).
5421 *
5422 * @since 1.15.3 (J) - 1.5.5 (WP)
5423 */
5424 $customer_pic = VikRequest::getString('pic', '', 'request');
5425 $customer_pic_img = VikRequest::getVar('picimg', null, 'files', 'array');
5426 if (is_array($customer_pic_img) && !empty($customer_pic_img['name'])) {
5427 $filename = JFile::makeSafe(rand(100, 9999).str_replace(" ", "_", strtolower($customer_pic_img['name'])));
5428 $src = $customer_pic_img['tmp_name'];
5429 $dest = VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR;
5430 $j = "";
5431 if (is_file($dest.$filename)) {
5432 $j = rand(1, 99999);
5433 while (is_file($dest . $j .$filename)) {
5434 $j++;
5435 }
5436 }
5437 $finaldest = $dest . $j . $filename;
5438 $check = getimagesize($customer_pic_img['tmp_name']);
5439 if (($check[2] & imagetypes())) {
5440 if (VikBooking::uploadFile($src, $finaldest)) {
5441 $customer_pic = $j . $filename;
5442 } else {
5443 VikError::raiseWarning('', 'Error while uploading image');
5444 }
5445 } else {
5446 VikError::raiseWarning('', 'Uploaded file is not an Image');
5447 }
5448 }
5449
5450 $q = "INSERT INTO `#__vikbooking_customers` (`first_name`,`last_name`,`email`,`phone`,`country`,`pin`,`ujid`,`address`,`city`,`zip`,`state`,`doctype`,`docnum`,`docimg`,`notes`,`ischannel`,`chdata`,`company`,`vat`,`gender`,`bdate`,`pbirth`,`fisccode`,`pec`,`recipcode`,`pic`) VALUES(".$dbo->quote($pfirst_name).", ".$dbo->quote($plast_name).", ".$dbo->quote($pemail).", ".$dbo->quote($pphone).", ".$dbo->quote($pcountry).", ".$dbo->quote($ppin).", ".$dbo->quote($pujid).", ".$dbo->quote($paddress).", ".$dbo->quote($pcity).", ".$dbo->quote($pzip).", ".$dbo->quote($pstate).", ".$dbo->quote($pdoctype).", ".$dbo->quote($pdocnum).", ".$dbo->quote($gimg).", ".$dbo->quote($pnotes).", ".$pischannel.", ".$dbo->quote(json_encode($chparams)).", ".$dbo->quote($pcompany).", ".$dbo->quote($pvat).", ".$dbo->quote($pgender).", ".$dbo->quote($pbdate).", ".$dbo->quote($ppbirth).", ".$dbo->quote($pfisccode).", ".$dbo->quote($ppec).", ".$dbo->quote($precipcode).", " . (!empty($customer_pic) ? $dbo->quote($customer_pic) : 'NULL') . ");";
5451 $dbo->setQuery($q);
5452 $dbo->execute();
5453 $lid = $dbo->insertid();
5454 $cpin->pluginCustomerSync($lid, 'insert');
5455 if (!empty($lid)) {
5456 $mainframe->enqueueMessage(JText::translate('VBCUSTOMERSAVED'));
5457 //check if coming from the Check-in view
5458 if (!empty($pcheckin) && !empty($pbid)) {
5459 $cpin->setNewPin($ppin);
5460 $cpin->setNewCustomerId($lid);
5461 $cpin->saveCustomerBooking($pbid);
5462 /**
5463 * @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
5464 */
5465 $mainframe->redirect("index.php?option=com_vikbooking&task=editorder&cid[]=".$pbid);
5466 //
5467 exit;
5468 }
5469 // check if coming from a specific task
5470 if (!empty($pgoto) && !empty($pbid)) {
5471 $cpin->setNewPin($ppin);
5472 $cpin->setNewCustomerId($lid);
5473 $cpin->saveCustomerBooking($pbid);
5474 $mainframe->redirect(base64_decode($pgoto));
5475 exit;
5476 }
5477 }
5478 } else {
5479 //email already exists
5480 $ex_customer = $dbo->loadAssoc();
5481 //check if coming from the Check-in view or not
5482 if (!empty($pcheckin) && !empty($pbid)) {
5483 $cpin->setNewPin($ex_customer['pin']);
5484 $cpin->setNewCustomerId($ex_customer['id']);
5485 $cpin->saveCustomerBooking($pbid);
5486 VikError::raiseWarning('', JText::translate('VBERRCUSTOMEREMAILEXISTS').' ('.$ex_customer['first_name'].' '.$ex_customer['last_name'].')');
5487 /**
5488 * @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
5489 */
5490 $mainframe->redirect("index.php?option=com_vikbooking&task=editorder&cid[]=".$pbid);
5491 //
5492 exit;
5493 } elseif (!empty($pgoto) && !empty($pbid)) {
5494 // check if coming from a specific task
5495 $cpin->setNewPin($ex_customer['pin']);
5496 $cpin->setNewCustomerId($ex_customer['id']);
5497 $cpin->saveCustomerBooking($pbid);
5498 VikError::raiseWarning('', JText::translate('VBERRCUSTOMEREMAILEXISTS').' ('.$ex_customer['first_name'].' '.$ex_customer['last_name'].')');
5499 $mainframe->redirect(base64_decode($pgoto));
5500 exit;
5501 } else {
5502 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>');
5503 }
5504 }
5505 }
5506 $mainframe->redirect("index.php?option=com_vikbooking&task=customers");
5507 }
5508
5509 public function customers() {
5510 VikBookingHelper::printHeader("22");
5511
5512 VikRequest::setVar('view', VikRequest::getCmd('view', 'customers'));
5513
5514 parent::display();
5515
5516 if (VikBooking::showFooter()) {
5517 VikBookingHelper::printFooter();
5518 }
5519 }
5520
5521 public function newcustomer() {
5522 VikBookingHelper::printHeader("22");
5523
5524 VikRequest::setVar('view', VikRequest::getCmd('view', 'managecustomer'));
5525
5526 parent::display();
5527
5528 if (VikBooking::showFooter()) {
5529 VikBookingHelper::printFooter();
5530 }
5531 }
5532
5533 public function editcustomer() {
5534 VikBookingHelper::printHeader("22");
5535
5536 VikRequest::setVar('view', VikRequest::getCmd('view', 'managecustomer'));
5537
5538 parent::display();
5539
5540 if (VikBooking::showFooter()) {
5541 VikBookingHelper::printFooter();
5542 }
5543 }
5544
5545 public function removecustomers() {
5546 if (!JSession::checkToken()) {
5547 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
5548 }
5549 $ids = VikRequest::getVar('cid', array(0));
5550 if (@count($ids)) {
5551 $dbo = JFactory::getDBO();
5552 $cpin = VikBooking::getCPinIstance();
5553 foreach ($ids as $d) {
5554 $cpin->pluginCustomerSync($d, 'delete');
5555 $q = "DELETE FROM `#__vikbooking_customers` WHERE `id`=".(int)$d.";";
5556 $dbo->setQuery($q);
5557 $dbo->execute();
5558 }
5559 }
5560 $mainframe = JFactory::getApplication();
5561 $mainframe->redirect("index.php?option=com_vikbooking&task=customers");
5562 }
5563
5564 public function restrictions() {
5565 VikBookingHelper::printHeader("restrictions");
5566
5567 VikRequest::setVar('view', VikRequest::getCmd('view', 'restrictions'));
5568
5569 parent::display();
5570
5571 if (VikBooking::showFooter()) {
5572 VikBookingHelper::printFooter();
5573 }
5574 }
5575
5576 public function newrestriction() {
5577 VikBookingHelper::printHeader("restrictions");
5578
5579 VikRequest::setVar('view', VikRequest::getCmd('view', 'managerestriction'));
5580
5581 parent::display();
5582
5583 if (VikBooking::showFooter()) {
5584 VikBookingHelper::printFooter();
5585 }
5586 }
5587
5588 public function editrestriction() {
5589 VikBookingHelper::printHeader("restrictions");
5590
5591 VikRequest::setVar('view', VikRequest::getCmd('view', 'managerestriction'));
5592
5593 parent::display();
5594
5595 if (VikBooking::showFooter()) {
5596 VikBookingHelper::printFooter();
5597 }
5598 }
5599
5600 public function createrestriction() {
5601 if (!JSession::checkToken()) {
5602 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
5603 }
5604 $dbo = JFactory::getDBO();
5605 $session = JFactory::getSession();
5606 $mainframe = JFactory::getApplication();
5607 $updforvcm = $session->get('vbVcmRatesUpd', '');
5608 $updforvcm = empty($updforvcm) || !is_array($updforvcm) ? array() : $updforvcm;
5609 $pname = VikRequest::getString('name', '', 'request');
5610 $pmonth = VikRequest::getInt('month', '', 'request');
5611 $pmonth = empty($pmonth) ? 0 : $pmonth;
5612 $pname = empty($pname) ? 'Restriction '.$pmonth : $pname;
5613 $pdfrom = VikRequest::getString('dfrom', '', 'request');
5614 $pdto = VikRequest::getString('dto', '', 'request');
5615 $pwday = VikRequest::getString('wday', '', 'request');
5616 $pwdaytwo = VikRequest::getString('wdaytwo', '', 'request');
5617 $pwdaytwo = strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday == $pwdaytwo ? '' : $pwdaytwo;
5618 $pcomboa = VikRequest::getString('comboa', '', 'request');
5619 $pcomboa = strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo ? $pcomboa : '';
5620 $pcombob = VikRequest::getString('combob', '', 'request');
5621 $pcombob = strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo ? $pcombob : '';
5622 $pcomboc = VikRequest::getString('comboc', '', 'request');
5623 $pcomboc = strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo ? $pcomboc : '';
5624 $pcombod = VikRequest::getString('combod', '', 'request');
5625 $pcombod = strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo ? $pcombod : '';
5626 $combostr = '';
5627 $combostr .= strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo && !empty($pcomboa) ? $pcomboa.':' : ':';
5628 $combostr .= strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo && !empty($pcombob) ? $pcombob.':' : ':';
5629 $combostr .= strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo && !empty($pcomboc) ? $pcomboc.':' : ':';
5630 $combostr .= strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo && !empty($pcombod) ? $pcombod : '';
5631 $pminlos = VikRequest::getInt('minlos', '', 'request');
5632 $pminlos = $pminlos < 1 ? 1 : $pminlos;
5633 $pmaxlos = VikRequest::getInt('maxlos', '', 'request');
5634 $pmaxlos = empty($pmaxlos) ? 0 : $pmaxlos;
5635 $pmultiplyminlos = VikRequest::getString('multiplyminlos', '', 'request');
5636 $pmultiplyminlos = empty($pmultiplyminlos) ? 0 : 1;
5637 $pallrooms = VikRequest::getString('allrooms', '', 'request');
5638 $pallrooms = $pallrooms == "1" ? 1 : 0;
5639 $pidrooms = VikRequest::getVar('idrooms', array(0));
5640 $ridr = '';
5641 $roomidsforsess = array();
5642 if (!empty($pidrooms) && @count($pidrooms) && $pallrooms == 0) {
5643 foreach ($pidrooms as $idr) {
5644 if (empty($idr)) {
5645 continue;
5646 }
5647 $ridr .= '-'.$idr.'-;';
5648 $roomidsforsess[] = (int)$idr;
5649 }
5650 } elseif ($pallrooms > 0) {
5651 $q = "SELECT `id` FROM `#__vikbooking_rooms`;";
5652 $dbo->setQuery($q);
5653 $dbo->execute();
5654 if ($dbo->getNumRows() > 0) {
5655 $fetchids = $dbo->loadAssocList();
5656 foreach ($fetchids as $fetchid) {
5657 $roomidsforsess[] = (int)$fetchid['id'];
5658 }
5659 }
5660 }
5661 $pcta = VikRequest::getInt('cta', '', 'request');
5662 $pctd = VikRequest::getInt('ctd', '', 'request');
5663 $pctad = VikRequest::getVar('ctad', array());
5664 $pctdd = VikRequest::getVar('ctdd', array());
5665 if ($pminlos == 1 && strlen($pwday) == 0 && empty($pctad) && empty($pctdd) && $pmaxlos < 1) {
5666 // VBO 1.11 - we now allow restrictions with just 1 night of stay
5667 // VikError::raiseWarning('', JText::translate('VBUSELESSRESTRICTION'));
5668 // $mainframe->redirect("index.php?option=com_vikbooking&task=newrestriction");
5669 // exit;
5670 }
5671
5672 //check if there are restrictions for this month
5673 if ($pmonth > 0) {
5674 $q = "SELECT `id` FROM `#__vikbooking_restrictions` WHERE `month`='".$pmonth."';";
5675 $dbo->setQuery($q);
5676 $dbo->execute();
5677 if ($dbo->getNumRows() > 0) {
5678 VikError::raiseWarning('', JText::translate('VBRESTRICTIONMONTHEXISTS'));
5679 $mainframe->redirect("index.php?option=com_vikbooking&task=newrestriction");
5680 exit;
5681 }
5682 $pdfrom = 0;
5683 $pdto = 0;
5684 } else {
5685 //dates range
5686 if (empty($pdfrom) || empty($pdto)) {
5687 VikError::raiseWarning('', JText::translate('VBRESTRICTIONERRDRANGE'));
5688 $mainframe->redirect("index.php?option=com_vikbooking&task=newrestriction");
5689 exit;
5690 } else {
5691 $housto = $pdfrom == $pdto ? 23 : 0;
5692 $minsto = $pdfrom == $pdto ? 59 : 0;
5693 $secsto = $pdfrom == $pdto ? 59 : 0;
5694 $pdfrom = VikBooking::getDateTimestamp($pdfrom, 0, 0);
5695 $pdto = VikBooking::getDateTimestamp($pdto, $housto, $minsto, $secsto);
5696 }
5697 if ($pdfrom > $pdto) {
5698 // invalid dates in the past
5699 VikError::raiseWarning('', JText::translate('VBRESTRICTIONERRDRANGE'));
5700 $mainframe->redirect("index.php?option=com_vikbooking&task=newrestriction");
5701 exit;
5702 }
5703 }
5704 //CTA and CTD
5705 $setcta = array();
5706 $setctd = array();
5707 if ($pcta > 0 && count($pctad) > 0) {
5708 foreach ($pctad as $ctwd) {
5709 if (strlen($ctwd)) {
5710 $setcta[] = '-'.(int)$ctwd.'-';
5711 }
5712 }
5713 }
5714 if ($pctd > 0 && count($pctdd) > 0) {
5715 foreach ($pctdd as $ctwd) {
5716 if (strlen($ctwd)) {
5717 $setctd[] = '-'.(int)$ctwd.'-';
5718 }
5719 }
5720 }
5721 //
5722 //update session values
5723 if (!($pdfrom > 0)) {
5724 $attemptyear = (int)date('Y');
5725 $attemptfrom = mktime(0, 0, 0, $pmonth, 1, $attemptyear);
5726 if ($attemptfrom < time()) {
5727 $attemptyear++;
5728 $attemptfrom = mktime(0, 0, 0, $pmonth, 1, $attemptyear);
5729 }
5730 $attemptto = mktime(0, 0, 0, $pmonth, date('t', $attemptfrom), $attemptyear);
5731 } else {
5732 $attemptfrom = $pdfrom;
5733 $attemptto = $pdto;
5734 }
5735 $updforvcm['count'] = array_key_exists('count', $updforvcm) && !empty($updforvcm['count']) ? ($updforvcm['count'] + 1) : 1;
5736 if (array_key_exists('dfrom', $updforvcm) && !empty($updforvcm['dfrom'])) {
5737 $updforvcm['dfrom'] = $updforvcm['dfrom'] > $attemptfrom ? $attemptfrom : $updforvcm['dfrom'];
5738 } else {
5739 $updforvcm['dfrom'] = $attemptfrom;
5740 }
5741 if (array_key_exists('dto', $updforvcm) && !empty($updforvcm['dto'])) {
5742 $updforvcm['dto'] = $updforvcm['dto'] < $attemptto ? $attemptto : $updforvcm['dto'];
5743 } else {
5744 $updforvcm['dto'] = $attemptto;
5745 }
5746 if (array_key_exists('rooms', $updforvcm) && is_array($updforvcm['rooms'])) {
5747 foreach ($roomidsforsess as $rid) {
5748 if (!in_array($rid, $updforvcm['rooms'])) {
5749 $updforvcm['rooms'][] = $rid;
5750 }
5751 }
5752 } else {
5753 $updforvcm['rooms'] = $roomidsforsess;
5754 }
5755 if (!array_key_exists('rplans', $updforvcm) || !is_array($updforvcm['rplans'])) {
5756 $updforvcm['rplans'] = array();
5757 }
5758 $session->set('vbVcmRatesUpd', $updforvcm);
5759 //
5760 $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").");";
5761 $dbo->setQuery($q);
5762 $dbo->execute();
5763 $lid = $dbo->insertid();
5764 if (!empty($lid)) {
5765 /**
5766 * Repeat restriction on the selected week days until the limit
5767 *
5768 * @since 1.13
5769 */
5770 $prepeat = VikRequest::getInt('repeat', 0, 'request');
5771 $prepeatuntil = VikRequest::getString('repeatuntil', '', 'request');
5772 if ($prepeat > 0 && !empty($prepeatuntil) && $pdfrom > 0 && $pdto > 0) {
5773 $repeat_intervals = array();
5774 $start = getdate($pdfrom);
5775 $end = getdate($pdto);
5776 $wdays = array();
5777 while ($start[0] <= $end[0]) {
5778 // push requested week day
5779 array_push($wdays, $start['wday']);
5780 // next day
5781 $start = getdate(mktime($start['hours'], $start['minutes'], $start['seconds'], $start['mon'], ($start['mday'] + 1), $start['year']));
5782 }
5783 $dtuntil = VikBooking::getDateTimestamp($prepeatuntil, 23, 59, 59);
5784 if (count($wdays) < 7 && $dtuntil > $pdto) {
5785 // increment end date for the repeat
5786 $end = getdate(mktime($end['hours'], $end['minutes'], $end['seconds'], $end['mon'], ($end['mday'] + 1), $end['year']));
5787 //
5788 $until_info = getdate($dtuntil);
5789 $interval = array();
5790 while ($end[0] <= $until_info[0]) {
5791 if (in_array($end['wday'], $wdays)) {
5792 if (!isset($interval['from'])) {
5793 $interval['from'] = $end[0];
5794 }
5795 $interval['to'] = $end[0];
5796 } else {
5797 if (isset($interval['from'])) {
5798 // append interval
5799 array_push($repeat_intervals, $interval);
5800 // reset interval
5801 $interval = array();
5802 }
5803 }
5804 // next day
5805 $end = getdate(mktime($end['hours'], $end['minutes'], $end['seconds'], $end['mon'], ($end['mday'] + 1), $end['year']));
5806 }
5807 if (isset($interval['from'])) {
5808 // append last hanging interval
5809 array_push($repeat_intervals, $interval);
5810 }
5811 if (count($repeat_intervals)) {
5812 // create the repeated records for the calculated intervals
5813 $repeat_count = 2;
5814 foreach ($repeat_intervals as $rp) {
5815 if (date('Y-m-d', $rp['from']) == date('Y-m-d', $rp['to'])) {
5816 // adjust time in case of equal dates (1 single day restriction)
5817 $rpfrom = getdate($rp['from']);
5818 $rpto = getdate($rp['to']);
5819 $rp['from'] = mktime(0, 0, 0, $rpfrom['mon'], $rpfrom['mday'], $rpfrom['year']);
5820 /**
5821 * The end date of the restriction must cover the whole day until 23:59:59.
5822 *
5823 * @since 1.15.4 (J) - 1.5.4 (WP)
5824 */
5825 $rp['to'] = mktime(23, 59, 59, $rpto['mon'], $rpto['mday'], $rpto['year']);
5826 }
5827 // adjust name
5828 $restr_rp_name = $pname . " #{$repeat_count}";
5829 //
5830 $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").");";
5831 $dbo->setQuery($q);
5832 $dbo->execute();
5833 $lid = $dbo->insertid();
5834 if (!empty($lid)) {
5835 $repeat_count++;
5836 }
5837 }
5838 }
5839 }
5840 }
5841 //
5842 $mainframe->enqueueMessage(JText::translate('VBRESTRICTIONSAVED'));
5843 $mainframe->redirect("index.php?option=com_vikbooking&task=restrictions");
5844 } else {
5845 VikError::raiseWarning('', 'Error while saving');
5846 $mainframe->redirect("index.php?option=com_vikbooking&task=newrestriction");
5847 }
5848 }
5849
5850 public function updaterestriction() {
5851 if (!JSession::checkToken()) {
5852 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
5853 }
5854 $dbo = JFactory::getDBO();
5855 $session = JFactory::getSession();
5856 $mainframe = JFactory::getApplication();
5857 $updforvcm = $session->get('vbVcmRatesUpd', '');
5858 $updforvcm = empty($updforvcm) || !is_array($updforvcm) ? array() : $updforvcm;
5859 $pwhere = VikRequest::getInt('where', '', 'request');
5860 $pname = VikRequest::getString('name', '', 'request');
5861 $pmonth = VikRequest::getInt('month', '', 'request');
5862 $pmonth = empty($pmonth) ? 0 : $pmonth;
5863 $pname = empty($pname) ? 'Restriction '.$pmonth : $pname;
5864 $pdfrom = VikRequest::getString('dfrom', '', 'request');
5865 $pdto = VikRequest::getString('dto', '', 'request');
5866 $pwday = VikRequest::getString('wday', '', 'request');
5867 $pwdaytwo = VikRequest::getString('wdaytwo', '', 'request');
5868 $pwdaytwo = strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday == $pwdaytwo ? '' : $pwdaytwo;
5869 $pcomboa = VikRequest::getString('comboa', '', 'request');
5870 $pcomboa = strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo ? $pcomboa : '';
5871 $pcombob = VikRequest::getString('combob', '', 'request');
5872 $pcombob = strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo ? $pcombob : '';
5873 $pcomboc = VikRequest::getString('comboc', '', 'request');
5874 $pcomboc = strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo ? $pcomboc : '';
5875 $pcombod = VikRequest::getString('combod', '', 'request');
5876 $pcombod = strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo ? $pcombod : '';
5877 $combostr = '';
5878 $combostr .= strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo && !empty($pcomboa) ? $pcomboa.':' : ':';
5879 $combostr .= strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo && !empty($pcombob) ? $pcombob.':' : ':';
5880 $combostr .= strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo && !empty($pcomboc) ? $pcomboc.':' : ':';
5881 $combostr .= strlen($pwday) > 0 && strlen($pwdaytwo) > 0 && $pwday != $pwdaytwo && !empty($pcombod) ? $pcombod : '';
5882 $pminlos = VikRequest::getInt('minlos', '', 'request');
5883 $pminlos = $pminlos < 1 ? 1 : $pminlos;
5884 $pmaxlos = VikRequest::getInt('maxlos', '', 'request');
5885 $pmaxlos = empty($pmaxlos) ? 0 : $pmaxlos;
5886 $pmultiplyminlos = VikRequest::getString('multiplyminlos', '', 'request');
5887 $pmultiplyminlos = empty($pmultiplyminlos) ? 0 : 1;
5888 $pallrooms = VikRequest::getString('allrooms', '', 'request');
5889 $pallrooms = $pallrooms == "1" ? 1 : 0;
5890 $pidrooms = VikRequest::getVar('idrooms', array(0));
5891 $ridr = '';
5892 $roomidsforsess = array();
5893 if (!empty($pidrooms) && @count($pidrooms) && $pallrooms == 0) {
5894 foreach ($pidrooms as $idr) {
5895 if (empty($idr)) {
5896 continue;
5897 }
5898 $ridr .= '-'.$idr.'-;';
5899 $roomidsforsess[] = (int)$idr;
5900 }
5901 } elseif ($pallrooms > 0) {
5902 $q = "SELECT `id` FROM `#__vikbooking_rooms`;";
5903 $dbo->setQuery($q);
5904 $dbo->execute();
5905 if ($dbo->getNumRows() > 0) {
5906 $fetchids = $dbo->loadAssocList();
5907 foreach ($fetchids as $fetchid) {
5908 $roomidsforsess[] = (int)$fetchid['id'];
5909 }
5910 }
5911 }
5912 $pcta = VikRequest::getInt('cta', '', 'request');
5913 $pctd = VikRequest::getInt('ctd', '', 'request');
5914 $pctad = VikRequest::getVar('ctad', array());
5915 $pctdd = VikRequest::getVar('ctdd', array());
5916 if ($pminlos == 1 && strlen($pwday) == 0 && empty($pctad) && empty($pctdd) && $pmaxlos < 1) {
5917 // VBO 1.11 - we now allow restrictions with just 1 night of stay
5918 // VikError::raiseWarning('', JText::translate('VBUSELESSRESTRICTION'));
5919 // $mainframe->redirect("index.php?option=com_vikbooking&task=editrestriction&cid[]=".$pwhere);
5920 // exit;
5921 }
5922 //check if there are restrictions for this month
5923 if ($pmonth > 0) {
5924 $q = "SELECT `id` FROM `#__vikbooking_restrictions` WHERE `month`='".$pmonth."' AND `id`!='".$pwhere."';";
5925 $dbo->setQuery($q);
5926 $dbo->execute();
5927 if ($dbo->getNumRows() > 0) {
5928 VikError::raiseWarning('', JText::translate('VBRESTRICTIONMONTHEXISTS'));
5929 $mainframe->redirect("index.php?option=com_vikbooking&task=editrestriction&cid[]=".$pwhere);
5930 exit;
5931 }
5932 $pdfrom = 0;
5933 $pdto = 0;
5934 } else {
5935 //dates range
5936 if (empty($pdfrom) || empty($pdto)) {
5937 VikError::raiseWarning('', JText::translate('VBRESTRICTIONERRDRANGE'));
5938 $mainframe->redirect("index.php?option=com_vikbooking&task=editrestriction&cid[]=".$pwhere);
5939 exit;
5940 } else {
5941 $housto = $pdfrom == $pdto ? 23 : 0;
5942 $minsto = $pdfrom == $pdto ? 59 : 0;
5943 $secsto = $pdfrom == $pdto ? 59 : 0;
5944 $pdfrom = VikBooking::getDateTimestamp($pdfrom, 0, 0);
5945 $pdto = VikBooking::getDateTimestamp($pdto, $housto, $minsto, $secsto);
5946 }
5947 if ($pdfrom > $pdto) {
5948 // invalid dates in the past
5949 VikError::raiseWarning('', JText::translate('VBRESTRICTIONERRDRANGE'));
5950 $mainframe->redirect("index.php?option=com_vikbooking&task=editrestriction&cid[]=".$pwhere);
5951 exit;
5952 }
5953 }
5954 //CTA and CTD
5955 $setcta = array();
5956 $setctd = array();
5957 if ($pcta > 0 && count($pctad) > 0) {
5958 foreach ($pctad as $ctwd) {
5959 if (strlen($ctwd)) {
5960 $setcta[] = '-'.(int)$ctwd.'-';
5961 }
5962 }
5963 }
5964 if ($pctd > 0 && count($pctdd) > 0) {
5965 foreach ($pctdd as $ctwd) {
5966 if (strlen($ctwd)) {
5967 $setctd[] = '-'.(int)$ctwd.'-';
5968 }
5969 }
5970 }
5971 //
5972 //update session values
5973 if (!($pdfrom > 0)) {
5974 $attemptyear = (int)date('Y');
5975 $attemptfrom = mktime(0, 0, 0, $pmonth, 1, $attemptyear);
5976 if ($attemptfrom < time()) {
5977 $attemptyear++;
5978 $attemptfrom = mktime(0, 0, 0, $pmonth, 1, $attemptyear);
5979 }
5980 $attemptto = mktime(0, 0, 0, $pmonth, date('t', $attemptfrom), $attemptyear);
5981 } else {
5982 $attemptfrom = $pdfrom;
5983 $attemptto = $pdto;
5984 }
5985 $updforvcm['count'] = array_key_exists('count', $updforvcm) && !empty($updforvcm['count']) ? ($updforvcm['count'] + 1) : 1;
5986 if (array_key_exists('dfrom', $updforvcm) && !empty($updforvcm['dfrom'])) {
5987 $updforvcm['dfrom'] = $updforvcm['dfrom'] > $attemptfrom ? $attemptfrom : $updforvcm['dfrom'];
5988 } else {
5989 $updforvcm['dfrom'] = $attemptfrom;
5990 }
5991 if (array_key_exists('dto', $updforvcm) && !empty($updforvcm['dto'])) {
5992 $updforvcm['dto'] = $updforvcm['dto'] < $attemptto ? $attemptto : $updforvcm['dto'];
5993 } else {
5994 $updforvcm['dto'] = $attemptto;
5995 }
5996 if (array_key_exists('rooms', $updforvcm) && is_array($updforvcm['rooms'])) {
5997 foreach ($roomidsforsess as $rid) {
5998 if (!in_array($rid, $updforvcm['rooms'])) {
5999 $updforvcm['rooms'][] = $rid;
6000 }
6001 }
6002 } else {
6003 $updforvcm['rooms'] = $roomidsforsess;
6004 }
6005 if (!array_key_exists('rplans', $updforvcm) || !is_array($updforvcm['rplans'])) {
6006 $updforvcm['rplans'] = array();
6007 }
6008 $session->set('vbVcmRatesUpd', $updforvcm);
6009 //
6010 $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."';";
6011 $dbo->setQuery($q);
6012 $dbo->execute();
6013 $mainframe->enqueueMessage(JText::translate('VBRESTRICTIONSAVED'));
6014 $mainframe->redirect("index.php?option=com_vikbooking&task=restrictions");
6015 }
6016
6017 public function removerestrictions() {
6018 if (!JSession::checkToken()) {
6019 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6020 }
6021 $ids = VikRequest::getVar('cid', array(0));
6022 if (@count($ids)) {
6023 $dbo = JFactory::getDBO();
6024 foreach ($ids as $d) {
6025 $q = "DELETE FROM `#__vikbooking_restrictions` WHERE `id`=".(int)$d.";";
6026 $dbo->setQuery($q);
6027 $dbo->execute();
6028 }
6029 }
6030 $mainframe = JFactory::getApplication();
6031 $mainframe->redirect("index.php?option=com_vikbooking&task=restrictions");
6032 }
6033
6034 public function prices() {
6035 VikBookingHelper::printHeader("1");
6036
6037 VikRequest::setVar('view', VikRequest::getCmd('view', 'prices'));
6038
6039 parent::display();
6040
6041 if (VikBooking::showFooter()) {
6042 VikBookingHelper::printFooter();
6043 }
6044 }
6045
6046 public function newprice() {
6047 VikBookingHelper::printHeader("1");
6048
6049 VikRequest::setVar('view', VikRequest::getCmd('view', 'manageprice'));
6050
6051 parent::display();
6052
6053 if (VikBooking::showFooter()) {
6054 VikBookingHelper::printFooter();
6055 }
6056 }
6057
6058 public function editprice() {
6059 VikBookingHelper::printHeader("1");
6060
6061 VikRequest::setVar('view', VikRequest::getCmd('view', 'manageprice'));
6062
6063 parent::display();
6064
6065 if (VikBooking::showFooter()) {
6066 VikBookingHelper::printFooter();
6067 }
6068 }
6069
6070 public function createprice() {
6071 if (!JSession::checkToken()) {
6072 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6073 }
6074 $this->do_createprice();
6075 }
6076
6077 public function createprice_new() {
6078 if (!JSession::checkToken()) {
6079 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6080 }
6081 $this->do_createprice(true);
6082 }
6083
6084 private function do_createprice($new = false)
6085 {
6086 $pprice = VikRequest::getString('price', '', 'request');
6087 $pattr = VikRequest::getString('attr', '', 'request');
6088 $ppraliq = VikRequest::getInt('praliq', '', 'request');
6089 $pmeal_plans = (array)VikRequest::getVar('meal_plans', []);
6090 $pbreakfast_included = in_array('breakfast', $pmeal_plans) ? 1 : 0;
6091 $pfree_cancellation = VikRequest::getInt('free_cancellation', 0, 'request');
6092 $pfree_cancellation = $pfree_cancellation == 1 ? 1 : 0;
6093 $pcanc_deadline = VikRequest::getInt('canc_deadline', '', 'request');
6094 $pminlos = VikRequest::getInt('minlos', 0, 'request');
6095 $pminlos = $pminlos < 0 ? 0 : $pminlos;
6096 $pminhadv = VikRequest::getInt('minhadv', '', 'request');
6097 $pminhadv = $pminhadv < 0 ? 0 : $pminhadv;
6098 $pcanc_policy = VikRequest::getString('canc_policy', '', 'request', VIKREQUEST_ALLOWHTML);
6099 if (!empty($pprice)) {
6100 $dbo = JFactory::getDbo();
6101 $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)) . ");";
6102 $dbo->setQuery($q);
6103 $dbo->execute();
6104 }
6105
6106 $app = JFactory::getApplication();
6107 $app->redirect("index.php?option=com_vikbooking&task=" . ($new ? 'newprice' : 'prices'));
6108 $app->close();
6109 }
6110
6111 public function updateprice()
6112 {
6113 if (!JSession::checkToken()) {
6114 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6115 }
6116 $this->do_updateprice();
6117 }
6118
6119 public function updatepricestay()
6120 {
6121 if (!JSession::checkToken()) {
6122 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6123 }
6124 $this->do_updateprice(true);
6125 }
6126
6127 private function do_updateprice($stay = false)
6128 {
6129 $pprice = VikRequest::getString('price', '', 'request');
6130 $pattr = VikRequest::getString('attr', '', 'request');
6131 $ppraliq = VikRequest::getInt('praliq', '', 'request');
6132 $pmeal_plans = (array)VikRequest::getVar('meal_plans', []);
6133 $pbreakfast_included = in_array('breakfast', $pmeal_plans) ? 1 : 0;
6134 $pfree_cancellation = VikRequest::getInt('free_cancellation', '', 'request');
6135 $pfree_cancellation = $pfree_cancellation == 1 ? 1 : 0;
6136 $pcanc_deadline = VikRequest::getInt('canc_deadline', '', 'request');
6137 $pminlos = VikRequest::getInt('minlos', 0, 'request');
6138 $pminlos = $pminlos < 0 ? 0 : $pminlos;
6139 $pminhadv = VikRequest::getInt('minhadv', '', 'request');
6140 $pminhadv = $pminhadv < 0 ? 0 : $pminhadv;
6141 $pcanc_policy = VikRequest::getString('canc_policy', '', 'request', VIKREQUEST_ALLOWHTML);
6142 $pwhereup = VikRequest::getInt('whereup', 0, 'request');
6143 if (!empty($pprice) && $pwhereup) {
6144 $dbo = JFactory::getDbo();
6145 $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) . ";";
6146 $dbo->setQuery($q);
6147 $dbo->execute();
6148 }
6149
6150 $app = JFactory::getApplication();
6151 $app->redirect("index.php?option=com_vikbooking&task=" . ($stay ? 'editprice&cid[]=' . $pwhereup : 'prices'));
6152 $app->close();
6153 }
6154
6155 public function removeprice() {
6156 if (!JSession::checkToken()) {
6157 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6158 }
6159 $ids = VikRequest::getVar('cid', array(0));
6160 if (@count($ids)) {
6161 $dbo = JFactory::getDBO();
6162 foreach ($ids as $d) {
6163 $q = "DELETE FROM `#__vikbooking_prices` WHERE `id`=".$dbo->quote($d).";";
6164 $dbo->setQuery($q);
6165 $dbo->execute();
6166 $q = "DELETE FROM `#__vikbooking_dispcost` WHERE `idprice`=".intval($d).";";
6167 $dbo->setQuery($q);
6168 $dbo->execute();
6169 }
6170 }
6171 $mainframe = JFactory::getApplication();
6172 $mainframe->redirect("index.php?option=com_vikbooking&task=prices");
6173 }
6174
6175 public function iva() {
6176 VikBookingHelper::printHeader("2");
6177
6178 VikRequest::setVar('view', VikRequest::getCmd('view', 'iva'));
6179
6180 parent::display();
6181
6182 if (VikBooking::showFooter()) {
6183 VikBookingHelper::printFooter();
6184 }
6185 }
6186
6187 public function newiva() {
6188 VikBookingHelper::printHeader("2");
6189
6190 VikRequest::setVar('view', VikRequest::getCmd('view', 'manageiva'));
6191
6192 parent::display();
6193
6194 if (VikBooking::showFooter()) {
6195 VikBookingHelper::printFooter();
6196 }
6197 }
6198
6199 public function editiva() {
6200 VikBookingHelper::printHeader("2");
6201
6202 VikRequest::setVar('view', VikRequest::getCmd('view', 'manageiva'));
6203
6204 parent::display();
6205
6206 if (VikBooking::showFooter()) {
6207 VikBookingHelper::printFooter();
6208 }
6209 }
6210
6211 public function createiva() {
6212 if (!JSession::checkToken()) {
6213 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6214 }
6215 $paliqname = VikRequest::getString('aliqname', '', 'request');
6216 $paliqperc = VikRequest::getFloat('aliqperc', '', 'request');
6217 $pbreakdown_name = VikRequest::getVar('breakdown_name', array());
6218 $pbreakdown_rate = VikRequest::getVar('breakdown_rate', array());
6219 $ptaxcap = VikRequest::getFloat('taxcap', 0, 'request');
6220 if (!empty($paliqperc)) {
6221 $dbo = JFactory::getDBO();
6222 $breakdown_str = '';
6223 if (count($pbreakdown_name) > 0) {
6224 $breakdown_values = array();
6225 $bkcount = 0;
6226 $tot_sub_aliq = 0;
6227 foreach ($pbreakdown_name as $key => $subtax) {
6228 if (!empty($subtax) && floatval($pbreakdown_rate[$key]) > 0) {
6229 $breakdown_values[$bkcount]['name'] = $subtax;
6230 $breakdown_values[$bkcount]['aliq'] = (float)$pbreakdown_rate[$key];
6231 $tot_sub_aliq += (float)$pbreakdown_rate[$key];
6232 $bkcount++;
6233 }
6234 }
6235 if (count($breakdown_values) > 0) {
6236 $breakdown_str = json_encode($breakdown_values);
6237 if ($tot_sub_aliq < (float)$paliqperc || $tot_sub_aliq > (float)$paliqperc) {
6238 VikError::raiseWarning('', JText::translate('VBOTAXBKDWNERRNOMATCH'));
6239 }
6240 }
6241 }
6242 $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').");";
6243 $dbo->setQuery($q);
6244 $dbo->execute();
6245 }
6246 $mainframe = JFactory::getApplication();
6247 $mainframe->redirect("index.php?option=com_vikbooking&task=iva");
6248 }
6249
6250 public function updateiva() {
6251 if (!JSession::checkToken()) {
6252 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6253 }
6254 $paliqname = VikRequest::getString('aliqname', '', 'request');
6255 $paliqperc = VikRequest::getFloat('aliqperc', '', 'request');
6256 $pbreakdown_name = VikRequest::getVar('breakdown_name', array());
6257 $pbreakdown_rate = VikRequest::getVar('breakdown_rate', array());
6258 $ptaxcap = VikRequest::getFloat('taxcap', 0, 'request');
6259 $pwhereup = VikRequest::getInt('whereup', 0, 'request');
6260 if (!empty($paliqperc)) {
6261 $dbo = JFactory::getDBO();
6262 $breakdown_str = '';
6263 if (count($pbreakdown_name) > 0) {
6264 $breakdown_values = array();
6265 $bkcount = 0;
6266 $tot_sub_aliq = 0;
6267 foreach ($pbreakdown_name as $key => $subtax) {
6268 if (!empty($subtax) && floatval($pbreakdown_rate[$key]) > 0) {
6269 $breakdown_values[$bkcount]['name'] = $subtax;
6270 $breakdown_values[$bkcount]['aliq'] = (float)$pbreakdown_rate[$key];
6271 $tot_sub_aliq += (float)$pbreakdown_rate[$key];
6272 $bkcount++;
6273 }
6274 }
6275 if (count($breakdown_values) > 0) {
6276 $breakdown_str = json_encode($breakdown_values);
6277 if ($tot_sub_aliq < (float)$paliqperc || $tot_sub_aliq > (float)$paliqperc) {
6278 VikError::raiseWarning('', JText::translate('VBOTAXBKDWNERRNOMATCH'));
6279 }
6280 }
6281 }
6282 $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).";";
6283 $dbo->setQuery($q);
6284 $dbo->execute();
6285 }
6286 $mainframe = JFactory::getApplication();
6287 $mainframe->redirect("index.php?option=com_vikbooking&task=iva");
6288 }
6289
6290 public function removeiva() {
6291 if (!JSession::checkToken()) {
6292 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6293 }
6294 $ids = VikRequest::getVar('cid', array(0));
6295 if (@count($ids)) {
6296 $dbo = JFactory::getDBO();
6297 foreach ($ids as $d) {
6298 $q = "DELETE FROM `#__vikbooking_iva` WHERE `id`=".$dbo->quote($d).";";
6299 $dbo->setQuery($q);
6300 $dbo->execute();
6301 }
6302 }
6303 $mainframe = JFactory::getApplication();
6304 $mainframe->redirect("index.php?option=com_vikbooking&task=iva");
6305 }
6306
6307 public function categories() {
6308 VikBookingHelper::printHeader("4");
6309
6310 VikRequest::setVar('view', VikRequest::getCmd('view', 'categories'));
6311
6312 parent::display();
6313
6314 if (VikBooking::showFooter()) {
6315 VikBookingHelper::printFooter();
6316 }
6317 }
6318
6319 public function newcat() {
6320 VikBookingHelper::printHeader("4");
6321
6322 VikRequest::setVar('view', VikRequest::getCmd('view', 'managecategory'));
6323
6324 parent::display();
6325
6326 if (VikBooking::showFooter()) {
6327 VikBookingHelper::printFooter();
6328 }
6329 }
6330
6331 public function editcat() {
6332 VikBookingHelper::printHeader("4");
6333
6334 VikRequest::setVar('view', VikRequest::getCmd('view', 'managecategory'));
6335
6336 parent::display();
6337
6338 if (VikBooking::showFooter()) {
6339 VikBookingHelper::printFooter();
6340 }
6341 }
6342
6343 public function createcat() {
6344 if (!JSession::checkToken()) {
6345 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6346 }
6347 $pcatname = VikRequest::getString('catname', '', 'request');
6348 $pdescr = VikRequest::getString('descr', '', 'request', VIKREQUEST_ALLOWHTML);
6349 if (!empty($pcatname)) {
6350 $dbo = JFactory::getDBO();
6351 $q = "INSERT INTO `#__vikbooking_categories` (`name`,`descr`) VALUES(".$dbo->quote($pcatname).", ".$dbo->quote($pdescr).");";
6352 $dbo->setQuery($q);
6353 $dbo->execute();
6354 }
6355 $mainframe = JFactory::getApplication();
6356 $mainframe->redirect("index.php?option=com_vikbooking&task=categories");
6357 }
6358
6359 public function updatecat() {
6360 if (!JSession::checkToken()) {
6361 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6362 }
6363 $pcatname = VikRequest::getString('catname', '', 'request');
6364 $pdescr = VikRequest::getString('descr', '', 'request', VIKREQUEST_ALLOWHTML);
6365 $pwhereup = VikRequest::getString('whereup', '', 'request');
6366 if (!empty($pcatname)) {
6367 $dbo = JFactory::getDBO();
6368 $q = "UPDATE `#__vikbooking_categories` SET `name`=".$dbo->quote($pcatname).", `descr`=".$dbo->quote($pdescr)." WHERE `id`=".$dbo->quote($pwhereup).";";
6369 $dbo->setQuery($q);
6370 $dbo->execute();
6371 }
6372 $mainframe = JFactory::getApplication();
6373 $mainframe->redirect("index.php?option=com_vikbooking&task=categories");
6374 }
6375
6376 public function removecat() {
6377 $ids = VikRequest::getVar('cid', array(0));
6378 if (@count($ids)) {
6379 $dbo = JFactory::getDBO();
6380 foreach ($ids as $d) {
6381 $q = "DELETE FROM `#__vikbooking_categories` WHERE `id`=".$dbo->quote($d).";";
6382 $dbo->setQuery($q);
6383 $dbo->execute();
6384 }
6385 }
6386 $mainframe = JFactory::getApplication();
6387 $mainframe->redirect("index.php?option=com_vikbooking&task=categories");
6388 }
6389
6390 public function carat() {
6391 VikBookingHelper::printHeader("5");
6392
6393 VikRequest::setVar('view', VikRequest::getCmd('view', 'carat'));
6394
6395 parent::display();
6396
6397 if (VikBooking::showFooter()) {
6398 VikBookingHelper::printFooter();
6399 }
6400 }
6401
6402 public function newcarat() {
6403 VikBookingHelper::printHeader("5");
6404
6405 VikRequest::setVar('view', VikRequest::getCmd('view', 'managecarat'));
6406
6407 parent::display();
6408
6409 if (VikBooking::showFooter()) {
6410 VikBookingHelper::printFooter();
6411 }
6412 }
6413
6414 public function editcarat() {
6415 VikBookingHelper::printHeader("5");
6416
6417 VikRequest::setVar('view', VikRequest::getCmd('view', 'managecarat'));
6418
6419 parent::display();
6420
6421 if (VikBooking::showFooter()) {
6422 VikBookingHelper::printFooter();
6423 }
6424 }
6425
6426 public function createcarat() {
6427 if (!JSession::checkToken()) {
6428 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6429 }
6430 $pcaratname = VikRequest::getString('caratname', '', 'request');
6431 $pcarattextimg = VikRequest::getString('carattextimg', '', 'request', VIKREQUEST_ALLOWHTML);
6432 $pautoresize = VikRequest::getString('autoresize', '', 'request');
6433 $presizeto = VikRequest::getString('resizeto', '', 'request');
6434 $pidrooms = VikRequest::getVar('idrooms', array());
6435 if (!empty($pcaratname)) {
6436 if (intval($_FILES['caraticon']['error']) == 0 && VikBooking::caniWrite(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR) && trim($_FILES['caraticon']['name'])!="") {
6437 jimport('joomla.filesystem.file');
6438 $updpath = VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR;
6439 if (@is_uploaded_file($_FILES['caraticon']['tmp_name'])) {
6440 $safename=JFile::makeSafe(str_replace(" ", "_", strtolower($_FILES['caraticon']['name'])));
6441 if (file_exists($updpath.$safename)) {
6442 $j=1;
6443 while (file_exists($updpath.$j.$safename)) {
6444 $j++;
6445 }
6446 $pwhere=$updpath.$j.$safename;
6447 } else {
6448 $j="";
6449 $pwhere=$updpath.$safename;
6450 }
6451 if (!getimagesize($_FILES['caraticon']['tmp_name']) || !preg_match("/\.(a?png|jpe?g|bmp|gif|ico|webp)\z/i", $safename)) {
6452 @unlink($pwhere);
6453 $picon="";
6454 } else {
6455 VikBooking::uploadFile($_FILES['caraticon']['tmp_name'], $pwhere);
6456 @chmod($pwhere, 0644);
6457 $picon=$j.$safename;
6458 if ($pautoresize=="1" && !empty($presizeto)) {
6459 $eforj = new vikResizer();
6460 $origmod = $eforj->proportionalImage($pwhere, $updpath.'r_'.$j.$safename, $presizeto, $presizeto);
6461 if ($origmod) {
6462 @unlink($pwhere);
6463 $picon='r_'.$j.$safename;
6464 }
6465 }
6466 }
6467 } else {
6468 $picon="";
6469 }
6470 } else {
6471 $picon="";
6472 }
6473 $dbo = JFactory::getDbo();
6474 // get new ordering
6475 $q = "SELECT `ordering` FROM `#__vikbooking_characteristics` ORDER BY `#__vikbooking_characteristics`.`ordering` DESC LIMIT 1;";
6476 $dbo->setQuery($q);
6477 $dbo->execute();
6478 if ($dbo->getNumRows()) {
6479 $newsortnum = $dbo->loadResult() + 1;
6480 } else {
6481 $newsortnum = 1;
6482 }
6483 $pordering = VikRequest::getInt('ordering', 0, 'request');
6484 $newsortnum = !empty($pordering) ? $pordering : $newsortnum;
6485 //
6486 $q = "INSERT INTO `#__vikbooking_characteristics` (`name`,`icon`,`textimg`,`ordering`) VALUES(".$dbo->quote($pcaratname).", ".$dbo->quote($picon).", ".$dbo->quote($pcarattextimg).", {$newsortnum});";
6487 $dbo->setQuery($q);
6488 $dbo->execute();
6489
6490 $new_carat_id = $dbo->insertid();
6491 if (!empty($new_carat_id)) {
6492 // assign/unset carat-rooms relations
6493 $rooms_with_carat = array();
6494 if (count($pidrooms)) {
6495 // assign this new carat to the requested rooms
6496 foreach ($pidrooms as $idroom) {
6497 if (empty($idroom)) {
6498 continue;
6499 }
6500 $q = "SELECT `id`, `idcarat` FROM `#__vikbooking_rooms` WHERE `id`=" . (int)$idroom . ";";
6501 $dbo->setQuery($q);
6502 $dbo->execute();
6503 if (!$dbo->getNumRows()) {
6504 continue;
6505 }
6506 $room_data = $dbo->loadAssoc();
6507 array_push($rooms_with_carat, $room_data['id']);
6508 $current_carats = empty($room_data['idcarat']) ? array() : explode(';', rtrim($room_data['idcarat'], ';'));
6509 if (in_array((string)$new_carat_id, $current_carats)) {
6510 continue;
6511 }
6512 if (count($current_carats) === 1 && (string)$current_carats[0] == '0') {
6513 // make sure we do not concatenate a real ID to 0
6514 $current_carats = array();
6515 }
6516 array_push($current_carats, $new_carat_id);
6517 $new_opts = implode(';', $current_carats) . ';';
6518 $q = "UPDATE `#__vikbooking_rooms` SET `idcarat`=" . $dbo->quote($new_opts) . " WHERE `id`={$room_data['id']};";
6519 $dbo->setQuery($q);
6520 $dbo->execute();
6521 }
6522 }
6523 if (!count($rooms_with_carat)) {
6524 // get all rooms to unset this carat (if previously set)
6525 array_push($rooms_with_carat, '0');
6526 }
6527 // unset the carat from the other rooms that may have it
6528 $q = "SELECT `id`, `idcarat` FROM `#__vikbooking_rooms` WHERE `id` NOT IN (" . implode(', ', $rooms_with_carat) . ");";
6529 $dbo->setQuery($q);
6530 $dbo->execute();
6531 if ($dbo->getNumRows()) {
6532 $unset_rooms_carat = $dbo->loadAssocList();
6533 foreach ($unset_rooms_carat as $room_data) {
6534 $current_carats = empty($room_data['idcarat']) ? array() : explode(';', rtrim($room_data['idcarat'], ';'));
6535 if (!in_array((string)$new_carat_id, $current_carats)) {
6536 // this room is not using this carat
6537 continue;
6538 }
6539 $caratkey = array_search((string)$new_carat_id, $current_carats);
6540 if ($caratkey === false) {
6541 // key not found
6542 continue;
6543 }
6544 // unset this carat ID from the string
6545 unset($current_carats[$caratkey]);
6546 if (!count($current_carats)) {
6547 // a room with no carats assigned will be listed as "0;"
6548 $current_carats = array(0);
6549 }
6550 $new_opts = implode(';', $current_carats) . ';';
6551 $q = "UPDATE `#__vikbooking_rooms` SET `idcarat`=" . $dbo->quote($new_opts) . " WHERE `id`={$room_data['id']};";
6552 $dbo->setQuery($q);
6553 $dbo->execute();
6554 }
6555 }
6556 //
6557 }
6558 }
6559 $mainframe = JFactory::getApplication();
6560 $mainframe->redirect("index.php?option=com_vikbooking&task=carat");
6561 }
6562
6563 public function updatecarat() {
6564 if (!JSession::checkToken()) {
6565 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6566 }
6567 $pcaratname = VikRequest::getString('caratname', '', 'request');
6568 $pcarattextimg = VikRequest::getString('carattextimg', '', 'request', VIKREQUEST_ALLOWHTML);
6569 $pwhereup = VikRequest::getString('whereup', '', 'request');
6570 $pautoresize = VikRequest::getString('autoresize', '', 'request');
6571 $presizeto = VikRequest::getString('resizeto', '', 'request');
6572 $pidrooms = VikRequest::getVar('idrooms', array());
6573 $pordering = VikRequest::getInt('ordering', 1, 'request');
6574 if (!empty($pcaratname)) {
6575 if (intval($_FILES['caraticon']['error']) == 0 && VikBooking::caniWrite(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR) && trim($_FILES['caraticon']['name'])!="") {
6576 jimport('joomla.filesystem.file');
6577 $updpath = VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR;
6578 if (@is_uploaded_file($_FILES['caraticon']['tmp_name'])) {
6579 $safename=JFile::makeSafe(str_replace(" ", "_", strtolower($_FILES['caraticon']['name'])));
6580 if (file_exists($updpath.$safename)) {
6581 $j=1;
6582 while (file_exists($updpath.$j.$safename)) {
6583 $j++;
6584 }
6585 $pwhere=$updpath.$j.$safename;
6586 } else {
6587 $j="";
6588 $pwhere=$updpath.$safename;
6589 }
6590 if (!getimagesize($_FILES['caraticon']['tmp_name']) || !preg_match("/\.(a?png|jpe?g|bmp|gif|ico|webp)\z/i", $safename)) {
6591 @unlink($pwhere);
6592 $picon="";
6593 } else {
6594 VikBooking::uploadFile($_FILES['caraticon']['tmp_name'], $pwhere);
6595 @chmod($pwhere, 0644);
6596 $picon=$j.$safename;
6597 if ($pautoresize=="1" && !empty($presizeto)) {
6598 $eforj = new vikResizer();
6599 $origmod = $eforj->proportionalImage($pwhere, $updpath.'r_'.$j.$safename, $presizeto, $presizeto);
6600 if ($origmod) {
6601 @unlink($pwhere);
6602 $picon='r_'.$j.$safename;
6603 }
6604 }
6605 }
6606 } else {
6607 $picon="";
6608 }
6609 } else {
6610 $picon="";
6611 }
6612 $dbo = JFactory::getDbo();
6613 $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).";";
6614 $dbo->setQuery($q);
6615 $dbo->execute();
6616
6617 // assign/unset carat-rooms relations
6618 $rooms_with_carat = array();
6619 if (count($pidrooms)) {
6620 // assign this new carat to the requested rooms
6621 foreach ($pidrooms as $idroom) {
6622 if (empty($idroom)) {
6623 continue;
6624 }
6625 $q = "SELECT `id`, `idcarat` FROM `#__vikbooking_rooms` WHERE `id`=" . (int)$idroom . ";";
6626 $dbo->setQuery($q);
6627 $dbo->execute();
6628 if (!$dbo->getNumRows()) {
6629 continue;
6630 }
6631 $room_data = $dbo->loadAssoc();
6632 array_push($rooms_with_carat, $room_data['id']);
6633 $current_carats = empty($room_data['idcarat']) ? array() : explode(';', rtrim($room_data['idcarat'], ';'));
6634 if (in_array((string)$pwhereup, $current_carats)) {
6635 continue;
6636 }
6637 if (count($current_carats) === 1 && (string)$current_carats[0] == '0') {
6638 // make sure we do not concatenate a real ID to 0
6639 $current_carats = array();
6640 }
6641 array_push($current_carats, $pwhereup);
6642 $new_carats = implode(';', $current_carats) . ';';
6643 $q = "UPDATE `#__vikbooking_rooms` SET `idcarat`=" . $dbo->quote($new_carats) . " WHERE `id`={$room_data['id']};";
6644 $dbo->setQuery($q);
6645 $dbo->execute();
6646 }
6647 }
6648 if (!count($rooms_with_carat)) {
6649 // get all rooms to unset this carat (if previously set)
6650 array_push($rooms_with_carat, '0');
6651 }
6652 // unset the carat from the other rooms that may have it
6653 $q = "SELECT `id`, `idcarat` FROM `#__vikbooking_rooms` WHERE `id` NOT IN (" . implode(', ', $rooms_with_carat) . ");";
6654 $dbo->setQuery($q);
6655 $dbo->execute();
6656 if ($dbo->getNumRows()) {
6657 $unset_rooms_carat = $dbo->loadAssocList();
6658 foreach ($unset_rooms_carat as $room_data) {
6659 $current_carats = empty($room_data['idcarat']) ? array() : explode(';', rtrim($room_data['idcarat'], ';'));
6660 if (!in_array((string)$pwhereup, $current_carats)) {
6661 // this room is not using this carat
6662 continue;
6663 }
6664 $caratkey = array_search((string)$pwhereup, $current_carats);
6665 if ($caratkey === false) {
6666 // key not found
6667 continue;
6668 }
6669 // unset this carat ID from the string
6670 unset($current_carats[$caratkey]);
6671 if (!count($current_carats)) {
6672 // a room with no carats assigned will be listed as "0;"
6673 $current_carats = array(0);
6674 }
6675 $new_carats = implode(';', $current_carats) . ';';
6676 $q = "UPDATE `#__vikbooking_rooms` SET `idcarat`=" . $dbo->quote($new_carats) . " WHERE `id`={$room_data['id']};";
6677 $dbo->setQuery($q);
6678 $dbo->execute();
6679 }
6680 }
6681 //
6682 }
6683 $mainframe = JFactory::getApplication();
6684 $mainframe->redirect("index.php?option=com_vikbooking&task=carat");
6685 }
6686
6687 public function removecarat() {
6688 if (!JSession::checkToken()) {
6689 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6690 }
6691 $ids = VikRequest::getVar('cid', array(0));
6692 if (@count($ids)) {
6693 $dbo = JFactory::getDBO();
6694 foreach ($ids as $d) {
6695 $q = "SELECT `icon` FROM `#__vikbooking_characteristics` WHERE `id`=".$dbo->quote($d).";";
6696 $dbo->setQuery($q);
6697 $dbo->execute();
6698 if ($dbo->getNumRows() == 1) {
6699 $rows = $dbo->loadAssocList();
6700 if (!empty($rows[0]['icon']) && file_exists(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR.$rows[0]['icon'])) {
6701 @unlink(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR.$rows[0]['icon']);
6702 }
6703 }
6704 $q = "DELETE FROM `#__vikbooking_characteristics` WHERE `id`=".$dbo->quote($d).";";
6705 $dbo->setQuery($q);
6706 $dbo->execute();
6707 }
6708 }
6709 $mainframe = JFactory::getApplication();
6710 $mainframe->redirect("index.php?option=com_vikbooking&task=carat");
6711 }
6712
6713 public function coupons() {
6714 VikBookingHelper::printHeader("17");
6715
6716 VikRequest::setVar('view', VikRequest::getCmd('view', 'coupons'));
6717
6718 parent::display();
6719
6720 if (VikBooking::showFooter()) {
6721 VikBookingHelper::printFooter();
6722 }
6723 }
6724
6725 public function newcoupon() {
6726 VikBookingHelper::printHeader("17");
6727
6728 VikRequest::setVar('view', VikRequest::getCmd('view', 'managecoupon'));
6729
6730 parent::display();
6731
6732 if (VikBooking::showFooter()) {
6733 VikBookingHelper::printFooter();
6734 }
6735 }
6736
6737 public function editcoupon() {
6738 VikBookingHelper::printHeader("17");
6739
6740 VikRequest::setVar('view', VikRequest::getCmd('view', 'managecoupon'));
6741
6742 parent::display();
6743
6744 if (VikBooking::showFooter()) {
6745 VikBookingHelper::printFooter();
6746 }
6747 }
6748
6749 public function createcoupon()
6750 {
6751 if (!JSession::checkToken()) {
6752 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6753 }
6754 $pcode = VikRequest::getString('code', '', 'request');
6755 $pvalue = VikRequest::getString('value', '', 'request');
6756 $pfrom = VikRequest::getString('from', '', 'request');
6757 $pto = VikRequest::getString('to', '', 'request');
6758 $pidrooms = VikRequest::getVar('idrooms', array(0));
6759 $ptype = VikRequest::getString('type', '', 'request');
6760 $ptype = $ptype == "1" ? 1 : 2;
6761 $ppercentot = VikRequest::getString('percentot', '', 'request');
6762 $ppercentot = $ppercentot == "1" ? 1 : 2;
6763 $pallvehicles = VikRequest::getString('allvehicles', '', 'request');
6764 $pallvehicles = $pallvehicles == "1" ? 1 : 0;
6765 $pmintotord = VikRequest::getFloat('mintotord', 0, 'request');
6766 $pmaxtotord = VikRequest::getFloat('maxtotord', 0, 'request');
6767 $pexcludetaxes = VikRequest::getInt('excludetaxes', 0, 'request');
6768 $pminlos = VikRequest::getInt('minlos', 0, 'request');
6769 $pcustomers = VikRequest::getVar('customers', array());
6770 $pautomatic = VikRequest::getInt('automatic', 0, 'request');
6771 $stridrooms = "";
6772 if (count($pidrooms) > 0 && $pallvehicles != 1) {
6773 foreach ($pidrooms as $ch) {
6774 if (!empty($ch)) {
6775 $stridrooms .= ";".$ch.";";
6776 }
6777 }
6778 }
6779 $strdatevalid = "";
6780 if (strlen($pfrom) > 0 && strlen($pto) > 0) {
6781 $first = VikBooking::getDateTimestamp($pfrom, 0, 0);
6782 $second = VikBooking::getDateTimestamp($pto, 0, 0);
6783 if ($first < $second) {
6784 $strdatevalid .= $first."-".$second;
6785 }
6786 }
6787
6788 $dbo = JFactory::getDbo();
6789 $app = JFactory::getApplication();
6790
6791 $q = "SELECT * FROM `#__vikbooking_coupons` WHERE `code`=".$dbo->quote($pcode).";";
6792 $dbo->setQuery($q);
6793 $dbo->execute();
6794 if ($dbo->getNumRows() > 0) {
6795 VikError::raiseWarning('', JText::translate('VBCOUPONEXISTS'));
6796 } else {
6797 $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) . ");";
6798 $dbo->setQuery($q);
6799 $dbo->execute();
6800
6801 $id_coupon = $dbo->insertid();
6802
6803 $app->enqueueMessage(JText::translate('VBCOUPONSAVEOK'));
6804
6805 // check if this coupon should be assigned to specific customers
6806 foreach ($pcustomers as $id_customer) {
6807 $customer_coupon = new stdClass;
6808 $customer_coupon->idcustomer = (int)$id_customer;
6809 $customer_coupon->idcoupon = (int)$id_coupon;
6810 $customer_coupon->automatic = $pautomatic ? 1 : 0;
6811
6812 $dbo->insertObject('#__vikbooking_customers_coupons', $customer_coupon, 'id');
6813 }
6814 }
6815 $app->redirect("index.php?option=com_vikbooking&task=coupons");
6816 }
6817
6818 public function updatecoupon()
6819 {
6820 if (!JSession::checkToken()) {
6821 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6822 }
6823
6824 $this->do_updatecoupon($stay = false);
6825 }
6826
6827 public function updatecoupon_stay()
6828 {
6829 if (!JSession::checkToken()) {
6830 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6831 }
6832
6833 $this->do_updatecoupon($stay = true);
6834 }
6835
6836 protected function do_updatecoupon($stay = false)
6837 {
6838 if (!JSession::checkToken()) {
6839 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6840 }
6841 $pcode = VikRequest::getString('code', '', 'request');
6842 $pvalue = VikRequest::getString('value', '', 'request');
6843 $pfrom = VikRequest::getString('from', '', 'request');
6844 $pto = VikRequest::getString('to', '', 'request');
6845 $pidrooms = VikRequest::getVar('idrooms', array(0));
6846 $pwhere = VikRequest::getInt('where', 0, 'request');
6847 $ptype = VikRequest::getString('type', '', 'request');
6848 $ptype = $ptype == "1" ? 1 : 2;
6849 $ppercentot = VikRequest::getString('percentot', '', 'request');
6850 $ppercentot = $ppercentot == "1" ? 1 : 2;
6851 $pallvehicles = VikRequest::getString('allvehicles', '', 'request');
6852 $pallvehicles = $pallvehicles == "1" ? 1 : 0;
6853 $pmintotord = VikRequest::getFloat('mintotord', 0, 'request');
6854 $pmaxtotord = VikRequest::getFloat('maxtotord', 0, 'request');
6855 $pexcludetaxes = VikRequest::getInt('excludetaxes', 0, 'request');
6856 $pminlos = VikRequest::getInt('minlos', 0, 'request');
6857 $pcustomers = VikRequest::getVar('customers', array());
6858 $pautomatic = VikRequest::getInt('automatic', 0, 'request');
6859 $stridrooms = "";
6860 if (count($pidrooms) > 0 && $pallvehicles != 1) {
6861 foreach ($pidrooms as $ch) {
6862 if (!empty($ch)) {
6863 $stridrooms .= ";".$ch.";";
6864 }
6865 }
6866 }
6867 $strdatevalid = "";
6868 if (strlen($pfrom) > 0 && strlen($pto) > 0) {
6869 $first = VikBooking::getDateTimestamp($pfrom, 0, 0);
6870 $second = VikBooking::getDateTimestamp($pto, 0, 0);
6871 if ($first < $second) {
6872 $strdatevalid .= $first."-".$second;
6873 }
6874 }
6875
6876 $dbo = JFactory::getDbo();
6877 $app = JFactory::getApplication();
6878
6879 $q = "SELECT * FROM `#__vikbooking_coupons` WHERE `code`=".$dbo->quote($pcode)." AND `id`!='".$pwhere."';";
6880 $dbo->setQuery($q);
6881 $dbo->execute();
6882 if ($dbo->getNumRows() > 0) {
6883 VikError::raiseWarning('', JText::translate('VBCOUPONEXISTS'));
6884 } else {
6885 $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 . ";";
6886 $dbo->setQuery($q);
6887 $dbo->execute();
6888
6889 $app->enqueueMessage(JText::translate('VBCOUPONSAVEOK'));
6890
6891 // clean up any previously created record with customers
6892 $q = "DELETE FROM `#__vikbooking_customers_coupons` WHERE `idcoupon`=" . $pwhere;
6893 $dbo->setQuery($q);
6894 $dbo->execute();
6895
6896 // check if this coupon should be assigned to specific customers
6897 foreach ($pcustomers as $id_customer) {
6898 $customer_coupon = new stdClass;
6899 $customer_coupon->idcustomer = (int)$id_customer;
6900 $customer_coupon->idcoupon = (int)$pwhere;
6901 $customer_coupon->automatic = $pautomatic ? 1 : 0;
6902
6903 $dbo->insertObject('#__vikbooking_customers_coupons', $customer_coupon, 'id');
6904 }
6905 }
6906
6907 if ($stay) {
6908 $app->redirect("index.php?option=com_vikbooking&task=editcoupon&cid[]=$pwhere");
6909 } else {
6910 $app->redirect("index.php?option=com_vikbooking&task=coupons");
6911 }
6912 }
6913
6914 public function removecoupons()
6915 {
6916 if (!JSession::checkToken()) {
6917 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6918 }
6919
6920 $dbo = JFactory::getDbo();
6921
6922 $ids = VikRequest::getVar('cid', array(0));
6923
6924 if (count($ids)) {
6925 foreach ($ids as $d) {
6926 // delete coupon record
6927 $q = "DELETE FROM `#__vikbooking_coupons` WHERE `id`=".$dbo->quote($d).";";
6928 $dbo->setQuery($q);
6929 $dbo->execute();
6930
6931 // clean up any previously created record with customers
6932 $q = "DELETE FROM `#__vikbooking_customers_coupons` WHERE `idcoupon`=" . (int)$d;
6933 $dbo->setQuery($q);
6934 $dbo->execute();
6935 }
6936 }
6937
6938 JFactory::getApplication()->redirect("index.php?option=com_vikbooking&task=coupons");
6939 }
6940
6941 public function removemoreimgs() {
6942 $mainframe = JFactory::getApplication();
6943 $proomid = VikRequest::getInt('roomid', '', 'request');
6944 $pimgind = VikRequest::getInt('imgind', '', 'request');
6945 if (!strlen($pimgind)) {
6946 $mainframe->redirect("index.php?option=com_vikbooking");
6947 exit;
6948 }
6949 $dbo = JFactory::getDBO();
6950 $q = "SELECT `moreimgs`,`imgcaptions` FROM `#__vikbooking_rooms` WHERE `id`='".$proomid."';";
6951 $dbo->setQuery($q);
6952 $dbo->execute();
6953 $row = $dbo->loadAssoc();
6954 $actmore = $row['moreimgs'];
6955 if (!empty($actmore)) {
6956 $actsplit = explode(';;', $actmore);
6957 $captions = json_decode($row['imgcaptions'], true);
6958 $captions = !is_array($captions) ? array() : $captions;
6959 if ($pimgind < 0) {
6960 foreach ($actsplit as $img) {
6961 @unlink(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR.'big_'.$img);
6962 @unlink(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR.'thumb_'.$img);
6963 }
6964 // reset images and captions
6965 $actsplit = array();
6966 $captions = array();
6967 } else {
6968 if (array_key_exists($pimgind, $actsplit)) {
6969 @unlink(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR.'big_'.$actsplit[$pimgind]);
6970 @unlink(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR.'thumb_'.$actsplit[$pimgind]);
6971 // unset current image
6972 unset($actsplit[$pimgind]);
6973 // unset caption if exists
6974 if (isset($captions[$pimgind])) {
6975 unset($captions[$pimgind]);
6976 $captions = array_values($captions);
6977 }
6978 }
6979 }
6980 $newstr = "";
6981 foreach ($actsplit as $oi) {
6982 if (!empty($oi)) {
6983 $newstr .= $oi.';;';
6984 }
6985 }
6986 $q = "UPDATE `#__vikbooking_rooms` SET `moreimgs`=".$dbo->quote($newstr).", `imgcaptions`=".$dbo->quote(json_encode($captions))." WHERE `id`='".$proomid."';";
6987 $dbo->setQuery($q);
6988 $dbo->execute();
6989 }
6990 $mainframe->redirect("index.php?option=com_vikbooking&task=editroom&cid[]=".$proomid);
6991 }
6992
6993 public function sortfield() {
6994 if (!JSession::checkToken('get')) {
6995 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
6996 }
6997 $mainframe = JFactory::getApplication();
6998 $sortid = VikRequest::getVar('cid', array(0));
6999 $pmode = VikRequest::getString('mode', '', 'request');
7000 $dbo = JFactory::getDBO();
7001 if (!empty($pmode)) {
7002 $q = "SELECT `id`,`ordering` FROM `#__vikbooking_custfields` ORDER BY `#__vikbooking_custfields`.`ordering` ASC;";
7003 $dbo->setQuery($q);
7004 $dbo->execute();
7005 $totr=$dbo->getNumRows();
7006 if ($totr > 1) {
7007 $data = $dbo->loadAssocList();
7008 if ($pmode == "up") {
7009 foreach ($data as $v) {
7010 if ($v['id'] == $sortid[0]) {
7011 $y = $v['ordering'];
7012 }
7013 }
7014 if ($y && $y > 1) {
7015 $vik = $y - 1;
7016 $found = false;
7017 foreach ($data as $v) {
7018 if (intval($v['ordering']) == intval($vik)) {
7019 $found=true;
7020 $q = "UPDATE `#__vikbooking_custfields` SET `ordering`='".$y."' WHERE `id`='".$v['id']."' LIMIT 1;";
7021 $dbo->setQuery($q);
7022 $dbo->execute();
7023 $q = "UPDATE `#__vikbooking_custfields` SET `ordering`='".$vik."' WHERE `id`='".$sortid[0]."' LIMIT 1;";
7024 $dbo->setQuery($q);
7025 $dbo->execute();
7026 break;
7027 }
7028 }
7029 if (!$found) {
7030 $q = "UPDATE `#__vikbooking_custfields` SET `ordering`='".$vik."' WHERE `id`='".$sortid[0]."' LIMIT 1;";
7031 $dbo->setQuery($q);
7032 $dbo->execute();
7033 }
7034 }
7035 } elseif ($pmode == "down") {
7036 foreach ($data as $v) {
7037 if ($v['id'] == $sortid[0]) {
7038 $y = $v['ordering'];
7039 }
7040 }
7041 if ($y) {
7042 $vik = $y + 1;
7043 $found = false;
7044 foreach ($data as $v) {
7045 if (intval($v['ordering']) == intval($vik)) {
7046 $found=true;
7047 $q = "UPDATE `#__vikbooking_custfields` SET `ordering`='".$y."' WHERE `id`='".$v['id']."' LIMIT 1;";
7048 $dbo->setQuery($q);
7049 $dbo->execute();
7050 $q = "UPDATE `#__vikbooking_custfields` SET `ordering`='".$vik."' WHERE `id`='".$sortid[0]."' LIMIT 1;";
7051 $dbo->setQuery($q);
7052 $dbo->execute();
7053 break;
7054 }
7055 }
7056 if (!$found) {
7057 $q = "UPDATE `#__vikbooking_custfields` SET `ordering`='".$vik."' WHERE `id`='".$sortid[0]."' LIMIT 1;";
7058 $dbo->setQuery($q);
7059 $dbo->execute();
7060 }
7061 }
7062 }
7063 }
7064 $mainframe->redirect("index.php?option=com_vikbooking&task=customf");
7065 } else {
7066 $mainframe->redirect("index.php?option=com_vikbooking");
7067 }
7068 }
7069
7070 public function customf() {
7071 VikBookingHelper::printHeader("16");
7072
7073 VikRequest::setVar('view', VikRequest::getCmd('view', 'customf'));
7074
7075 parent::display();
7076
7077 if (VikBooking::showFooter()) {
7078 VikBookingHelper::printFooter();
7079 }
7080 }
7081
7082 public function newcustomf() {
7083 VikBookingHelper::printHeader("16");
7084
7085 VikRequest::setVar('view', VikRequest::getCmd('view', 'managecustomf'));
7086
7087 parent::display();
7088
7089 if (VikBooking::showFooter()) {
7090 VikBookingHelper::printFooter();
7091 }
7092 }
7093
7094 public function editcustomf() {
7095 VikBookingHelper::printHeader("16");
7096
7097 VikRequest::setVar('view', VikRequest::getCmd('view', 'managecustomf'));
7098
7099 parent::display();
7100
7101 if (VikBooking::showFooter()) {
7102 VikBookingHelper::printFooter();
7103 }
7104 }
7105
7106 public function createcustomf() {
7107 if (!JSession::checkToken()) {
7108 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
7109 }
7110 $pname = VikRequest::getString('name', '', 'request', VIKREQUEST_ALLOWHTML);
7111 $ptype = VikRequest::getString('type', '', 'request');
7112 $pchoose = VikRequest::getVar('choose', array(0));
7113 $prequired = VikRequest::getString('required', '', 'request');
7114 $prequired = $prequired == "1" ? 1 : 0;
7115 $pflag = VikRequest::getString('flag', '', 'request');
7116 $pisemail = $pflag == 'isemail' ? 1 : 0;
7117 $pisnominative = $pflag == 'isnominative' && $ptype == 'text' ? 1 : 0;
7118 $pisphone = $pflag == 'isphone' && $ptype == 'text' ? 1 : 0;
7119 $pisaddress = $pflag == 'isaddress' && $ptype == 'text' ? 1 : 0;
7120 $piscity = $pflag == 'iscity' && $ptype == 'text' ? 1 : 0;
7121 $piszip = $pflag == 'iszip' && $ptype == 'text' ? 1 : 0;
7122 $piscompany = $pflag == 'iscompany' && $ptype == 'text' ? 1 : 0;
7123 $pisvat = $pflag == 'isvat' && $ptype == 'text' ? 1 : 0;
7124 $pisfisccode = $pflag == 'isfisccode' && $ptype == 'text' ? 1 : 0;
7125 $pispec = $pflag == 'ispec' && $ptype == 'text' ? 1 : 0;
7126 $pisrecipcode = $pflag == 'isrecipcode' && $ptype == 'text' ? 1 : 0;
7127 $fieldflag = '';
7128 if ($pisaddress == 1) {
7129 $fieldflag = 'address';
7130 } elseif ($piscity == 1) {
7131 $fieldflag = 'city';
7132 } elseif ($piszip == 1) {
7133 $fieldflag = 'zip';
7134 } elseif ($piscompany == 1) {
7135 $fieldflag = 'company';
7136 } elseif ($pisvat == 1) {
7137 $fieldflag = 'vat';
7138 } elseif ($pisfisccode == 1) {
7139 $fieldflag = 'fisccode';
7140 } elseif ($pispec == 1) {
7141 $fieldflag = 'pec';
7142 } elseif ($pisrecipcode == 1) {
7143 $fieldflag = 'recipcode';
7144 }
7145 $ppoplink = VikRequest::getString('poplink', '', 'request');
7146 $choosestr = "";
7147 if (is_array($pchoose)) {
7148 foreach ($pchoose as $ch) {
7149 if (!empty($ch)) {
7150 $choosestr .= $ch.";;__;;";
7151 }
7152 }
7153 }
7154 $defvalue = VikRequest::getString('defvalue', '', 'request');
7155
7156 $dbo = JFactory::getDbo();
7157
7158 $q = "SELECT `ordering` FROM `#__vikbooking_custfields` ORDER BY `#__vikbooking_custfields`.`ordering` DESC LIMIT 1;";
7159 $dbo->setQuery($q);
7160 $dbo->execute();
7161 if ($dbo->getNumRows() == 1) {
7162 $getlast = $dbo->loadResult();
7163 $newsortnum = $getlast + 1;
7164 } else {
7165 $newsortnum = 1;
7166 }
7167 $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).");";
7168 $dbo->setQuery($q);
7169 $dbo->execute();
7170 $mainframe = JFactory::getApplication();
7171 $mainframe->redirect("index.php?option=com_vikbooking&task=customf");
7172 }
7173
7174 public function updatecustomf() {
7175 if (!JSession::checkToken()) {
7176 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
7177 }
7178 $pname = VikRequest::getString('name', '', 'request', VIKREQUEST_ALLOWHTML);
7179 $ptype = VikRequest::getString('type', '', 'request');
7180 $pchoose = VikRequest::getVar('choose', array(0));
7181 $prequired = VikRequest::getString('required', '', 'request');
7182 $prequired = $prequired == "1" ? 1 : 0;
7183 $pflag = VikRequest::getString('flag', '', 'request');
7184 $pisemail = $pflag == 'isemail' ? 1 : 0;
7185 $pisnominative = $pflag == 'isnominative' && $ptype == 'text' ? 1 : 0;
7186 $pisphone = $pflag == 'isphone' && $ptype == 'text' ? 1 : 0;
7187 $pisaddress = $pflag == 'isaddress' && $ptype == 'text' ? 1 : 0;
7188 $piscity = $pflag == 'iscity' && $ptype == 'text' ? 1 : 0;
7189 $piszip = $pflag == 'iszip' && $ptype == 'text' ? 1 : 0;
7190 $piscompany = $pflag == 'iscompany' && $ptype == 'text' ? 1 : 0;
7191 $pisvat = $pflag == 'isvat' && $ptype == 'text' ? 1 : 0;
7192 $pisfisccode = $pflag == 'isfisccode' && $ptype == 'text' ? 1 : 0;
7193 $pispec = $pflag == 'ispec' && $ptype == 'text' ? 1 : 0;
7194 $pisrecipcode = $pflag == 'isrecipcode' && $ptype == 'text' ? 1 : 0;
7195 $fieldflag = '';
7196 if ($pisaddress == 1) {
7197 $fieldflag = 'address';
7198 } elseif ($piscity == 1) {
7199 $fieldflag = 'city';
7200 } elseif ($piszip == 1) {
7201 $fieldflag = 'zip';
7202 } elseif ($piscompany == 1) {
7203 $fieldflag = 'company';
7204 } elseif ($pisvat == 1) {
7205 $fieldflag = 'vat';
7206 } elseif ($pisfisccode == 1) {
7207 $fieldflag = 'fisccode';
7208 } elseif ($pispec == 1) {
7209 $fieldflag = 'pec';
7210 } elseif ($pisrecipcode == 1) {
7211 $fieldflag = 'recipcode';
7212 }
7213 $ppoplink = VikRequest::getString('poplink', '', 'request');
7214 $pwhere = VikRequest::getInt('where', '', 'request');
7215 $choosestr = "";
7216 if (is_array($pchoose)) {
7217 foreach ($pchoose as $ch) {
7218 if (!empty($ch)) {
7219 $choosestr .= $ch.";;__;;";
7220 }
7221 }
7222 }
7223 $defvalue = VikRequest::getString('defvalue', '', 'request');
7224
7225 $dbo = JFactory::getDbo();
7226
7227 $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).";";
7228 $dbo->setQuery($q);
7229 $dbo->execute();
7230 $mainframe = JFactory::getApplication();
7231 $mainframe->redirect("index.php?option=com_vikbooking&task=customf");
7232 }
7233
7234 public function removecustomf() {
7235 if (!JSession::checkToken()) {
7236 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
7237 }
7238 $ids = VikRequest::getVar('cid', array(0));
7239 if (@count($ids)) {
7240 $dbo = JFactory::getDBO();
7241 foreach ($ids as $d) {
7242 $q = "DELETE FROM `#__vikbooking_custfields` WHERE `id`=".$dbo->quote($d).";";
7243 $dbo->setQuery($q);
7244 $dbo->execute();
7245 }
7246 }
7247 $mainframe = JFactory::getApplication();
7248 $mainframe->redirect("index.php?option=com_vikbooking&task=customf");
7249 }
7250
7251 public function overv() {
7252 VikBookingHelper::printHeader("15");
7253
7254 VikRequest::setVar('view', VikRequest::getCmd('view', 'overv'));
7255
7256 parent::display();
7257
7258 if (VikBooking::showFooter()) {
7259 VikBookingHelper::printFooter();
7260 }
7261 }
7262
7263 public function translations() {
7264 VikBookingHelper::printHeader("21");
7265
7266 VikRequest::setVar('view', VikRequest::getCmd('view', 'translations'));
7267
7268 parent::display();
7269
7270 if (VikBooking::showFooter()) {
7271 VikBookingHelper::printFooter();
7272 }
7273 }
7274
7275 public function savetranslation() {
7276 if (!JSession::checkToken()) {
7277 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
7278 }
7279 $this->do_savetranslation();
7280 }
7281
7282 public function savetranslationstay() {
7283 if (!JSession::checkToken()) {
7284 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
7285 }
7286 $this->do_savetranslation(true);
7287 }
7288
7289 private function do_savetranslation($stay = false) {
7290 $dbo = JFactory::getDBO();
7291 $mainframe = JFactory::getApplication();
7292 $vbo_tn = VikBooking::getTranslator();
7293 $table = VikRequest::getString('vbo_table', '', 'request');
7294 $cur_langtab = VikRequest::getString('vbo_lang', '', 'request');
7295 $langs = $vbo_tn->getLanguagesList();
7296 $xml_tables = $vbo_tn->getTranslationTables();
7297 if (!empty($table) && array_key_exists($table, $xml_tables)) {
7298 $tn = VikRequest::getVar('tn', array(), 'request', 'array', VIKREQUEST_ALLOWRAW);
7299 $tn_saved = 0;
7300 $table_cols = $vbo_tn->getTableColumns($table);
7301 foreach ($langs as $ltag => $lang) {
7302 if ($ltag == $vbo_tn->default_lang) {
7303 continue;
7304 }
7305 if (array_key_exists($ltag, $tn) && count($tn[$ltag]) > 0) {
7306 foreach ($tn[$ltag] as $reference_id => $translation) {
7307 $lang_translation = array();
7308 foreach ($table_cols as $field => $fdetails) {
7309 if (!array_key_exists($field, $translation)) {
7310 continue;
7311 }
7312 $ftype = $fdetails['type'];
7313 if ($ftype == 'skip') {
7314 continue;
7315 }
7316
7317 if (is_array($translation[$field])) {
7318 foreach ($translation[$field] as $tn_field_k => $tn_field_v) {
7319 if (!is_string($tn_field_v)) {
7320 continue;
7321 }
7322 // replace any possible placeholder for special tags
7323 $translation[$field][$tn_field_k] = preg_replace_callback("/(<strong class=\"vbo-editor-hl-specialtag\">)([^<]+)(<\/strong>)/", function($match) {
7324 return $match[2];
7325 }, $translation[$field][$tn_field_k]);
7326 }
7327 } elseif (!empty($translation[$field])) {
7328 // replace any possible placeholder for special tags
7329 $translation[$field] = preg_replace_callback("/(<strong class=\"vbo-editor-hl-specialtag\">)([^<]+)(<\/strong>)/", function($match) {
7330 return $match[2];
7331 }, $translation[$field]);
7332 }
7333
7334 if ($ftype == 'json' && !is_scalar($translation[$field])) {
7335 $translation[$field] = json_encode($translation[$field]);
7336 }
7337 $lang_translation[$field] = $translation[$field];
7338 }
7339 if (count($lang_translation) > 0) {
7340 $q = "SELECT `id` FROM `#__vikbooking_translations` WHERE `table`=".$dbo->quote($table)." AND `lang`=".$dbo->quote($ltag)." AND `reference_id`=".$dbo->quote((int)$reference_id).";";
7341 $dbo->setQuery($q);
7342 $dbo->execute();
7343 if ($dbo->getNumRows() > 0) {
7344 $last_id = $dbo->loadResult();
7345 $q = "UPDATE `#__vikbooking_translations` SET `content`=".$dbo->quote(json_encode($lang_translation))." WHERE `id`=".(int)$last_id.";";
7346 } else {
7347 $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)).");";
7348 }
7349 $dbo->setQuery($q);
7350 $dbo->execute();
7351 $tn_saved++;
7352 }
7353 }
7354 }
7355 }
7356 if ($tn_saved > 0) {
7357 $mainframe->enqueueMessage(JText::translate('VBOTRANSLSAVEDOK'));
7358 }
7359 } else {
7360 VikError::raiseWarning('', JText::translate('VBTRANSLATIONERRINVTABLE'));
7361 }
7362 $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);
7363 }
7364
7365 public function choosebusy() {
7366 VikBookingHelper::printHeader("8");
7367
7368 VikRequest::setVar('view', VikRequest::getCmd('view', 'choosebusy'));
7369
7370 parent::display();
7371
7372 if (VikBooking::showFooter()) {
7373 VikBookingHelper::printFooter();
7374 }
7375 }
7376
7377 public function orders() {
7378 VikBookingHelper::printHeader("8");
7379
7380 VikRequest::setVar('view', VikRequest::getCmd('view', 'orders'));
7381
7382 parent::display();
7383
7384 if (VikBooking::showFooter()) {
7385 VikBookingHelper::printFooter();
7386 }
7387 }
7388
7389 public function vieworders() {
7390 //alias method of orders() for backward compatibility with VCM
7391 $this->orders();
7392 }
7393
7394 public function editorder() {
7395 VikBookingHelper::printHeader("8");
7396
7397 VikRequest::setVar('view', VikRequest::getCmd('view', 'editorder'));
7398
7399 parent::display();
7400
7401 if (VikBooking::showFooter()) {
7402 VikBookingHelper::printFooter();
7403 }
7404 }
7405
7406 public function removeorders()
7407 {
7408 $dbo = JFactory::getDbo();
7409 $app = JFactory::getApplication();
7410
7411 $ids = VikRequest::getVar('cid', array(0));
7412 $pgoto = VikRequest::getString('goto', '', 'request', VIKREQUEST_ALLOWRAW);
7413
7414 $config = VBOFactory::getConfig();
7415
7416 $prev_conf_ids = [];
7417 $purged = false;
7418
7419 $tot_cancs = 0;
7420
7421 if (is_array($ids) && count($ids)) {
7422 foreach ($ids as $d) {
7423 $q = "SELECT * FROM `#__vikbooking_orders` WHERE `id`=" . $dbo->quote($d);
7424 $dbo->setQuery($q, 0, 1);
7425 $row = $dbo->loadAssoc();
7426
7427 // check for any cancellation constraints
7428 $canc_denied = false;
7429 if ($row && class_exists('VCMFeesCancellation')) {
7430 // let VCM detect if there are any constraints for the cancellation
7431 $canc_denied = VCMFeesCancellation::getInstance($row, $anew = true)->isBookingConstrained();
7432 if ($canc_denied) {
7433 // set error message
7434 $canc_deny_error = VCMFeesCancellation::getInstance()->getError();
7435 if ($canc_deny_error) {
7436 $app->enqueueMessage($canc_deny_error, 'error');
7437 }
7438 }
7439 }
7440
7441 if ($row && !$canc_denied) {
7442 // increase counter
7443 $tot_cancs++;
7444
7445 // set status to cancelled
7446 if ($row['status'] != 'cancelled') {
7447 $q = "UPDATE `#__vikbooking_orders` SET `status`='cancelled' WHERE `id`=".(int)$row['id'].";";
7448 $dbo->setQuery($q);
7449 $dbo->execute();
7450 $q = "DELETE FROM `#__vikbooking_tmplock` WHERE `idorder`=" . intval($row['id']) . ";";
7451 $dbo->setQuery($q);
7452 $dbo->execute();
7453 if ($row['status'] == 'confirmed') {
7454 $prev_conf_ids[] = $row['id'];
7455 }
7456 // Booking History
7457 VikBooking::getBookingHistoryInstance()->setBid($row['id'])->store('CB');
7458 }
7459
7460 // free records up
7461 $q = "SELECT * FROM `#__vikbooking_ordersbusy` WHERE `idorder`=".(int)$row['id'].";";
7462 $dbo->setQuery($q);
7463 $ordbusy = $dbo->loadAssocList();
7464 if ($ordbusy) {
7465 foreach ($ordbusy as $ob) {
7466 $q = "DELETE FROM `#__vikbooking_busy` WHERE `id`='".$ob['idbusy']."';";
7467 $dbo->setQuery($q);
7468 $dbo->execute();
7469 }
7470 }
7471
7472 $q = "DELETE FROM `#__vikbooking_ordersbusy` WHERE `idorder`=".(int)$row['id'].";";
7473 $dbo->setQuery($q);
7474 $dbo->execute();
7475
7476 // check for purge removal
7477 if ($row['status'] == 'cancelled') {
7478 $q = "DELETE FROM `#__vikbooking_customers_orders` WHERE `idorder`=" . intval($row['id']) . ";";
7479 $dbo->setQuery($q);
7480 $dbo->execute();
7481 $q = "DELETE FROM `#__vikbooking_ordersrooms` WHERE `idorder`=".(int)$row['id'].";";
7482 $dbo->setQuery($q);
7483 $dbo->execute();
7484 $q = "DELETE FROM `#__vikbooking_orderhistory` WHERE `idorder`=".(int)$row['id'].";";
7485 $dbo->setQuery($q);
7486 $dbo->execute();
7487 $q = "DELETE FROM `#__vikbooking_orders` WHERE `id`=".(int)$row['id'].";";
7488 $dbo->setQuery($q);
7489 $dbo->execute();
7490 // in case of split stay booking, remove the transient
7491 if ($row['split_stay']) {
7492 $config->remove('split_stay_' . $row['id']);
7493 }
7494 // turn flag on
7495 $purged = true;
7496 }
7497 }
7498 }
7499
7500 if ($tot_cancs) {
7501 // enqueue system message
7502 $app->enqueueMessage(JText::translate('VBMESSDELBUSY'));
7503 }
7504 }
7505
7506 if ($prev_conf_ids) {
7507 $prev_conf_ids_str = '';
7508 foreach ($prev_conf_ids as $prev_id) {
7509 $prev_conf_ids_str .= '&cid[]='.$prev_id;
7510 }
7511 //Invoke Channel Manager
7512 $vcm_autosync = VikBooking::vcmAutoUpdate();
7513 if ($vcm_autosync > 0) {
7514 $vcm_obj = VikBooking::getVcmInvoker();
7515 $vcm_obj->setOids($prev_conf_ids)->setSyncType('cancel');
7516 $sync_result = $vcm_obj->doSync();
7517 if ($sync_result === false) {
7518 $vcm_err = $vcm_obj->getError();
7519 VikError::raiseWarning('', JText::translate('VBCHANNELMANAGERRESULTKO').' <a href="index.php?option=com_vikchannelmanager" target="_blank">'.JText::translate('VBCHANNELMANAGEROPEN').'</a> '.(strlen($vcm_err) > 0 ? '('.$vcm_err.')' : ''));
7520 }
7521 } elseif (file_exists(VCM_SITE_PATH . DIRECTORY_SEPARATOR . "helpers" . DIRECTORY_SEPARATOR . "synch.vikbooking.php")) {
7522 $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');
7523 VikError::raiseNotice('', JText::translate('VBCHANNELMANAGERINVOKEASK').' <button type="button" class="btn btn-primary" onclick="document.location.href=\''.$vcm_sync_url.'\';">'.JText::translate('VBCHANNELMANAGERSENDRQ').'</button>');
7524 }
7525 //
7526 }
7527
7528 if (!empty($pgoto)) {
7529 if (is_numeric($pgoto) && is_array($ids) && count($ids) === 1) {
7530 if ($purged) {
7531 // go back to the bookings list page
7532 $app->redirect("index.php?option=com_vikbooking&task=orders");
7533 } else {
7534 // go back to the booking details page
7535 $app->redirect("index.php?option=com_vikbooking&task=editorder&cid[]=" . (int)$ids[0]);
7536 }
7537 exit;
7538 }
7539 // we expect the goto URL to be base64 encoded
7540 $app->redirect(base64_decode($pgoto));
7541 exit;
7542 }
7543
7544 // go back to the bookings list page
7545 $app->redirect("index.php?option=com_vikbooking&task=orders");
7546 }
7547
7548 public function config() {
7549 VikBookingHelper::printHeader("11");
7550
7551 VikRequest::setVar('view', VikRequest::getCmd('view', 'config'));
7552
7553 parent::display();
7554
7555 if (VikBooking::showFooter()) {
7556 VikBookingHelper::printFooter();
7557 }
7558 }
7559
7560 public function saveconfig()
7561 {
7562 if (!JSession::checkToken()) {
7563 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
7564 }
7565
7566 $dbo = JFactory::getDbo();
7567 $app = JFactory::getApplication();
7568
7569 $config = VBOFactory::getConfig();
7570
7571 $pallowbooking = VikRequest::getString('allowbooking', '', 'request');
7572 $pdisabledbookingmsg = VikRequest::getString('disabledbookingmsg', '', 'request', VIKREQUEST_ALLOWHTML);
7573 $ptimeopenstorefh = VikRequest::getString('timeopenstorefh', '', 'request');
7574 $ptimeopenstorefm = VikRequest::getString('timeopenstorefm', '', 'request');
7575 $ptimeopenstoreth = VikRequest::getString('timeopenstoreth', '', 'request');
7576 $ptimeopenstoretm = VikRequest::getString('timeopenstoretm', '', 'request');
7577 $phoursmorebookingback = VikRequest::getString('hoursmorebookingback', '', 'request');
7578 $pdateformat = VikRequest::getString('dateformat', '', 'request');
7579 $pdatesep = VikRequest::getString('datesep', '', 'request');
7580 $pdatesep = empty($pdatesep) ? "/" : $pdatesep;
7581 $presmodcanc = VikRequest::getInt('resmodcanc', 1, 'request');
7582 $presmodcancmin = VikRequest::getInt('resmodcancmin', 1, 'request');
7583 $pshowcategories = VikRequest::getString('showcategories', '', 'request');
7584 $pshowchildren = VikRequest::getString('showchildren', '', 'request');
7585 $psearchsuggestions = VikRequest::getInt('searchsuggestions', '', 'request');
7586 $ptokenform = VikRequest::getString('tokenform', '', 'request');
7587 $padminemail = VikRequest::getString('adminemail', '', 'request');
7588 $psenderemail = VikRequest::getString('senderemail', '', 'request');
7589 $pminuteslock = VikRequest::getString('minuteslock', '', 'request');
7590 $pminautoremove = VikRequest::getInt('minautoremove', '', 'request');
7591 $pfooterordmail = VikRequest::getString('footerordmail', '', 'request', VIKREQUEST_ALLOWHTML);
7592 $ptermsconds = VikRequest::getString('termsconds', '', 'request', VIKREQUEST_ALLOWHTML);
7593 $prequirelogin = VikRequest::getString('requirelogin', '', 'request');
7594 $pautoroomunit = VikRequest::getInt('autoroomunit', '', 'request');
7595 $ptodaybookings = VikRequest::getInt('todaybookings', '', 'request');
7596 $ptodaybookings = $ptodaybookings === 1 ? 1 : 0;
7597 $ploadbootstrap = VikRequest::getInt('loadbootstrap', '', 'request');
7598 $ploadbootstrap = $ploadbootstrap === 1 ? 1 : 0;
7599 $pusefa = VikRequest::getInt('usefa', '', 'request');
7600 $pusefa = $pusefa > 0 ? 1 : 0;
7601 $ploadjquery = VikRequest::getString('loadjquery', '', 'request');
7602 $ploadjquery = $ploadjquery == "yes" ? "1" : "0";
7603 $pcalendar = VikRequest::getString('calendar', '', 'request');
7604 $pcalendar = $pcalendar == "joomla" ? "joomla" : "jqueryui";
7605 $penablecoupons = VikRequest::getString('enablecoupons', '', 'request');
7606 $penablecoupons = $penablecoupons == "1" ? 1 : 0;
7607 $penablepin = VikRequest::getString('enablepin', '', 'request');
7608 $penablepin = $penablepin == "1" ? 1 : 0;
7609 $pmindaysadvance = VikRequest::getInt('mindaysadvance', '', 'request');
7610 $pmindaysadvance = $pmindaysadvance < 0 ? 0 : $pmindaysadvance;
7611 $pautodefcalnights = VikRequest::getInt('autodefcalnights', '', 'request');
7612 $pautodefcalnights = $pautodefcalnights >= 1 ? $pautodefcalnights : '1';
7613 $pnumrooms = VikRequest::getInt('numrooms', '', 'request');
7614 $pnumrooms = $pnumrooms > 0 ? $pnumrooms : '5';
7615 $pnumadultsfrom = VikRequest::getString('numadultsfrom', '', 'request');
7616 $pnumadultsfrom = intval($pnumadultsfrom) >= 0 ? $pnumadultsfrom : '1';
7617 $pnumadultsto = VikRequest::getString('numadultsto', '', 'request');
7618 $pnumadultsto = intval($pnumadultsto) > 0 ? $pnumadultsto : '10';
7619 if (intval($pnumadultsfrom) > intval($pnumadultsto)) {
7620 $pnumadultsfrom = '1';
7621 $pnumadultsto = '10';
7622 }
7623 $pnumchildrenfrom = VikRequest::getString('numchildrenfrom', '', 'request');
7624 $pnumchildrenfrom = intval($pnumchildrenfrom) >= 0 ? $pnumchildrenfrom : '1';
7625 $pnumchildrento = VikRequest::getString('numchildrento', '', 'request');
7626 $pnumchildrento = intval($pnumchildrento) > 0 ? $pnumchildrento : '4';
7627 if (intval($pnumchildrenfrom) > intval($pnumchildrento)) {
7628 $pnumadultsfrom = '1';
7629 $pnumadultsto = '4';
7630 }
7631 $confnumadults = $pnumadultsfrom.'-'.$pnumadultsto;
7632 $confnumchildren = $pnumchildrenfrom.'-'.$pnumchildrento;
7633 $pmaxdate = VikRequest::getString('maxdate', '', 'request');
7634 $pmaxdate = intval($pmaxdate) < 1 ? 2 : $pmaxdate;
7635 $pmaxdateinterval = VikRequest::getString('maxdateinterval', '', 'request');
7636 $pmaxdateinterval = !in_array($pmaxdateinterval, array('d', 'w', 'm', 'y')) ? 'y' : $pmaxdateinterval;
7637 $maxdate_str = '+'.$pmaxdate.$pmaxdateinterval;
7638 $pcronkey = VikRequest::getString('cronkey', '', 'request');
7639 $pcdsfrom = VikRequest::getVar('cdsfrom', array());
7640 $pcdsto = VikRequest::getVar('cdsto', array());
7641 $closing_dates = array();
7642 if (count($pcdsfrom)) {
7643 foreach ($pcdsfrom as $kcd => $vcdfrom) {
7644 if (!empty($vcdfrom) && array_key_exists($kcd, $pcdsto) && !empty($pcdsto[$kcd])) {
7645 $tscdfrom = VikBooking::getDateTimestamp($vcdfrom, '0', '0');
7646 $tscdto = VikBooking::getDateTimestamp($pcdsto[$kcd], '0', '0');
7647 if (!empty($tscdfrom) && !empty($tscdto) && $tscdto >= $tscdfrom) {
7648 $cdval = array('from' => $tscdfrom, 'to' => $tscdto);
7649 if (!in_array($cdval, $closing_dates)) {
7650 $closing_dates[] = $cdval;
7651 }
7652 }
7653 }
7654 }
7655 }
7656 $psmartsearch = VikRequest::getString('smartsearch', '', 'request');
7657 $psmartsearch = $psmartsearch == "dynamic" ? "dynamic" : "automatic";
7658 $pvbosef = VikRequest::getInt('vbosef', '', 'request');
7659 $vbosef = file_exists(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'router.php');
7660 if ($pvbosef === 1) {
7661 if (!$vbosef) {
7662 rename(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'_router.php', VBO_SITE_PATH.DIRECTORY_SEPARATOR.'router.php');
7663 }
7664 } else {
7665 if ($vbosef) {
7666 rename(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'router.php', VBO_SITE_PATH.DIRECTORY_SEPARATOR.'_router.php');
7667 }
7668 }
7669 $pmultilang = VikRequest::getString('multilang', '', 'request');
7670 $pmultilang = $pmultilang == "1" ? 1 : 0;
7671 $pvcmautoupd = VikRequest::getInt('vcmautoupd', '', 'request');
7672 $pvcmautoupd = $pvcmautoupd > 0 ? 1 : 0;
7673 /**
7674 * Chat params and configuration settings
7675 *
7676 * @since 1.12
7677 */
7678 $pchatenabled = VikRequest::getInt('chatenabled', 0, 'request');
7679 if (is_file(VCM_SITE_PATH.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'lib.vikchannelmanager.php')) {
7680 $config->set('chatenabled', $pchatenabled);
7681
7682 // chat params
7683 $pchat_res_status = explode(';', VikRequest::getString('chat_res_status', '', 'request'));
7684 $chat_res_status = array();
7685 foreach ($pchat_res_status as $chatrs) {
7686 if (!empty($chatrs)) {
7687 array_push($chat_res_status, $chatrs);
7688 }
7689 }
7690 $chatparams = new stdClass;
7691 $chatparams->res_status = $chat_res_status;
7692 $chatparams->av_type = VikRequest::getString('chat_av_type', '', 'request');
7693 $chatparams->av_days = VikRequest::getInt('chat_av_days', 0, 'request');
7694
7695 $config->set('chatparams', $chatparams);
7696 }
7697
7698 /**
7699 * Pre check-in configuration settings
7700 *
7701 * @since 1.12
7702 */
7703 $pprecheckinenabled = VikRequest::getInt('precheckinenabled', 0, 'request');
7704 $pprecheckinenabled = $pprecheckinenabled > 0 ? 1 : 0;
7705
7706 $config->set('precheckinenabled', $pprecheckinenabled);
7707 $config->set('precheckinminoffset', VikRequest::getInt('precheckinminoffset', 0, 'request'));
7708
7709 $pupsellingenabled = VikRequest::getInt('upsellingenabled', 0, 'request');
7710 $pupsellingenabled = $pupsellingenabled > 0 ? 1 : 0;
7711 $config->set('upselling', $pupsellingenabled);
7712
7713 $porphanscal = VikRequest::getString('orphanscal', 'next', 'request');
7714 $porphanscal = $porphanscal == 'prevnext' ? 'prevnext' : 'next';
7715 $config->set('orphanscalculation', $porphanscal);
7716
7717 $psrcrtpl = VikRequest::getString('srcrtpl', 'compact', 'request');
7718 $config->set('searchrestmpl', $psrcrtpl);
7719
7720 /**
7721 * Guest Reviews settings
7722 *
7723 * @since 1.13
7724 */
7725 $pgrenabled = VikRequest::getInt('grenabled', 0, 'request');
7726 $pgrminchars = VikRequest::getInt('grminchars', 0, 'request');
7727 $pgrappr = VikRequest::getString('grappr', 'auto', 'request');
7728 $pgrappr = $pgrappr == 'auto' ? 'auto' : 'manual';
7729 $pgrtype = VikRequest::getString('grtype', 'service', 'request');
7730 $pgrtype = $pgrtype == 'service' ? 'service' : 'global';
7731 $pgrsrv = VikRequest::getVar('grsrv', array(), 'request', 'array');
7732 $config->set('grenabled', $pgrenabled);
7733 $config->set('grminchars', $pgrminchars);
7734 $config->set('grappr', $pgrappr);
7735 $config->set('grtype', $pgrtype);
7736 try {
7737 // always truncate service names (this query may require special permissions)
7738 $q = "TRUNCATE TABLE `#__vikbooking_greview_service`;";
7739 $dbo->setQuery($q);
7740 $dbo->execute();
7741 } catch (Exception $e) {
7742 // do nothing
7743 }
7744 foreach ($pgrsrv as $srvname) {
7745 $q = "INSERT INTO `#__vikbooking_greview_service` (`service_name`) VALUES (" . $dbo->quote($srvname) . ");";
7746 $dbo->setQuery($q);
7747 $dbo->execute();
7748 }
7749
7750 /**
7751 * Preferred countries ordering, or custom countries.
7752 *
7753 * @since 1.14 (J) - 1.3.11 (WP)
7754 * @since 1.14.1 (J) - 1.4.1 (WP) we also support "cust_pref_countries"
7755 */
7756 $pref_countries = VikRequest::getVar('pref_countries', array());
7757 $cust_pref_countries = VikRequest::getString('cust_pref_countries', '', 'request');
7758 $pref_countries = !is_array($pref_countries) || empty($pref_countries[0]) ? VikBooking::preferredCountriesOrdering() : $pref_countries;
7759 if (!empty($cust_pref_countries)) {
7760 $all_custom_prefcountries = array();
7761 $cust_pref_countries = explode(',', $cust_pref_countries);
7762 foreach ($cust_pref_countries as $cust_pref_country) {
7763 $cust_pref_country = trim(strtolower($cust_pref_country));
7764 if (empty($cust_pref_country) || strlen($cust_pref_country) != 2) {
7765 continue;
7766 }
7767 array_push($all_custom_prefcountries, $cust_pref_country);
7768 }
7769 if (count($all_custom_prefcountries)) {
7770 $pref_countries = $all_custom_prefcountries;
7771 }
7772 }
7773 $config->set('preferred_countries', $pref_countries);
7774 //
7775
7776 $gmapskey = VikRequest::getString('gmapskey', '', 'request');
7777 $config->set('gmapskey', $gmapskey);
7778
7779 $pref_textcolor = VikRequest::getString('pref_textcolor', '', 'request');
7780 $pref_bgcolor = VikRequest::getString('pref_bgcolor', '', 'request');
7781 $pref_fontcolor = VikRequest::getString('pref_fontcolor', '', 'request');
7782 $pref_bgcolorhov = VikRequest::getString('pref_bgcolorhov', '', 'request');
7783 $pref_fontcolorhov = VikRequest::getString('pref_fontcolorhov', '', 'request');
7784 $pref_colors = array(
7785 'textcolor' => $pref_textcolor,
7786 'bgcolor' => $pref_bgcolor,
7787 'fontcolor' => $pref_fontcolor,
7788 'bgcolorhov' => $pref_bgcolorhov,
7789 'fontcolorhov' => $pref_fontcolorhov,
7790 );
7791 $config->set('pref_colors', $pref_colors);
7792
7793 $interactive_map = VikRequest::getInt('interactive_map', 0, 'request');
7794 $config->set('interactive_map', $interactive_map);
7795
7796 $noemptydecimals = VikRequest::getInt('noemptydecimals', 0, 'request');
7797 $config->set('noemptydecimals', $noemptydecimals);
7798
7799 /**
7800 * Appearance preferences (light, auto, dark mode).
7801 *
7802 * @since 1.15.0 (J) - 1.5.0 (WP)
7803 */
7804 $appearance_pref = VikRequest::getString('appearance_pref', '');
7805 $config->set('appearance_pref', $appearance_pref);
7806
7807 $res_backend_path = VBO_ADMIN_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR;
7808 $picon = "";
7809 if (intval($_FILES['sitelogo']['error']) == 0 && trim($_FILES['sitelogo']['name'])!="") {
7810 jimport('joomla.filesystem.file');
7811 if (@is_uploaded_file($_FILES['sitelogo']['tmp_name'])) {
7812 $safename = JFile::makeSafe(str_replace(" ", "_", strtolower($_FILES['sitelogo']['name'])));
7813 if (file_exists($res_backend_path.$safename)) {
7814 $j = 1;
7815 while (file_exists($res_backend_path.$j.$safename)) {
7816 $j++;
7817 }
7818 $pwhere = $res_backend_path.$j.$safename;
7819 } else {
7820 $j = "";
7821 $pwhere = $res_backend_path.$safename;
7822 }
7823 if (!getimagesize($_FILES['sitelogo']['tmp_name']) || !preg_match("/\.(a?png|jpe?g|bmp|gif|ico|webp)\z/i", $safename)) {
7824 @unlink($pwhere);
7825 $picon = "";
7826 } else {
7827 VikBooking::uploadFile($_FILES['sitelogo']['tmp_name'], $pwhere);
7828 @chmod($pwhere, 0644);
7829 $picon = $j.$safename;
7830 }
7831 }
7832 if (!empty($picon)) {
7833 $config->set('sitelogo', $picon);
7834 }
7835 }
7836 $pbackicon = "";
7837 if (intval($_FILES['backlogo']['error']) == 0 && trim($_FILES['backlogo']['name'])!="") {
7838 jimport('joomla.filesystem.file');
7839 if (@is_uploaded_file($_FILES['backlogo']['tmp_name'])) {
7840 $safename = JFile::makeSafe(str_replace(" ", "_", strtolower($_FILES['backlogo']['name'])));
7841 if (file_exists($res_backend_path.$safename)) {
7842 $j = 1;
7843 while (file_exists($res_backend_path.$j.$safename)) {
7844 $j++;
7845 }
7846 $pwhere = $res_backend_path.$j.$safename;
7847 } else {
7848 $j = "";
7849 $pwhere = $res_backend_path.$safename;
7850 }
7851 if (!getimagesize($_FILES['backlogo']['tmp_name']) || !preg_match("/\.(a?png|jpe?g|bmp|gif|ico|webp)\z/i", $safename)) {
7852 @unlink($pwhere);
7853 $pbackicon = "";
7854 } else {
7855 VikBooking::uploadFile($_FILES['backlogo']['tmp_name'], $pwhere);
7856 @chmod($pwhere, 0644);
7857 $pbackicon = $j.$safename;
7858 }
7859 }
7860 if (!empty($pbackicon)) {
7861 $config->set('backlogo', $pbackicon);
7862 }
7863 }
7864 $config->set('vcmautoupd', $pvcmautoupd);
7865 $config->set('allowbooking', empty($pallowbooking) || $pallowbooking != "1" ? 0 : 1);
7866 $config->set('showcategories', empty($pshowcategories) || $pshowcategories != "yes" ? 0 : 1);
7867 $config->set('showchildren', empty($pshowchildren) || $pshowchildren != "yes" ? 0 : 1);
7868 $config->set('searchsuggestions', $psearchsuggestions);
7869 $config->set('tokenform', empty($ptokenform) || $ptokenform != "yes" ? 0 : 1);
7870
7871 // translatable text
7872 $q = "UPDATE `#__vikbooking_texts` SET `setting`=".$dbo->quote($pfooterordmail)." WHERE `param`='footerordmail';";
7873 $dbo->setQuery($q);
7874 $dbo->execute();
7875
7876 // translatable text
7877 $q = "UPDATE `#__vikbooking_texts` SET `setting`=".$dbo->quote($pdisabledbookingmsg)." WHERE `param`='disabledbookingmsg';";
7878 $dbo->setQuery($q);
7879 $dbo->execute();
7880
7881 // terms and conditions
7882 $q = "SELECT `id`,`setting` FROM `#__vikbooking_texts` WHERE `param`='termsconds';";
7883 $dbo->setQuery($q);
7884 $dbo->execute();
7885 if ($dbo->getNumRows() > 0) {
7886 $q = "UPDATE `#__vikbooking_texts` SET `setting`=".$dbo->quote($ptermsconds)." WHERE `param`='termsconds';";
7887 $dbo->setQuery($q);
7888 $dbo->execute();
7889 } else {
7890 $q = "INSERT INTO `#__vikbooking_texts` (`param`,`exp`,`setting`) VALUES ('termsconds','Terms and Conditions',".$dbo->quote($ptermsconds).");";
7891 $dbo->setQuery($q);
7892 $dbo->execute();
7893 }
7894
7895 $config->set('adminemail', $padminemail);
7896 $config->set('senderemail', $psenderemail);
7897 $config->set('dateformat', empty($pdateformat) ? "%d/%m/%Y" : $pdateformat);
7898 $config->set('datesep', $pdatesep);
7899 $config->set('resmodcanc', $presmodcanc);
7900 $config->set('resmodcancmin', $presmodcancmin);
7901 $config->set('minuteslock', $pminuteslock);
7902 $config->set('minautoremove', $pminautoremove);
7903
7904 $openingh = $ptimeopenstorefh * 3600;
7905 $openingm = $ptimeopenstorefm * 60;
7906 $openingts = $openingh + $openingm;
7907 $closingh = $ptimeopenstoreth * 3600;
7908 $closingm = $ptimeopenstoretm * 60;
7909 $closingts = $closingh + $closingm;
7910 // check if the check-in/out times have changed and if there are future bookings with the old time to prevent availability errors
7911 $prevtimes = $config->get('timeopenstore', '');
7912 if ($prevtimes != $openingts . "-" . $closingts) {
7913 $q = "SELECT `id` FROM `#__vikbooking_orders` WHERE `checkout`>".time().";";
7914 $dbo->setQuery($q);
7915 $dbo->execute();
7916 if ($dbo->getNumRows() > 0) {
7917 VikError::raiseWarning('', JText::translate('VBOCONFIGWARNDIFFCHECKINOUT'));
7918 /**
7919 * VBO 1.10 Patch - we concatenate a button to unify the check-in/out times
7920 * for all reservations to avoid issues with the availability.
7921 *
7922 * @since August 29th 2018
7923 */
7924 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>');
7925 //
7926 }
7927 }
7928 $config->set('timeopenstore', $openingts . "-" . $closingts);
7929
7930 // set the hours of extended gratuity period to the difference between checkin and checkout if checkout is later
7931 $phoursmorebookingback = "0";
7932 if ($closingts > $openingts) {
7933 $diffcheck = ($closingts - $openingts) / 3600;
7934 $phoursmorebookingback = ceil($diffcheck);
7935 }
7936 $config->set('hoursmorebookingback', $phoursmorebookingback);
7937 $config->set('hoursmoreroomavail', '0');
7938 $config->set('multilang', $pmultilang);
7939 $config->set('requirelogin', $prequirelogin == "1" ? 1 : 0);
7940 $config->set('autoroomunit', $pautoroomunit ? 1 : 0);
7941 $config->set('todaybookings', $ptodaybookings);
7942 $config->set('bootstrap', $ploadbootstrap);
7943 $config->set('usefa', $pusefa);
7944 $config->set('loadjquery', $ploadjquery);
7945 $config->set('calendar', $pcalendar);
7946 $config->set('enablecoupons', $penablecoupons);
7947 $config->set('enablepin', $penablepin);
7948 $config->set('mindaysadvance', $pmindaysadvance);
7949 $config->set('autodefcalnights', $pautodefcalnights);
7950 $config->set('numrooms', $pnumrooms);
7951 $config->set('numadults', $confnumadults);
7952 $config->set('numchildren', $confnumchildren);
7953 $config->set('closingdates', $closing_dates);
7954 $config->set('smartsearch', $psmartsearch);
7955 $config->set('maxdate', $maxdate_str);
7956 $config->set('cronkey', $pcronkey);
7957
7958 $pfronttitle = VikRequest::getString('fronttitle', '', 'request');
7959 $pfronttitletag = VikRequest::getString('fronttitletag', '', 'request');
7960 $pfronttitletagclass = VikRequest::getString('fronttitletagclass', '', 'request');
7961 $pshowfooter = VikRequest::getString('showfooter', '', 'request');
7962 $pintromain = VikRequest::getString('intromain', '', 'request', VIKREQUEST_ALLOWHTML);
7963 $pclosingmain = VikRequest::getString('closingmain', '', 'request', VIKREQUEST_ALLOWHTML);
7964 $pcurrencyname = VikRequest::getString('currencyname', '', 'request', VIKREQUEST_ALLOWHTML);
7965 $pcurrencysymb = VikRequest::getString('currencysymb', '', 'request', VIKREQUEST_ALLOWHTML);
7966 $pcurrencycodepp = VikRequest::getString('currencycodepp', '', 'request');
7967 $pnumdecimals = VikRequest::getString('numdecimals', '', 'request');
7968 $pnumdecimals = intval($pnumdecimals);
7969 $pdecseparator = VikRequest::getString('decseparator', '', 'request');
7970 $pdecseparator = empty($pdecseparator) ? '.' : $pdecseparator;
7971 $pthoseparator = VikRequest::getString('thoseparator', '', 'request');
7972 $numberformatstr = $pnumdecimals.':'.$pdecseparator.':'.$pthoseparator;
7973 $pshowpartlyreserved = VikRequest::getString('showpartlyreserved', '', 'request');
7974 $pshowpartlyreserved = $pshowpartlyreserved == "yes" ? 1 : 0;
7975 $pshowcheckinoutonly = VikRequest::getInt('showcheckinoutonly', '', 'request');
7976 $pshowcheckinoutonly = $pshowcheckinoutonly > 0 ? 1 : 0;
7977 $pnumcalendars = VikRequest::getInt('numcalendars', '', 'request');
7978 $pnumcalendars = $pnumcalendars > -1 ? $pnumcalendars : 3;
7979 $pthumbsize = VikRequest::getInt('thumbsize', 0, 'request');
7980 $pfirstwday = VikRequest::getString('firstwday', '', 'request');
7981 $pfirstwday = intval($pfirstwday) >= 0 && intval($pfirstwday) <= 6 ? $pfirstwday : '0';
7982 $pbctagname = VikRequest::getVar('bctagname', array());
7983 $pbctagcolor = VikRequest::getVar('bctagcolor', array());
7984 $pbctagrule = VikRequest::getVar('bctagrule', array());
7985 $bctags_arr = array();
7986 $bctags_rules = array();
7987 if (count($pbctagname) > 0) {
7988 foreach ($pbctagname as $bctk => $bctv) {
7989 if (!empty($bctv) && !empty($pbctagcolor[$bctk]) && strlen($pbctagrule[$bctk]) > 0) {
7990 if (intval($pbctagrule[$bctk]) == 0 || !in_array($pbctagrule[$bctk], $bctags_rules)) {
7991 $bctags_rules[] = $pbctagrule[$bctk];
7992 $bctags_arr[] = array('color' => $pbctagcolor[$bctk], 'name' => $bctv, 'rule' => $pbctagrule[$bctk]);
7993 }
7994 }
7995 }
7996 }
7997 //theme
7998 $ptheme = VikRequest::getString('theme', '', 'request');
7999 if (empty($ptheme) || $ptheme == 'default') {
8000 $ptheme = 'default';
8001 } else {
8002 $validtheme = false;
8003 $themes = glob(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'themes'.DIRECTORY_SEPARATOR.'*');
8004 if (count($themes) > 0) {
8005 $strip = VBO_SITE_PATH.DIRECTORY_SEPARATOR.'themes'.DIRECTORY_SEPARATOR;
8006 foreach ($themes as $th) {
8007 if (is_dir($th)) {
8008 $tname = str_replace($strip, '', $th);
8009 if ($tname == $ptheme) {
8010 $validtheme = true;
8011 break;
8012 }
8013 }
8014 }
8015 }
8016 if ($validtheme == false) {
8017 $ptheme = 'default';
8018 }
8019 }
8020 $config->set('theme', $ptheme);
8021 //
8022 $config->set('showpartlyreserved', $pshowpartlyreserved);
8023 $config->set('showcheckinoutonly', $pshowcheckinoutonly);
8024 $config->set('numcalendars', $pnumcalendars);
8025
8026 // record may not be set
8027 $config->set('thumbsize', $pthumbsize);
8028
8029 $config->set('firstwday', $pfirstwday);
8030
8031 // translatable text
8032 $q = "UPDATE `#__vikbooking_texts` SET `setting`=".$dbo->quote($pfronttitle)." WHERE `param`='fronttitle';";
8033 $dbo->setQuery($q);
8034 $dbo->execute();
8035
8036 $config->set('fronttitletag', $pfronttitletag);
8037 $config->set('fronttitletagclass', $pfronttitletagclass);
8038 $config->set('showfooter', empty($pshowfooter) || $pshowfooter != "yes" ? 0 : 1);
8039
8040 // translatable texts
8041 $q = "UPDATE `#__vikbooking_texts` SET `setting`=".$dbo->quote($pintromain)." WHERE `param`='intromain';";
8042 $dbo->setQuery($q);
8043 $dbo->execute();
8044 $q = "UPDATE `#__vikbooking_texts` SET `setting`=".$dbo->quote($pclosingmain)." WHERE `param`='closingmain';";
8045 $dbo->setQuery($q);
8046 $dbo->execute();
8047
8048 $config->set('currencyname', $pcurrencyname);
8049 $config->set('currencysymb', $pcurrencysymb);
8050 $config->set('currencycodepp', $pcurrencycodepp);
8051 $config->set('numberformat', $numberformatstr);
8052 // bookings color tags
8053 $config->set('bookingsctags', $bctags_arr);
8054
8055 $pivainclusa = VikRequest::getString('ivainclusa', '', 'request');
8056 $ptaxsummary = VikRequest::getString('taxsummary', '', 'request');
8057 $ptaxsummary = empty($ptaxsummary) || $ptaxsummary != "yes" ? "0" : "1";
8058 $pccpaypal = VikRequest::getString('ccpaypal', '', 'request');
8059 $ppaytotal = VikRequest::getString('paytotal', '', 'request');
8060 $ppayaccpercent = VikRequest::getString('payaccpercent', '', 'request');
8061 $ptypedeposit = VikRequest::getString('typedeposit', '', 'request');
8062 $ptypedeposit = $ptypedeposit == 'fixed' ? 'fixed' : 'pcent';
8063 $pdepoverrides = VikRequest::getString('depoverrides', '', 'request');
8064 $ppaymentname = VikRequest::getString('paymentname', '', 'request');
8065 $pdisclaimer = VikRequest::getString('disclaimer', '', 'request', VIKREQUEST_ALLOWHTML);
8066 $pmultipay = VikRequest::getString('multipay', '', 'request');
8067 $pmultipay = $pmultipay == "yes" ? 1 : 0;
8068 $pdepifdaysadv = VikRequest::getInt('depifdaysadv', '', 'request');
8069 $pnodepnonrefund = VikRequest::getInt('nodepnonrefund', '', 'request');
8070 $pdepcustchoice = VikRequest::getString('depcustchoice', '', 'request');
8071 $pdepcustchoice = $pdepcustchoice == "yes" ? 1 : 0;
8072
8073 // translatable text
8074 $q = "UPDATE `#__vikbooking_texts` SET `setting`=" . $dbo->q($ppaymentname) . " WHERE `param`='paymentname';";
8075 $dbo->setQuery($q);
8076 $dbo->execute();
8077 $q = "UPDATE `#__vikbooking_texts` SET `setting`=" . $dbo->q($pdisclaimer) . " WHERE `param`='disclaimer';";
8078 $dbo->setQuery($q);
8079 $dbo->execute();
8080
8081 $config->set('ivainclusa', empty($pivainclusa) || $pivainclusa != "yes" ? 0 : 1);
8082 $config->set('taxsummary', $ptaxsummary);
8083 $config->set('paytotal', empty($ppaytotal) || $ppaytotal != "yes" ? 0 : 1);
8084
8085 $config->set('ccpaypal', $pccpaypal);
8086 $config->set('payaccpercent', $ppayaccpercent);
8087 $config->set('typedeposit', $ptypedeposit);
8088 $config->set('depoverrides', $pdepoverrides);
8089 $config->set('multipay', $pmultipay);
8090 $config->set('depifdaysadv', $pdepifdaysadv);
8091 $config->set('nodepnonrefund', $pnodepnonrefund);
8092 $config->set('depcustchoice', $pdepcustchoice);
8093
8094 $psendemailwhen = VikRequest::getInt('sendemailwhen', '', 'request');
8095 $psendemailwhen = $psendemailwhen > 1 ? 2 : 1;
8096 $pattachical = VikRequest::getInt('attachical', 0, 'request');
8097 $pattachical = $pattachical >= 0 && $pattachical <= 3 ? $pattachical : 1;
8098 $config->set('emailsendwhen', $psendemailwhen);
8099 $config->set('attachical', $pattachical);
8100
8101 // SMS APIs
8102 $psmsapi = VikRequest::getString('smsapi', '', 'request');
8103 $psmsautosend = VikRequest::getString('smsautosend', '', 'request');
8104 $psmsautosend = intval($psmsautosend) > 0 ? 1 : 0;
8105 $psmssendto = VikRequest::getVar('smssendto', array());
8106 $sms_sendto = array();
8107 foreach ($psmssendto as $sto) {
8108 if (in_array($sto, array('admin', 'customer'))) {
8109 $sms_sendto[] = $sto;
8110 }
8111 }
8112 $psmssendwhen = VikRequest::getInt('smssendwhen', '', 'request');
8113 $psmssendwhen = $psmssendwhen > 1 ? 2 : 1;
8114 $psmsadminphone = VikRequest::getString('smsadminphone', '', 'request');
8115 $psmsadmintpl = VikRequest::getString('smsadmintpl', '', 'request', VIKREQUEST_ALLOWRAW);
8116 $psmscustomertpl = VikRequest::getString('smscustomertpl', '', 'request', VIKREQUEST_ALLOWRAW);
8117 $psmsadmintplpend = VikRequest::getString('smsadmintplpend', '', 'request', VIKREQUEST_ALLOWRAW);
8118 $psmscustomertplpend = VikRequest::getString('smscustomertplpend', '', 'request', VIKREQUEST_ALLOWRAW);
8119 $psmsadmintplcanc = VikRequest::getString('smsadmintplcanc', '', 'request', VIKREQUEST_ALLOWRAW);
8120 $psmscustomertplcanc = VikRequest::getString('smscustomertplcanc', '', 'request', VIKREQUEST_ALLOWRAW);
8121 $viksmsparams = VikRequest::getVar('viksmsparams', array());
8122 $smsparamarr = array();
8123 if (count($viksmsparams) > 0) {
8124 foreach ($viksmsparams as $setting => $cont) {
8125 if (strlen($setting) > 0) {
8126 $smsparamarr[$setting] = $cont;
8127 }
8128 }
8129 }
8130 $config->set('smsapi', $psmsapi);
8131 $config->set('smsautosend', $psmsautosend);
8132 $config->set('smssendto', $sms_sendto);
8133 $config->set('smssendwhen', $psmssendwhen);
8134 $config->set('smsadminphone', $psmsadminphone);
8135 $config->set('smsparams', $smsparamarr);
8136
8137 // translatable texts
8138 $q = "UPDATE `#__vikbooking_texts` SET `setting`=".$dbo->quote($psmsadmintpl)." WHERE `param`='smsadmintpl';";
8139 $dbo->setQuery($q);
8140 $dbo->execute();
8141 $q = "UPDATE `#__vikbooking_texts` SET `setting`=".$dbo->quote($psmscustomertpl)." WHERE `param`='smscustomertpl';";
8142 $dbo->setQuery($q);
8143 $dbo->execute();
8144 $q = "UPDATE `#__vikbooking_texts` SET `setting`=".$dbo->quote($psmsadmintplpend)." WHERE `param`='smsadmintplpend';";
8145 $dbo->setQuery($q);
8146 $dbo->execute();
8147 $q = "UPDATE `#__vikbooking_texts` SET `setting`=".$dbo->quote($psmscustomertplpend)." WHERE `param`='smscustomertplpend';";
8148 $dbo->setQuery($q);
8149 $dbo->execute();
8150 $q = "UPDATE `#__vikbooking_texts` SET `setting`=".$dbo->quote($psmsadmintplcanc)." WHERE `param`='smsadmintplcanc';";
8151 $dbo->setQuery($q);
8152 $dbo->execute();
8153 $q = "UPDATE `#__vikbooking_texts` SET `setting`=".$dbo->quote($psmscustomertplcanc)." WHERE `param`='smscustomertplcanc';";
8154 $dbo->setQuery($q);
8155 $dbo->execute();
8156
8157 /**
8158 * Backup settings
8159 *
8160 * @since 1.15.0 (J) - 1.5.0 (WP)
8161 */
8162 $backup_type = $app->input->getString('backuptype', 'full');
8163 $backup_folder = $app->input->getString('backupfolder', '');
8164
8165 $tmp = $app->get('tmp_path');
8166
8167 if (!$backup_folder)
8168 {
8169 // path not specified, use temporary folder
8170 $backup_folder = $tmp;
8171 }
8172
8173 $current = $config->get('backupfolder');
8174
8175 if (!$current)
8176 {
8177 // path was missing, use temporary folder
8178 $current = $tmp;
8179 }
8180
8181 // check whether the backup folder has been moved
8182 if ($current && $backup_folder && rtrim($current, DIRECTORY_SEPARATOR) !== rtrim($backup_folder, DIRECTORY_SEPARATOR))
8183 {
8184 $backupModel = new VBOModelBackup();
8185
8186 // backup folder moved, try to copy all the existing overrides
8187 if (!$backupModel->moveArchives($backup_folder))
8188 {
8189 // iterate all errors and display them
8190 foreach ($backupModel->getErrors() as $error)
8191 {
8192 $app->enqueueMessage($error, 'warning');
8193 }
8194 }
8195 }
8196
8197 // save configuration
8198 $config->set('backuptype', $backup_type);
8199 $config->set('backupfolder', $backup_folder);
8200
8201 /**
8202 * Check-in data collection type.
8203 *
8204 * @since 1.15.0 (J) - 1.5.0 (WP)
8205 */
8206 $config->set('checkindata', VikRequest::getString('checkindata', 'basic', 'request'));
8207
8208 /**
8209 * Front-end appearance.
8210 *
8211 * @since 1.15.0 (J) - 1.5.0 (WP) (patch)
8212 */
8213 $config->set('appearance_front', VikRequest::getInt('appearance_front', 0, 'request'));
8214
8215 /**
8216 * Split stays.
8217 *
8218 * @since 1.16.0 (J) - 1.6.0 (WP)
8219 */
8220 $glob_split_stay = VikRequest::getInt('split_stay', 0, 'request');
8221 $split_stay_ratio = VikRequest::getFloat('split_stay_ratio', 0, 'request');
8222 $split_stay_ratio = $split_stay_ratio > 100 ? 100 : $split_stay_ratio;
8223 $config->set('split_stay_ratio', ($glob_split_stay && $split_stay_ratio > 0 ? $split_stay_ratio : 0));
8224
8225 // redirect
8226 $app->enqueueMessage(JText::translate('VBSETTINGSAVED'));
8227 $app->redirect("index.php?option=com_vikbooking&task=config");
8228 }
8229
8230 /**
8231 * Unify the check-in and check-out times for all reservations.
8232 *
8233 * @since 1.10 - Patch August 29th 2018
8234 */
8235 public function unifycheckinout() {
8236 $dbo = JFactory::getDBO();
8237 $mainframe = JFactory::getApplication();
8238 $fh = VikRequest::getInt('fh', 12, 'request');
8239 $fm = VikRequest::getInt('fm', 0, 'request');
8240 $th = VikRequest::getInt('th', 10, 'request');
8241 $tm = VikRequest::getInt('tm', 0, 'request');
8242 $totmod = 0;
8243 $totbookmod = 0;
8244 $q = "SELECT * FROM `#__vikbooking_busy`;";
8245 $dbo->setQuery($q);
8246 $dbo->execute();
8247 $records = $dbo->loadAssocList();
8248 foreach ($records as $v) {
8249 $info_start = getdate($v['checkin']);
8250 $info_end = getdate($v['checkout']);
8251 $new_start = mktime($fh, $fm, 0, $info_start['mon'], $info_start['mday'], $info_start['year']);
8252 $new_end = mktime($th, $tm, 0, $info_end['mon'], $info_end['mday'], $info_end['year']);
8253 $q = "UPDATE `#__vikbooking_busy` SET `checkin`=".$new_start.",`checkout`=".$new_end.",`realback`=".$new_end." WHERE `id`=".$v['id']." LIMIT 1;";
8254 $dbo->setQuery($q);
8255 $dbo->execute();
8256 $totmod++;
8257 }
8258
8259 $q = "SELECT * FROM `#__vikbooking_orders`;";
8260 $dbo->setQuery($q);
8261 $dbo->execute();
8262 $records = $dbo->loadAssocList();
8263 foreach ($records as $v) {
8264 $info_start = getdate($v['checkin']);
8265 $info_end = getdate($v['checkout']);
8266 $new_start = mktime($fh, $fm, 0, $info_start['mon'], $info_start['mday'], $info_start['year']);
8267 $new_end = mktime($th, $tm, 0, $info_end['mon'], $info_end['mday'], $info_end['year']);
8268 $q = "UPDATE `#__vikbooking_orders` SET `checkin`=".$new_start.",`checkout`=".$new_end." WHERE `id`=".$v['id']." LIMIT 1;";
8269 $dbo->setQuery($q);
8270 $dbo->execute();
8271 $totbookmod++;
8272 }
8273 $mainframe->enqueueMessage('OK: '.$totbookmod);
8274 $mainframe->redirect("index.php?option=com_vikbooking&task=config");
8275 }
8276
8277 public function savetmplfile() {
8278 if (!JSession::checkToken()) {
8279 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
8280 }
8281 $fpath = VikRequest::getString('path', '', 'request', VIKREQUEST_ALLOWRAW);
8282 $pcont = VikRequest::getString('cont', '', 'request', VIKREQUEST_ALLOWRAW);
8283 $mainframe = JFactory::getApplication();
8284 $exists = file_exists($fpath) ? true : false;
8285 if (!$exists) {
8286 $fpath = urldecode($fpath);
8287 }
8288 $fpath = file_exists($fpath) ? $fpath : '';
8289 if (!empty($fpath)) {
8290 $fp = fopen($fpath, 'wb');
8291 $byt = (int)fwrite($fp, $pcont);
8292 fclose($fp);
8293 if ($byt > 0) {
8294 $mainframe->enqueueMessage(JText::translate('VBOUPDTMPLFILEOK'));
8295 /**
8296 * @wponly call the UpdateManager Class to temporarily store modifications made to template files
8297 */
8298 VikBookingUpdateManager::storeTemplateContent($fpath, $pcont);
8299 //
8300 } else {
8301 VikError::raiseWarning('', JText::translate('VBOUPDTMPLFILENOBYTES'));
8302 }
8303 } else {
8304 VikError::raiseWarning('', JText::translate('VBOUPDTMPLFILEERR'));
8305 }
8306 $mainframe->redirect("index.php?option=com_vikbooking&task=edittmplfile&path=".$fpath."&tmpl=component");
8307
8308 exit;
8309 }
8310
8311 public function edittmplfile() {
8312 //modal box, so we do not set menu or footer
8313
8314 VikRequest::setVar('view', VikRequest::getCmd('view', 'edittmplfile'));
8315
8316 parent::display();
8317 }
8318
8319 public function tmplfileprew() {
8320 //modal box, so we do not set menu or footer
8321
8322 VikRequest::setVar('view', VikRequest::getCmd('view', 'tmplfileprew'));
8323
8324 parent::display();
8325 }
8326
8327 public function invoices() {
8328 VikBookingHelper::printHeader("invoices");
8329
8330 VikRequest::setVar('view', VikRequest::getCmd('view', 'invoices'));
8331
8332 parent::display();
8333
8334 if (VikBooking::showFooter()) {
8335 VikBookingHelper::printFooter();
8336 }
8337 }
8338
8339 public function newmaninvoice() {
8340 VikBookingHelper::printHeader("invoices");
8341
8342 VikRequest::setVar('view', VikRequest::getCmd('view', 'managemaninvoice'));
8343
8344 parent::display();
8345
8346 if (VikBooking::showFooter()) {
8347 VikBookingHelper::printFooter();
8348 }
8349 }
8350
8351 public function editmaninvoice() {
8352 VikBookingHelper::printHeader("invoices");
8353
8354 VikRequest::setVar('view', VikRequest::getCmd('view', 'managemaninvoice'));
8355
8356 parent::display();
8357
8358 if (VikBooking::showFooter()) {
8359 VikBookingHelper::printFooter();
8360 }
8361 }
8362
8363 public function savemaninvoice() {
8364 if (!JSession::checkToken()) {
8365 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
8366 }
8367 $this->do_storemaninvoice('save');
8368 $mainframe = JFactory::getApplication();
8369 $mainframe->enqueueMessage(JText::sprintf('VBOTOTINVOICESGEND', 1, 0));
8370 $pgoto = VikRequest::getString('goto', '', 'request', VIKREQUEST_ALLOWRAW);
8371 if (!empty($pgoto)) {
8372 $mainframe->redirect(base64_decode($pgoto));
8373 exit;
8374 }
8375 $mainframe->redirect("index.php?option=com_vikbooking&task=invoices");
8376 }
8377
8378 public function updatemaninvoice() {
8379 if (!JSession::checkToken()) {
8380 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
8381 }
8382 $invid = VikRequest::getInt('whereup', 0, 'request');
8383 $this->do_storemaninvoice('update', $invid);
8384 $mainframe = JFactory::getApplication();
8385 $mainframe->enqueueMessage(JText::sprintf('VBOTOTINVOICESGEND', 1, 0));
8386 $pgoto = VikRequest::getString('goto', '', 'request', VIKREQUEST_ALLOWRAW);
8387 if (!empty($pgoto)) {
8388 $mainframe->redirect(base64_decode($pgoto));
8389 exit;
8390 }
8391 $mainframe->redirect("index.php?option=com_vikbooking&task=invoices");
8392 }
8393
8394 public function updatemaninvoicestay() {
8395 $invid = VikRequest::getInt('whereup', 0, 'request');
8396 $this->do_storemaninvoice('updatestay', $invid);
8397 $mainframe = JFactory::getApplication();
8398 $mainframe->enqueueMessage(JText::sprintf('VBOTOTINVOICESGEND', 1, 0));
8399 $pgoto = VikRequest::getString('goto', '', 'request', VIKREQUEST_ALLOWRAW);
8400 if (!empty($pgoto)) {
8401 $mainframe->redirect(base64_decode($pgoto));
8402 exit;
8403 }
8404 $mainframe->redirect("index.php?option=com_vikbooking&task=editmaninvoice&cid[]=".$invid);
8405 }
8406
8407 private function do_storemaninvoice($action, $invid = 0) {
8408 $dbo = JFactory::getDBO();
8409 $mainframe = JFactory::getApplication();
8410 $pinvoice_num = VikRequest::getInt('invoice_num', '', 'request');
8411 $pinvoice_num = $pinvoice_num <= 0 ? 1 : $pinvoice_num;
8412 $pinvoice_suff = VikRequest::getString('invoice_suff', '', 'request');
8413 $pcompany_info = VikRequest::getString('company_info', '', 'request', VIKREQUEST_ALLOWHTML);
8414 $pcompany_info = strpos($pcompany_info, '<') !== false ? $pcompany_info : nl2br($pcompany_info);
8415 $pinvoice_notes = VikRequest::getString('invoice_notes', '', 'request', VIKREQUEST_ALLOWHTML);
8416 $pinvoice_notes = strpos($pinvoice_notes, '<') !== false ? $pinvoice_notes : nl2br($pinvoice_notes);
8417 $pidcustomer = VikRequest::getInt('idcustomer', '', 'request');
8418 $error_uri = strpos($action, 'update') !== false && !empty($invid) ? 'index.php?option=com_vikbooking&task=editmaninvoice&cid[]='.$invid : 'index.php?option=com_vikbooking&task=newmaninvoice';
8419 if (empty($pidcustomer)) {
8420 VikError::raiseWarning('', JText::translate('VBNOCUSTOMERS'));
8421 $mainframe->redirect($error_uri);
8422 exit;
8423 }
8424 $services = VikRequest::getVar('service', array());
8425 $nets = VikRequest::getVar('net', array());
8426 $aliqs = VikRequest::getVar('aliq', array());
8427 $taxs = VikRequest::getVar('tax', array());
8428 $tots = VikRequest::getVar('tot', array());
8429 $ptotalnet = VikRequest::getFloat('totalnet', 0, 'request');
8430 $ptotaltax = VikRequest::getFloat('totaltax', 0, 'request');
8431 $ptotaltot = VikRequest::getFloat('totaltot', 0, 'request');
8432 if (!count($services) || count($services) != count($nets) || count($services) != count($taxs) || count($services) != count($tots)) {
8433 VikError::raiseWarning('', 'Missing data.');
8434 $mainframe->redirect($error_uri);
8435 exit;
8436 }
8437 $rawcont = array(
8438 'rows' => array(),
8439 'totalnet' => $ptotalnet,
8440 'totaltax' => $ptotaltax,
8441 'totaltot' => $ptotaltot,
8442 'notes' => $pinvoice_notes,
8443 );
8444 foreach ($services as $k => $service) {
8445 if (empty($service)) {
8446 continue;
8447 }
8448 array_push($rawcont['rows'], array(
8449 'service' => $service,
8450 'net' => (float)$nets[$k],
8451 'aliq' => (isset($aliqs[$k]) ? (float)$aliqs[$k] : 0),
8452 'tax' => (float)$taxs[$k],
8453 'tot' => (float)$tots[$k],
8454 ));
8455 }
8456 // store/update manual invoice
8457 $nowts = time();
8458 $retval = 0;
8459 if (strpos($action, 'save') !== false) {
8460 $pdffname = $nowts . '_' . rand() . '.pdf';
8461 $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)).");";
8462 $dbo->setQuery($q);
8463 $dbo->execute();
8464 $retval = $dbo->insertid();
8465 } else {
8466 // fetch old record
8467 $q = "SELECT * FROM `#__vikbooking_invoices` WHERE `id`=".(int)$invid.";";
8468 $dbo->setQuery($q);
8469 $dbo->execute();
8470 if (!$dbo->getNumRows()) {
8471 VikError::raiseWarning('', JText::translate('VBNOINVOICESFOUND'));
8472 $mainframe->redirect($error_uri);
8473 exit;
8474 }
8475 $previnvoice = $dbo->loadAssoc();
8476 //
8477 $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'].";";
8478 $dbo->setQuery($q);
8479 $dbo->execute();
8480 $retval = $previnvoice['id'];
8481 }
8482 // update config values for the invoice
8483 $q = "UPDATE `#__vikbooking_config` SET `setting`=".$dbo->quote($pcompany_info)." WHERE `param`='invcompanyinfo';";
8484 $dbo->setQuery($q);
8485 $dbo->execute();
8486 // generate the custom invoice
8487 $result = VikBooking::generateCustomInvoice($retval);
8488 //
8489 $nextinv = VikBooking::getNextInvoiceNumber();
8490 $updatenum = ($pinvoice_num >= $nextinv);
8491 if ($updatenum) {
8492 /**
8493 * IMPORTANT: update the next invoice number after calling the e-Invocing drivers
8494 * to avoid conflicts with the drivers for the e-invoices generation.
8495 */
8496 $q = "UPDATE `#__vikbooking_config` SET `setting`=".$dbo->quote(($pinvoice_num - 1))." WHERE `param`='invoiceinum';";
8497 $dbo->setQuery($q);
8498 $dbo->execute();
8499 }
8500
8501 return $retval;
8502 }
8503
8504 public function downloadinvoices() {
8505 $ids = VikRequest::getVar('cid', array(0));
8506 if (@count($ids) > 0) {
8507 $dbo = JFactory::getDBO();
8508 $q = "SELECT * FROM `#__vikbooking_invoices` WHERE `id` IN (".implode(', ', $ids).");";
8509 $dbo->setQuery($q);
8510 $dbo->execute();
8511 if ($dbo->getNumRows() > 0) {
8512 $invoices = $dbo->loadAssocList();
8513 if (!(count($invoices) > 1)) {
8514 //Single Invoice Download
8515 if (file_exists(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'invoices'.DIRECTORY_SEPARATOR.'generated'.DIRECTORY_SEPARATOR.$invoices[0]['file_name'])) {
8516 header("Content-type:application/pdf");
8517 header("Content-Disposition:attachment;filename=".$invoices[0]['file_name']);
8518 readfile(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'invoices'.DIRECTORY_SEPARATOR.'generated'.DIRECTORY_SEPARATOR.$invoices[0]['file_name']);
8519 exit;
8520 }
8521 } else {
8522 //Multiple Invoices Download
8523 $to_zip = array();
8524 foreach ($invoices as $k => $invoice) {
8525 $to_zip[$k]['name'] = $invoice['file_name'];
8526 $to_zip[$k]['path'] = VBO_SITE_PATH.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'invoices'.DIRECTORY_SEPARATOR.'generated'.DIRECTORY_SEPARATOR.$invoice['file_name'];
8527 }
8528 if (class_exists('ZipArchive')) {
8529 $zip_path = VBO_SITE_PATH.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'invoices'.DIRECTORY_SEPARATOR.'generated'.DIRECTORY_SEPARATOR.date('Y-m-d').'-invoices.zip';
8530 $zip = new ZipArchive;
8531 $zip->open($zip_path, ZipArchive::CREATE);
8532 foreach ($to_zip as $k => $zipv) {
8533 $zip->addFile($zipv['path'], $zipv['name']);
8534 }
8535 $zip->close();
8536 header("Content-type:application/zip");
8537 header("Content-Disposition:attachment;filename=".date('Y-m-d').'-invoices.zip');
8538 header("Content-Length:".filesize($zip_path));
8539 readfile($zip_path);
8540 unlink($zip_path);
8541 exit;
8542 } else {
8543 //Class ZipArchive does not exist
8544 VikError::raiseWarning('', 'Class ZipArchive does not exist on your server. Download the files one by one.');
8545 }
8546 }
8547 }
8548 }
8549 $mainframe = JFactory::getApplication();
8550 $mainframe->redirect("index.php?option=com_vikbooking&task=invoices");
8551 }
8552
8553 public function resendinvoices() {
8554 $ids = VikRequest::getVar('cid', array(0));
8555 $mainframe = JFactory::getApplication();
8556 if (!(count($ids) > 0)) {
8557 $mainframe->redirect("index.php?option=com_vikbooking&task=invoices");
8558 exit;
8559 }
8560 $dbo = JFactory::getDBO();
8561 $invoices = array();
8562 $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` ".
8563 "FROM `#__vikbooking_invoices` AS `i` " .
8564 "LEFT JOIN `#__vikbooking_orders` `o` ON `o`.`id`=`i`.`idorder` " .
8565 "LEFT JOIN `#__vikbooking_customers` `c` ON `c`.`id`=`i`.`idcustomer` " .
8566 "LEFT JOIN `#__vikbooking_countries` `nat` ON `nat`.`country_3_code`=`c`.`country` " .
8567 "WHERE `i`.`id` IN (".implode(', ', $ids).") AND (`i`.`idorder` < 0 OR (`o`.`status`='confirmed' AND `o`.`total` > 0)) ORDER BY `o`.`id` ASC;";
8568 $dbo->setQuery($q);
8569 $dbo->execute();
8570 if ($dbo->getNumRows() > 0) {
8571 $invoices = $dbo->loadAssocList();
8572 }
8573 if (!(count($invoices) > 0)) {
8574 VikError::raiseWarning('', JText::translate('VBOGENINVERRNOBOOKINGS'));
8575 $mainframe->redirect("index.php?option=com_vikbooking&task=invoices");
8576 exit;
8577 }
8578 $tot_generated = 0;
8579 $tot_sent = 0;
8580 foreach ($invoices as $bkey => $invoice) {
8581 $invoice['custmail'] = empty($invoice['custmail']) && !empty($invoice['customer_email']) ? $invoice['customer_email'] : $invoice['custmail'];
8582 $invoices[$bkey] = $invoice;
8583 $send_res = VikBooking::sendBookingInvoice($invoice['id'], $invoice);
8584 if ($send_res !== false) {
8585 $tot_sent++;
8586 }
8587 }
8588 $mainframe->enqueueMessage(JText::sprintf('VBOTOTINVOICESGEND', $tot_generated, $tot_sent));
8589 $mainframe->redirect("index.php?option=com_vikbooking&task=invoices");
8590 }
8591
8592 public function removeinvoices() {
8593 $ids = VikRequest::getVar('cid', array());
8594 $tot_removed = 0;
8595 $dbo = JFactory::getDbo();
8596
8597 foreach ($ids as $d) {
8598 $q = "SELECT * FROM `#__vikbooking_invoices` WHERE `id`=".(int)$d.";";
8599 $dbo->setQuery($q);
8600 $dbo->execute();
8601 if ($dbo->getNumRows() == 1) {
8602 $cur_invoice = $dbo->loadAssoc();
8603 if (file_exists(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'invoices'.DIRECTORY_SEPARATOR.'generated'.DIRECTORY_SEPARATOR.$cur_invoice['file_name'])) {
8604 unlink(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'invoices'.DIRECTORY_SEPARATOR.'generated'.DIRECTORY_SEPARATOR.$cur_invoice['file_name']);
8605 }
8606 $q = "DELETE FROM `#__vikbooking_invoices` WHERE `id`=".(int)$d.";";
8607 $dbo->setQuery($q);
8608 $dbo->execute();
8609 $tot_removed++;
8610 }
8611 }
8612
8613 $mainframe = JFactory::getApplication();
8614 $mainframe->enqueueMessage(JText::sprintf('VBOTOTINVOICESRMVD', $tot_removed));
8615 $mainframe->redirect("index.php?option=com_vikbooking&task=invoices");
8616 }
8617
8618 public function geninvoices() {
8619 $ids = VikRequest::getVar('cid', array(0));
8620 $mainframe = JFactory::getApplication();
8621 if (!count($ids)) {
8622 $mainframe->redirect("index.php?option=com_vikbooking&task=orders");
8623 exit;
8624 }
8625 $dbo = JFactory::getDBO();
8626 $pinvoice_num = VikRequest::getInt('invoice_num', '', 'request');
8627 $pinvoice_num = $pinvoice_num <= 0 ? 1 : $pinvoice_num;
8628 $pinvoice_suff = VikRequest::getString('invoice_suff', '', 'request');
8629 $pinvoice_date = VikRequest::getString('invoice_date', '', 'request');
8630 $pcompany_info = VikRequest::getString('company_info', '', 'request', VIKREQUEST_ALLOWHTML);
8631 $pcompany_info = strpos($pcompany_info, '<') !== false ? $pcompany_info : nl2br($pcompany_info);
8632 $pinvoice_send = VikRequest::getInt('invoice_send', '', 'request');
8633 $pinvoice_send = $pinvoice_send > 0 ? true : false;
8634 $increment_inv = true;
8635 $pconfirmgen = VikRequest::getInt('confirmgen', '', 'request');
8636 //if editing an invoice (re-creating an existing invoice for a booking), do not increment the invoice number
8637 if (count($ids) == 1) {
8638 $q = "SELECT `number` FROM `#__vikbooking_invoices` WHERE `idorder`=".(int)$ids[0].";";
8639 $dbo->setQuery($q);
8640 $dbo->execute();
8641 if ($dbo->getNumRows() == 1) {
8642 $increment_inv = false;
8643 }
8644 }
8645 //
8646 $bookings = array();
8647 $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` 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` IN (".implode(', ', $ids).") AND `o`.`status`='confirmed' AND `o`.`total` > 0 ORDER BY `o`.`id` ASC;";
8648 $dbo->setQuery($q);
8649 $dbo->execute();
8650 if ($dbo->getNumRows() > 0) {
8651 $bookings = $dbo->loadAssocList();
8652 }
8653 if (!count($bookings)) {
8654 VikError::raiseWarning('', JText::translate('VBOGENINVERRNOBOOKINGS'));
8655 $mainframe->redirect("index.php?option=com_vikbooking&task=orders");
8656 exit;
8657 }
8658 $tot_generated = 0;
8659 $tot_sent = 0;
8660 foreach ($bookings as $bkey => $booking) {
8661 $gen_res = VikBooking::generateBookingInvoice($booking, $pinvoice_num, $pinvoice_suff, $pinvoice_date, $pcompany_info);
8662 if ($gen_res !== false && $gen_res > 0) {
8663 $tot_generated++;
8664 $pinvoice_num++;
8665 if ($pinvoice_send) {
8666 $send_res = VikBooking::sendBookingInvoice($gen_res, $booking);
8667 if ($send_res !== false) {
8668 $tot_sent++;
8669 }
8670 }
8671 } else {
8672 VikError::raiseWarning('', JText::sprintf('VBOGENINVERRBOOKING', $booking['id']));
8673 }
8674 }
8675 if ($tot_generated > 0 && $increment_inv === true) {
8676 /**
8677 * IMPORTANT: update the next invoice number after calling generateBookingInvoice()
8678 * to avoid conflicts with the drivers for the e-invoices generation.
8679 */
8680 $q = "UPDATE `#__vikbooking_config` SET `setting`=".$dbo->quote(($pinvoice_num - 1))." WHERE `param`='invoiceinum';";
8681 $dbo->setQuery($q);
8682 $dbo->execute();
8683 }
8684 $q = "UPDATE `#__vikbooking_config` SET `setting`=".$dbo->quote($pinvoice_suff)." WHERE `param`='invoicesuffix';";
8685 $dbo->setQuery($q);
8686 $dbo->execute();
8687 $q = "UPDATE `#__vikbooking_config` SET `setting`=".$dbo->quote($pcompany_info)." WHERE `param`='invcompanyinfo';";
8688 $dbo->setQuery($q);
8689 $dbo->execute();
8690 $mainframe->enqueueMessage(JText::sprintf('VBOTOTINVOICESGEND', $tot_generated, $tot_sent));
8691 if ($pconfirmgen > 0) {
8692 $mainframe->redirect("index.php?option=com_vikbooking&task=invoices&show=".$pconfirmgen);
8693 } elseif (count($bookings) === 1) {
8694 // go to the back-end booking details page
8695 $mainframe->redirect("index.php?option=com_vikbooking&task=editorder&cid[]=" . $bookings[0]['id']);
8696 } else {
8697 $mainframe->redirect("index.php?option=com_vikbooking&task=orders");
8698 }
8699 }
8700
8701 public function optionals() {
8702 VikBookingHelper::printHeader("6");
8703
8704 VikRequest::setVar('view', VikRequest::getCmd('view', 'optionals'));
8705
8706 parent::display();
8707
8708 if (VikBooking::showFooter()) {
8709 VikBookingHelper::printFooter();
8710 }
8711 }
8712
8713 public function newoptionals() {
8714 VikBookingHelper::printHeader("6");
8715
8716 VikRequest::setVar('view', VikRequest::getCmd('view', 'manageoptional'));
8717
8718 parent::display();
8719
8720 if (VikBooking::showFooter()) {
8721 VikBookingHelper::printFooter();
8722 }
8723 }
8724
8725 public function editoptional() {
8726 VikBookingHelper::printHeader("6");
8727
8728 VikRequest::setVar('view', VikRequest::getCmd('view', 'manageoptional'));
8729
8730 parent::display();
8731
8732 if (VikBooking::showFooter()) {
8733 VikBookingHelper::printFooter();
8734 }
8735 }
8736
8737 public function updateoptional() {
8738 if (!JSession::checkToken()) {
8739 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
8740 }
8741 $this->do_updateoptional();
8742 }
8743
8744 public function updateoptionalstay() {
8745 if (!JSession::checkToken()) {
8746 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
8747 }
8748 $this->do_updateoptional(true);
8749 }
8750
8751 private function do_updateoptional($stay = false) {
8752 $dbo = JFactory::getDbo();
8753 $app = JFactory::getApplication();
8754 $poptname = VikRequest::getString('optname', '', 'request');
8755 $poptdescr = VikRequest::getString('optdescr', '', 'request', VIKREQUEST_ALLOWHTML);
8756 $poptcost = VikRequest::getFloat('optcost', '', 'request');
8757 $poptperday = VikRequest::getString('optperday', '', 'request');
8758 $poptperperson = VikRequest::getString('optperperson', '', 'request');
8759 $pmaxprice = VikRequest::getFloat('maxprice', '', 'request');
8760 $popthmany = VikRequest::getString('opthmany', '', 'request');
8761 $poptaliq = VikRequest::getInt('optaliq', '', 'request');
8762 $pwhereup = VikRequest::getString('whereup', '', 'request');
8763 $pautoresize = VikRequest::getString('autoresize', '', 'request');
8764 $presizeto = VikRequest::getString('resizeto', '', 'request');
8765 $pifchildren = VikRequest::getString('ifchildren', '', 'request');
8766 $pifchildren = $pifchildren == "1" ? 1 : 0;
8767 $pmaxquant = VikRequest::getString('maxquant', '', 'request');
8768 $pmaxquant = empty($pmaxquant) ? 0 : intval($pmaxquant);
8769 $pforcesel = VikRequest::getString('forcesel', '', 'request');
8770 $pforceval = VikRequest::getString('forceval', '', 'request');
8771 $pforcevalperday = VikRequest::getString('forcevalperday', '', 'request');
8772 $pforcevalperchild = VikRequest::getString('forcevalperchild', '', 'request');
8773 $pforcesummary = VikRequest::getString('forcesummary', '', 'request');
8774 $pforcesel = $pforcesel == "1" ? 1 : 0;
8775 $pis_citytax = VikRequest::getString('is_citytax', '', 'request');
8776 $pis_fee = VikRequest::getString('is_fee', '', 'request');
8777 $pis_citytax = $pis_citytax == "1" && $pis_fee != "1" ? 1 : 0;
8778 $pis_fee = $pis_fee == "1" && $pis_citytax == 0 ? 1 : 0;
8779 $pagefrom = VikRequest::getVar('agefrom', array());
8780 $pageto = VikRequest::getVar('ageto', array());
8781 $pagecost = VikRequest::getVar('agecost', array());
8782 $pagectype = VikRequest::getVar('agectype', array());
8783 $palwaysav = VikRequest::getInt('alwaysav', 0, 'request');
8784 $pavfrom = VikRequest::getString('avfrom', '', 'request');
8785 $pavto = VikRequest::getString('avto', '', 'request');
8786 $ppcentroom = VikRequest::getInt('pcentroom', 0, 'request');
8787 $pidrooms = VikRequest::getVar('idrooms', array());
8788 $optavstr = empty($palwaysav) && !empty($pavfrom) && !empty($pavto) ? VikBooking::getDateTimestamp($pavfrom, 0, 0, 0).';'.VikBooking::getDateTimestamp($pavto, 23, 59, 59) : '';
8789 if ($pforcesel == 1) {
8790 $strforceval = intval($pforceval)."-".($pforcevalperday == "1" ? "1" : "0")."-".($pforcevalperchild == "1" ? "1" : "0")."-".($pforcesummary == "1" ? "1" : "0");
8791 } else {
8792 $strforceval = "";
8793 }
8794 $minguestsnum = VikRequest::getInt('minguestsnum', 0, 'request');
8795 $mingueststype = VikRequest::getString('mingueststype', 'guests', 'request');
8796 $minguestsnum = $minguestsnum < 0 ? 0 : $minguestsnum;
8797 $mingueststype = !empty($mingueststype) && !in_array($mingueststype, array('adults', 'guests')) ? 'guests' : $mingueststype;
8798 $maxguestsnum = VikRequest::getInt('maxguestsnum', 0, 'request');
8799 $maxgueststype = VikRequest::getString('maxgueststype', 'guests', 'request');
8800 $maxguestsnum = $maxguestsnum < 0 ? 0 : $maxguestsnum;
8801 $maxgueststype = !empty($maxgueststype) && !in_array($maxgueststype, array('adults', 'guests')) ? 'guests' : $maxgueststype;
8802 $minguests = VikRequest::getInt('minguests', 0, 'request');
8803 $minguests_conflict = false;
8804 if ($minguests > 0 && $minguestsnum > 0 && $maxguestsnum > 0) {
8805 if ($minguestsnum >= $maxguestsnum) {
8806 $minguests_conflict = JText::translate('VBOMINMAXGUESTSOPTCONFL1');
8807 } elseif (($maxguestsnum - $minguestsnum) < 2) {
8808 $minguests_conflict = JText::translate('VBOMINMAXGUESTSOPTCONFL2');
8809 }
8810 }
8811 if (!$minguests || $minguests_conflict !== false) {
8812 $minguestsnum = 0;
8813 $maxguestsnum = 0;
8814 if ($minguests_conflict !== false) {
8815 // raise warning, but do not stop the process
8816 VikError::raiseWarning('', $minguests_conflict);
8817 }
8818 }
8819 $damagedep = VikRequest::getInt('damagedep', 0, 'request');
8820 $pet_fee = VikRequest::getInt('pet_fee', 0, 'request');
8821 $oparams = array(
8822 'minguestsnum' => $minguestsnum,
8823 'mingueststype' => $mingueststype,
8824 'maxguestsnum' => $maxguestsnum,
8825 'maxgueststype' => $maxgueststype,
8826 'damagedep' => $damagedep,
8827 'pet_fee' => $pet_fee,
8828 );
8829 /**
8830 * We fetch the previous params to merge them with the new ones
8831 * in case some properties have been set somewhere else.
8832 * For example, the damage deposit transmission to Booking.com.
8833 */
8834 $cur_oparams = array();
8835 $q = "SELECT `oparams` FROM `#__vikbooking_optionals` WHERE `id`=" . (int)$pwhereup . ";";
8836 $dbo->setQuery($q);
8837 $dbo->execute();
8838 if ($dbo->getNumRows()) {
8839 $cur_oparams = $dbo->loadResult();
8840 $cur_oparams = !empty($cur_oparams) ? json_decode($cur_oparams, true) : array();
8841 $cur_oparams = !is_array($cur_oparams) ? array() : $cur_oparams;
8842 // merge previous params with the new ones to get the new values
8843 $oparams = array_merge($cur_oparams, $oparams);
8844 }
8845 //
8846 if (!empty($poptname)) {
8847 if (intval($_FILES['optimg']['error']) == 0 && VikBooking::caniWrite(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR) && trim($_FILES['optimg']['name'])!="") {
8848 jimport('joomla.filesystem.file');
8849 $updpath = VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR;
8850 if (@is_uploaded_file($_FILES['optimg']['tmp_name'])) {
8851 $safename=JFile::makeSafe(str_replace(" ", "_", strtolower($_FILES['optimg']['name'])));
8852 if (file_exists($updpath.$safename)) {
8853 $j=1;
8854 while (file_exists($updpath.$j.$safename)) {
8855 $j++;
8856 }
8857 $pwhere=$updpath.$j.$safename;
8858 } else {
8859 $j="";
8860 $pwhere=$updpath.$safename;
8861 }
8862 if (!getimagesize($_FILES['optimg']['tmp_name']) || !preg_match("/\.(a?png|jpe?g|bmp|gif|ico|webp)\z/i", $safename)) {
8863 @unlink($pwhere);
8864 $picon="";
8865 } else {
8866 VikBooking::uploadFile($_FILES['optimg']['tmp_name'], $pwhere);
8867 @chmod($pwhere, 0644);
8868 $picon=$j.$safename;
8869 if ($pautoresize=="1" && !empty($presizeto)) {
8870 $eforj = new vikResizer();
8871 $origmod = $eforj->proportionalImage($pwhere, $updpath.'r_'.$j.$safename, $presizeto, $presizeto);
8872 if ($origmod) {
8873 @unlink($pwhere);
8874 $picon='r_'.$j.$safename;
8875 }
8876 }
8877 }
8878 } else {
8879 $picon="";
8880 }
8881 } else {
8882 $picon="";
8883 }
8884 ($poptperday=="each" ? $poptperday="1" : $poptperday="0");
8885 $poptperperson=($poptperperson=="each" ? "1" : "0");
8886 ($popthmany=="yes" ? $popthmany="1" : $popthmany="0");
8887 $ageintervalstr = '';
8888 if ($pifchildren == 1 && count($pagefrom) > 0 && count($pagecost) > 0 && count($pagefrom) == count($pagecost)) {
8889 foreach ($pagefrom as $kage => $vage) {
8890 $afrom = intval($vage);
8891 $ato = intval($pageto[$kage]);
8892 $acost = floatval($pagecost[$kage]);
8893 if (strlen($vage) > 0 && strlen($pagecost[$kage]) > 0) {
8894 if ($ato < $afrom) $ato = $afrom;
8895 $ageintervalstr .= $afrom.'_'.$ato.'_'.$acost.(array_key_exists($kage, $pagectype) && strpos($pagectype[$kage], '%') !== false ? '_%'.(strpos($pagectype[$kage], '%b') !== false ? 'b' : '') : '').';;';
8896 }
8897 }
8898 $ageintervalstr = rtrim($ageintervalstr, ';;');
8899 if (!empty($ageintervalstr)) {
8900 $pforcesel = 1;
8901 }
8902 }
8903 $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).";";
8904 $dbo->setQuery($q);
8905 $dbo->execute();
8906 $app->enqueueMessage(JText::translate('VBOSUCCUPDOPTION'));
8907
8908 // assign/unset option-rooms relations
8909 $rooms_with_opt = array();
8910 if (count($pidrooms)) {
8911 // assign this new option to the requested rooms
8912 foreach ($pidrooms as $idroom) {
8913 if (empty($idroom)) {
8914 continue;
8915 }
8916 $q = "SELECT `id`, `idopt` FROM `#__vikbooking_rooms` WHERE `id`=" . (int)$idroom . ";";
8917 $dbo->setQuery($q);
8918 $dbo->execute();
8919 if (!$dbo->getNumRows()) {
8920 continue;
8921 }
8922 $room_data = $dbo->loadAssoc();
8923 array_push($rooms_with_opt, $room_data['id']);
8924 $current_opts = empty($room_data['idopt']) ? array() : explode(';', rtrim($room_data['idopt'], ';'));
8925 if (in_array((string)$pwhereup, $current_opts)) {
8926 continue;
8927 }
8928 if (count($current_opts) === 1 && (string)$current_opts[0] == '0') {
8929 // make sure we do not concatenate a real ID to 0
8930 $current_opts = array();
8931 }
8932 array_push($current_opts, $pwhereup);
8933 $new_opts = implode(';', $current_opts) . ';';
8934 $q = "UPDATE `#__vikbooking_rooms` SET `idopt`=" . $dbo->quote($new_opts) . " WHERE `id`={$room_data['id']};";
8935 $dbo->setQuery($q);
8936 $dbo->execute();
8937 }
8938 }
8939 if (!count($rooms_with_opt)) {
8940 // get all rooms to unset this option (if previously set)
8941 array_push($rooms_with_opt, '0');
8942 }
8943 // unset the option from the other rooms that may have it
8944 $q = "SELECT `id`, `idopt` FROM `#__vikbooking_rooms` WHERE `id` NOT IN (" . implode(', ', $rooms_with_opt) . ");";
8945 $dbo->setQuery($q);
8946 $dbo->execute();
8947 if ($dbo->getNumRows()) {
8948 $unset_rooms_opt = $dbo->loadAssocList();
8949 foreach ($unset_rooms_opt as $room_data) {
8950 $current_opts = empty($room_data['idopt']) ? array() : explode(';', rtrim($room_data['idopt'], ';'));
8951 if (!in_array((string)$pwhereup, $current_opts)) {
8952 // this room is not using this option
8953 continue;
8954 }
8955 $optkey = array_search((string)$pwhereup, $current_opts);
8956 if ($optkey === false) {
8957 // key not found
8958 continue;
8959 }
8960 // unset this option ID from the string
8961 unset($current_opts[$optkey]);
8962 if (!count($current_opts)) {
8963 // a room with no options assigned will be listed as "0;"
8964 $current_opts = array(0);
8965 }
8966 $new_opts = implode(';', $current_opts) . ';';
8967 $q = "UPDATE `#__vikbooking_rooms` SET `idopt`=" . $dbo->quote($new_opts) . " WHERE `id`={$room_data['id']};";
8968 $dbo->setQuery($q);
8969 $dbo->execute();
8970 }
8971 }
8972 //
8973
8974 }
8975 $app->redirect("index.php?option=com_vikbooking&task=" . ($stay ? 'editoptional&cid[]=' . $pwhereup : 'optionals'));
8976 }
8977
8978 public function createoptionals() {
8979 if (!JSession::checkToken()) {
8980 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
8981 }
8982 $this->do_createoptionals();
8983 }
8984
8985 public function createoptionalsstay() {
8986 if (!JSession::checkToken()) {
8987 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
8988 }
8989 $this->do_createoptionals(true);
8990 }
8991
8992 private function do_createoptionals($stay = false) {
8993 $dbo = JFactory::getDbo();
8994 $poptname = VikRequest::getString('optname', '', 'request');
8995 $poptdescr = VikRequest::getString('optdescr', '', 'request', VIKREQUEST_ALLOWHTML);
8996 $poptcost = VikRequest::getFloat('optcost', '', 'request');
8997 $poptperday = VikRequest::getString('optperday', '', 'request');
8998 $poptperperson = VikRequest::getString('optperperson', '', 'request');
8999 $pmaxprice = VikRequest::getFloat('maxprice', '', 'request');
9000 $popthmany = VikRequest::getString('opthmany', '', 'request');
9001 $poptaliq = VikRequest::getInt('optaliq', '', 'request');
9002 $pautoresize = VikRequest::getString('autoresize', '', 'request');
9003 $presizeto = VikRequest::getString('resizeto', '', 'request');
9004 $pifchildren = VikRequest::getString('ifchildren', '', 'request');
9005 $pifchildren = $pifchildren == "1" ? 1 : 0;
9006 $pmaxquant = VikRequest::getString('maxquant', '', 'request');
9007 $pmaxquant = empty($pmaxquant) ? 0 : intval($pmaxquant);
9008 $pforcesel = VikRequest::getString('forcesel', '', 'request');
9009 $pforceval = VikRequest::getString('forceval', '', 'request');
9010 $pforcevalperday = VikRequest::getString('forcevalperday', '', 'request');
9011 $pforcevalperchild = VikRequest::getString('forcevalperchild', '', 'request');
9012 $pforcesummary = VikRequest::getString('forcesummary', '', 'request');
9013 $pforcesel = $pforcesel == "1" ? 1 : 0;
9014 $pis_citytax = VikRequest::getString('is_citytax', '', 'request');
9015 $pis_fee = VikRequest::getString('is_fee', '', 'request');
9016 $pis_citytax = $pis_citytax == "1" && $pis_fee != "1" ? 1 : 0;
9017 $pis_fee = $pis_fee == "1" && $pis_citytax == 0 ? 1 : 0;
9018 $pagefrom = VikRequest::getVar('agefrom', array());
9019 $pageto = VikRequest::getVar('ageto', array());
9020 $pagecost = VikRequest::getVar('agecost', array());
9021 $pagectype = VikRequest::getVar('agectype', array());
9022 $palwaysav = VikRequest::getInt('alwaysav', 0, 'request');
9023 $pavfrom = VikRequest::getString('avfrom', '', 'request');
9024 $pavto = VikRequest::getString('avto', '', 'request');
9025 $ppcentroom = VikRequest::getInt('pcentroom', 0, 'request');
9026 $pidrooms = VikRequest::getVar('idrooms', array());
9027 $optavstr = empty($palwaysav) && !empty($pavfrom) && !empty($pavto) ? VikBooking::getDateTimestamp($pavfrom, 0, 0, 0).';'.VikBooking::getDateTimestamp($pavto, 23, 59, 59) : '';
9028 if ($pforcesel == 1) {
9029 $strforceval = intval($pforceval)."-".($pforcevalperday == "1" ? "1" : "0")."-".($pforcevalperchild == "1" ? "1" : "0")."-".($pforcesummary == "1" ? "1" : "0");
9030 } else {
9031 $strforceval = "";
9032 }
9033 $minguestsnum = VikRequest::getInt('minguestsnum', 0, 'request');
9034 $mingueststype = VikRequest::getString('mingueststype', 'guests', 'request');
9035 $minguestsnum = $minguestsnum < 0 ? 0 : $minguestsnum;
9036 $mingueststype = !empty($mingueststype) && !in_array($mingueststype, array('adults', 'guests')) ? 'guests' : $mingueststype;
9037 $maxguestsnum = VikRequest::getInt('maxguestsnum', 0, 'request');
9038 $maxgueststype = VikRequest::getString('maxgueststype', 'guests', 'request');
9039 $maxguestsnum = $maxguestsnum < 0 ? 0 : $maxguestsnum;
9040 $maxgueststype = !empty($maxgueststype) && !in_array($maxgueststype, array('adults', 'guests')) ? 'guests' : $maxgueststype;
9041 $minguests = VikRequest::getInt('minguests', 0, 'request');
9042 $minguests_conflict = false;
9043 if ($minguests > 0 && $minguestsnum > 0 && $maxguestsnum > 0) {
9044 if ($minguestsnum >= $maxguestsnum) {
9045 $minguests_conflict = JText::translate('VBOMINMAXGUESTSOPTCONFL1');
9046 } elseif (($maxguestsnum - $minguestsnum) < 2) {
9047 $minguests_conflict = JText::translate('VBOMINMAXGUESTSOPTCONFL2');
9048 }
9049 }
9050 if (!$minguests || $minguests_conflict !== false) {
9051 $minguestsnum = 0;
9052 $maxguestsnum = 0;
9053 if ($minguests_conflict !== false) {
9054 // raise warning, but do not stop the process
9055 VikError::raiseWarning('', $minguests_conflict);
9056 }
9057 }
9058 $damagedep = VikRequest::getInt('damagedep', 0, 'request');
9059 $pet_fee = VikRequest::getInt('pet_fee', 0, 'request');
9060 $oparams = array(
9061 'minguestsnum' => $minguestsnum,
9062 'mingueststype' => $mingueststype,
9063 'maxguestsnum' => $maxguestsnum,
9064 'maxgueststype' => $maxgueststype,
9065 'damagedep' => $damagedep,
9066 'pet_fee' => $pet_fee,
9067 );
9068 if (!empty($poptname)) {
9069 if (intval($_FILES['optimg']['error']) == 0 && VikBooking::caniWrite(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR) && trim($_FILES['optimg']['name'])!="") {
9070 jimport('joomla.filesystem.file');
9071 $updpath = VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR;
9072 if (@is_uploaded_file($_FILES['optimg']['tmp_name'])) {
9073 $safename=JFile::makeSafe(str_replace(" ", "_", strtolower($_FILES['optimg']['name'])));
9074 if (file_exists($updpath.$safename)) {
9075 $j = 1;
9076 while (file_exists($updpath.$j.$safename)) {
9077 $j++;
9078 }
9079 $pwhere = $updpath.$j.$safename;
9080 } else {
9081 $j = "";
9082 $pwhere = $updpath.$safename;
9083 }
9084 if (!getimagesize($_FILES['optimg']['tmp_name']) || !preg_match("/\.(a?png|jpe?g|bmp|gif|ico|webp)\z/i", $safename)) {
9085 @unlink($pwhere);
9086 $picon = "";
9087 } else {
9088 VikBooking::uploadFile($_FILES['optimg']['tmp_name'], $pwhere);
9089 @chmod($pwhere, 0644);
9090 $picon = $j.$safename;
9091 if ($pautoresize == "1" && !empty($presizeto)) {
9092 $eforj = new vikResizer();
9093 $origmod = $eforj->proportionalImage($pwhere, $updpath.'r_'.$j.$safename, $presizeto, $presizeto);
9094 if ($origmod) {
9095 @unlink($pwhere);
9096 $picon = 'r_'.$j.$safename;
9097 }
9098 }
9099 }
9100 } else {
9101 $picon = "";
9102 }
9103 } else {
9104 $picon = "";
9105 }
9106 $poptperday = ($poptperday == "each" ? "1" : "0");
9107 $poptperperson = ($poptperperson == "each" ? "1" : "0");
9108 ($popthmany == "yes" ? $popthmany = "1" : $popthmany = "0");
9109 $ageintervalstr = '';
9110 if ($pifchildren == 1 && count($pagefrom) > 0 && count($pagecost) > 0 && count($pagefrom) == count($pagecost)) {
9111 foreach ($pagefrom as $kage => $vage) {
9112 $afrom = intval($vage);
9113 $ato = intval($pageto[$kage]);
9114 $acost = floatval($pagecost[$kage]);
9115 if (strlen($vage) > 0 && strlen($pagecost[$kage]) > 0) {
9116 if ($ato < $afrom) $ato = $afrom;
9117 $ageintervalstr .= $afrom.'_'.$ato.'_'.$acost.(array_key_exists($kage, $pagectype) && strpos($pagectype[$kage], '%') !== false ? '_%'.(strpos($pagectype[$kage], '%b') !== false ? 'b' : '') : '').';;';
9118 }
9119 }
9120 $ageintervalstr = rtrim($ageintervalstr, ';;');
9121 if (!empty($ageintervalstr)) {
9122 $pforcesel = 1;
9123 }
9124 }
9125 $q = "SELECT `ordering` FROM `#__vikbooking_optionals` ORDER BY `#__vikbooking_optionals`.`ordering` DESC LIMIT 1;";
9126 $dbo->setQuery($q);
9127 $dbo->execute();
9128 if ($dbo->getNumRows() == 1) {
9129 $getlast = $dbo->loadResult();
9130 $newsortnum = $getlast + 1;
9131 } else {
9132 $newsortnum = 1;
9133 }
9134 $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)) . ");";
9135 $dbo->setQuery($q);
9136 $dbo->execute();
9137 $newoptid = $dbo->insertid();
9138
9139 if (!empty($newoptid)) {
9140 // assign/unset option-rooms relations
9141 $rooms_with_opt = array();
9142 if (count($pidrooms)) {
9143 // assign this new option to the requested rooms
9144 foreach ($pidrooms as $idroom) {
9145 if (empty($idroom)) {
9146 continue;
9147 }
9148 $q = "SELECT `id`, `idopt` FROM `#__vikbooking_rooms` WHERE `id`=" . (int)$idroom . ";";
9149 $dbo->setQuery($q);
9150 $dbo->execute();
9151 if (!$dbo->getNumRows()) {
9152 continue;
9153 }
9154 $room_data = $dbo->loadAssoc();
9155 array_push($rooms_with_opt, $room_data['id']);
9156 $current_opts = empty($room_data['idopt']) ? array() : explode(';', rtrim($room_data['idopt'], ';'));
9157 if (in_array((string)$newoptid, $current_opts)) {
9158 continue;
9159 }
9160 if (count($current_opts) === 1 && (string)$current_opts[0] == '0') {
9161 // make sure we do not concatenate a real ID to 0
9162 $current_opts = array();
9163 }
9164 array_push($current_opts, $newoptid);
9165 $new_opts = implode(';', $current_opts) . ';';
9166 $q = "UPDATE `#__vikbooking_rooms` SET `idopt`=" . $dbo->quote($new_opts) . " WHERE `id`={$room_data['id']};";
9167 $dbo->setQuery($q);
9168 $dbo->execute();
9169 }
9170 }
9171 if (!count($rooms_with_opt)) {
9172 // get all rooms to unset this option (if previously set)
9173 array_push($rooms_with_opt, '0');
9174 }
9175 // unset the option from the other rooms that may have it
9176 $q = "SELECT `id`, `idopt` FROM `#__vikbooking_rooms` WHERE `id` NOT IN (" . implode(', ', $rooms_with_opt) . ");";
9177 $dbo->setQuery($q);
9178 $dbo->execute();
9179 if ($dbo->getNumRows()) {
9180 $unset_rooms_opt = $dbo->loadAssocList();
9181 foreach ($unset_rooms_opt as $room_data) {
9182 $current_opts = empty($room_data['idopt']) ? array() : explode(';', rtrim($room_data['idopt'], ';'));
9183 if (!in_array((string)$newoptid, $current_opts)) {
9184 // this room is not using this option
9185 continue;
9186 }
9187 $optkey = array_search((string)$newoptid, $current_opts);
9188 if ($optkey === false) {
9189 // key not found
9190 continue;
9191 }
9192 // unset this option ID from the string
9193 unset($current_opts[$optkey]);
9194 if (!count($current_opts)) {
9195 // a room with no options assigned will be listed as "0;"
9196 $current_opts = array(0);
9197 }
9198 $new_opts = implode(';', $current_opts) . ';';
9199 $q = "UPDATE `#__vikbooking_rooms` SET `idopt`=" . $dbo->quote($new_opts) . " WHERE `id`={$room_data['id']};";
9200 $dbo->setQuery($q);
9201 $dbo->execute();
9202 }
9203 }
9204 //
9205 }
9206
9207 }
9208 $mainframe = JFactory::getApplication();
9209 $mainframe->redirect("index.php?option=com_vikbooking&task=" . ($stay && isset($newoptid) && !empty($newoptid) ? 'editoptional&cid[]=' . $newoptid : 'optionals'));
9210 }
9211
9212 public function removeoptionals() {
9213 if (!JSession::checkToken()) {
9214 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
9215 }
9216 $ids = VikRequest::getVar('cid', array(0));
9217 if (@count($ids)) {
9218 $dbo = JFactory::getDbo();
9219 foreach ($ids as $d) {
9220 $q = "SELECT `img` FROM `#__vikbooking_optionals` WHERE `id`=".$dbo->quote($d).";";
9221 $dbo->setQuery($q);
9222 $dbo->execute();
9223 if ($dbo->getNumRows() == 1) {
9224 $rows = $dbo->loadAssocList();
9225 if (!empty($rows[0]['img']) && file_exists(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR.$rows[0]['img'])) {
9226 @unlink(VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR.$rows[0]['img']);
9227 }
9228 }
9229 $q = "DELETE FROM `#__vikbooking_optionals` WHERE `id`=".$dbo->quote($d).";";
9230 $dbo->setQuery($q);
9231 $dbo->execute();
9232 }
9233 }
9234 $mainframe = JFactory::getApplication();
9235 $mainframe->redirect("index.php?option=com_vikbooking&task=optionals");
9236 }
9237
9238 public function sendcustomsms() {
9239 $mainframe = JFactory::getApplication();
9240 $pphone = VikRequest::getString('phone', '', 'request');
9241 $psmscont = VikRequest::getString('smscont', '', 'request');
9242 $pgoto = VikRequest::getString('goto', '', 'request', VIKREQUEST_ALLOWRAW);
9243 $pgoto = !empty($pgoto) ? urldecode($pgoto) : 'index.php?option=com_vikbooking';
9244 if (!empty($pphone) && !empty($psmscont)) {
9245 $sms_api = VikBooking::getSMSAPIClass();
9246 $sms_api_params = VikBooking::getSMSParams();
9247 if (!empty($sms_api) && file_exists(VBO_ADMIN_PATH.DIRECTORY_SEPARATOR.'smsapi'.DIRECTORY_SEPARATOR.$sms_api) && !empty($sms_api_params)) {
9248 require_once(VBO_ADMIN_PATH.DIRECTORY_SEPARATOR.'smsapi'.DIRECTORY_SEPARATOR.$sms_api);
9249 $sms_obj = new VikSmsApi(array(), $sms_api_params);
9250 $response_obj = $sms_obj->sendMessage($pphone, $psmscont);
9251 if ( !$sms_obj->validateResponse($response_obj) ) {
9252 VikError::raiseWarning('', $sms_obj->getLog());
9253 } else {
9254 $mainframe->enqueueMessage(JText::translate('VBSENDSMSOK'));
9255 }
9256 } else {
9257 VikError::raiseWarning('', JText::translate('VBSENDSMSERRMISSAPI'));
9258 }
9259 } else {
9260 VikError::raiseWarning('', JText::translate('VBSENDSMSERRMISSDATA'));
9261 }
9262 $mainframe->redirect($pgoto);
9263 }
9264
9265 public function sendcustomemail() {
9266 $dbo = JFactory::getDbo();
9267 $mainframe = JFactory::getApplication();
9268 $vbo_tn = VikBooking::getTranslator();
9269 $pbid = VikRequest::getInt('bid', '', 'request');
9270 $pemailsubj = VikRequest::getString('emailsubj', '', 'request');
9271 $pemail = VikRequest::getString('email', '', 'request');
9272 $pemailcont = VikRequest::getString('emailcont', '', 'request', VIKREQUEST_ALLOWRAW);
9273 $pemailfrom = VikRequest::getString('emailfrom', '', 'request');
9274 $pgoto = VikRequest::getString('goto', '', 'request', VIKREQUEST_ALLOWRAW);
9275 $pgoto = !empty($pgoto) ? urldecode($pgoto) : 'index.php?option=com_vikbooking';
9276 if (!empty($pemail) && !empty($pemailcont)) {
9277 $email_attach = null;
9278 jimport('joomla.filesystem.file');
9279 $pemailattch = VikRequest::getVar('emailattch', null, 'files', 'array');
9280 if (isset($pemailattch) && strlen(trim($pemailattch['name']))) {
9281 $filename = JFile::makeSafe(str_replace(" ", "_", strtolower($pemailattch['name'])));
9282 $src = $pemailattch['tmp_name'];
9283 $dest = VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR;
9284 $j = "";
9285 if (file_exists($dest.$filename)) {
9286 $j = rand(171, 1717);
9287 while (file_exists($dest.$j.$filename)) {
9288 $j++;
9289 }
9290 }
9291 $finaldest = $dest.$j.$filename;
9292 if (VikBooking::uploadFile($src, $finaldest)) {
9293 $email_attach = $finaldest;
9294 } else {
9295 VikError::raiseWarning('', 'Error uploading the attachment. Email not sent.');
9296 $mainframe->redirect($pgoto);
9297 exit;
9298 }
9299 }
9300 //VBO 1.10 - special tags for the custom email template files and messages
9301 $orig_mail_cont = $pemailcont;
9302 if (strpos($pemailcont, '{') !== false && strpos($pemailcont, '}') !== false) {
9303 // replace any possible placeholder for special tags
9304 $pemailcont = preg_replace_callback("/(<strong class=\"vbo-editor-hl-specialtag\">)([^<]+)(<\/strong>)/", function($match) {
9305 return $match[2];
9306 }, $pemailcont);
9307
9308 $booking = array();
9309 $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.";";
9310 $dbo->setQuery($q);
9311 $dbo->execute();
9312 if ($dbo->getNumRows() > 0) {
9313 $booking = $dbo->loadAssoc();
9314 }
9315 $booking_rooms = array();
9316 $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.";";
9317 $dbo->setQuery($q);
9318 $dbo->execute();
9319 if ($dbo->getNumRows() > 0) {
9320 $booking_rooms = $dbo->loadAssocList();
9321 if (!empty($booking['lang'])) {
9322 $vbo_tn->translateContents($booking_rooms, '#__vikbooking_rooms', array('id' => 'idroom', 'room_name' => 'name'), array(), $booking['lang']);
9323 }
9324 }
9325 //we use the same parsing function as the one for the Customer SMS Template
9326 $pemailcont = VikBooking::parseCustomerSMSTemplate($booking, $booking_rooms, null, $pemailcont);
9327 }
9328 //
9329 // allow the use of token {booking_id} in subject
9330 $pemailsubj = str_replace('{booking_id}', $pbid, $pemailsubj);
9331 //
9332 $is_html = (strpos($pemailcont, '<') !== false && strpos($pemailcont, '>') !== false);
9333 $pemailcont = $is_html ? nl2br($pemailcont) : $pemailcont;
9334 $vbo_app = VikBooking::getVboApplication();
9335 $vbo_app->sendMail($pemailfrom, $pemailfrom, $pemail, $pemailfrom, $pemailsubj, $pemailcont, $is_html, 'base64', $email_attach);
9336 $mainframe->enqueueMessage(JText::translate('VBSENDEMAILOK'));
9337 if ($email_attach !== null) {
9338 @unlink($email_attach);
9339 }
9340 //Booking History
9341 VikBooking::getBookingHistoryInstance()->setBid($pbid)->store('CE', nl2br($pemailsubj . "\n\n" . $pemailcont));
9342 //
9343 //Save email template for future sending
9344 $config_rec_exists = false;
9345 $emtpl = array(
9346 'emailsubj' => $pemailsubj,
9347 'emailcont' => $orig_mail_cont,
9348 'emailfrom' => $pemailfrom
9349 );
9350 $cur_emtpl = array();
9351 $q = "SELECT `setting` FROM `#__vikbooking_config` WHERE `param`='customemailtpls';";
9352 $dbo->setQuery($q);
9353 $dbo->execute();
9354 if ($dbo->getNumRows() > 0) {
9355 $config_rec_exists = true;
9356 $cur_emtpl = $dbo->loadResult();
9357 $cur_emtpl = empty($cur_emtpl) ? array() : json_decode($cur_emtpl, true);
9358 $cur_emtpl = is_array($cur_emtpl) ? $cur_emtpl : array();
9359 }
9360 if (count($cur_emtpl) > 0) {
9361 $existing_subj = false;
9362 foreach ($cur_emtpl as $emk => $emv) {
9363 if (array_key_exists('emailsubj', $emv) && $emv['emailsubj'] == $emtpl['emailsubj']) {
9364 $cur_emtpl[$emk] = $emtpl;
9365 $existing_subj = true;
9366 break;
9367 }
9368 }
9369 if ($existing_subj === false) {
9370 $cur_emtpl[] = $emtpl;
9371 }
9372 } else {
9373 $cur_emtpl[] = $emtpl;
9374 }
9375 if (count($cur_emtpl) > 10) {
9376 //Max 10 templates to avoid problems with the size of the field and truncated json strings
9377 $exceed = count($cur_emtpl) - 10;
9378 for ($tl=0; $tl < $exceed; $tl++) {
9379 unset($cur_emtpl[$tl]);
9380 }
9381 $cur_emtpl = array_values($cur_emtpl);
9382 }
9383 if ($config_rec_exists === true) {
9384 $q = "UPDATE `#__vikbooking_config` SET `setting`=".$dbo->quote(json_encode($cur_emtpl))." WHERE `param`='customemailtpls';";
9385 $dbo->setQuery($q);
9386 $dbo->execute();
9387 } else {
9388 $q = "INSERT INTO `#__vikbooking_config` (`param`,`setting`) VALUES ('customemailtpls', ".$dbo->quote(json_encode($cur_emtpl)).");";
9389 $dbo->setQuery($q);
9390 $dbo->execute();
9391 }
9392 //
9393 } else {
9394 VikError::raiseWarning('', JText::translate('VBSENDEMAILERRMISSDATA'));
9395 }
9396 $mainframe->redirect($pgoto);
9397 }
9398
9399 public function rmcustomemailtpl() {
9400 $cid = VikRequest::getVar('cid', array(0));
9401 $oid = $cid[0];
9402 $dbo = JFactory::getDBO();
9403 $mainframe = JFactory::getApplication();
9404 $tplind = VikRequest::getInt('tplind', '', 'request');
9405 if (empty($oid) || !(strlen($tplind) > 0)) {
9406 VikError::raiseWarning('', 'Missing Data.');
9407 $mainframe->redirect('index.php?option=com_vikbooking');
9408 exit;
9409 }
9410 $cur_emtpl = array();
9411 $q = "SELECT `setting` FROM `#__vikbooking_config` WHERE `param`='customemailtpls';";
9412 $dbo->setQuery($q);
9413 $dbo->execute();
9414 if ($dbo->getNumRows() > 0) {
9415 $cur_emtpl = $dbo->loadResult();
9416 $cur_emtpl = empty($cur_emtpl) ? array() : json_decode($cur_emtpl, true);
9417 $cur_emtpl = is_array($cur_emtpl) ? $cur_emtpl : array();
9418 } else {
9419 VikError::raiseWarning('', 'Missing Templates Record.');
9420 $mainframe->redirect('index.php?option=com_vikbooking');
9421 exit;
9422 }
9423 if (array_key_exists($tplind, $cur_emtpl)) {
9424 unset($cur_emtpl[$tplind]);
9425 $cur_emtpl = count($cur_emtpl) > 0 ? array_values($cur_emtpl) : array();
9426 $q = "UPDATE `#__vikbooking_config` SET `setting`=".$dbo->quote(json_encode($cur_emtpl))." WHERE `param`='customemailtpls';";
9427 $dbo->setQuery($q);
9428 $dbo->execute();
9429 }
9430 $mainframe->redirect('index.php?option=com_vikbooking&task=editorder&cid[]='.$oid.'&customemail=1');
9431 exit;
9432 }
9433
9434 public function exportcustomers() {
9435 //we do not set the menu for this view
9436
9437 VikRequest::setVar('view', VikRequest::getCmd('view', 'exportcustomers'));
9438
9439 parent::display();
9440
9441 if (VikBooking::showFooter()) {
9442 VikBookingHelper::printFooter();
9443 }
9444 }
9445
9446 public function csvexportprepare() {
9447 //modal box, so we do not set menu or footer
9448
9449 VikRequest::setVar('view', VikRequest::getCmd('view', 'csvexportprepare'));
9450
9451 parent::display();
9452 }
9453
9454 public function icsexportprepare() {
9455 //modal box, so we do not set menu or footer
9456
9457 VikRequest::setVar('view', VikRequest::getCmd('view', 'icsexportprepare'));
9458
9459 parent::display();
9460 }
9461
9462 public function bookingcheckin() {
9463 //modal box, so we do not set menu or footer
9464
9465 VikRequest::setVar('view', VikRequest::getCmd('view', 'bookingcheckin'));
9466
9467 parent::display();
9468 }
9469
9470 public function gencheckindoc() {
9471 //modal box, so we do not set menu or footer
9472
9473 VikRequest::setVar('view', VikRequest::getCmd('view', 'gencheckindoc'));
9474
9475 parent::display();
9476 }
9477
9478 public function checkversion() {
9479 //to be called via ajax
9480 $params = new stdClass;
9481 $params->version = VIKBOOKING_SOFTWARE_VERSION;
9482 $params->alias = 'com_vikbooking';
9483
9484 $result = array();
9485
9486 if (!count($result)) {
9487 $result = new stdClass;
9488 $result->status = 0;
9489 } else {
9490 $result = $result[0];
9491 }
9492
9493 echo json_encode($result);
9494 exit;
9495 }
9496
9497 public function updateprogram() {
9498 $params = new stdClass;
9499 $params->version = VIKBOOKING_SOFTWARE_VERSION;
9500 $params->alias = 'com_vikbooking';
9501
9502 $result = array();
9503
9504 if (!count($result) || !$result[0]) {
9505 if (class_exists('JEventDispatcher')) {
9506 $dispatcher = JEventDispatcher::getInstance();
9507 $result = $dispatcher->trigger('checkVersion', array(&$params));
9508 } else {
9509 $app = JFactory::getApplication();
9510 if (method_exists($app, 'triggerEvent')) {
9511 $result = $app->triggerEvent('checkVersion', array(&$params));
9512 }
9513 }
9514 }
9515
9516 if (!count($result) || !$result[0]->status || !$result[0]->response->status) {
9517 exit('Error, plugin disabled');
9518 }
9519
9520 JToolbarHelper::title(JText::translate('VBMAINTITLEUPDATEPROGRAM'));
9521
9522 VikBookingHelper::pUpdateProgram($result[0]->response);
9523 }
9524
9525 public function updateprogramlaunch() {
9526 $params = new stdClass;
9527 $params->version = VIKBOOKING_SOFTWARE_VERSION;
9528 $params->alias = 'com_vikbooking';
9529
9530 $json = new stdClass;
9531 $json->status = false;
9532
9533 echo json_encode($json);
9534 exit;
9535 }
9536
9537 public function invoke_vcm() {
9538 $oids = VikRequest::getVar('cid', array(0));
9539 $mainframe = JFactory::getApplication();
9540 $sync_type = VikRequest::getString('stype', 'new', 'request');
9541 $sync_type = !in_array($sync_type, array('new', 'modify', 'cancel')) ? 'new' : $sync_type;
9542 $original_booking_js = VikRequest::getString('origb', '', 'request', VIKREQUEST_ALLOWRAW);
9543 $return_url = VikRequest::getString('returl', '', 'request', VIKREQUEST_ALLOWRAW);
9544 $return_url = !empty($return_url) ? urldecode($return_url) : $return_url;
9545 if (!(count($oids) > 0) || !file_exists(VCM_SITE_PATH . DIRECTORY_SEPARATOR . "helpers" . DIRECTORY_SEPARATOR . "synch.vikbooking.php")) {
9546 $mainframe->redirect("index.php?option=com_vikbooking&task=orders");
9547 exit;
9548 }
9549
9550 $vcm_obj = VikBooking::getVcmInvoker();
9551 $vcm_obj->setOids($oids)->setSyncType($sync_type)->setOriginalBooking($original_booking_js, true);
9552 $result = $vcm_obj->doSync();
9553
9554 if ($result === true) {
9555 $mainframe->enqueueMessage(JText::translate('VBCHANNELMANAGERRESULTOK'));
9556 } else {
9557 VikError::raiseWarning('', JText::translate('VBCHANNELMANAGERRESULTKO').' <a href="index.php?option=com_vikchannelmanager" target="_blank">'.JText::translate('VBCHANNELMANAGEROPEN').'</a>');
9558 }
9559
9560 if (!empty($return_url)) {
9561 $mainframe->redirect($return_url);
9562 } else {
9563 $mainframe->redirect("index.php?option=com_vikbooking&task=orders");
9564 }
9565 }
9566
9567 public function multiphotosupload() {
9568 jimport('joomla.filesystem.file');
9569
9570 $dbo = JFactory::getDBO();
9571 $proomid = VikRequest::getInt('roomid', '', 'request');
9572
9573 $resp = array('files' => array());
9574 $error_messages = array(
9575 1 => 'The uploaded file exceeds the upload_max_filesize directive in php.ini',
9576 2 => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form',
9577 3 => 'The uploaded file was only partially uploaded',
9578 4 => 'No file was uploaded',
9579 6 => 'Missing a temporary folder',
9580 7 => 'Failed to write file to disk',
9581 8 => 'A PHP extension stopped the file upload',
9582 'post_max_size' => 'The uploaded file exceeds the post_max_size directive in php.ini',
9583 'max_file_size' => 'File is too big',
9584 'min_file_size' => 'File is too small',
9585 'accept_file_types' => 'Filetype not allowed',
9586 'max_number_of_files' => 'Maximum number of files exceeded',
9587 'max_width' => 'Image exceeds maximum width',
9588 'min_width' => 'Image requires a minimum width',
9589 'max_height' => 'Image exceeds maximum height',
9590 'min_height' => 'Image requires a minimum height',
9591 'abort' => 'File upload aborted',
9592 'image_resize' => 'Failed to resize image',
9593 'vbo_type' => 'The file type cannot be accepted',
9594 'vbo_jupload' => 'The upload has failed. Check the Joomla Configuration',
9595 'vbo_perm' => 'Error moving the uploaded files. Check your permissions'
9596 );
9597
9598 $creativik = new vikResizer();
9599 $updpath = VBO_SITE_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'uploads'.DIRECTORY_SEPARATOR;
9600 $bigsdest = $updpath;
9601 $thumbsdest = $updpath;
9602 $dest = $updpath;
9603 $moreimagestr = '';
9604 $cur_captions = json_encode(array());
9605
9606 $q = "SELECT `moreimgs`,`imgcaptions` FROM `#__vikbooking_rooms` WHERE `id`=".$proomid.";";
9607 $dbo->setQuery($q);
9608 $dbo->execute();
9609 if ($dbo->getNumRows() == 1) {
9610 $photo_data = $dbo->loadAssocList();
9611 $cur_captions = $photo_data[0]['imgcaptions'];
9612 $cur_photos = $photo_data[0]['moreimgs'];
9613 if (!empty($cur_photos)) {
9614 $moreimagestr .= $cur_photos;
9615 }
9616 }
9617
9618 $bulkphotos = VikRequest::getVar('bulkphotos', null, 'files', 'array');
9619
9620 if (is_array($bulkphotos) && count($bulkphotos) > 0 && array_key_exists('name', $bulkphotos) && count($bulkphotos['name']) > 0) {
9621 foreach ($bulkphotos['name'] as $updk => $photoname) {
9622 $uploaded_image = array();
9623 $filename = JFile::makeSafe(str_replace(" ", "_", strtolower($photoname)));
9624 $src = $bulkphotos['tmp_name'][$updk];
9625 $j = "";
9626 if (file_exists($dest.$filename)) {
9627 $j = rand(171, 1717);
9628 while (file_exists($dest.$j.$filename)) {
9629 $j++;
9630 }
9631 }
9632 $finaldest=$dest.$j.$filename;
9633 $is_error = false;
9634 $err_key = '';
9635 if (array_key_exists('error', $bulkphotos) && array_key_exists($updk, $bulkphotos['error']) && !empty($bulkphotos['error'][$updk])) {
9636 if (array_key_exists($bulkphotos['error'][$updk], $error_messages)) {
9637 $is_error = true;
9638 $err_key = $bulkphotos['error'][$updk];
9639 }
9640 }
9641 if (!$is_error) {
9642 $check = getimagesize($bulkphotos['tmp_name'][$updk]);
9643 if ($check[2] & imagetypes()) {
9644 if (VikBooking::uploadFile($src, $finaldest)) {
9645 $gimg = $j.$filename;
9646 //orig img
9647 $origmod = true;
9648 VikBooking::uploadFile($finaldest, $bigsdest.'big_'.$j.$filename, true);
9649 //thumb
9650 $thumbsize = VikBooking::getThumbSize();
9651 $thumb = $creativik->proportionalImage($finaldest, $thumbsdest.'thumb_'.$j.$filename, $thumbsize, $thumbsize);
9652 if (!$thumb || !$origmod) {
9653 if (file_exists($bigsdest.'big_'.$j.$filename)) @unlink($bigsdest.'big_'.$j.$filename);
9654 if (file_exists($thumbsdest.'thumb_'.$j.$filename)) @unlink($thumbsdest.'thumb_'.$j.$filename);
9655 $is_error = true;
9656 $err_key = 'vbo_perm';
9657 } else {
9658 $moreimagestr.=$j.$filename.";;";
9659 }
9660 @unlink($finaldest);
9661 } else {
9662 $is_error = true;
9663 $err_key = 'vbo_jupload';
9664 }
9665 } else {
9666 $is_error = true;
9667 $err_key = 'vbo_type';
9668 }
9669 }
9670 $img = new stdClass();
9671 if ($is_error) {
9672 $img->name = '';
9673 $img->size = '';
9674 $img->type = '';
9675 $img->url = '';
9676 $img->error = array_key_exists($err_key, $error_messages) ? $error_messages[$err_key] : 'Generic Error for Upload';
9677 } else {
9678 $img->name = $photoname;
9679 $img->size = $bulkphotos['size'][$updk];
9680 $img->type = $bulkphotos['type'][$updk];
9681 $img->url = VBO_SITE_URI.'resources/uploads/big_'.$j.$filename;
9682 }
9683 $resp['files'][] = $img;
9684 }
9685 } else {
9686 $res = new stdClass();
9687 $res->name = '';
9688 $res->size = '';
9689 $res->type = '';
9690 $res->url = '';
9691 $res->error = 'No images received for upload';
9692 $resp['files'][] = $res;
9693 }
9694 //Update current extra images string
9695 $q = "UPDATE `#__vikbooking_rooms` SET `moreimgs`=".$dbo->quote($moreimagestr)." WHERE `id`=".$proomid.";";
9696 $dbo->setQuery($q);
9697 $dbo->execute();
9698 $resp['actmoreimgs'] = $moreimagestr;
9699 //Update current extra images uploaded
9700 $cur_thumbs = '';
9701 $morei=explode(';;', $moreimagestr);
9702 if (@count($morei) > 0) {
9703 $imgcaptions = json_decode($cur_captions, true);
9704 $usecaptions = empty($imgcaptions) || is_null($imgcaptions) || !is_array($imgcaptions) || !(count($imgcaptions) > 0) ? false : true;
9705 $cur_thumbs .= '<ul class="vbo-sortable">';
9706 foreach ($morei as $ki => $mi) {
9707 if (!empty($mi)) {
9708 $cur_thumbs .= '<li class="vbo-editroom-currentphoto">';
9709 $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>';
9710 $cur_thumbs .= '<a class="vbo-toggle-imgcaption" href="javascript: void(0);" onclick="vbOpenImgDetails(\''.$ki.'\', this)"><i class="'.VikBookingIcons::i('cog').'"></i></a>';
9711 $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>';
9712 $cur_thumbs .= '</li>';
9713 }
9714 }
9715 $cur_thumbs .= '</ul>';
9716 $cur_thumbs .= '<br clear="all"/>';
9717 }
9718 $resp['currentthumbs'] = $cur_thumbs;
9719
9720 echo json_encode($resp);
9721 exit;
9722 }
9723
9724 public function loadsmsbalance() {
9725 //to be called via ajax
9726 $html = 'Error1 [N/A]';
9727 $sms_api = VikBooking::getSMSAPIClass();
9728 if (file_exists(VBO_ADMIN_PATH.DIRECTORY_SEPARATOR.'smsapi'.DIRECTORY_SEPARATOR.$sms_api)) {
9729 require_once(VBO_ADMIN_PATH.DIRECTORY_SEPARATOR.'smsapi'.DIRECTORY_SEPARATOR.$sms_api);
9730 $sms_obj = new VikSmsApi(array(), VikBooking::getSMSParams());
9731 if (method_exists('VikSmsApi', 'estimate')) {
9732 $array_result = $sms_obj->estimate("+393711271611", "estimate credit");
9733 if ( $array_result->errorCode != 0 ) {
9734 $html = 'Error3 ['.$array_result->errorMsg.']';
9735 } else {
9736 $html = VikBooking::getCurrencySymb().' '.$array_result->userCredit;
9737 }
9738 } else {
9739 $html = 'Error2 [N/A]';
9740 }
9741 }
9742 echo $html;
9743 exit;
9744 }
9745
9746 public function loadsmsparams() {
9747 //to be called via ajax
9748 $html = '---------';
9749 $phpfile = VikRequest::getString('phpfile', '', 'request');
9750 if (!empty($phpfile)) {
9751 $sms_api = VikBooking::getSMSAPIClass();
9752 $sms_params = $sms_api == $phpfile ? VikBooking::getSMSParams(false) : '';
9753 $html = VikBooking::displaySMSParameters($phpfile, $sms_params);
9754 }
9755 echo $html;
9756 exit;
9757 }
9758
9759 public function loadcronparams() {
9760 //to be called via ajax
9761 $html = '---------';
9762 $phpfile = VikRequest::getString('phpfile', '', 'request');
9763 if (!empty($phpfile)) {
9764 $html = VikBooking::displayCronParameters($phpfile);
9765 }
9766 echo $html;
9767 exit;
9768 }
9769
9770 public function loadpaymentparams() {
9771 //to be called via ajax
9772 $html = '<p>---------</p>';
9773 $phpfile = VikRequest::getString('phpfile', '', 'request');
9774 if (!empty($phpfile)) {
9775 $html = VikBooking::displayPaymentParameters($phpfile);
9776 }
9777 echo $html;
9778 exit;
9779 }
9780
9781 public function setbookingtag() {
9782 //to be called via ajax
9783 $dbo = JFactory::getDBO();
9784 $pidorder = VikRequest::getInt('idorder', '', 'request');
9785 $ptagkey = VikRequest::getInt('tagkey', '', 'request');
9786 if (!empty($pidorder) && $ptagkey >= 0) {
9787 $all_tags = VikBooking::loadBookingsColorTags();
9788 if (array_key_exists($ptagkey, $all_tags)) {
9789 $q = "SELECT `id` FROM `#__vikbooking_orders` WHERE `id`=".(int)$pidorder.";";
9790 $dbo->setQuery($q);
9791 $dbo->execute();
9792 if ($dbo->getNumRows() > 0) {
9793 $newcolortag = json_encode($all_tags[$ptagkey]);
9794 $q = "UPDATE `#__vikbooking_orders` SET `colortag`=".$dbo->quote($newcolortag)." WHERE `id`=".(int)$pidorder.";";
9795 $dbo->setQuery($q);
9796 $dbo->execute();
9797 $newcolortag = $all_tags[$ptagkey];
9798 $newcolortag['name'] = JText::translate($newcolortag['name']);
9799 $newcolortag['fontcolor'] = VikBooking::getBestColorContrast($newcolortag['color']);
9800 echo json_encode($newcolortag);
9801 } else {
9802 echo 'e4j.error.Booking ('.$pidorder.') not found';
9803 }
9804 } else {
9805 echo 'e4j.error.Color Tag ('.$ptagkey.') not found';
9806 }
9807 } else {
9808 echo 'e4j.error.Missing Data';
9809 }
9810 exit;
9811 }
9812
9813 public function updatereceiptnum() {
9814 //to be called via ajax
9815 $pnewnum = VikRequest::getInt('newnum', '', 'request');
9816 $pnewnotes = VikRequest::getString('newnotes', '', 'request', VIKREQUEST_ALLOWRAW);
9817 $poid = VikRequest::getInt('oid', '', 'request');
9818 if ($pnewnum > 0) {
9819 VikBooking::getNextReceiptNumber($poid, $pnewnum);
9820 VikBooking::getReceiptNotes($pnewnotes);
9821 //Booking History
9822 VikBooking::getBookingHistoryInstance()->setBid($poid)->store('BR', JText::translate('VBOFISCRECEIPTNUM').': '.$pnewnum);
9823 //
9824 echo 'e4j.ok';
9825 exit;
9826 }
9827 echo 'e4j.error';
9828 exit;
9829 }
9830
9831 public function isroombookable() {
9832 //to be called via ajax
9833 $dbo = JFactory::getDBO();
9834 $res = array(
9835 'status' => 0,
9836 'err' => ''
9837 );
9838 $prid = VikRequest::getInt('rid', '', 'request');
9839 $pfdate = VikRequest::getString('fdate', '', 'request');
9840 $ptdate = VikRequest::getString('tdate', '', 'request');
9841 $room_info = array();
9842 $q = "SELECT * FROM `#__vikbooking_rooms` WHERE `id`=".(int)$prid.";";
9843 $dbo->setQuery($q);
9844 $dbo->execute();
9845 if ($dbo->getNumRows() > 0) {
9846 $room_info = $dbo->loadAssoc();
9847 }
9848 $pcheckinh = 0;
9849 $pcheckinm = 0;
9850 $pcheckouth = 0;
9851 $pcheckoutm = 0;
9852 $timeopst = VikBooking::getTimeOpenStore();
9853 if (is_array($timeopst)) {
9854 $opent = VikBooking::getHoursMinutes($timeopst[0]);
9855 $closet = VikBooking::getHoursMinutes($timeopst[1]);
9856 $pcheckinh = $opent[0];
9857 $pcheckinm = $opent[1];
9858 $pcheckouth = $closet[0];
9859 $pcheckoutm = $closet[1];
9860 }
9861 $from_ts = VikBooking::getDateTimestamp($pfdate, $pcheckinh, $pcheckinm);
9862 $to_ts = VikBooking::getDateTimestamp($ptdate, $pcheckouth, $pcheckoutm);
9863 if (
9864 count($room_info) > 0 &&
9865 (!empty($pfdate) && !empty($ptdate) && !empty($from_ts) && !empty($to_ts)) &&
9866 VikBooking::roomBookable($room_info['id'], $room_info['units'], $from_ts, $to_ts))
9867 {
9868 $res['status'] = 1;
9869 } else {
9870 if (!(count($room_info) > 0)) {
9871 $res['err'] = 'Room not found';
9872 } elseif (empty($pfdate) || empty($ptdate) || empty($from_ts) || empty($to_ts)) {
9873 $res['err'] = 'Invalid dates';
9874 } else {
9875 //not available
9876 $res['err'] = JText::sprintf('VBOBOOKADDROOMERR', $room_info['name'], $pfdate, $ptdate);
9877 }
9878 }
9879
9880 echo json_encode($res);
9881 exit;
9882 }
9883
9884 public function uploadsnapshot() {
9885 $snap_base_path = VBO_ADMIN_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'idscans';
9886 /**
9887 * We no longer access the uploaded file from php://input, we now retrieve it as a regular file upload.
9888 * The old snapshot collection script with Flash no longer works in 2021.
9889 *
9890 * @since 1.14 (J) - 1.4.0 (WP)
9891 */
9892 $result = null;
9893 try {
9894 $result = VikBooking::uploadFileFromRequest(VikRequest::getVar('snapshot', null, 'files', 'array'), $snap_base_path);
9895 } catch (RuntimeException $e) {
9896 echo "e4j.error.Error " . $e->getMessage();
9897 exit;
9898 }
9899
9900 if (!is_object($result)) {
9901 echo "e4j.error.Invalid upload response";
9902 exit;
9903 }
9904
9905 echo $result->filename;
9906 exit;
9907 }
9908
9909 public function checkvcmrateschanges() {
9910 //to be called via ajax
9911 $session = JFactory::getSession();
9912 $ret = array('changesCount' => 0, 'changesData' => '');
9913 $updforvcm = $session->get('vbVcmRatesUpd', '');
9914 if (!empty($updforvcm) && is_array($updforvcm) && count($updforvcm) > 0) {
9915 $ret['changesCount'] = $updforvcm['count'];
9916 $ret['changesData'] = $updforvcm;
9917 }
9918
9919 echo json_encode($ret);
9920 exit;
9921 }
9922
9923 /**
9924 * AJAX endpoint to load the details of one or more bookings.
9925 *
9926 * @return void
9927 *
9928 * @since 1.16.0 (J) - 1.6.0 (WP) the method was refactored.
9929 */
9930 public function getbookingsinfo()
9931 {
9932 //to be called via ajax
9933 $dbo = JFactory::getDbo();
9934
9935 $booking_infos = [];
9936 $bookings = [];
9937
9938 $pidorders = VikRequest::getString('idorders', '', 'request');
9939 $psubroom = VikRequest::getString('subroom', '', 'request');
9940 $pstatus = VikRequest::getString('status', '', 'request');
9941 $pstay_date = VikRequest::getString('stay_date', '', 'request');
9942 $pidroom = VikRequest::getInt('idroom', 0, 'request');
9943 $psharedcal = VikRequest::getInt('sharedcal', 0, 'request');
9944
9945 if (!empty($pidorders)) {
9946 $bookings = explode(',', $pidorders);
9947 foreach ($bookings as $k => $v) {
9948 $v = intval(str_replace('-', '', $v));
9949 if (empty($v)) {
9950 unset($bookings[$k]);
9951 continue;
9952 }
9953 $bookings[$k] = $v;
9954 }
9955 }
9956 $bookings = array_values($bookings);
9957
9958 if (!$bookings) {
9959 /**
9960 * AJAX requests made by the page availability overview may contain empty booking IDs
9961 * due to SQL errors that only occupied the room, but could not save the booking record.
9962 * Clean up busy records where the busy relations contain empty booking IDs.
9963 *
9964 * @since 1.14 (J) - 1.4.0 (WP)
9965 */
9966 $hanging_busy_ids = [];
9967
9968 $q = "SELECT `idbusy` FROM `#__vikbooking_ordersbusy` WHERE `idorder` = 0 OR `idorder` IS NULL;";
9969 $dbo->setQuery($q);
9970 $removelist = $dbo->loadAssocList();
9971 if ($removelist) {
9972 foreach ($removelist as $hanging_busy) {
9973 $hanging_busy_id = (int)$hanging_busy['idbusy'];
9974 if (!in_array($hanging_busy_id, $hanging_busy_ids)) {
9975 array_push($hanging_busy_ids, $hanging_busy_id);
9976 }
9977 }
9978 }
9979
9980 // let's check also for ghost records that only occupy the room
9981 $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);";
9982 $dbo->setQuery($q);
9983 $removelist = $dbo->loadAssocList();
9984 if ($removelist) {
9985 foreach ($removelist as $hanging_busy) {
9986 $hanging_busy_id = (int)$hanging_busy['id'];
9987 if (!in_array($hanging_busy_id, $hanging_busy_ids)) {
9988 array_push($hanging_busy_ids, $hanging_busy_id);
9989 }
9990 }
9991 }
9992
9993 if ($hanging_busy_ids) {
9994 $q = "DELETE FROM `#__vikbooking_busy` WHERE `id` IN (" . implode(', ', $hanging_busy_ids) . ");";
9995 $dbo->setQuery($q);
9996 $dbo->execute();
9997 }
9998 //
9999
10000 // output the error
10001 VBOHttpDocument::getInstance()->close(500, '1 - ' . JText::translate('VBOVWGETBKERRMISSDATA'));
10002 }
10003
10004 $nowdf = VikBooking::getDateFormat(true);
10005 if ($nowdf == "%d/%m/%Y") {
10006 $df = 'd/m/Y';
10007 } elseif ($nowdf == "%m/%d/%Y") {
10008 $df = 'm/d/Y';
10009 } else {
10010 $df = 'Y/m/d';
10011 }
10012 $datesep = VikBooking::getDateSeparator(true);
10013 $currencysymb = VikBooking::getCurrencySymb();
10014 $current_y = date('Y');
10015 $current_ts = time();
10016 $short_meal_enums = VBOMealplanManager::getInstance()->getShortMealPlans();
10017
10018 $query = $dbo->getQuery(true);
10019 $query->select('o.*');
10020 $query->from($dbo->qn('#__vikbooking_orders', 'o'));
10021 if (!empty($pstay_date) && !empty($pidroom) && $pstatus == 'any') {
10022 // include the requested booking IDs and the cancelled reservations for this stay date
10023 $stay_date_info = getdate(strtotime($pstay_date));
10024 $lim_ts_to = mktime(23, 59, 59, $stay_date_info['mon'], $stay_date_info['mday'], $stay_date_info['year']);
10025 $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) . '))');
10026 // exclude the pending reservations
10027 $query->where($dbo->qn('o.status') . ' IN (' . $dbo->q('confirmed') . ', ' . $dbo->q('cancelled') . ')');
10028 } else {
10029 // include only the requested booking IDs
10030 $query->where($dbo->qn('o.id') . ' IN (' . implode(', ', $bookings) . ')');
10031 }
10032 if ($pstatus != 'any') {
10033 $query->where($dbo->qn('o.status') . ' != ' . $dbo->q('cancelled'));
10034 }
10035 if (!empty($pstay_date) && $pstatus == 'any') {
10036 // sort by confirmed status before cancelled status
10037 $query->order('CASE WHEN ' . $dbo->qn('o.status') . ' = ' . $dbo->q('confirmed') . ' THEN 1 ELSE 0 END DESC');
10038 $query->order($dbo->qn('o.id') . ' ASC');
10039 }
10040 $dbo->setQuery($query);
10041 $booking_infos = $dbo->loadAssocList();
10042
10043 foreach ($booking_infos as $k => $row) {
10044 // rooms, amounts and guests information
10045 $rooms = VikBooking::loadOrdersRoomsData($row['id']);
10046 $rids_involved = [];
10047 $room_names = [];
10048 $totadults = 0;
10049 $totchildren = 0;
10050 foreach ($rooms as $rr) {
10051 $rids_involved[] = $rr['idroom'];
10052 $totadults += $rr['adults'];
10053 $totchildren += $rr['children'];
10054 $room_names[] = $rr['room_name'];
10055 if ($row['split_stay']) {
10056 // do not sum guests in case of split stay booking
10057 $totadults = $rr['adults'];
10058 $totchildren = $rr['children'];
10059 }
10060 }
10061
10062 if (!empty($pstay_date) && !empty($pidroom) && $pstatus == 'any') {
10063 // make sure we have fetched a reservation for the correct room (in case of cancellations included)
10064 if (!in_array($pidroom, $rids_involved)) {
10065 $is_out_of_scope = true;
10066 if ($psharedcal && count($bookings) === 1) {
10067 $is_out_of_scope = ($row['id'] != $bookings[0]);
10068 }
10069 if ($is_out_of_scope) {
10070 // out of scope reservation, unset it and go to the next one
10071 unset($booking_infos[$k]);
10072 continue;
10073 }
10074 }
10075 }
10076
10077 // included meal plans to be displayed in case of single-room booking
10078 $included_meals = [];
10079 $rplan_name = '';
10080 if (count($rooms) === 1) {
10081 // rate plan name and ID, if any
10082 $active_rplan_id = 0;
10083 if (!empty($rooms[0]['otarplan'])) {
10084 $rplan_name = $rooms[0]['otarplan'];
10085 } else {
10086 list($rplan_name, $active_rplan_id) = VBOMealplanManager::getInstance()->getPriceData($rooms[0]['idtar']);
10087 }
10088
10089 // find the included meals
10090 if (!empty($rooms[0]['meals'])) {
10091 // display included meals defined at room-reservation record
10092 $included_meals = VBOMealplanManager::getInstance()->roomRateIncludedMeals($rooms[0]);
10093 } else {
10094 // fetch default included meals in the selected rate plan
10095 $included_meals = $active_rplan_id ? VBOMealplanManager::getInstance()->ratePlanIncludedMeals($active_rplan_id) : [];
10096 }
10097 if (!$included_meals && empty($row['meals']) && !empty($row['idorderota']) && !empty($row['channel']) && !empty($row['custdata'])) {
10098 // attempt to fetch the included meal plans from the raw customer data or OTA reservation and room
10099 $included_meals = VBOMealplanManager::getInstance()->otaDataIncludedMeals($row, $rooms[0]);
10100 }
10101 }
10102
10103 if ($included_meals) {
10104 $short_incl_meals = [];
10105 foreach ($included_meals as $meal_enum => $meal_name) {
10106 $short_incl_meals[] = $short_meal_enums[$meal_enum];
10107 }
10108 $booking_infos[$k]['meals_included'] = $short_incl_meals;
10109 }
10110
10111 $booking_infos[$k]['rateplan_name'] = $rplan_name;
10112 $booking_infos[$k]['currency_symb'] = $currencysymb;
10113 if ($row['status'] == 'confirmed') {
10114 $booking_infos[$k]['status_lbl'] = JText::translate('VBCONFIRMED');
10115 if ($row['checkout'] < $current_ts) {
10116 $booking_infos[$k]['status_lbl'] = JText::translate('VBOCHECKEDSTATUSOUT');
10117 } elseif ($row['checkin'] < $current_ts && $row['checkout'] > $current_ts) {
10118 if ($row['checked'] == 1) {
10119 $booking_infos[$k]['status_lbl'] = JText::translate('VBOCHECKEDSTATUSIN');
10120 } elseif ($row['checked'] == -1) {
10121 $booking_infos[$k]['status_lbl'] = JText::translate('VBOCHECKEDSTATUSNOS');
10122 }
10123 }
10124 } elseif ($row['status'] == 'standby') {
10125 $booking_infos[$k]['status_lbl'] = JText::translate('VBSTANDBY');
10126 } elseif ($row['status'] == 'cancelled') {
10127 $booking_infos[$k]['status_lbl'] = JText::translate('VBCANCELLED');
10128 } else {
10129 $booking_infos[$k]['status_lbl'] = $row['status'];
10130 }
10131 $booking_infos[$k]['colortag'] = VikBooking::applyBookingColorTag($row);
10132 if ($booking_infos[$k]['colortag']) {
10133 $booking_infos[$k]['colortag']['name'] = JText::translate($booking_infos[$k]['colortag']['name']);
10134 }
10135 $booking_infos[$k]['room_names'] = implode(', ', $room_names);
10136 $booking_infos[$k]['tot_adults'] = $totadults;
10137 $booking_infos[$k]['tot_children'] = $totchildren;
10138 $booking_infos[$k]['format_tot'] = VikBooking::numberFormat($row['total']);
10139 $booking_infos[$k]['format_totpaid'] = VikBooking::numberFormat($row['totpaid']);
10140
10141 // room indexes
10142 $rindexes = [];
10143 $av_room_indexes = [];
10144 $used_indexes_map = [];
10145 $sub_units_data = [];
10146 $optindexes = [];
10147 $subroomdata = !empty($psubroom) ? explode('-', $psubroom) : array();
10148 $missing_index = false;
10149 foreach ($rooms as $kor => $or) {
10150 if ($row['status'] != "confirmed" || $row['closure'] || empty($or['params'])) {
10151 // cannot build room indexes data
10152 continue;
10153 }
10154
10155 $room_params = json_decode($or['params'], true);
10156 if (!is_array($room_params) || empty($room_params['features']) || !is_array($room_params['features'])) {
10157 // no distinctive features information
10158 continue;
10159 }
10160
10161 if (!strlen($or['roomindex'])) {
10162 // turn flag on for missing index when room does support them
10163 $missing_index = true;
10164 // build array with available room indexes
10165 $av_indexes = [];
10166 $unavailable_indexes = VikBooking::getRoomUnitNumsUnavailable($row, $or['idroom']);
10167 foreach ($room_params['features'] as $rind => $rfeatures) {
10168 if (in_array($rind, $unavailable_indexes) || (isset($used_indexes_map[$or['idroom']]) && in_array($rind, $used_indexes_map[$or['idroom']]))) {
10169 continue;
10170 }
10171 foreach ($rfeatures as $fname => $fval) {
10172 if ($fval) {
10173 $av_indexes[$rind] = '#' . $rind . ' - ' . JText::translate($fname) . ': ' . $fval;
10174 break;
10175 }
10176 }
10177 }
10178 if ($av_indexes) {
10179 // push available indexes for this room
10180 $av_room_indexes[$kor] = [
10181 'rid' => $or['idroom'],
10182 'name' => $or['room_name'],
10183 'list' => $av_indexes,
10184 ];
10185 }
10186 // do not proceed any further
10187 continue;
10188 }
10189
10190 // parse distinctive features
10191 foreach ($room_params['features'] as $rind => $rfeatures) {
10192 if ($rind != $or['roomindex']) {
10193 continue;
10194 }
10195 $ind_str = '';
10196 $ind_str_short = '';
10197 foreach ($rfeatures as $fname => $fval) {
10198 if (strlen($fval)) {
10199 $ind_str = '#' . $rind . ' - ' . JText::translate($fname) . ': ' . $fval;
10200 $ind_str_short = $fval;
10201 break;
10202 }
10203 }
10204 if (!isset($rindexes[$or['room_name']])) {
10205 $rindexes[$or['room_name']] = $ind_str;
10206 $sub_units_data[$or['room_name']] = $ind_str_short;
10207 } else {
10208 $rindexes[$or['room_name']] .= ', ' . $ind_str;
10209 $sub_units_data[$or['room_name']] .= ', ' . $ind_str_short;
10210 }
10211 break;
10212 }
10213
10214 // build options to switch sub-unit index
10215 if (count($subroomdata) && !count($optindexes) && $or['idroom'] == (int)$subroomdata[0]) {
10216 // build the options for switching the room index for this room
10217 foreach ($room_params['features'] as $rind => $rfeatures) {
10218 foreach ($rfeatures as $fname => $fval) {
10219 if (strlen((string)$fval)) {
10220 $optindexes[] = '<option value="'.$rind.'"'.($rind == (int)$subroomdata[1] ? ' selected="selected"' : '').'>#'.$rind.' - '.JText::translate($fname).': '.$fval.'</option>';
10221 break;
10222 }
10223 }
10224 }
10225 }
10226 }
10227
10228 if ($rindexes) {
10229 $booking_infos[$k]['rindexes'] = $rindexes;
10230 $booking_infos[$k]['sub_units_data'] = $sub_units_data;
10231 }
10232
10233 if ($optindexes) {
10234 $booking_infos[$k]['optindexes'] = $optindexes;
10235 }
10236
10237 if ($missing_index && $av_room_indexes) {
10238 $booking_infos[$k]['av_room_indexes'] = $av_room_indexes;
10239 }
10240
10241 // include flag for missing room index
10242 $booking_infos[$k]['missing_index'] = $missing_index;
10243
10244 // channel provenience and small logo URL
10245 $ota_logo_img = JText::translate('VBORDFROMSITE');
10246 $booking_avatar_src = null;
10247 $booking_avatar_alt = null;
10248 if (!empty($row['channel'])) {
10249 $channelparts = explode('_', $row['channel']);
10250 $otachannel = array_key_exists(1, $channelparts) && strlen($channelparts[1]) > 0 ? $channelparts[1] : ucwords($channelparts[0]);
10251 $ota_logo_img = VikBooking::getVcmChannelsLogo($row['channel']);
10252 if ($ota_logo_img === false) {
10253 $ota_logo_img = $otachannel;
10254 } else {
10255 $ota_logo_img = '<img src="'.$ota_logo_img.'" class="vbo-channelimg-small"/>';
10256 }
10257 $logo_helper = VikBooking::getVcmChannelsLogo($row['channel'], $get_istance = true);
10258 if ($logo_helper !== false) {
10259 $booking_avatar_src = $logo_helper->getSmallLogoURL();
10260 $booking_avatar_alt = $logo_helper->provenience;
10261 }
10262 }
10263 $booking_infos[$k]['channelimg'] = $ota_logo_img;
10264 $booking_infos[$k]['avatar_src'] = $booking_avatar_src;
10265 $booking_infos[$k]['avatar_alt'] = $booking_avatar_alt;
10266
10267 // Customer Details
10268 $custdata = $row['custdata'];
10269 $custdata_parts = explode("\n", $row['custdata']);
10270 if (count($custdata_parts) > 2 && strpos($custdata_parts[0], ':') !== false && strpos($custdata_parts[1], ':') !== false) {
10271 //get the first two fields
10272 $custvalues = [];
10273 foreach ($custdata_parts as $custdet) {
10274 if (strlen($custdet) < 1) {
10275 continue;
10276 }
10277 $custdet_parts = explode(':', $custdet);
10278 if (count($custdet_parts) >= 2) {
10279 unset($custdet_parts[0]);
10280 array_push($custvalues, trim(implode(':', $custdet_parts)));
10281 }
10282 if (count($custvalues) > 1) {
10283 break;
10284 }
10285 }
10286 if (count($custvalues) > 1) {
10287 $custdata = implode(' ', $custvalues);
10288 }
10289 }
10290 if (strlen($custdata) > 45) {
10291 $custdata = substr($custdata, 0, 45)." ...";
10292 }
10293
10294 // customer record details
10295 $customer = [];
10296 $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'];
10297 $dbo->setQuery($q, 0, 1);
10298 $dbo->execute();
10299 if ($dbo->getNumRows()) {
10300 $customer = $dbo->loadAssoc();
10301 if (!empty($customer['first_name'])) {
10302 $custdata = $customer['first_name'].' '.$customer['last_name'];
10303 if (!empty($customer['country'])) {
10304 if (file_exists(VBO_ADMIN_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'countries'.DIRECTORY_SEPARATOR.$customer['country'].'.png')) {
10305 $custdata .= '<img src="'.VBO_ADMIN_URI.'resources/countries/'.$customer['country'].'.png'.'" title="'.htmlspecialchars($customer['country']).'" class="vbo-country-flag vbo-country-flag-left"/>';
10306 }
10307 }
10308 }
10309 }
10310 $booking_infos[$k]['customer'] = $customer;
10311
10312 // check if a profile picture is available for the customer
10313 if (!empty($customer['pic'])) {
10314 $booking_avatar_src = strpos($customer['pic'], 'http') === 0 ? $customer['pic'] : VBO_SITE_URI . 'resources/uploads/' . $customer['pic'];
10315 $booking_avatar_alt = basename($booking_avatar_src);
10316 $booking_infos[$k]['avatar_src'] = $booking_avatar_src;
10317 $booking_infos[$k]['avatar_alt'] = $booking_avatar_alt;
10318 }
10319
10320 // whether this is a closure
10321 $booking_infos[$k]['closure'] = (int)$row['closure'];
10322 $booking_infos[$k]['closure_txt'] = $row['closure'] ? JText::translate('VBDBTEXTROOMCLOSED') : null;
10323
10324 // short customer information
10325 $custdata = JText::translate('VBDBTEXTROOMCLOSED') == $row['custdata'] ? '<span class="vbordersroomclosed">'.JText::translate('VBDBTEXTROOMCLOSED').'</span>' : $custdata;
10326 $booking_infos[$k]['cinfo'] = $custdata;
10327
10328 // formatted dates
10329 $booking_infos[$k]['ts'] = date(str_replace("/", $datesep, $df).' H:i', $row['ts']);
10330 $booking_infos[$k]['checkin'] = date(str_replace("/", $datesep, $df).' H:i', $row['checkin']);
10331 $booking_infos[$k]['checkout'] = date(str_replace("/", $datesep, $df).' H:i', $row['checkout']);
10332
10333 // short booking date, check-in, check-out date format
10334 $stay_info_in = getdate($row['checkin']);
10335 $stay_info_out = getdate($row['checkout']);
10336 $str_checkin = date('d', $row['checkin']);
10337 $str_checkin .= $stay_info_in['mon'] != $stay_info_out['mon'] ? ' ' . VikBooking::sayMonth($stay_info_in['mon'], $short = true) : '';
10338 $str_checkout = date('d', $row['checkout']) . ' ' . VikBooking::sayMonth($stay_info_out['mon'], $short = true);
10339 if ($stay_info_in['year'] != $stay_info_out['year'] || $stay_info_in['year'] != $current_y || $stay_info_out['year'] != $current_y) {
10340 $str_checkout .= ' ' . $stay_info_out['year'];
10341 }
10342 $booking_infos[$k]['checkin_short'] = $str_checkin;
10343 $booking_infos[$k]['checkout_short'] = $str_checkout;
10344 $booking_infos[$k]['book_date'] = date(str_replace("/", $datesep, $df), $row['ts']);
10345 $booking_infos[$k]['book_time'] = date('H:i', $row['ts']);
10346 }
10347
10348 if (!$booking_infos) {
10349 // output the error
10350 VBOHttpDocument::getInstance()->close(500, '2 - ' . JText::translate('VBOVWGETBKERRMISSDATA'));
10351 }
10352
10353 // output the JSON encoded response and exit
10354 VBOHttpDocument::getInstance()->json($booking_infos);
10355 }
10356
10357 public function switchRoomIndex() {
10358 //to be called via ajax
10359 $dbo = JFactory::getDBO();
10360 $bid = VikRequest::getInt('bid', '', 'request');
10361 $rid = VikRequest::getInt('rid', '', 'request');
10362 $old_rindex = VikRequest::getInt('old_rindex', '', 'request');
10363 $new_rindex = VikRequest::getInt('new_rindex', '', 'request');
10364 if (empty($bid) || empty($rid) || empty($old_rindex) || empty($new_rindex)) {
10365 echo 'e4j.error.#1 Missing Data';
10366 exit;
10367 }
10368 $q = "SELECT * FROM `#__vikbooking_ordersrooms` WHERE `idorder`=".$bid." AND `idroom`=".$rid." AND `roomindex`=".$old_rindex.";";
10369 $dbo->setQuery($q);
10370 $dbo->execute();
10371 if ($dbo->getNumRows() < 1) {
10372 echo 'e4j.error.#2 Record not found';
10373 exit;
10374 }
10375 $rows = $dbo->loadAssocList();
10376 $q = "UPDATE `#__vikbooking_ordersrooms` SET `roomindex`=".$new_rindex." WHERE `id`=".$rows[0]['id'].";";
10377 $dbo->setQuery($q);
10378 $dbo->execute();
10379 echo 'e4j.ok';
10380 exit;
10381 }
10382
10383 public function searchcustomer()
10384 {
10385 // to be called via ajax
10386 $dbo = JFactory::getDbo();
10387
10388 $kw = VikRequest::getString('kw', '', 'request');
10389 $nopin = VikRequest::getInt('nopin', '', 'request');
10390 $email = VikRequest::getInt('email', 0, 'request');
10391 $selector = VikRequest::getString('selector', 'vbo-custsearchres-entry', 'request');
10392 $no_script = VikRequest::getInt('no_script', 0, 'request');
10393
10394 if (!strlen($kw)) {
10395 VBOHttpDocument::getInstance()->close(200, '');
10396 }
10397
10398 if ($nopin > 0) {
10399 //page all bookings
10400 $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;";
10401 } elseif ($email > 0) {
10402 // page calendar for checking if an email exists
10403 $q = "SELECT `first_name`, `last_name`, `email` FROM `#__vikbooking_customers` WHERE `email`=".$dbo->quote($kw).";";
10404 } else {
10405 //page calendar
10406 $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;";
10407 }
10408 $dbo->setQuery($q);
10409 $customers = $dbo->loadAssocList();
10410
10411 if (!$customers) {
10412 VBOHttpDocument::getInstance()->close(200, '');
10413 }
10414
10415 if ($email > 0) {
10416 VBOHttpDocument::getInstance()->json($customers[0]);
10417 }
10418
10419 $cust_old_fields = array();
10420 $cstring_search = '<div class="vbo-custsearchres-inner">' . "\n";
10421 foreach ($customers as $k => $v) {
10422 $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";
10423 $cstring_search .= '<span class="vbo-custsearchres-cflag">';
10424 if (!empty($v['pic'])) {
10425 $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";
10426 } elseif (is_file(VBO_ADMIN_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'countries'.DIRECTORY_SEPARATOR.$v['country'].'.png')) {
10427 $cstring_search .= '<img src="'.VBO_ADMIN_URI.'resources/countries/'.$v['country'].'.png'.'" title="'.htmlspecialchars($v['country']).'" class="vbo-country-flag"/>'."\n";
10428 } else {
10429 $cstring_search .= '<i class="' . VikBookingIcons::i('globe') . '"></i>';
10430 }
10431 $cstring_search .= '</span>';
10432 $cstring_search .= '<span class="vbo-custsearchres-name" title="'.htmlspecialchars($v['email']).'">'.$v['first_name'].' '.$v['last_name'].'</span>'."\n";
10433 if (!($nopin > 0)) {
10434 $cstring_search .= '<span class="vbo-custsearchres-pin">'.$v['pin'].'</span>'."\n";
10435 }
10436 $cstring_search .= '</div>'."\n";
10437 if (!empty($v['cfields'])) {
10438 $oldfields = json_decode($v['cfields'], true);
10439 if (is_array($oldfields) && count($oldfields)) {
10440 $cust_old_fields[$v['id']] = $oldfields;
10441 }
10442 }
10443 }
10444 $cstring_search .= '</div>'."\n";
10445
10446 /**
10447 * Add the necessary JS code for the arrow navigation.
10448 */
10449 $cstring_search_js = '<script type="text/javascript">';
10450 $cstring_search_js .= '
10451 var vboCust = jQuery(".' . $selector . '");
10452 var vboCustSelected = null;
10453 jQuery(window).keydown(function(e) {
10454 if (e.which === 40) {
10455 if (vboCustSelected) {
10456 vboCustSelected.removeClass("' . $selector . '-highligthed");
10457 next = vboCustSelected.next();
10458 if (next.length > 0) {
10459 vboCustSelected = next.addClass("' . $selector . '-highligthed");
10460 } else {
10461 vboCustSelected = vboCust.eq(0).addClass("' . $selector . '-highligthed");
10462 }
10463 } else {
10464 vboCustSelected = vboCust.eq(0).addClass("' . $selector . '-highligthed");
10465 }
10466 } else if (e.which === 38) {
10467 if (vboCustSelected) {
10468 vboCustSelected.removeClass("' . $selector . '-highligthed");
10469 next = vboCustSelected.prev();
10470 if (next.length > 0) {
10471 vboCustSelected = next.addClass("' . $selector . '-highligthed");
10472 } else {
10473 vboCustSelected = vboCust.last().addClass("' . $selector . '-highligthed");
10474 }
10475 } else {
10476 vboCustSelected = vboCust.last().addClass("' . $selector . '-highligthed");
10477 }
10478 } else if (e.which === 13) {
10479 if (vboCustSelected) {
10480 vboCustSelected.trigger("click");
10481 }
10482 }
10483 });
10484 jQuery(".' . $selector . '").off("hover");
10485 jQuery(".' . $selector . '").hover(function() {
10486 if (vboCustSelected) {
10487 vboCustSelected.removeClass("' . $selector . '-highligthed");
10488 vboCustSelected = null;
10489 }
10490 vboCustSelected = jQuery(this).addClass("' . $selector . '-highligthed");
10491 }, function() {
10492 if (vboCustSelected) {
10493 vboCustSelected.removeClass("' . $selector . '-highligthed");
10494 vboCustSelected = null;
10495 }
10496 jQuery(this).removeClass("' . $selector . '-highligthed");
10497 });';
10498 $cstring_search_js .= '</script>';
10499
10500 if (!$no_script) {
10501 // append JS
10502 $cstring_search .= $cstring_search_js;
10503 }
10504
10505 VBOHttpDocument::getInstance()->json([($nopin > 0 ? '' : $cust_old_fields), $cstring_search]);
10506 }
10507
10508 public function sharesignaturelink() {
10509 //to be called via ajax
10510 $dbo = JFactory::getDBO();
10511 $response = array(
10512 'status' => 0,
10513 'error' => 'Generic Error'
10514 );
10515 $pbid = VikRequest::getInt('bid', '', 'request');
10516 $phow = VikRequest::getString('how', '', 'request');
10517 $pto = VikRequest::getString('to', '', 'request');
10518 $pcustomer = VikRequest::getInt('customer', '', 'request');
10519 $cpin = VikBooking::getCPinIstance();
10520 $customer_info = $cpin->getCustomerByID($pcustomer);
10521 if (!empty($pbid) && !empty($phow) && !empty($pto) && count($customer_info) > 0) {
10522 $q = "SELECT * FROM `#__vikbooking_orders` WHERE `id`=".(int)$pbid." AND `status`='confirmed' AND `checked` > 0;";
10523 $dbo->setQuery($q);
10524 $dbo->execute();
10525 if ($dbo->getNumRows() > 0) {
10526 $row = $dbo->loadAssoc();
10527
10528 $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'];
10529 if (VBOPlatformDetection::isWordPress()) {
10530 /**
10531 * @wponly Rewrite URI for front-end signature
10532 */
10533 $share_link = str_replace(JUri::root(), '', $share_link);
10534 $model = JModel::getInstance('vikbooking', 'shortcodes');
10535 $itemid = $model->all('post_id', $full = true);
10536 if (count($itemid)) {
10537 $share_link = JRoute::rewrite($share_link . "&Itemid={$itemid[0]->post_id}", false);
10538 }
10539 } else {
10540 /**
10541 * @joomlaonly
10542 */
10543 $best_menuitem_id = VikBooking::findProperItemIdType(['vikbooking', 'booking'], $row['lang']);
10544 if ($best_menuitem_id) {
10545 $share_base = str_replace(JUri::root(), '', $share_link);
10546 $share_link = VikBooking::externalroute($share_base, $xhtml = false, $best_menuitem_id);
10547 }
10548 }
10549
10550 $share_message = JText::sprintf('VBOSIGNSHAREMESSAGE', ltrim($customer_info['first_name'].' '.$customer_info['last_name']), $share_link, VikBooking::getFrontTitle());
10551 if ($phow == 'email') {
10552 $sender = VikBooking::getSenderMail();
10553 $vbo_app = VikBooking::getVboApplication();
10554 $vbo_app->sendMail($sender, $sender, $pto, $sender, JText::translate('VBOSIGNSHARESUBJECT'), $share_message, false);
10555 $response['status'] = 1;
10556 } elseif ($phow == 'sms') {
10557 $share_message = JText::sprintf('VBOSIGNSHAREMESSAGESMS', ltrim($customer_info['first_name'].' '.$customer_info['last_name']), $share_link, VikBooking::getFrontTitle());
10558 $sms_api = VikBooking::getSMSAPIClass();
10559 $sms_api_params = VikBooking::getSMSParams();
10560 if (!empty($sms_api) && file_exists(VBO_ADMIN_PATH.DIRECTORY_SEPARATOR.'smsapi'.DIRECTORY_SEPARATOR.$sms_api) && !empty($sms_api_params)) {
10561 require_once(VBO_ADMIN_PATH.DIRECTORY_SEPARATOR.'smsapi'.DIRECTORY_SEPARATOR.$sms_api);
10562 $sms_obj = new VikSmsApi(array(), $sms_api_params);
10563 $response_obj = $sms_obj->sendMessage($pto, $share_message);
10564 if ($sms_obj->validateResponse($response_obj)) {
10565 $response['status'] = 1;
10566 } else {
10567 $response['error'] = $sms_obj->getLog();
10568 }
10569 } else {
10570 $response['error'] = 'No SMS Provider Configured';
10571 }
10572 } else {
10573 $response['error'] = 'Invalid Sending Method';
10574 }
10575 } else {
10576 $response['error'] = 'Invalid Booking ID';
10577 }
10578 } else {
10579 $response['error'] = 'Empty values';
10580 }
10581
10582 echo json_encode($response);
10583 exit;
10584 }
10585
10586 public function dayselectioncount() {
10587 //to be called via ajax
10588 $tsinit = VikRequest::getString('dinit', '', 'request');
10589 $tsend = VikRequest::getString('dend', '', 'request');
10590 if (strlen($tsinit) > 0 && strlen($tsend) > 0) {
10591 $ptsinit=VikBooking::getDateTimestamp($tsinit, '0', '0');
10592 $ptsend=VikBooking::getDateTimestamp($tsend, '23', '59');
10593 $diff = $ptsend - $ptsinit;
10594 if ($diff >= 172800) {
10595 $datef = VikBooking::getDateFormat(true);
10596 if ($datef=="%d/%m/%Y") {
10597 $df = 'd-m-Y';
10598 } else {
10599 $df = 'Y-m-d';
10600 }
10601 //minimum 2 days for excluding some days
10602 $daysdiff = floor($diff / 86400);
10603 $infoinit = getdate($ptsinit);
10604 $select = '';
10605 $select .= '<div style="display: inline-block;"><select name="excludeday[]" multiple="multiple" size="'.($daysdiff > 8 ? 8 : $daysdiff).'" id="vboexclusion">';
10606 for($i = 0; $i <= $daysdiff; $i++) {
10607 $ts = $i > 0 ? mktime(0, 0, 0, $infoinit['mon'], ((int)$infoinit['mday'] + $i), $infoinit['year']) : $ptsinit;
10608 $infots = getdate($ts);
10609 $optval = $infots['mon'].'-'.$infots['mday'].'-'.$infots['year'];
10610 $select .= '<option value="'.$optval.'">'.date($df, $ts).'</option>';
10611 }
10612 $select .= '</select></div>';
10613 //excluded days of the week
10614 if ($daysdiff >= 14) {
10615 $select .= '<div style="display: inline-block; margin-left: 40px;"><select name="excludewdays[]" multiple="multiple" size="8" id="excludewdays" onchange="vboExcludeWDays();">';
10616 $select .= '<optgroup label="'.JText::translate('VBOEXCLWEEKD').'">';
10617 $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>';
10618 $select .= '</optgroup>';
10619 $select .= '</select></div>';
10620 }
10621 //
10622 echo $select;
10623 } else {
10624 echo '';
10625 }
10626 } else {
10627 echo '';
10628 }
10629 exit;
10630 }
10631
10632 public function createcheckindoc() {
10633 $cid = VikRequest::getVar('cid', array(0));
10634 $id = $cid[0];
10635
10636 $dbo = JFactory::getDBO();
10637 $mainframe = JFactory::getApplication();
10638 $vbo_tn = VikBooking::getTranslator();
10639 $lang = JFactory::getLanguage();
10640 $ptmpl = VikRequest::getString('tmpl', '', 'request');
10641 $psignature = VikRequest::getString('signature', '', 'request', VIKREQUEST_ALLOWRAW);
10642 $ppad_width = VikRequest::getInt('pad_width', '', 'request');
10643 $ppad_ratio = VikRequest::getInt('pad_ratio', '', 'request');
10644 $q = "SELECT * FROM `#__vikbooking_orders` WHERE `id`=".(int)$id." AND `status`='confirmed' AND `checked` > 0;";
10645 $dbo->setQuery($q);
10646 $dbo->execute();
10647 if ($dbo->getNumRows() < 1) {
10648 $mainframe->redirect('index.php');
10649 exit;
10650 }
10651 $row = $dbo->loadAssoc();
10652 if (!empty($row['lang'])) {
10653 if ($lang->getTag() != $row['lang']) {
10654 if (VBOPlatformDetection::isWordPress()) {
10655 $lang->load('com_vikbooking', VIKBOOKING_LANG, $row['lang'], true);
10656 } else {
10657 $lang->load('com_vikbooking', JPATH_SITE, $row['lang'], true);
10658 $lang->load('com_vikbooking', JPATH_ADMINISTRATOR, $row['lang'], true);
10659 $lang->load('joomla', JPATH_SITE, $row['lang'], true);
10660 $lang->load('joomla', JPATH_ADMINISTRATOR, $row['lang'], true);
10661 }
10662 }
10663 if ($vbo_tn->getDefaultLang() != $row['lang']) {
10664 // force the translation to start because contents should be translated
10665 $vbo_tn::$force_tolang = $row['lang'];
10666 }
10667 }
10668 $customer = array();
10669 $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'].";";
10670 $dbo->setQuery($q);
10671 $dbo->execute();
10672 if ($dbo->getNumRows() > 0) {
10673 $customer = $dbo->loadAssoc();
10674 if (!empty($customer['country'])) {
10675 if (file_exists(VBO_ADMIN_PATH.DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'countries'.DIRECTORY_SEPARATOR.$customer['country'].'.png')) {
10676 $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"/>';
10677 }
10678 }
10679 }
10680 if (!(count($customer) > 0)) {
10681 VikError::raiseWarning('', JText::translate('VBOCHECKINERRNOCUSTOMER'));
10682 $mainframe->redirect('index.php?option=com_vikbooking&task=newcustomer&checkin=1&bid='.$row['id'].($ptmpl == 'component' ? '&tmpl=component' : ''));
10683 exit;
10684 }
10685 $customer['pax_data'] = !empty($customer['pax_data']) ? json_decode($customer['pax_data'], true) : array();
10686 //check if the signature has been submitted
10687 $signature_data = '';
10688 $cont_type = '';
10689 if (!empty($psignature)) {
10690 //check whether the format is accepted
10691 if (strpos($psignature, 'image/png') !== false || strpos($psignature, 'image/jpeg') !== false || strpos($psignature, 'image/svg') !== false) {
10692 $parts = explode(';base64,', $psignature);
10693 $cont_type_parts = explode('image/', $parts[0]);
10694 $cont_type = $cont_type_parts[1];
10695 if (!empty($parts[1])) {
10696 $signature_data = base64_decode($parts[1]);
10697 }
10698 }
10699 }
10700 if (!empty($signature_data)) {
10701 //write file
10702 $sign_fname = $row['id'].'_'.$row['sid'].'_'.$customer['id'].'.'.$cont_type;
10703 $filepath = VBO_ADMIN_PATH . DIRECTORY_SEPARATOR . 'resources' . DIRECTORY_SEPARATOR . 'idscans' . DIRECTORY_SEPARATOR . $sign_fname;
10704 $fp = fopen($filepath, 'w+');
10705 $bytes = fwrite($fp, $signature_data);
10706 fclose($fp);
10707 if ($bytes !== false && $bytes > 0) {
10708 //update the signature in the DB
10709 $q = "UPDATE `#__vikbooking_customers_orders` SET `signature`=".$dbo->quote($sign_fname)." WHERE `idorder`=".(int)$row['id'].";";
10710 $dbo->setQuery($q);
10711 $dbo->execute();
10712 $customer['signature'] = $sign_fname;
10713 //resize image for screens with high resolution
10714 if ($ppad_ratio > 1) {
10715 $new_width = floor(($ppad_width / 2));
10716 $creativik = new vikResizer();
10717 $creativik->proportionalImage($filepath, $filepath, $new_width, $new_width);
10718 } else {
10719 /**
10720 * @wponly - trigger files mirroring
10721 */
10722 VikBookingLoader::import('update.manager');
10723 VikBookingUpdateManager::triggerUploadBackup($filepath);
10724 //
10725 }
10726 //
10727 } else {
10728 VikError::raiseWarning('', JText::translate('VBOERRSTORESIGNFILE'));
10729 }
10730 }
10731 //
10732 //generate PDF for check-in document by parsing the apposite template file
10733 $booking_rooms = array();
10734 $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'].";";
10735 $dbo->setQuery($q);
10736 $dbo->execute();
10737 if ($dbo->getNumRows() > 0) {
10738 $booking_rooms = $dbo->loadAssocList();
10739 if (!empty($row['lang'])) {
10740 $vbo_tn->translateContents($booking_rooms, '#__vikbooking_rooms', array('id' => 'idroom', 'room_name' => 'name'), array(), $row['lang']);
10741 }
10742 }
10743 if (!class_exists('TCPDF')) {
10744 require_once(VBO_SITE_PATH . DIRECTORY_SEPARATOR . "helpers" . DIRECTORY_SEPARATOR . "tcpdf" . DIRECTORY_SEPARATOR . 'tcpdf.php');
10745 }
10746 $usepdffont = is_file(VBO_SITE_PATH . DIRECTORY_SEPARATOR . "helpers" . DIRECTORY_SEPARATOR . "tcpdf" . DIRECTORY_SEPARATOR . "fonts" . DIRECTORY_SEPARATOR . "dejavusans.php") ? 'dejavusans' : 'helvetica';
10747
10748 /**
10749 * Trigger event to allow third party plugins to return a specific font name.
10750 *
10751 * @since 1.16.0 (J) - 1.6.0 (WP)
10752 */
10753 $custom_pdf_font = VBOFactory::getPlatform()->getDispatcher()->filter('onGetPdfFontNameVikBooking', [$usepdffont]);
10754 if (is_array($custom_pdf_font) && !empty($custom_pdf_font[0])) {
10755 $usepdffont = $custom_pdf_font[0];
10756 }
10757
10758 list($checkintpl, $pdfparams) = VikBooking::loadCheckinDocTmpl($row, $booking_rooms, $customer);
10759 $checkin_body = VikBooking::parseCheckinDocTemplate($checkintpl, $row, $booking_rooms, $customer);
10760 $pdffname = $row['id'] . '_' . $row['sid'] . '.pdf';
10761 $pathpdf = VBO_SITE_PATH . DIRECTORY_SEPARATOR . "helpers" . DIRECTORY_SEPARATOR . "checkins" . DIRECTORY_SEPARATOR . "generated" . DIRECTORY_SEPARATOR . $pdffname;
10762 if (file_exists($pathpdf)) @unlink($pathpdf);
10763 $pdf_page_format = is_array($pdfparams['pdf_page_format']) ? $pdfparams['pdf_page_format'] : constant($pdfparams['pdf_page_format']);
10764 $pdf = new TCPDF(constant($pdfparams['pdf_page_orientation']), constant($pdfparams['pdf_unit']), $pdf_page_format, true, 'UTF-8', false);
10765 $pdf->SetTitle(JText::translate('VBOCHECKINDOCTITLE'));
10766 //Header for each page of the pdf
10767 if ($pdfparams['show_header'] == 1 && count($pdfparams['header_data']) > 0) {
10768 $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]);
10769 }
10770 //header and footer fonts
10771 $pdf->setHeaderFont(array($usepdffont, '', $pdfparams['header_font_size']));
10772 $pdf->setFooterFont(array($usepdffont, '', $pdfparams['footer_font_size']));
10773 //margins
10774 $pdf->SetMargins(constant($pdfparams['pdf_margin_left']), constant($pdfparams['pdf_margin_top']), constant($pdfparams['pdf_margin_right']));
10775 $pdf->SetHeaderMargin(constant($pdfparams['pdf_margin_header']));
10776 $pdf->SetFooterMargin(constant($pdfparams['pdf_margin_footer']));
10777 //
10778 $pdf->SetAutoPageBreak(true, constant($pdfparams['pdf_margin_bottom']));
10779 $pdf->setImageScale(constant($pdfparams['pdf_image_scale_ratio']));
10780 $pdf->SetFont($usepdffont, '', (int)$pdfparams['body_font_size']);
10781 if ($pdfparams['show_header'] == 0 || !(count($pdfparams['header_data']) > 0)) {
10782 $pdf->SetPrintHeader(false);
10783 }
10784 if ($pdfparams['show_footer'] == 0) {
10785 $pdf->SetPrintFooter(false);
10786 }
10787 $pdf->AddPage();
10788 $pdf->writeHTML($checkin_body, true, false, true, false, '');
10789 $pdf->lastPage();
10790 $pdf->Output($pathpdf, 'F');
10791 if (!file_exists($pathpdf)) {
10792 VikError::raiseWarning('', JText::translate('VBOERRGENCHECKINDOC'));
10793 } else {
10794 $q = "UPDATE `#__vikbooking_customers_orders` SET `checkindoc`=".$dbo->quote($pdffname)." WHERE `idorder`=".(int)$row['id'].";";
10795 $dbo->setQuery($q);
10796 $dbo->execute();
10797 $mainframe->enqueueMessage(JText::translate('VBOGENCHECKINDOCSUCCESS'));
10798 /**
10799 * @wponly - trigger files mirroring
10800 */
10801 VikBookingLoader::import('update.manager');
10802 VikBookingUpdateManager::triggerUploadBackup($pathpdf);
10803 //
10804 }
10805 //
10806 /**
10807 * @wponly - this task is executed via Ajax for the Modal forms listener. We cannot redirect to tmpl=component
10808 */
10809 $mainframe->redirect('index.php?option=com_vikbooking&task=bookingcheckin&cid[]='.$row['id']);
10810 exit;
10811 }
10812
10813 public function updatebookingcheckin() {
10814 $cid = VikRequest::getVar('cid', array(0));
10815 $id = $cid[0];
10816
10817 $dbo = JFactory::getDbo();
10818 $app = JFactory::getApplication();
10819
10820 $ptmpl = VikRequest::getString('tmpl', '', 'request');
10821 $pnewtotpaid = VikRequest::getFloat('newtotpaid', 0, 'request');
10822 $pguests = VikRequest::getVar('guests', array());
10823 $pcomments = VikRequest::getString('comments', '', 'request', VIKREQUEST_ALLOWHTML);
10824 $pcheckin_action = VikRequest::getInt('checkin_action', '', 'request');
10825 $valid_actions = array(-1, 0, 1, 2);
10826 if (!in_array($pcheckin_action, $valid_actions)) {
10827 $app->redirect('index.php');
10828 exit;
10829 }
10830 $q = "SELECT * FROM `#__vikbooking_orders` WHERE `id`=".(int)$id." AND `status`='confirmed';";
10831 $dbo->setQuery($q);
10832 $dbo->execute();
10833 if ($dbo->getNumRows() < 1) {
10834 $app->redirect('index.php');
10835 exit;
10836 }
10837 $row = $dbo->loadAssoc();
10838 $q = "SELECT * FROM `#__vikbooking_customers_orders` WHERE `idorder`=".$row['id'].";";
10839 $dbo->setQuery($q);
10840 $dbo->execute();
10841 if ($dbo->getNumRows() < 1) {
10842 VikError::raiseWarning('', JText::translate('VBOCHECKINERRNOCUSTOMER'));
10843 $app->redirect('index.php?option=com_vikbooking&task=bookingcheckin&cid[]='.$row['id'].($ptmpl == 'component' ? '&tmpl=component' : ''));
10844 exit;
10845 }
10846 $custorder = $dbo->loadAssoc();
10847 //update checked status and new total paid
10848 $q = "UPDATE `#__vikbooking_orders` SET `checked`=".$pcheckin_action."".($pnewtotpaid > 0 ? ', `totpaid`='.$pnewtotpaid : '')." WHERE `id`=".$row['id'].";";
10849 $dbo->setQuery($q);
10850 $dbo->execute();
10851 // Booking History log for new amount paid (payment update)
10852 if ($pnewtotpaid > 0 && $pnewtotpaid > (float)$row['totpaid']) {
10853 $extra_data = new stdClass;
10854 $extra_data->amount_paid = ($pnewtotpaid - (float)$row['totpaid']);
10855 VikBooking::getBookingHistoryInstance()->setBid($row['id'])->setExtraData($extra_data)->store('PU', JText::sprintf('VBOPREVAMOUNTPAID', VikBooking::numberFormat((float)$row['totpaid'])));
10856 }
10857 //
10858 //Booking History
10859 $hist_type = 'A';
10860 if ($pcheckin_action < 0) {
10861 $hist_type = 'Z';
10862 } elseif ($pcheckin_action == 1) {
10863 $hist_type = 'B';
10864 } elseif ($pcheckin_action == 2) {
10865 $hist_type = 'C';
10866 }
10867 $user = JFactory::getUser();
10868 VikBooking::getBookingHistoryInstance()->setBid($row['id'])->store('R' . $hist_type, "({$user->name})");
10869 //
10870 //Guests Details
10871 $guests_details = array();
10872 list($pax_fields, $pax_fields_attributes) = VikBooking::getPaxFields();
10873 // grab also the fields for front-end pre check-in
10874 list($pre_pax_fields, $pre_pax_fields_attributes) = VikBooking::getPaxFields(true);
10875 //
10876 foreach ($pguests as $ind => $adults) {
10877 foreach ($adults as $aduind => $details) {
10878 foreach ($pax_fields as $key => $v) {
10879 if (isset($details[$key]) && ((is_scalar($details[$key]) && strlen($details[$key])) || !empty($details[$key]))) {
10880 if (!isset($guests_details[$ind])) {
10881 $guests_details[$ind] = array();
10882 }
10883 if (!isset($guests_details[$ind][$aduind])) {
10884 $guests_details[$ind][$aduind] = array();
10885 }
10886 $guests_details[$ind][$aduind][$key] = $details[$key];
10887 }
10888 }
10889 foreach ($pre_pax_fields as $key => $v) {
10890 if (isset($pax_fields[$key])) {
10891 // we must have parsed this back-end field already
10892 continue;
10893 }
10894 if (isset($details[$key]) && ((is_scalar($details[$key]) && strlen($details[$key])) || !empty($details[$key]))) {
10895 if (!isset($guests_details[$ind])) {
10896 $guests_details[$ind] = array();
10897 }
10898 if (!isset($guests_details[$ind][$aduind])) {
10899 $guests_details[$ind][$aduind] = array();
10900 }
10901 if (!isset($guests_details[$ind][$aduind][$key])) {
10902 $guests_details[$ind][$aduind][$key] = $details[$key];
10903 }
10904 }
10905 }
10906 }
10907 }
10908 if (count($guests_details)) {
10909 // current pax data may contain some extra information collected via front-end pre-checkin so we need to merge them
10910 $curpaxdata = json_decode($custorder['pax_data'], true);
10911 if (is_array($curpaxdata) && count($curpaxdata)) {
10912 foreach ($guests_details as $ind => $groom) {
10913 foreach ($groom as $aduind => $aduinfo) {
10914 if (isset($curpaxdata[$ind][$aduind])) {
10915 $guests_details[$ind][$aduind] = array_merge($curpaxdata[$ind][$aduind], $guests_details[$ind][$aduind]);
10916 // unset some default pax fields that were not specified now, or data cannot be deleted for guests
10917 foreach ($guests_details[$ind][$aduind] as $key => $det) {
10918 if (isset($pguests[$ind][$aduind][$key]) && empty($pguests[$ind][$aduind][$key])) {
10919 // this default pax field was specified as empty now, so we cannot merge it
10920 unset($guests_details[$ind][$aduind][$key]);
10921 }
10922 }
10923 }
10924 }
10925 }
10926 }
10927 //
10928 $q = "UPDATE `#__vikbooking_customers_orders` SET `pax_data`=".$dbo->quote(json_encode($guests_details))." WHERE `id`=".$custorder['id'].";";
10929 $dbo->setQuery($q);
10930 $dbo->execute();
10931 }
10932
10933 //'checked' status comments
10934 $q = "UPDATE `#__vikbooking_customers_orders` SET `comments`=".$dbo->quote($pcomments)." WHERE `id`=".$custorder['id'].";";
10935 $dbo->setQuery($q);
10936 $dbo->execute();
10937
10938 $app->enqueueMessage(JText::translate('VBOCHECKINSTATUSUPDATED'));
10939 $app->redirect('index.php?option=com_vikbooking&task=bookingcheckin&cid[]='.$row['id'].($pcheckin_action != $row['checked'] ? '&changed=1' : '').($ptmpl == 'component' ? '&tmpl=component' : ''));
10940 exit;
10941 }
10942
10943 public function alterbooking()
10944 {
10945 $dbo = JFactory::getDbo();
10946 $app = JFactory::getApplication();
10947 $user = JFactory::getUser();
10948
10949 $response = array(
10950 'esit' => 1,
10951 'message' => '',
10952 'vcm' => '',
10953 );
10954
10955 // must be a string as it may contain a dash
10956 $pidorder = VikRequest::getString('idorder', '', 'request');
10957 $pidorder = intval(str_replace('-', '', $pidorder));
10958
10959 $poldidroom = VikRequest::getInt('oldidroom', '', 'request');
10960 $pidroom = VikRequest::getInt('idroom', 0, 'request');
10961 $pfromdate = VikRequest::getString('fromdate', '', 'request');
10962 $ptodate = VikRequest::getString('todate', '', 'request');
10963 $pdebug = VikRequest::getInt('e4j_debug', 0, 'request');
10964 if ($pdebug == 1) {
10965 echo 'e4j.error.'.print_r($app->input->post->getArray(), true);
10966 exit;
10967 }
10968
10969 $nowdf = VikBooking::getDateFormat(true);
10970 if ($nowdf == "%d/%m/%Y") {
10971 $df = 'd/m/Y';
10972 } elseif ($nowdf == "%m/%d/%Y") {
10973 $df = 'm/d/Y';
10974 } else {
10975 $df = 'Y/m/d';
10976 }
10977 $pcheckinh = 0;
10978 $pcheckinm = 0;
10979 $pcheckouth = 0;
10980 $pcheckoutm = 0;
10981 $timeopst = VikBooking::getTimeOpenStore();
10982 if (is_array($timeopst)) {
10983 $opent = VikBooking::getHoursMinutes($timeopst[0]);
10984 $closet = VikBooking::getHoursMinutes($timeopst[1]);
10985 $pcheckinh = $opent[0];
10986 $pcheckinm = $opent[1];
10987 $pcheckouth = $closet[0];
10988 $pcheckoutm = $closet[1];
10989 }
10990 $info_tsto = getdate(strtotime($ptodate));
10991 $actualtsto = mktime(0, 0, 0, $info_tsto['mon'], ($info_tsto['mday'] + 1), $info_tsto['year']);
10992 $first = VikBooking::getDateTimestamp(date($df, strtotime($pfromdate)), $pcheckinh, $pcheckinm);
10993 $second = VikBooking::getDateTimestamp(date($df, $actualtsto), $pcheckouth, $pcheckoutm);
10994 $ptodate = date('Y-m-d', $second);
10995 if (!($second > $first)) {
10996 echo 'e4j.error.1 '.addslashes(JText::translate('VBOVWALTBKERRMISSDATA'));
10997 exit;
10998 }
10999 if (!($pidorder > 0) || !($pidroom > 0) || empty($pfromdate) || empty($ptodate)) {
11000 echo 'e4j.error.2 '.addslashes(JText::translate('VBOVWALTBKERRMISSDATA'));
11001 exit;
11002 }
11003
11004 $q = "SELECT * FROM `#__vikbooking_orders` WHERE `id`=" . $pidorder . " AND `status`='confirmed'";
11005 $dbo->setQuery($q, 0, 1);
11006 $dbo->execute();
11007 if (!$dbo->getNumRows()) {
11008 echo 'e4j.error.3 '.addslashes(JText::translate('VBOVWALTBKERRMISSDATA'));
11009 exit;
11010 }
11011 $ord = $dbo->loadAssoc();
11012
11013 $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;";
11014 $dbo->setQuery($q);
11015 $dbo->execute();
11016 $ordersrooms = $dbo->loadAssocList();
11017
11018 // store for VCM the current rooms before the modification
11019 $ord['rooms_info'] = $ordersrooms;
11020
11021 // package or custom rate
11022 $is_package = !empty($ord['pkg']) ? true : false;
11023 $is_cust_cost = false;
11024 foreach ($ordersrooms as $kor => $or) {
11025 if ($is_package !== true && !empty($or['cust_cost']) && $or['cust_cost'] > 0.00) {
11026 $is_cust_cost = true;
11027 break;
11028 }
11029 }
11030
11031 // availability helper
11032 $av_helper = VikBooking::getAvailabilityInstance();
11033
11034 // room stay dates in case of split stay
11035 $room_stay_dates = [];
11036 if ($ord['split_stay']) {
11037 // no need to get the transient based on booking status, as the booking must be confirmed
11038 $room_stay_dates = $av_helper->loadSplitStayBusyRecords($ord['id']);
11039 // immediately count the number of nights of stay for each split room
11040 foreach ($room_stay_dates as $sps_r_k => $sps_r_v) {
11041 $room_stay_dates[$sps_r_k]['nights'] = $av_helper->countNightsOfStay($sps_r_v['checkin'], $sps_r_v['checkout']);
11042 }
11043 }
11044
11045 // determine if dates have changed
11046 $dates_changed = false;
11047 if (date('Y-m-d', $ord['checkin']) != $pfromdate || date('Y-m-d', $ord['checkout']) != $ptodate) {
11048 $dates_changed = true;
11049 }
11050
11051 $toswitch = array();
11052 $idbooked = array();
11053 $rooms_units = array();
11054 $q = "SELECT `id`,`name`,`units` FROM `#__vikbooking_rooms`;";
11055 $dbo->setQuery($q);
11056 $dbo->execute();
11057 $all_rooms = $dbo->loadAssocList();
11058 foreach ($all_rooms as $rr) {
11059 $rooms_units[$rr['id']]['name'] = $rr['name'];
11060 $rooms_units[$rr['id']]['units'] = $rr['units'];
11061 }
11062
11063 // switch room
11064 if ($poldidroom != $pidroom) {
11065 foreach ($ordersrooms as $ind => $or) {
11066 if ($poldidroom == $or['idroom'] && array_key_exists($pidroom, $rooms_units)) {
11067 if (!isset($idbooked[$or['idroom']])) {
11068 $idbooked[$or['idroom']] = 0;
11069 }
11070 // $idbooked is not really needed as switch is never made for the same room id
11071 $idbooked[$or['idroom']]++;
11072 //
11073 $orkey = count($toswitch);
11074 $toswitch[$orkey]['from'] = $or['idroom'];
11075 $toswitch[$orkey]['to'] = $pidroom;
11076 $toswitch[$orkey]['record'] = $or;
11077 $toswitch[$orkey]['record_ind'] = $ind;
11078 break;
11079 }
11080 }
11081 }
11082 if (count($toswitch)) {
11083 foreach ($toswitch as $ksw => $rsw) {
11084 $plusunit = array_key_exists($rsw['to'], $idbooked) ? $idbooked[$rsw['to']] : 0;
11085 $room_checkin = $ord['checkin'];
11086 $room_checkout = $ord['checkout'];
11087 if ($ord['split_stay'] && count($room_stay_dates) && isset($room_stay_dates[$rsw['record_ind']]) && $room_stay_dates[$rsw['record_ind']]['idroom'] == $rsw['from']) {
11088 $room_checkin = $room_stay_dates[$rsw['record_ind']]['checkin'];
11089 $room_checkout = $room_stay_dates[$rsw['record_ind']]['checkout'];
11090 }
11091 if (!VikBooking::roomBookable($rsw['to'], ($rooms_units[$rsw['to']]['units'] + $plusunit), $room_checkin, $room_checkout)) {
11092 // the room is not available
11093 unset($toswitch[$ksw]);
11094 echo 'e4j.error.'.JText::sprintf('VBSWITCHRERR', $rsw['record']['name'], $rooms_units[$rsw['to']]['name']);
11095 exit;
11096 }
11097 }
11098 if (count($toswitch)) {
11099 //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)
11100 reset($ordersrooms);
11101 $q = "UPDATE `#__vikbooking_ordersrooms` SET `idtar`=NULL,`roomindex`=NULL,`room_cost`=NULL WHERE `id`=".$ordersrooms[0]['id'].";";
11102 $dbo->setQuery($q);
11103 $dbo->execute();
11104 //
11105 foreach ($toswitch as $ksw => $rsw) {
11106 // update room reservation record
11107 $q = "UPDATE `#__vikbooking_ordersrooms` SET `idroom`=" . $rsw['to'] . ",`idtar`=NULL,`roomindex`=NULL,`room_cost`=NULL WHERE `id`=" . $rsw['record']['id'] . ";";
11108 $dbo->setQuery($q);
11109 $dbo->execute();
11110 $response['message'] .= JText::sprintf('VBOVWALTBKSWITCHROK', $rsw['record']['name'], $rooms_units[$rsw['to']]['name'])."\n";
11111
11112 // update Notes field for this booking to keep track of the previous room that was assigned
11113 $prev_room_name = array_key_exists($rsw['from'], $rooms_units) ? $rooms_units[$rsw['from']]['name'] : '';
11114 if (!empty($prev_room_name)) {
11115 $new_notes = JText::sprintf('VBOPREVROOMMOVED', $prev_room_name, date($df.' H:i:s'))."\n".$ord['adminnotes'];
11116 $q = "UPDATE `#__vikbooking_orders` SET `adminnotes`=".$dbo->quote($new_notes)." WHERE `id`=".(int)$ord['id'].";";
11117 $dbo->setQuery($q);
11118 $dbo->execute();
11119 }
11120
11121 if ($ord['status'] == 'confirmed') {
11122 // update room record in _busy
11123 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'])) {
11124 // in case of a split stay it is fundamental to update the exact busy record ID
11125 $q = "UPDATE `#__vikbooking_busy` SET `idroom`=" . $rsw['to'] . " WHERE `id`=" . (int)$room_stay_dates[$rsw['record_ind']]['id'];
11126 $dbo->setQuery($q);
11127 $dbo->execute();
11128 } else {
11129 // regular processing of a room ID for a reservation, no matter which one, we switch it
11130 $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;";
11131 $dbo->setQuery($q);
11132 $dbo->execute();
11133 if ($dbo->getNumRows() == 1) {
11134 $cur_busy = $dbo->loadAssocList();
11135 $q = "UPDATE `#__vikbooking_busy` SET `idroom`=".$rsw['to']." WHERE `id`=".$cur_busy[0]['id']." AND `idroom`=".$cur_busy[0]['idroom']." LIMIT 1;";
11136 $dbo->setQuery($q);
11137 $dbo->execute();
11138 }
11139 }
11140
11141 // if automated updates enabled, keep $response['vcm'] empty
11142 // Invoke Channel Manager
11143 if (file_exists(VCM_SITE_PATH . DIRECTORY_SEPARATOR . "helpers" . DIRECTORY_SEPARATOR . "synch.vikbooking.php")) {
11144 $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>';
11145 }
11146 } elseif ($ord['status'] == 'standby') {
11147 // remove record in _tmplock
11148 $q = "DELETE FROM `#__vikbooking_tmplock` WHERE `idorder`=" . intval($ord['id']) . ";";
11149 $dbo->setQuery($q);
11150 $dbo->execute();
11151 }
11152 }
11153
11154 // check if sub-units should be assigned again when switching room
11155 if (!$dates_changed && !$ord['split_stay'] && VikBooking::autoRoomUnit()) {
11156 $new_order_rooms = VikBooking::loadOrdersRoomsData($ord['id']);
11157 $room_indexes_usemap = [];
11158 foreach ($new_order_rooms as $kor => $or) {
11159 $num = $kor + 1;
11160 // assign room specific unit
11161 $room_indexes = VikBooking::getRoomUnitNumsAvailable($ord, $or['idroom']);
11162 $use_ind_key = 0;
11163 if ($room_indexes) {
11164 if (!array_key_exists($or['idroom'], $room_indexes_usemap)) {
11165 $room_indexes_usemap[$or['idroom']] = $use_ind_key;
11166 } else {
11167 $use_ind_key = $room_indexes_usemap[$or['idroom']];
11168 }
11169 $q = "UPDATE `#__vikbooking_ordersrooms` SET `roomindex`=".(int)$room_indexes[$use_ind_key]." WHERE `id`=".(int)$or['id'].";";
11170 $dbo->setQuery($q);
11171 $dbo->execute();
11172 $room_indexes_usemap[$or['idroom']]++;
11173 }
11174 }
11175 }
11176
11177 // do not terminate the process when there is a switch, proceed to check the dates.
11178 }
11179 }
11180
11181 // change dates
11182 if ($dates_changed) {
11183 if ($ord['split_stay']) {
11184 // we do not allow to drag and change dates for rooms in a split stay reservation
11185 echo 'e4j.error.' . JText::sprintf('VBO_BOOK_SPLIT_STAY_CANNOTDRAG', $ord['id']);
11186 exit;
11187 }
11188
11189 // total nights of stay
11190 $daysdiff = $ord['days'];
11191
11192 // re-read ordersrooms (as rooms may have been switched)
11193 $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;";
11194 $dbo->setQuery($q);
11195 $dbo->execute();
11196 $ordersrooms = $dbo->loadAssocList();
11197
11198 $groupdays = VikBooking::getGroupDays($first, $second, $daysdiff);
11199 $opertwounits = true;
11200 $units_counter = array();
11201 foreach ($ordersrooms as $ind => $or) {
11202 if (!isset($units_counter[$or['idroom']])) {
11203 $units_counter[$or['idroom']] = -1;
11204 }
11205 $units_counter[$or['idroom']]++;
11206 }
11207
11208 foreach ($ordersrooms as $ind => $or) {
11209 $num = $ind + 1;
11210 $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'] . ";";
11211 $dbo->setQuery($check);
11212 $dbo->execute();
11213 if ($dbo->getNumRows() > 0) {
11214 $busy = $dbo->loadAssocList();
11215 foreach ($groupdays as $gday) {
11216 $bfound = 0;
11217 foreach ($busy as $bu) {
11218 if ($gday >= $bu['checkin'] && $gday <= $bu['realback']) {
11219 $bfound++;
11220 }
11221 }
11222 if ($bfound >= ($or['units'] - $units_counter[$or['idroom']]) || !VikBooking::roomNotLocked($or['idroom'], $or['units'], $first, $second)) {
11223 $opertwounits = false;
11224 break 2;
11225 }
11226 }
11227 }
11228 }
11229 if ($opertwounits !== true) {
11230 $response['esit'] = 0;
11231 $response['message'] = JText::translate('VBROOMNOTRIT')." ".date($df.' H:i', $first)." ".JText::translate('VBROOMNOTCONSTO')." ".date($df.' H:i', $second);
11232 echo json_encode($response);
11233 exit;
11234 }
11235
11236 // update dates and busy records
11237 $realback = VikBooking::getHoursRoomAvail() * 3600;
11238 $realback += $second;
11239 $q = "UPDATE `#__vikbooking_orders` SET `checkin`='".$first."', `checkout`='".$second."' WHERE `id`=".$ord['id'].";";
11240 $dbo->setQuery($q);
11241 $dbo->execute();
11242 if ($ord['status'] == 'confirmed') {
11243 $q = "SELECT `b`.`id` FROM `#__vikbooking_busy` AS `b`,`#__vikbooking_ordersbusy` AS `ob` WHERE `b`.`id`=`ob`.`idbusy` AND `ob`.`idorder`=".$ord['id'].";";
11244 $dbo->setQuery($q);
11245 $dbo->execute();
11246 $allbusy = $dbo->loadAssocList();
11247 foreach ($allbusy as $bb) {
11248 $q = "UPDATE `#__vikbooking_busy` SET `checkin`='".$first."', `checkout`='".$second."', `realback`='".$realback."' WHERE `id`='".$bb['id']."';";
11249 $dbo->setQuery($q);
11250 $dbo->execute();
11251 }
11252 // if automated updates enabled, keep $response['vcm'] empty
11253 // Invoke Channel Manager
11254 if (file_exists(VCM_SITE_PATH . DIRECTORY_SEPARATOR . "helpers" . DIRECTORY_SEPARATOR . "synch.vikbooking.php")) {
11255 $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>';
11256 }
11257 }
11258 $response['message'] .= JText::translate('RESUPDATED')."\n";
11259 }
11260
11261 if (count($toswitch)) {
11262 /**
11263 * Rooms have changed so the new rates must be re-calculated.
11264 * Maybe they should be calculated in any case, even if just
11265 * the dates have changed. For the moment the rates are reset.
11266 */
11267 }
11268
11269 // unset any previously booked room due to calendar sharing
11270 VikBooking::cleanSharedCalendarsBusy($ord['id']);
11271 // check if some of the rooms booked have shared calendars
11272 VikBooking::updateSharedCalendars($ord['id']);
11273 //
11274
11275 //Booking History
11276 VikBooking::getBookingHistoryInstance()->setBid($ord['id'])->store('MB', "({$user->name}) " . VikBooking::getLogBookingModification($ord));
11277 //
11278
11279 $vcm_autosync = VikBooking::vcmAutoUpdate();
11280 if ($vcm_autosync > 0 && !empty($response['vcm'])) {
11281 //unset the vcm property as no buttons should be displayed when in auto-sync
11282 $response['vcm'] = '';
11283 $vcm_obj = VikBooking::getVcmInvoker();
11284 $vcm_obj->setOids(array($ord['id']))->setSyncType('modify')->setOriginalBooking($ord);
11285 $sync_result = $vcm_obj->doSync();
11286 if ($sync_result === false) {
11287 $response['message'] .= JText::translate('VBCHANNELMANAGERRESULTKO')." (".$vcm_obj->getError().")\n";
11288 }
11289 }
11290
11291 // in case of error but not empty VCM message, set an error that will be displayed after the mustReload
11292 if ($response['esit'] < 1 && !empty($response['vcm'])) {
11293 VikError::raiseNotice('', $response['vcm']);
11294 }
11295
11296 $response['message'] = nl2br($response['message']);
11297 echo json_encode($response);
11298 exit;
11299 }
11300
11301 public function modroomrateplans() {
11302 $dbo = JFactory::getDBO();
11303 $session = JFactory::getSession();
11304 $updforvcm = $session->get('vbVcmRatesUpd', '');
11305 $updforvcm = empty($updforvcm) || !is_array($updforvcm) ? array() : $updforvcm;
11306 $pid_room = VikRequest::getInt('id_room', '', 'request');
11307 $pid_price = VikRequest::getInt('id_price', '', 'request');
11308 $ptype = VikRequest::getString('type', '', 'request');
11309 $pfromdate = VikRequest::getString('fromdate', '', 'request');
11310 $ptodate = VikRequest::getString('todate', '', 'request');
11311 if (empty($pid_room) || empty($pid_price) || empty($ptype) || empty($pfromdate) || empty($ptodate) || !(strtotime($pfromdate) > 0) || !(strtotime($ptodate) > 0)) {
11312 echo 'e4j.error.'.addslashes(JText::translate('VBRATESOVWERRMODRPLANS'));
11313 exit;
11314 }
11315 $price_record = array();
11316 $q = "SELECT * FROM `#__vikbooking_prices` WHERE `id`=".$pid_price.";";
11317 $dbo->setQuery($q);
11318 $dbo->execute();
11319 if ($dbo->getNumRows() > 0) {
11320 $price_record = $dbo->loadAssoc();
11321 }
11322 if (!count($price_record) > 0) {
11323 echo 'e4j.error.'.addslashes(JText::translate('VBRATESOVWERRMODRPLANS')).'.';
11324 exit;
11325 }
11326 $current_closed = array();
11327 if (!empty($price_record['closingd'])) {
11328 $current_closed = json_decode($price_record['closingd'], true);
11329 }
11330 $current_closed = !is_array($current_closed) ? array() : $current_closed;
11331 $start_ts = strtotime($pfromdate);
11332 $end_ts = strtotime($ptodate);
11333 $infostart = getdate($start_ts);
11334 $all_days = array();
11335 $output = array();
11336 while ($infostart[0] > 0 && $infostart[0] <= $end_ts) {
11337 $all_days[] = date('Y-m-d', $infostart[0]);
11338 $indkey = $infostart['mday'].'-'.$infostart['mon'].'-'.$infostart['year'].'-'.$pid_price;
11339 $output[$indkey] = array();
11340 $infostart = getdate(mktime(0, 0, 0, $infostart['mon'], ($infostart['mday'] + 1), $infostart['year']));
11341 }
11342 if ($ptype == 'close') {
11343 if (!array_key_exists($pid_room, $current_closed)) {
11344 $current_closed[$pid_room] = array();
11345 }
11346 foreach ($all_days as $daymod) {
11347 if (!in_array($daymod, $current_closed[$pid_room])) {
11348 $current_closed[$pid_room][] = $daymod;
11349 }
11350 }
11351 } else {
11352 //open
11353 if (array_key_exists($pid_room, $current_closed)) {
11354 foreach ($all_days as $daymod) {
11355 if (in_array($daymod, $current_closed[$pid_room])) {
11356 foreach ($current_closed[$pid_room] as $ck => $cv) {
11357 if ($daymod == $cv) {
11358 unset($current_closed[$pid_room][$ck]);
11359 }
11360 }
11361 }
11362 }
11363 } else {
11364 $current_closed[$pid_room] = array();
11365 }
11366 }
11367 if (!count($current_closed[$pid_room]) > 0) {
11368 unset($current_closed[$pid_room]);
11369 }
11370 $q = "UPDATE `#__vikbooking_prices` SET `closingd`=".(count($current_closed) > 0 ? $dbo->quote(json_encode($current_closed)) : "NULL")." WHERE `id`=".(int)$pid_price.";";
11371 $dbo->setQuery($q);
11372 $dbo->execute();
11373 $oldcsscls = $ptype == 'close' ? 'vbo-roverw-rplan-on' : 'vbo-roverw-rplan-off';
11374 $newcsscls = $ptype == 'close' ? 'vbo-roverw-rplan-off' : 'vbo-roverw-rplan-on';
11375 foreach ($output as $ok => $ov) {
11376 $output[$ok] = array('oldcls' => $oldcsscls, 'newcls' => $newcsscls);
11377 }
11378 //update session values
11379 $updforvcm['count'] = array_key_exists('count', $updforvcm) && !empty($updforvcm['count']) ? ($updforvcm['count'] + 1) : 1;
11380 if (array_key_exists('dfrom', $updforvcm) && !empty($updforvcm['dfrom'])) {
11381 $updforvcm['dfrom'] = $updforvcm['dfrom'] > $start_ts ? $start_ts : $updforvcm['dfrom'];
11382 } else {
11383 $updforvcm['dfrom'] = $start_ts;
11384 }
11385 if (array_key_exists('dto', $updforvcm) && !empty($updforvcm['dto'])) {
11386 $updforvcm['dto'] = $updforvcm['dto'] < $end_ts ? $end_ts : $updforvcm['dto'];
11387 } else {
11388 $updforvcm['dto'] = $end_ts;
11389 }
11390 if (array_key_exists('rooms', $updforvcm) && is_array($updforvcm['rooms'])) {
11391 if (!in_array($pid_room, $updforvcm['rooms'])) {
11392 $updforvcm['rooms'][] = $pid_room;
11393 }
11394 } else {
11395 $updforvcm['rooms'] = array($pid_room);
11396 }
11397 if (array_key_exists('rplans', $updforvcm) && is_array($updforvcm['rplans'])) {
11398 if (array_key_exists($pid_room, $updforvcm['rplans'])) {
11399 if (!in_array($pid_price, $updforvcm['rplans'][$pid_room])) {
11400 $updforvcm['rplans'][$pid_room][] = $pid_price;
11401 }
11402 } else {
11403 $updforvcm['rplans'][$pid_room] = array($pid_price);
11404 }
11405 } else {
11406 $updforvcm['rplans'] = array($pid_room => array($pid_price));
11407 }
11408 $session->set('vbVcmRatesUpd', $updforvcm);
11409 //
11410 $pdebug = VikRequest::getInt('e4j_debug', '', 'request');
11411 if ($pdebug == 1) {
11412 echo "e4j.error.\n".print_r($current_closed, true)."\n";
11413 echo print_r($output, true)."\n\n";
11414 echo print_r($all_days, true)."\n";
11415 }
11416 echo json_encode($output);
11417 exit;
11418 }
11419
11420 public function icsexportlaunch() {
11421 $dbo = JFactory::getDBO();
11422 $pcheckindate = VikRequest::getString('checkindate', '', 'request');
11423 $pcheckoutdate = VikRequest::getString('checkoutdate', '', 'request');
11424 $pstatus = VikRequest::getString('status', '', 'request');
11425 $validstatus = array('confirmed', 'standby', 'cancelled');
11426 $filterstatus = '';
11427 $filterfirst = 0;
11428 $filtersecond = 0;
11429 $nowdf = VikBooking::getDateFormat(true);
11430 if ($nowdf == "%d/%m/%Y") {
11431 $df = 'd/m/Y';
11432 } elseif ($nowdf == "%m/%d/%Y") {
11433 $df = 'm/d/Y';
11434 } else {
11435 $df = 'Y/m/d';
11436 }
11437 $currencyname = VikBooking::getCurrencyName();
11438 if (!empty($pstatus) && in_array($pstatus, $validstatus)) {
11439 $filterstatus = $pstatus;
11440 }
11441 if (!empty($pcheckindate)) {
11442 if (VikBooking::dateIsValid($pcheckindate)) {
11443 $first=VikBooking::getDateTimestamp($pcheckindate, '0', '0');
11444 $filterfirst = $first;
11445 }
11446 }
11447 if (!empty($pcheckoutdate)) {
11448 if (VikBooking::dateIsValid($pcheckoutdate)) {
11449 $second=VikBooking::getDateTimestamp($pcheckoutdate, '23', '59');
11450 if ($second > $first) {
11451 $filtersecond = $second;
11452 }
11453 }
11454 }
11455 $clause = array();
11456 if ($filterfirst > 0) {
11457 $clause[] = "`o`.`checkin` >= ".$filterfirst;
11458 }
11459 if ($filtersecond > 0) {
11460 $clause[] = "`o`.`checkout` <= ".$filtersecond;
11461 }
11462 if (!empty($filterstatus)) {
11463 $clause[] = "`o`.`status` = '".$filterstatus."'";
11464 }
11465 $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;";
11466 $dbo->setQuery($q);
11467 $dbo->execute();
11468 if ($dbo->getNumRows() > 0) {
11469 $orders = $dbo->loadAssocList();
11470 $icscontent = "BEGIN:VCALENDAR\n";
11471 $icscontent .= "VERSION:2.0\n";
11472 $icscontent .= "PRODID:-//e4j//VikBooking//EN\n";
11473 $icscontent .= "CALSCALE:GREGORIAN\n";
11474 $str = "";
11475 foreach ($orders as $kord => $ord) {
11476 if (isset($orders[($kord + 1)]) && $orders[($kord + 1)]['id'] == $ord['id']) {
11477 continue;
11478 }
11479 $usecurrencyname = $currencyname;
11480 $usecurrencyname = !empty($ord['idorderota']) && !empty($ord['chcurrency']) ? $ord['chcurrency'] : $usecurrencyname;
11481 $statusstr = '';
11482 if ($ord['status'] == 'confirmed') {
11483 $statusstr = JText::translate('VBCSVSTATUSCONFIRMED');
11484 } elseif ($ord['status'] == 'standby') {
11485 $statusstr = JText::translate('VBCSVSTATUSSTANDBY');
11486 } elseif ($ord['status'] == 'cancelled') {
11487 $statusstr = JText::translate('VBCSVSTATUSCANCELLED');
11488 }
11489 $uri = JURI::root().'index.php?option=com_vikbooking&view=booking&sid='.$ord['sid'].'&ts='.$ord['ts'];
11490 /**
11491 * @wponly Rewrite URI for front-end
11492 */
11493 $uri = str_replace(JUri::root(), '', $uri);
11494 $model = JModel::getInstance('vikbooking', 'shortcodes');
11495 $itemid = $model->best('booking');
11496 if ($itemid) {
11497 $uri = JRoute::rewrite($uri . "&Itemid={$itemid}", false);
11498 }
11499 //
11500 $ordnumbstr = $ord['id'].(!empty($ord['confirmnumber']) ? ' - '.$ord['confirmnumber'] : '').(!empty($ord['idorderota']) ? ' ('.ucwords($ord['channel']).')' : '').' - '.$statusstr;
11501 $peoplestr = ($ord['adults'] + $ord['children']).($ord['children'] > 0 ? ' ('.JText::translate('VBCSVCHILDREN').': '.$ord['children'].')' : '');
11502 $totalstring = ($ord['total'] > 0 ? ($usecurrencyname.' '.VikBooking::numberFormat($ord['total'])) : '');
11503 $totalpaidstring = ($ord['totpaid'] > 0 ? (' ('.VikBooking::numberFormat($ord['totpaid']).')') : '');
11504 $description = JText::sprintf('VBICSEXPDESCRIPTION', $ordnumbstr."\\n", $peoplestr."\\n", $ord['days']."\\n", $totalstring.$totalpaidstring."\\n", "\\n".str_replace("\n", "\\n", trim($ord['custdata'])));
11505 $str .= "BEGIN:VEVENT\n";
11506 $str .= "DTEND:" . JFactory::getDate(date('Y-m-d H:i:s', $ord['checkout']), date_default_timezone_get())->format('Ymd\THis\Z') . "\n";
11507 $str .= "UID:" . uniqid() . "\n";
11508 $str .= "DTSTAMP:" . JFactory::getDate(date('Y-m-d H:i:s'), date_default_timezone_get())->format('Ymd\THis\Z') . "\n";
11509 $str .= ((strlen($description) > 0 ) ? "DESCRIPTION:".preg_replace('/([\,;])/','\\\$1', $description)."\n" : "");
11510 $str .= "URL;VALUE=URI:" . preg_replace('/([\,;])/','\\\$1', $uri) . "\n";
11511 $str .= "SUMMARY:" . JText::sprintf('VBICSEXPSUMMARY', date($df, $ord['checkin'])) . "\n";
11512 $str .= "DTSTART:" . JFactory::getDate(date('Y-m-d H:i:s', $ord['checkin']), date_default_timezone_get())->format('Ymd\THis\Z') . "\n";
11513 $str .= "END:VEVENT\n";
11514 }
11515 $icscontent .= $str;
11516 $icscontent .= "END:VCALENDAR\n";
11517 //download file from buffer
11518 header("Content-Type: application/octet-stream; ");
11519 header("Cache-Control: no-store, no-cache");
11520 header('Content-Disposition: attachment; filename="bookings_export.ics"');
11521 $f = fopen('php://output', "w");
11522 fwrite($f, $icscontent);
11523 fclose($f);
11524 exit;
11525 } else {
11526 VikError::raiseWarning('', JText::translate('VBICSEXPNORECORDS'));
11527 $mainframe = JFactory::getApplication();
11528 $mainframe->redirect("index.php?option=com_vikbooking&task=icsexportprepare&checkindate=".$pcheckindate."&checkoutdate=".$pcheckoutdate."&status=".$pstatus."&tmpl=component");
11529 }
11530 }
11531
11532 public function csvexportlaunch()
11533 {
11534 $dbo = JFactory::getDbo();
11535 $app = JFactory::getApplication();
11536
11537 $pdatefilt = VikRequest::getString('datefilt', '', 'request');
11538 $proomfilt = VikRequest::getString('roomfilt', '', 'request');
11539 $pchfilt = VikRequest::getString('chfilt', '', 'request');
11540 $ppayfilt = VikRequest::getString('payfilt', '', 'request');
11541 $pcheckindate = VikRequest::getString('checkindate', '', 'request');
11542 $pcheckoutdate = VikRequest::getString('checkoutdate', '', 'request');
11543 $pstatus = VikRequest::getString('status', '', 'request');
11544 $pcatfilt = VikRequest::getInt('catfilt', 0, 'request');
11545 $pformat = VikRequest::getString('format', 'csv', 'request');
11546
11547 // let the report class (a generic one) generate the CSV file in the proper format
11548 $report_obj = VikBooking::getReportInstance('revenue')->setExportCSVFormat($pformat);
11549
11550 $validstatus = array('confirmed', 'standby', 'cancelled');
11551 $validdates = array('ts', 'checkin', 'checkout');
11552
11553 $filterdate = '';
11554 $filterstatus = '';
11555 $first = 0;
11556 $filterfirst = 0;
11557 $filtersecond = 0;
11558 $nowdf = VikBooking::getDateFormat(true);
11559 if ($nowdf == "%d/%m/%Y") {
11560 $df = 'd/m/Y';
11561 } elseif ($nowdf == "%m/%d/%Y") {
11562 $df = 'm/d/Y';
11563 } else {
11564 $df = 'Y/m/d';
11565 }
11566 $datesep = VikBooking::getDateSeparator(true);
11567 $currencyname = VikBooking::getCurrencyName();
11568
11569 if (!empty($pstatus) && in_array($pstatus, $validstatus)) {
11570 $filterstatus = $pstatus;
11571 }
11572 if (!empty($pdatefilt) && in_array($pdatefilt, $validdates)) {
11573 $filterdate = $pdatefilt;
11574 }
11575 if (!empty($pcheckindate) && !empty($filterdate)) {
11576 if (VikBooking::dateIsValid($pcheckindate)) {
11577 $first = VikBooking::getDateTimestamp($pcheckindate, '0', '0');
11578 $filterfirst = $first;
11579 }
11580 }
11581 if (!empty($pcheckoutdate) && !empty($filterdate)) {
11582 if (VikBooking::dateIsValid($pcheckoutdate)) {
11583 $second = VikBooking::getDateTimestamp($pcheckoutdate, '23', '59');
11584 if ($second > $first) {
11585 $filtersecond = $second;
11586 }
11587 }
11588 }
11589 $clause = array();
11590 if ($filterfirst > 0) {
11591 $clause[] = "`o`.`".$filterdate."` >= ".$filterfirst;
11592 }
11593 if ($filtersecond > 0) {
11594 $clause[] = "`o`.`".$filterdate."` <= ".$filtersecond;
11595 }
11596 if (!empty($filterstatus)) {
11597 $clause[] = "`o`.`status` = '".$filterstatus."'";
11598 }
11599 if (!empty($pchfilt)) {
11600 $clause[] = "`o`.`channel` LIKE ".$dbo->quote("%".$pchfilt."%");
11601 }
11602 if (!empty($ppayfilt)) {
11603 $clause[] = "`o`.`idpayment` LIKE '".$ppayfilt."=%'";
11604 }
11605 if (!empty($proomfilt)) {
11606 $clause[] = "`or`.`idroom` = '".(int)$proomfilt."'";
11607 }
11608
11609 if (!empty($pcatfilt)) {
11610 $room_cat_ids = array();
11611 $q = "SELECT `id`,`idcat` FROM `#__vikbooking_rooms` WHERE `idcat` LIKE " . $dbo->quote("%$pcatfilt%");
11612 $dbo->setQuery($q);
11613 $dbo->execute();
11614 if ($dbo->getNumRows()) {
11615 $records = $dbo->loadAssocList();
11616 foreach ($records as $rcat) {
11617 $parts = explode(';', $rcat['idcat']);
11618 if (in_array($pcatfilt, $parts)) {
11619 $room_cat_ids[] = $rcat['id'];
11620 }
11621 }
11622 }
11623 if (count($room_cat_ids)) {
11624 $clause[] = "`or`.`idroom` IN (" . implode(', ', $room_cat_ids) . ")";
11625 }
11626 }
11627
11628 $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;";
11629 $dbo->setQuery($q);
11630 $orders = $dbo->loadAssocList();
11631 if (!$orders) {
11632 $app->enqueueMessage(JText::translate('VBCSVEXPNORECORDS'), 'error');
11633 $app->redirect("index.php?option=com_vikbooking&task=csvexportprepare&checkindate=".$pcheckindate."&checkoutdate=".$pcheckoutdate."&status=".$pstatus."&tmpl=component");
11634 $app->close();
11635 }
11636
11637 // options
11638 $all_options = array();
11639 $q = "SELECT * FROM `#__vikbooking_optionals` ORDER BY `#__vikbooking_optionals`.`ordering` ASC;";
11640 $dbo->setQuery($q);
11641 $options = $dbo->loadAssocList();
11642 if ($options) {
11643 foreach ($options as $ok => $ov) {
11644 $all_options[$ov['id']] = $ov;
11645 }
11646 }
11647
11648 // set CSV columns
11649 $report_obj->setReportCols([
11650 [
11651 'label' => JText::translate('VBDASHBOOKINGID'),
11652 ],
11653 [
11654 'label' => JText::translate('VBPVIEWORDERSONE'),
11655 ],
11656 [
11657 'label' => JText::translate('VBCSVCHECKIN'),
11658 ],
11659 [
11660 'label' => JText::translate('VBCSVCHECKOUT'),
11661 ],
11662 [
11663 'label' => JText::translate('VBCSVNIGHTS'),
11664 ],
11665 [
11666 'label' => JText::translate('VBCSVROOM'),
11667 ],
11668 [
11669 'label' => JText::translate('VBCSVPEOPLE'),
11670 ],
11671 [
11672 'label' => JText::translate('VBCSVCUSTINFO'),
11673 ],
11674 [
11675 'label' => JText::translate('ORDER_SPREQUESTS'),
11676 ],
11677 [
11678 'label' => JText::translate('ORDER_NOTES'),
11679 ],
11680 [
11681 'label' => JText::translate('VBCSVCREATEDBY'),
11682 ],
11683 [
11684 'label' => JText::translate('VBCSVCUSTMAIL'),
11685 ],
11686 [
11687 'label' => JText::translate('ORDER_PHONE'),
11688 ],
11689 [
11690 'label' => JText::translate('VBCSVOPTIONS'),
11691 ],
11692 [
11693 'label' => JText::translate('VBCSVPAYMENTMETHOD'),
11694 ],
11695 [
11696 'label' => JText::translate('VBCSVORDIDCONFNUMB'),
11697 ],
11698 [
11699 'label' => JText::translate('VBCSVEXPFILTBSTATUS'),
11700 ],
11701 [
11702 'label' => JText::translate('VBCSVTOTAL'),
11703 ],
11704 [
11705 'label' => JText::translate('VBCSVTOTPAID'),
11706 ],
11707 [
11708 'label' => JText::translate('VBCSVTOTTAXES'),
11709 ],
11710 ]);
11711
11712 // prepare the container for the CSV rows
11713 $orderscsv = [];
11714
11715 // availability helper
11716 $av_helper = VikBooking::getAvailabilityInstance();
11717
11718 $room_inds = [];
11719 $room_stay_dates = [];
11720 foreach ($orders as $kord => $ord) {
11721 // room index in this booking
11722 if (!isset($room_inds[$ord['id']])) {
11723 $room_inds[$ord['id']] = -1;
11724 }
11725 $room_inds[$ord['id']]++;
11726
11727 /**
11728 * Split stay reservation.
11729 *
11730 * @since 1.16.0 (J) - 1.6.0 (WP)
11731 */
11732 $room_stay_dates = $room_inds[$ord['id']] > 0 ? $room_stay_dates : [];
11733 if ($ord['split_stay']) {
11734 if ($ord['status'] == 'confirmed') {
11735 $room_stay_dates = $av_helper->loadSplitStayBusyRecords($ord['id']);
11736 } else {
11737 $room_stay_dates = VBOFactory::getConfig()->getArray('split_stay_' . $ord['id'], []);
11738 }
11739 // immediately count the number of nights of stay for each split room
11740 foreach ($room_stay_dates as $sps_r_k => $sps_r_v) {
11741 if (!empty($sps_r_v['checkin_ts']) && !empty($sps_r_v['checkout_ts'])) {
11742 // overwrite values for compatibility with non-confirmed bookings
11743 $sps_r_v['checkin'] = $sps_r_v['checkin_ts'];
11744 $sps_r_v['checkout'] = $sps_r_v['checkout_ts'];
11745 }
11746 $sps_r_v['nights'] = $av_helper->countNightsOfStay($sps_r_v['checkin'], $sps_r_v['checkout']);
11747 // overwrite the whole array
11748 $room_stay_dates[$sps_r_k] = $sps_r_v;
11749 }
11750 }
11751
11752 // determine nights and dates for this room booking
11753 $booking_nights = $ord['days'];
11754 $booking_checkin = $ord['checkin'];
11755 $booking_checkout = $ord['checkout'];
11756 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']) {
11757 $booking_nights = $room_stay_dates[$room_inds[$ord['id']]]['nights'];
11758 $booking_checkin = $room_stay_dates[$room_inds[$ord['id']]]['checkin'];
11759 $booking_checkout = $room_stay_dates[$room_inds[$ord['id']]]['checkout'];
11760 }
11761
11762 $usecurrencyname = $currencyname;
11763 $usecurrencyname = !empty($ord['idorderota']) && !empty($ord['chcurrency']) ? $ord['chcurrency'] : $usecurrencyname;
11764 $peoplestr = ($ord['adults'] + $ord['children']).($ord['children'] > 0 ? ' ('.JText::translate('VBCSVCHILDREN').': '.$ord['children'].')' : '');
11765 $custinfostr = str_replace(",", " ", $ord['custdata']);
11766 $customer = VikBooking::getCPinIstance()->getCustomerFromBooking($ord['id']);
11767 if (count($customer)) {
11768 $custinfostr = $customer['first_name'] . ' ' . $customer['last_name'];
11769 }
11770 $special_requests = '';
11771 if (preg_match("/(?:special requests:\s*)(.*?)$/is", $ord['custdata'], $match)) {
11772 $special_requests = $match[1];
11773 } elseif (preg_match("/(?:special request:\s*)(.*?)$/is", $ord['custdata'], $match)) {
11774 $special_requests = $match[1];
11775 } elseif (preg_match("/(?:special request\s*)(.*?)$/is", $ord['custdata'], $match)) {
11776 $special_requests = $match[1];
11777 } elseif (preg_match("/(?:" . JText::translate('ORDER_SPREQUESTS') . ":\s*)(.*?)$/is", $ord['custdata'], $match)) {
11778 $special_requests = $match[1];
11779 }
11780 $paystr = '';
11781 if (!empty($ord['idpayment'])) {
11782 $payparts = explode('=', $ord['idpayment']);
11783 $paystr = $payparts[1];
11784 }
11785 $ordnumbstr = $ord['id'].' - '.$ord['confirmnumber'].(!empty($ord['idorderota']) ? ' ('.ucwords($ord['channel']).')' : '');
11786 $statusstr = '';
11787 if ($ord['status'] == 'confirmed') {
11788 $statusstr = JText::translate('VBCSVSTATUSCONFIRMED');
11789 } elseif ($ord['status'] == 'standby') {
11790 $statusstr = JText::translate('VBCSVSTATUSSTANDBY');
11791 } elseif ($ord['status'] == 'cancelled') {
11792 $statusstr = JText::translate('VBCSVSTATUSCANCELLED');
11793 }
11794 $totalstring = $usecurrencyname . ' ' . VikBooking::numberFormat($ord['total']);
11795 if ($ord['roomsnum'] > 1) {
11796 // take the cost for the individual room
11797 $totalstring = !empty($ord['cust_cost']) && $ord['cust_cost'] > 0 ? ($usecurrencyname . ' ' . VikBooking::numberFormat($ord['cust_cost'])) : ($usecurrencyname . ' ' . VikBooking::numberFormat($ord['room_cost']));
11798 }
11799 $totalpaidstring = $usecurrencyname . ' ' . VikBooking::numberFormat($ord['totpaid']);
11800 if (isset($orders[($kord + 1)]) && $orders[($kord + 1)]['id'] == $ord['id']) {
11801 // total paid will be printed only for the last room booked
11802 $totalpaidstring = '';
11803 }
11804 $options_str = '';
11805 if (!empty($ord['optionals'])) {
11806 $stepo = explode(";", $ord['optionals']);
11807 foreach ($stepo as $roptkey => $oo) {
11808 if (!empty($oo)) {
11809 $stept = explode(":", $oo);
11810 if (array_key_exists($stept[0], $all_options)) {
11811 $actopt = $all_options[$stept[0]];
11812 $optpcent = false;
11813 if (!empty($actopt['ageintervals']) && $ord['children'] > 0 && strstr($stept[1], '-') != false) {
11814 $optagenames = VikBooking::getOptionIntervalsAges($actopt['ageintervals']);
11815 $optagepcent = VikBooking::getOptionIntervalsPercentage($actopt['ageintervals']);
11816 $optageovrct = VikBooking::getOptionIntervalChildOverrides($actopt, $ord['adults'], $ord['children']);
11817 $child_num = VikBooking::getRoomOptionChildNumber($ord['optionals'], $actopt['id'], $roptkey, $ord['children']);
11818 $optagecosts = VikBooking::getOptionIntervalsCosts(isset($optageovrct['ageintervals_child' . ($child_num + 1)]) ? $optageovrct['ageintervals_child' . ($child_num + 1)] : $actopt['ageintervals']);
11819 $agestept = explode('-', $stept[1]);
11820 $stept[1] = $agestept[0];
11821 $chvar = $agestept[1];
11822 if (array_key_exists(($chvar - 1), $optagepcent) && $optagepcent[($chvar - 1)] > 0) {
11823 $optpcent = true;
11824 }
11825 $actopt['chageintv'] = $chvar;
11826 if (isset($optagenames[($chvar - 1)])) {
11827 $actopt['name'] .= ' ('.$optagenames[($chvar - 1)].')';
11828 }
11829 if (isset($optagecosts[($chvar - 1)])) {
11830 $realcost = (intval($actopt['perday']) == 1 ? (floatval($optagecosts[($chvar - 1)]) * $booking_nights * $stept[1]) : (floatval($optagecosts[($chvar - 1)]) * $stept[1]));
11831 } else {
11832 $realcost = 0;
11833 }
11834 } else {
11835 // VBO 1.11 - options percentage cost of the room total fee
11836 $optpcent = (int)$actopt['pcentroom'] ? true : $optpcent;
11837 //
11838 $realcost = (intval($actopt['perday']) == 1 ? ($actopt['cost'] * $booking_nights * $stept[1]) : ($actopt['cost'] * $stept[1]));
11839 }
11840 if ($actopt['maxprice'] > 0 && $realcost > $actopt['maxprice']) {
11841 $realcost=$actopt['maxprice'];
11842 if (intval($actopt['hmany']) == 1 && intval($stept[1]) > 1) {
11843 $realcost = $actopt['maxprice'] * $stept[1];
11844 }
11845 }
11846 $realcost = $actopt['perperson'] == 1 ? ($realcost * $ord['adults']) : $realcost;
11847 $tmpopr = VikBooking::sayOptionalsPlusIva($realcost, $actopt['idiva']);
11848 $options_str .= ($stept[1] > 1 ? $stept[1]." " : "").$actopt['name'].": ".(!$optpcent ? $currencyname : '')." ".VikBooking::numberFormat($tmpopr).($optpcent ? ' %' : '')." \r\n";
11849 }
11850 }
11851 }
11852 }
11853
11854 // custom extra costs
11855 if (!empty($ord['extracosts'])) {
11856 $cur_extra_costs = json_decode($ord['extracosts'], true);
11857 foreach ($cur_extra_costs as $eck => $ecv) {
11858 $ecplustax = !empty($ecv['idtax']) ? VikBooking::sayOptionalsPlusIva($ecv['cost'], $ecv['idtax']) : $ecv['cost'];
11859 $options_str .= $ecv['name'].": ".$currencyname." ".VikBooking::numberFormat($ecplustax)." \r\n";
11860 }
11861 }
11862
11863 // taxes
11864 $taxes_str = '';
11865 if ($ord['tot_taxes'] > 0.00) {
11866 $taxes_str .= $usecurrencyname.' '.VikBooking::numberFormat($ord['tot_taxes']);
11867 if (!empty($ord['aliq']) && !empty($ord['breakdown'])) {
11868 $tax_breakdown = json_decode($ord['breakdown'], true);
11869 $tax_breakdown = is_array($tax_breakdown) && count($tax_breakdown) > 0 ? $tax_breakdown : array();
11870 if (count($tax_breakdown)) {
11871 foreach ($tax_breakdown as $tbkk => $tbkv) {
11872 $tax_break_cost = $ord['tot_taxes'] * floatval($tbkv['aliq']) / $ord['aliq'];
11873 $taxes_str .= "\r\n".$tbkv['name'].": ".$usecurrencyname.' '.VikBooking::numberFormat($tax_break_cost);
11874 }
11875 }
11876 }
11877 }
11878 if (isset($orders[($kord + 1)]) && $orders[($kord + 1)]['id'] == $ord['id']) {
11879 // total taxes will be printed only for the last room booked
11880 $taxes_str = '';
11881 }
11882
11883 // created by
11884 $created_by = '';
11885 if (!empty($ord['ujid'])) {
11886 $creator = new JUser($ord['ujid']);
11887 if (property_exists($creator, 'name')) {
11888 $created_by = $creator->name.' ('.$creator->username.')';
11889 }
11890 }
11891 if (empty($created_by) && !empty($ord['t_first_name'])) {
11892 $created_by = $ord['t_first_name'].' '.$ord['t_last_name'];
11893 }
11894
11895 // push line for export
11896 $orderscsv[] = [
11897 [
11898 'value' => $ord['id'],
11899 ],
11900 [
11901 'value' => date(str_replace("/", $datesep, $df), $ord['ts']),
11902 ],
11903 [
11904 'value' => date(str_replace("/", $datesep, $df), $booking_checkin),
11905 ],
11906 [
11907 'value' => date(str_replace("/", $datesep, $df), $booking_checkout),
11908 ],
11909 [
11910 'value' => $booking_nights,
11911 ],
11912 [
11913 'value' => $ord['name'],
11914 ],
11915 [
11916 'value' => $peoplestr,
11917 ],
11918 [
11919 'value' => $custinfostr,
11920 ],
11921 [
11922 'value' => $special_requests,
11923 ],
11924 [
11925 'value' => $ord['adminnotes'],
11926 ],
11927 [
11928 'value' => $created_by,
11929 ],
11930 [
11931 'value' => $ord['custmail'],
11932 ],
11933 [
11934 'value' => $ord['phone'],
11935 ],
11936 [
11937 'value' => $options_str,
11938 ],
11939 [
11940 'value' => $paystr,
11941 ],
11942 [
11943 'value' => $ordnumbstr,
11944 ],
11945 [
11946 'value' => $statusstr,
11947 ],
11948 [
11949 'value' => $totalstring,
11950 ],
11951 [
11952 'value' => $totalpaidstring,
11953 ],
11954 [
11955 'value' => $taxes_str,
11956 ],
11957 ];
11958 }
11959
11960 // set CSV rows
11961 $report_obj->setReportRows($orderscsv);
11962
11963 // build lines to export
11964 $csvlines = $report_obj->getExportCSVLines($no_data = true);
11965
11966 // set export file name
11967 $report_obj->setExportCSVFileName('bookings_export_' . date('Y-m-d') . '.csv');
11968
11969 // force the download of the CSV file
11970 $report_obj->outputHeaders();
11971
11972 // send lines to output
11973 $report_obj->outputCSV($csvlines);
11974
11975 exit;
11976 }
11977
11978 public function exportcustomerslaunch() {
11979 $cid = VikRequest::getVar('cid', array(0));
11980 $dbo = JFactory::getDBO();
11981 $pnotes = VikRequest::getInt('notes', '', 'request');
11982 $pscanimg = VikRequest::getInt('scanimg', '', 'request');
11983 $ppin = VikRequest::getInt('pin', '', 'request');
11984 $pcountry = VikRequest::getString('country', '', 'request');
11985 $pfromdate = VikRequest::getString('fromdate', '', 'request');
11986 $ptodate = VikRequest::getString('todate', '', 'request');
11987 $pdatefilt = VikRequest::getInt('datefilt', '', 'request');
11988 $clauses = array();
11989 if (count($cid) > 0 && !empty($cid[0])) {
11990 $clauses[] = "`c`.`id` IN (".implode(', ', $cid).")";
11991 }
11992 if (!empty($pcountry)) {
11993 $clauses[] = "`c`.`country`=".$dbo->quote($pcountry);
11994 }
11995 $datescol = '`bk`.`ts`';
11996 if ($pdatefilt > 0) {
11997 if ($pdatefilt == 1) {
11998 $datescol = '`bk`.`ts`';
11999 } elseif ($pdatefilt == 2) {
12000 $datescol = '`bk`.`checkin`';
12001 } elseif ($pdatefilt == 3) {
12002 $datescol = '`bk`.`checkout`';
12003 }
12004 }
12005 if (!empty($pfromdate)) {
12006 $from_ts = VikBooking::getDateTimestamp($pfromdate, 0, 0);
12007 $clauses[] = $datescol.">=".$from_ts;
12008 }
12009 if (!empty($ptodate)) {
12010 $to_ts = VikBooking::getDateTimestamp($ptodate, 23, 59);
12011 $clauses[] = $datescol."<=".$to_ts;
12012 }
12013 //this query below is safe with the error #1055 when sql_mode=only_full_group_by
12014 $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`,".
12015 "(SELECT COUNT(*) FROM `#__vikbooking_customers_orders` AS `co` WHERE `co`.`idcustomer`=`c`.`id`) AS `tot_bookings`,".
12016 "`cy`.`country_3_code`,`cy`.`country_name` ".
12017 "FROM `#__vikbooking_customers` AS `c` LEFT JOIN `#__vikbooking_countries` `cy` ON `cy`.`country_3_code`=`c`.`country` ".
12018 "LEFT JOIN `#__vikbooking_customers_orders` `co` ON `co`.`idcustomer`=`c`.`id` ".
12019 "LEFT JOIN `#__vikbooking_orders` `bk` ON `bk`.`id`=`co`.`idorder`".
12020 (count($clauses) > 0 ? " WHERE ".implode(' AND ', $clauses) : "")."
12021 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` ".
12022 "ORDER BY `c`.`last_name` ASC;";
12023 $dbo->setQuery($q);
12024 $dbo->execute();
12025 if (!($dbo->getNumRows() > 0)) {
12026 VikError::raiseWarning('', JText::translate('VBONORECORDSCSVCUSTOMERS'));
12027 $mainframe = JFactory::getApplication();
12028 $mainframe->redirect("index.php?option=com_vikbooking&task=customers");
12029 exit;
12030 }
12031 $customers = $dbo->loadAssocList();
12032 $csvlines = array();
12033 $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'));
12034 if ($ppin > 0) {
12035 $csvheadline[] = JText::translate('VBCUSTOMERPIN');
12036 }
12037 if ($pscanimg > 0) {
12038 $csvheadline[] = JText::translate('VBCUSTOMERDOCTYPE');
12039 $csvheadline[] = JText::translate('VBCUSTOMERDOCNUM');
12040 $csvheadline[] = JText::translate('VBCUSTOMERDOCIMG');
12041 }
12042 if ($pnotes > 0) {
12043 $csvheadline[] = JText::translate('VBCUSTOMERNOTES');
12044 }
12045 $csvlines[] = $csvheadline;
12046 foreach ($customers as $customer) {
12047 $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']);
12048 if ($ppin > 0) {
12049 $csvcustomerline[] = $customer['pin'];
12050 }
12051 if ($pscanimg > 0) {
12052 $csvcustomerline[] = $customer['doctype'];
12053 $csvcustomerline[] = $customer['docnum'];
12054 $csvcustomerline[] = (!empty($customer['docimg']) ? VBO_ADMIN_URI.'resources/idscans/'.$customer['docimg'] : '');
12055 }
12056 if ($pnotes > 0) {
12057 $csvcustomerline[] = $customer['notes'];
12058 }
12059 $csvlines[] = $csvcustomerline;
12060 }
12061 header("Content-type: text/csv");
12062 header("Cache-Control: no-store, no-cache");
12063 header('Content-Disposition: attachment; filename="customers_export_'.(!empty($pcountry) ? strtolower($pcountry).'_' : '').date('Y-m-d').'.csv"');
12064 $outstream = fopen("php://output", 'w');
12065 foreach ($csvlines as $csvline) {
12066 fputcsv($outstream, $csvline);
12067 }
12068 fclose($outstream);
12069 exit;
12070 }
12071
12072 public function renewsession() {
12073 /*
12074 * @wponly
12075 * We just destroy the session
12076 */
12077 JSessionHandler::destroy();
12078 $mainframe = JFactory::getApplication();
12079 $mainframe->redirect("index.php?option=com_vikbooking&task=config");
12080 }
12081
12082 public function trackings() {
12083 VikBookingHelper::printHeader("trackings");
12084
12085 VikRequest::setVar('view', VikRequest::getCmd('view', 'trackings'));
12086
12087 parent::display();
12088
12089 if (VikBooking::showFooter()) {
12090 VikBookingHelper::printFooter();
12091 }
12092 }
12093
12094 public function trkconfig() {
12095 VikBookingHelper::printHeader("trackings");
12096
12097 VikRequest::setVar('view', VikRequest::getCmd('view', 'trkconfig'));
12098
12099 parent::display();
12100
12101 if (VikBooking::showFooter()) {
12102 VikBookingHelper::printFooter();
12103 }
12104 }
12105
12106 public function savetrkconfigstay() {
12107 if (!JSession::checkToken()) {
12108 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
12109 }
12110 $this->do_savetrkconfig(true);
12111 }
12112
12113 public function savetrkconfig() {
12114 if (!JSession::checkToken()) {
12115 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
12116 }
12117 $this->do_savetrkconfig();
12118 }
12119
12120 private function do_savetrkconfig($stay = false) {
12121 $dbo = JFactory::getDBO();
12122 $trkenabled = VikRequest::getInt('trkenabled', 0, 'request');
12123 $trkenabled = $trkenabled == 1 ? 1 : 0;
12124 $trkcookierfrdur = VikRequest::getFloat('trkcookierfrdur', 1, 'request');
12125 $trkcookierfrdur = $trkcookierfrdur < 0.1 ? 1 : $trkcookierfrdur;
12126 $trkcampname = VikRequest::getVar('trkcampname', array());
12127 $trkcampkey = VikRequest::getVar('trkcampkey', array());
12128 $trkcampval = VikRequest::getVar('trkcampval', array());
12129 $trkcampaigns = array();
12130 foreach ($trkcampname as $k => $v) {
12131 if (empty($trkcampkey[$k])) {
12132 continue;
12133 }
12134 $trkcampkey[$k] = str_replace(' ', '', trim($trkcampkey[$k]));
12135 $name = !empty($v) ? $v : date('Y-m-d').' '.(count($trkcampaigns) + 1);
12136 $trkcampaigns[$trkcampkey[$k]] = array(
12137 'key' => $trkcampkey[$k],
12138 'value' => $trkcampval[$k],
12139 'name' => $name,
12140 );
12141 }
12142
12143 $q = "UPDATE `#__vikbooking_config` SET `setting`=".$dbo->quote($trkenabled)." WHERE `param`='trkenabled';";
12144 $dbo->setQuery($q);
12145 $dbo->execute();
12146 $q = "UPDATE `#__vikbooking_config` SET `setting`=".$dbo->quote($trkcookierfrdur)." WHERE `param`='trkcookierfrdur';";
12147 $dbo->setQuery($q);
12148 $dbo->execute();
12149 $q = "UPDATE `#__vikbooking_config` SET `setting`=".$dbo->quote(json_encode($trkcampaigns))." WHERE `param`='trkcampaigns';";
12150 $dbo->setQuery($q);
12151 $dbo->execute();
12152
12153 $mainframe = JFactory::getApplication();
12154 $mainframe->redirect("index.php?option=com_vikbooking&task=".($stay ? 'trkconfig' : 'trackings'));
12155 }
12156
12157 public function modtracking() {
12158 $dbo = JFactory::getDbo();
12159 $cid = VikRequest::getVar('cid', array());
12160 foreach ($cid as $id) {
12161 if (!empty($id)) {
12162 $q = "SELECT `id`,`published` FROM `#__vikbooking_trackings` WHERE `id`=".(int)$id.";";
12163 $dbo->setQuery($q);
12164 $dbo->execute();
12165 if ($dbo->getNumRows()) {
12166 $data = $dbo->loadAssoc();
12167 $q = "UPDATE `#__vikbooking_trackings` SET `published`=".($data['published'] ? '0' : '1')." WHERE `id`=".(int)$data['id'].";";
12168 $dbo->setQuery($q);
12169 $dbo->execute();
12170 }
12171 }
12172 }
12173 $mainframe = JFactory::getApplication();
12174 $mainframe->redirect("index.php?option=com_vikbooking&task=trackings");
12175 }
12176
12177 public function removetrackings() {
12178 $ids = VikRequest::getVar('cid', array());
12179 $dbo = JFactory::getDbo();
12180
12181 foreach ($ids as $d) {
12182 $q = "DELETE FROM `#__vikbooking_trackings` WHERE `id`=".(int)$d.";";
12183 $dbo->setQuery($q);
12184 $dbo->execute();
12185 $q = "DELETE FROM `#__vikbooking_tracking_infos` WHERE `idtracking`=".(int)$d.";";
12186 $dbo->setQuery($q);
12187 $dbo->execute();
12188 }
12189
12190 $mainframe = JFactory::getApplication();
12191 $mainframe->redirect("index.php?option=com_vikbooking&task=trackings");
12192 }
12193
12194 /**
12195 * Invokes the Tracker class to obtain
12196 * geo information about the IP addresses.
12197 * This task is called via ajax.
12198 *
12199 * @since 1.11
12200 */
12201 public function getgeoinfo() {
12202 $ips = VikRequest::getVar('ips', array());
12203 if (!count($ips)) {
12204 echo 'e4j.error.empty IPs';
12205 exit;
12206 }
12207
12208 // require the Tracker class without instantiating the object
12209 VikBooking::getTracker(true);
12210 $geo_info = VikBookingTracker::getIpGeoInfo($ips);
12211
12212 if ($geo_info === false) {
12213 echo 'e4j.error.Tracker error, could not get geo info from IPs';
12214 exit;
12215 }
12216
12217 // update db values and compose response
12218 $dbo = JFactory::getDbo();
12219 $resp = array();
12220 foreach ($geo_info as $id => $geo) {
12221 if (is_null($geo) || $geo === false) {
12222 continue;
12223 }
12224 // compose geo info string
12225 $geovals = array();
12226 if (!empty($geo['city'])) {
12227 array_push($geovals, $geo['city']);
12228 }
12229 if (!empty($geo['region'])) {
12230 array_push($geovals, $geo['region']);
12231 }
12232 $threecode = '';
12233 $cname = '';
12234 if (!empty($geo['country'])) {
12235 // returned country is a 2-char code, get the 3-char country code
12236 $q = "SELECT `country_3_code`,`country_name` FROM `#__vikbooking_countries` WHERE `country_2_code`=".$dbo->quote($geo['country']).";";
12237 $dbo->setQuery($q);
12238 $dbo->execute();
12239 if ($dbo->getNumRows()) {
12240 $cinfo = $dbo->loadAssoc();
12241 $threecode = $cinfo['country_3_code'];
12242 $cname = $cinfo['country_name'];
12243 }
12244 array_push($geovals, (empty($cname) ? $geo['country'] : $cname));
12245 }
12246
12247 // full geo information string
12248 $geoinfostr = implode(', ', $geovals);
12249
12250 // push data to the response pool
12251 $resp[$id] = array();
12252 $resp[$id]['geo'] = $geoinfostr;
12253 if (!empty($cname)) {
12254 $resp[$id]['country'] = $cname;
12255 }
12256 if (!empty($threecode)) {
12257 $resp[$id]['country3'] = $threecode;
12258 }
12259
12260 // update main tracking record
12261 $q = "UPDATE `#__vikbooking_trackings` SET `geo`=".$dbo->quote($geoinfostr).(!empty($threecode) ? ', `country`='.$dbo->quote($threecode) : '')." WHERE `id`=".(int)$id.";";
12262 $dbo->setQuery($q);
12263 $dbo->execute();
12264 }
12265
12266 // output the JSON response
12267 echo json_encode($resp);
12268 exit;
12269 }
12270
12271 /**
12272 * Counts the orphan dates for all published rooms
12273 * depending on their restrictions and booked dates.
12274 * By default, the task takes up to 3 months ahead.
12275 * It is possible to filter the request by rooms and months.
12276 * This task should be called via ajax.
12277 *
12278 * @since 1.11
12279 */
12280 public function orphanscount()
12281 {
12282 $dbo = JFactory::getDbo();
12283 $orphans = array();
12284
12285 $nowdf = VikBooking::getDateFormat();
12286 if ($nowdf == "%d/%m/%Y") {
12287 $df = 'd/m/Y';
12288 } elseif ($nowdf == "%m/%d/%Y") {
12289 $df = 'm/d/Y';
12290 } else {
12291 $df = 'Y/m/d';
12292 }
12293
12294 // global min los
12295 $glob_minlos = VikBooking::getDefaultNightsCalendar();
12296 $glob_minlos = $glob_minlos < 1 ? 1 : $glob_minlos;
12297
12298 // rooms and dates
12299 $roomids = VikRequest::getVar('roomids', array(), 'request', 'int');
12300 $months = VikRequest::getInt('months', 3, 'request');
12301 $from = VikRequest::getString('from', '', 'request');
12302 $today = strtotime(date('Y').'-'.date('m').'-'.date('d'));
12303 if (!empty($from)) {
12304 $fromts = VikBooking::getDateTimestamp($from, 0, 0);
12305 if (!empty($fromts)) {
12306 // custom starting date
12307 $today = $fromts;
12308 }
12309 }
12310 $until = strtotime("+{$months} months", $today);
12311
12312 // load all rooms
12313 $rooms = array();
12314 $q = "SELECT `id`,`name`,`units` FROM `#__vikbooking_rooms` WHERE `avail`=1".(count($roomids) ? ' AND `id` IN ('.implode(', ', $roomids).')' : '').";";
12315 $dbo->setQuery($q);
12316 $dbo->execute();
12317 if ($dbo->getNumRows()) {
12318 $allrooms = $dbo->loadAssocList();
12319 foreach ($allrooms as $r) {
12320 $rooms[$r['id']] = $r;
12321 }
12322 }
12323 if (!count($rooms)) {
12324 // no rooms found, exit
12325 echo json_encode($orphans);
12326 exit;
12327 }
12328
12329 // load availabilities
12330 $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.");";
12331 $dbo->setQuery($q);
12332 $dbo->execute();
12333 if (!$dbo->getNumRows()) {
12334 // no booked dates found, exit
12335 echo json_encode($orphans);
12336 exit;
12337 }
12338 $busy = $dbo->loadAssocList();
12339
12340 // sort booked dates by room id
12341 $rooms_busy = array();
12342 foreach ($busy as $b) {
12343 if (!isset($rooms_busy[$b['idroom']])) {
12344 $rooms_busy[$b['idroom']] = array();
12345 }
12346 array_push($rooms_busy[$b['idroom']], $b);
12347 }
12348
12349 // load restrictions
12350 $rooms_restr = array();
12351 foreach ($rooms as $rid => $r) {
12352 $restrictions = VikBooking::loadRestrictions(true, array($rid));
12353 if (count($restrictions)) {
12354 $rooms_restr[$rid] = $restrictions;
12355 }
12356 }
12357 if (!count($rooms_restr) && $glob_minlos < 2) {
12358 // no restrictions found and minlos=1, exit
12359 echo json_encode($orphans);
12360 exit;
12361 }
12362
12363 // count availability and minlos per day
12364 $rooms_data = array();
12365 foreach ($rooms as $rid => $r) {
12366 $rooms_data[$rid] = array(
12367 'avail' => array(),
12368 'restr' => array()
12369 );
12370 $nowts = getdate($today);
12371 while ($nowts[0] <= $until) {
12372 $dateind = date('Y-m-d', $nowts[0]);
12373
12374 // remaining availability
12375 if (!isset($rooms_busy[$rid])) {
12376 // no bookings for this room, set full availability for this day
12377 $rooms_data[$rid]['avail'][] = array(
12378 'dt' => $dateind,
12379 'units' => $r['units']
12380 );
12381 } else {
12382 // check remaining availability for this day
12383 $totfound = 0;
12384 foreach ($rooms_busy[$rid] as $b) {
12385 $tmpone = getdate($b['checkin']);
12386 $rit = ($tmpone['mon'] < 10 ? "0".$tmpone['mon'] : $tmpone['mon'])."/".($tmpone['mday'] < 10 ? "0".$tmpone['mday'] : $tmpone['mday'])."/".$tmpone['year'];
12387 $ritts = strtotime($rit);
12388 $tmptwo = getdate($b['checkout']);
12389 $con = ($tmptwo['mon'] < 10 ? "0".$tmptwo['mon'] : $tmptwo['mon'])."/".($tmptwo['mday'] < 10 ? "0".$tmptwo['mday'] : $tmptwo['mday'])."/".$tmptwo['year'];
12390 $conts = strtotime($con);
12391 if ($nowts[0] >= $ritts && $nowts[0] < $conts) {
12392 $totfound++;
12393 }
12394 }
12395 $totfound = $totfound > $r['units'] ? $r['units'] : $totfound;
12396 $rooms_data[$rid]['avail'][] = array(
12397 'dt' => $dateind,
12398 'units' => ($r['units'] - $totfound)
12399 );
12400 }
12401
12402 // restrictions
12403 if (!isset($rooms_restr[$rid])) {
12404 // no restrictions for this room, set global minlos for this day
12405 $rooms_data[$rid]['restr'][] = array(
12406 'dt' => $dateind,
12407 'minlos' => $glob_minlos
12408 );
12409 } else {
12410 // get restriction for this day
12411 $today_tsin = mktime(0, 0, 0, $nowts['mon'], $nowts['mday'], $nowts['year']);
12412 $today_tsout = mktime(0, 0, 0, $nowts['mon'], ($nowts['mday'] + 1), $nowts['year']);
12413
12414 $restr = VikBooking::parseSeasonRestrictions($today_tsin, $today_tsout, 1, $rooms_restr[$rid]);
12415 $minlos = count($restr) ? $restr['minlos'] : $glob_minlos;
12416
12417 $rooms_data[$rid]['restr'][] = array(
12418 'dt' => $dateind,
12419 'minlos' => $minlos
12420 );
12421 }
12422
12423 // next loop
12424 $dayts = mktime(0, 0, 0, $nowts['mon'], ($nowts['mday'] + 1), $nowts['year']);
12425 $nowts = getdate($dayts);
12426 }
12427 }
12428
12429 // week days and months labels
12430 $days_labels = array(
12431 JText::translate('VBSUNDAY'),
12432 JText::translate('VBMONDAY'),
12433 JText::translate('VBTUESDAY'),
12434 JText::translate('VBWEDNESDAY'),
12435 JText::translate('VBTHURSDAY'),
12436 JText::translate('VBFRIDAY'),
12437 JText::translate('VBSATURDAY')
12438 );
12439 $months_labels = array(
12440 JText::translate('VBMONTHONE'),
12441 JText::translate('VBMONTHTWO'),
12442 JText::translate('VBMONTHTHREE'),
12443 JText::translate('VBMONTHFOUR'),
12444 JText::translate('VBMONTHFIVE'),
12445 JText::translate('VBMONTHSIX'),
12446 JText::translate('VBMONTHSEVEN'),
12447 JText::translate('VBMONTHEIGHT'),
12448 JText::translate('VBMONTHNINE'),
12449 JText::translate('VBMONTHTEN'),
12450 JText::translate('VBMONTHELEVEN'),
12451 JText::translate('VBMONTHTWELVE')
12452 );
12453
12454 // orphan dates calculation method
12455 $calc_method = VikBooking::orphansCalculation();
12456
12457 // parse data and build orphans if any
12458 foreach ($rooms_data as $rid => $data) {
12459 foreach ($data['avail'] as $ind => $av) {
12460 if (!isset($data['restr'][$ind]) || $av['units'] < 1) {
12461 // continue, no restriction set or no availability for this day
12462 continue;
12463 }
12464 if ($data['restr'][$ind]['minlos'] < 2) {
12465 // continue, no min los > 1 set for this day
12466 continue;
12467 }
12468 // check if any night after today, until min los, is fully booked
12469 $hasorphans = false;
12470 $forward_count = 0;
12471 for ($i = 1; $i < $data['restr'][$ind]['minlos']; $i++) {
12472 if (!isset($data['avail'][($ind + $i)])) {
12473 // break loop, no info for this day after
12474 break;
12475 }
12476 if ($data['avail'][($ind + $i)]['units'] > 0) {
12477 // continue, availability found for tomorrow, we need a non available next-day
12478 continue;
12479 }
12480 // orphan found
12481 $hasorphans = true;
12482 $forward_count = $i;
12483 break;
12484 }
12485
12486 /**
12487 * Backward calculation method only if "prevnext".
12488 *
12489 * @since 1.3.0
12490 */
12491 $backward_count = 0;
12492 for ($i = 1; $i <= $data['restr'][$ind]['minlos']; $i++) {
12493 if (!isset($data['avail'][($ind - $i)])) {
12494 // break loop, no info for this prev day
12495 break;
12496 }
12497 if ($data['avail'][($ind - $i)]['units'] > 0) {
12498 // increase free nights going backward
12499 $backward_count++;
12500 }
12501 }
12502 if ($calc_method == 'prevnext' && $hasorphans && $backward_count > 0 && ($backward_count >= $data['restr'][$ind]['minlos'] || ($backward_count + $forward_count) >= $data['restr'][$ind]['minlos'])) {
12503 // this should not be an orphan date because of enough free days back, or enough free days in between
12504 $hasorphans = false;
12505 }
12506 //
12507
12508 if ($hasorphans) {
12509 // 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
12510 if (!isset($orphans[$rid])) {
12511 $orphans[$rid] = array(
12512 'name' => $rooms[$rid]['name'],
12513 'dates' => array(),
12514 'rdates' => array(),
12515 'linkd' => date($df, strtotime($av['dt']))
12516 );
12517 }
12518 array_push($orphans[$rid]['dates'], $av['dt']);
12519 // build the value for the readable date
12520 $dtinfo = getdate(strtotime($av['dt']));
12521 $rdate = $days_labels[$dtinfo['wday']] . ', ' . $months_labels[($dtinfo['mon'] - 1)] . ' ' . $dtinfo['mday'] . ' ' . $dtinfo['year'];
12522 array_push($orphans[$rid]['rdates'], $rdate);
12523 }
12524 }
12525 }
12526
12527 // output response
12528 echo json_encode($orphans);
12529 exit;
12530 }
12531
12532 public function tableaux() {
12533 VikBookingHelper::printHeader("tableaux");
12534
12535 VikRequest::setVar('view', VikRequest::getCmd('view', 'tableaux'));
12536
12537 parent::display();
12538
12539 if (VikBooking::showFooter()) {
12540 VikBookingHelper::printFooter();
12541 }
12542 }
12543
12544 public function operators() {
12545 VikBookingHelper::printHeader("operators");
12546
12547 VikRequest::setVar('view', VikRequest::getCmd('view', 'operators'));
12548
12549 parent::display();
12550
12551 if (VikBooking::showFooter()) {
12552 VikBookingHelper::printFooter();
12553 }
12554 }
12555
12556 public function newoperator() {
12557 VikBookingHelper::printHeader("operators");
12558
12559 VikRequest::setVar('view', VikRequest::getCmd('view', 'manageoperator'));
12560
12561 parent::display();
12562
12563 if (VikBooking::showFooter()) {
12564 VikBookingHelper::printFooter();
12565 }
12566 }
12567
12568 public function editoperator() {
12569 VikBookingHelper::printHeader("operators");
12570
12571 VikRequest::setVar('view', VikRequest::getCmd('view', 'manageoperator'));
12572
12573 parent::display();
12574
12575 if (VikBooking::showFooter()) {
12576 VikBookingHelper::printFooter();
12577 }
12578 }
12579
12580 public function updateoperator() {
12581 if (!JSession::checkToken()) {
12582 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
12583 }
12584 $this->do_updateoperator();
12585 }
12586
12587 public function updateoperatorstay() {
12588 if (!JSession::checkToken()) {
12589 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
12590 }
12591 $this->do_updateoperator(true);
12592 }
12593
12594 private function do_updateoperator($stay = false) {
12595 $dbo = JFactory::getDBO();
12596 $mainframe = JFactory::getApplication();
12597 $pfirst_name = VikRequest::getString('first_name', '', 'request');
12598 $plast_name = VikRequest::getString('last_name', '', 'request');
12599 $pemail = VikRequest::getString('email', '', 'request');
12600 $pphone = VikRequest::getString('phone', '', 'request');
12601 $pcode = VikRequest::getString('code', '', 'request');
12602 $pujid = VikRequest::getInt('ujid', '', 'request');
12603 $pwhere = VikRequest::getInt('where', '', 'request');
12604 if (!empty($pfirst_name) && !empty($pemail) && (!empty($pcode) || !empty($pujid))) {
12605 $q = "SELECT * FROM `#__vikbooking_operators` WHERE `id`=".(int)$pwhere." LIMIT 1;";
12606 $dbo->setQuery($q);
12607 $dbo->execute();
12608 if ($dbo->getNumRows() == 1) {
12609 $customer = $dbo->loadAssoc();
12610 } else {
12611 $mainframe->redirect("index.php?option=com_vikbooking&task=operators");
12612 exit;
12613 }
12614 $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;";
12615 $dbo->setQuery($q);
12616 $dbo->execute();
12617 if ($dbo->getNumRows() == 0) {
12618 // update fingerprint for the operator
12619 $fingpt = md5($pwhere.$pemail);
12620 //
12621 $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.";";
12622 $dbo->setQuery($q);
12623 $dbo->execute();
12624 $mainframe->enqueueMessage(JText::translate('VBOPERATORSAVED'));
12625 } else {
12626 //email already exists
12627 $ex_operator = $dbo->loadAssoc();
12628 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>');
12629 $mainframe->redirect("index.php?option=com_vikbooking&task=editoperator&cid[]=".$pwhere);
12630 exit;
12631 }
12632 } else {
12633 VikError::raiseWarning('', JText::translate('VBERROPERATORDATA'));
12634 }
12635 if ($stay) {
12636 $mainframe->redirect("index.php?option=com_vikbooking&task=editoperator&cid[]=".$pwhere);
12637 } else {
12638 $mainframe->redirect("index.php?option=com_vikbooking&task=operators");
12639 }
12640 }
12641
12642 public function saveoperator() {
12643 if (!JSession::checkToken()) {
12644 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
12645 }
12646 $dbo = JFactory::getDbo();
12647 $mainframe = JFactory::getApplication();
12648 $pfirst_name = VikRequest::getString('first_name', '', 'request');
12649 $plast_name = VikRequest::getString('last_name', '', 'request');
12650 $pemail = VikRequest::getString('email', '', 'request');
12651 $pphone = VikRequest::getString('phone', '', 'request');
12652 $pcode = VikRequest::getString('code', '', 'request');
12653 $pujid = VikRequest::getInt('ujid', '', 'request');
12654 if (!empty($pfirst_name) && !empty($pemail) && (!empty($pcode) || !empty($pujid))) {
12655 $q = "SELECT * FROM `#__vikbooking_operators` WHERE `email`=".$dbo->quote($pemail)." OR ".(!empty($pcode) ? "`code`=".$dbo->quote($pcode) : "`ujid`=".$dbo->quote($pujid))." LIMIT 1;";
12656 $dbo->setQuery($q);
12657 $dbo->execute();
12658 if ($dbo->getNumRows() == 0) {
12659 $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).");";
12660 $dbo->setQuery($q);
12661 $dbo->execute();
12662 $lid = $dbo->insertid();
12663 if (!empty($lid)) {
12664 $mainframe->enqueueMessage(JText::translate('VBOPERATORSAVED'));
12665 // generate fingerprint for the operator
12666 $q = "UPDATE `#__vikbooking_operators` SET `fingpt`=".$dbo->quote(md5($lid.$pemail))." WHERE `id`=".(int)$lid.";";
12667 $dbo->setQuery($q);
12668 $dbo->execute();
12669 //
12670 }
12671 } else {
12672 //email already exists
12673 $ex_operator = $dbo->loadAssoc();
12674 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>');
12675 }
12676 } else {
12677 VikError::raiseWarning('', JText::translate('VBERROPERATORDATA'));
12678 }
12679 $mainframe->redirect("index.php?option=com_vikbooking&task=operators");
12680 }
12681
12682 public function removeoperators() {
12683 if (!JSession::checkToken()) {
12684 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
12685 }
12686 $ids = VikRequest::getVar('cid', array(0));
12687 if (@count($ids)) {
12688 $dbo = JFactory::getDBO();
12689 foreach ($ids as $d) {
12690 $q = "DELETE FROM `#__vikbooking_operators` WHERE `id`=".(int)$d.";";
12691 $dbo->setQuery($q);
12692 $dbo->execute();
12693 }
12694 }
12695 $mainframe = JFactory::getApplication();
12696 $mainframe->redirect("index.php?option=com_vikbooking&task=operators");
12697 }
12698
12699 public function operatorperms() {
12700 $dbo = JFactory::getDbo();
12701 $permtype = VikRequest::getString('permtype', 'tableaux', 'request');
12702 $permschanged = 0;
12703
12704 if ($permtype == 'tableaux') {
12705 $oper_id = VikRequest::getVar('oper_id', array());
12706 $oper_days = VikRequest::getVar('oper_days', array());
12707 $oper_rooms = VikRequest::getVar('oper_rooms', array());
12708 $oper_guestname = VikRequest::getVar('oper_guestname', array());
12709 $oper_roomextras = VikRequest::getVar('oper_roomextras', array());
12710 $oper_rm = VikRequest::getVar('oper_rm', array());
12711 if (count($oper_rm)) {
12712 // remove permissions first
12713 foreach ($oper_rm as $operatorid) {
12714 $q = "SELECT `id`,`perms` FROM `#__vikbooking_operators` WHERE `id`=".(int)$operatorid.";";
12715 $dbo->setQuery($q);
12716 $dbo->execute();
12717 if ($dbo->getNumRows()) {
12718 $current = $dbo->loadAssoc();
12719 $perms = !empty($current['perms']) ? json_decode($current['perms'], true) : array();
12720 $perms = !is_array($perms) ? array() : $perms;
12721 foreach ($perms as $kp => $perm) {
12722 if (isset($perm['type']) && $perm['type'] == $permtype) {
12723 unset($perms[$kp]);
12724 break;
12725 }
12726 }
12727 // update permissions for this operator
12728 $q = "UPDATE `#__vikbooking_operators` SET `perms`=".$dbo->quote(json_encode($perms))." WHERE `id`=".$current['id'].";";
12729 $dbo->setQuery($q);
12730 $dbo->execute();
12731 $permschanged++;
12732 }
12733 }
12734 }
12735 foreach ($oper_id as $k => $v) {
12736 if (empty($v) || !isset($oper_days[$k])) {
12737 // missing data
12738 continue;
12739 }
12740 // get operator
12741 $q = "SELECT `id`,`perms` FROM `#__vikbooking_operators` WHERE `id`=".(int)$v.";";
12742 $dbo->setQuery($q);
12743 $dbo->execute();
12744 if (!$dbo->getNumRows()) {
12745 continue;
12746 }
12747 $current = $dbo->loadAssoc();
12748 $perms = !empty($current['perms']) ? json_decode($current['perms'], true) : array();
12749 $perms = !is_array($perms) ? array() : $perms;
12750 foreach ($perms as $kp => $perm) {
12751 if (isset($perm['type']) && $perm['type'] == $permtype) {
12752 unset($perms[$kp]);
12753 break;
12754 }
12755 }
12756 // push new permission
12757 array_push($perms, array(
12758 'type' => $permtype,
12759 'perms' => array(
12760 'days' => (int)$oper_days[$k],
12761 'rooms' => (isset($oper_rooms[$k]) && is_array($oper_rooms[$k]) ? $oper_rooms[$k] : array()),
12762 'guestname' => (isset($oper_guestname[$k]) && (int)$oper_guestname[$k] > 0 ? 1 : 0),
12763 'roomextras' => (isset($oper_roomextras[$k]) && (int)$oper_roomextras[$k] > 0 ? 1 : 0),
12764 )
12765 ));
12766 // update permissions for this operator
12767 $q = "UPDATE `#__vikbooking_operators` SET `perms`=".$dbo->quote(json_encode($perms))." WHERE `id`=".$current['id'].";";
12768 $dbo->setQuery($q);
12769 $dbo->execute();
12770 $permschanged++;
12771 }
12772 }
12773
12774 $mainframe = JFactory::getApplication();
12775 if ($permschanged > 0) {
12776 $mainframe->enqueueMessage(JText::translate('VBOPERMSUPDOPEROK'));
12777 }
12778 $mainframe->redirect("index.php?option=com_vikbooking&task=".$permtype);
12779 }
12780
12781 public function canceloperator() {
12782 $mainframe = JFactory::getApplication();
12783 $mainframe->redirect("index.php?option=com_vikbooking&task=operators");
12784 }
12785
12786 public function cancelcrons() {
12787 $mainframe = JFactory::getApplication();
12788 $mainframe->redirect("index.php?option=com_vikbooking&task=crons");
12789 }
12790
12791 public function cancelpackages() {
12792 $mainframe = JFactory::getApplication();
12793 $mainframe->redirect("index.php?option=com_vikbooking&task=packages");
12794 }
12795
12796 public function cancelcustomer() {
12797 $mainframe = JFactory::getApplication();
12798 $pgoto = VikRequest::getString('goto', '', 'request', VIKREQUEST_ALLOWRAW);
12799 if (!empty($pgoto)) {
12800 $mainframe->redirect(base64_decode($pgoto));
12801 exit;
12802 }
12803 $mainframe->redirect("index.php?option=com_vikbooking&task=customers");
12804 }
12805
12806 public function cancelbusyvcm() {
12807 $mainframe = JFactory::getApplication();
12808 $mainframe->redirect("index.php?option=com_vikchannelmanager&task=oversight");
12809 }
12810
12811 public function cancelrestriction() {
12812 $mainframe = JFactory::getApplication();
12813 $mainframe->redirect("index.php?option=com_vikbooking&task=restrictions");
12814 }
12815
12816 public function cancelcoupon() {
12817 $mainframe = JFactory::getApplication();
12818 $mainframe->redirect("index.php?option=com_vikbooking&task=coupons");
12819 }
12820
12821 public function cancelcustomf() {
12822 $mainframe = JFactory::getApplication();
12823 $mainframe->redirect("index.php?option=com_vikbooking&task=customf");
12824 }
12825
12826 public function cancelpayment() {
12827 $mainframe = JFactory::getApplication();
12828 $mainframe->redirect("index.php?option=com_vikbooking&task=payments");
12829 }
12830
12831 public function cancelseason() {
12832 $mainframe = JFactory::getApplication();
12833 $mainframe->redirect("index.php?option=com_vikbooking&task=seasons");
12834 }
12835
12836 public function goconfig() {
12837 $mainframe = JFactory::getApplication();
12838 $mainframe->redirect("index.php?option=com_vikbooking&task=config");
12839 }
12840
12841 public function canceledorder() {
12842 $pgoto = VikRequest::getString('goto', 'orders', 'request');
12843 $mainframe = JFactory::getApplication();
12844 $mainframe->redirect("index.php?option=com_vikbooking&task=" . $pgoto);
12845 }
12846
12847 public function cancelbusy() {
12848 $pidorder = VikRequest::getString('idorder', '', 'request');
12849 $pgoto = VikRequest::getString('goto', '', 'request');
12850 $mainframe = JFactory::getApplication();
12851 $mainframe->redirect("index.php?option=com_vikbooking&task=editorder&cid[]=".$pidorder.($pgoto == 'overv' ? '&goto=overv' : ''));
12852 }
12853
12854 public function canceloverv() {
12855 $mainframe = JFactory::getApplication();
12856 $mainframe->redirect("index.php?option=com_vikbooking&task=overv");
12857 }
12858
12859 public function canceltableaux() {
12860 $mainframe = JFactory::getApplication();
12861 $mainframe->redirect("index.php?option=com_vikbooking&task=tableaux");
12862 }
12863
12864 public function cancelcalendar() {
12865 $pidroom = VikRequest::getString('idroom', '', 'request');
12866 $mainframe = JFactory::getApplication();
12867 $mainframe->redirect("index.php?option=com_vikbooking&task=calendar&cid[]=".$pidroom);
12868 }
12869
12870 public function canceloptionals() {
12871 $mainframe = JFactory::getApplication();
12872 $mainframe->redirect("index.php?option=com_vikbooking&task=optionals");
12873 }
12874
12875 public function cancel() {
12876 $mainframe = JFactory::getApplication();
12877 $mainframe->redirect("index.php?option=com_vikbooking&task=rooms");
12878 }
12879
12880 public function cancelcarat() {
12881 $mainframe = JFactory::getApplication();
12882 $mainframe->redirect("index.php?option=com_vikbooking&task=carat");
12883 }
12884
12885 public function cancelcat() {
12886 $mainframe = JFactory::getApplication();
12887 $mainframe->redirect("index.php?option=com_vikbooking&task=categories");
12888 }
12889
12890 public function cancelprice() {
12891 $mainframe = JFactory::getApplication();
12892 $mainframe->redirect("index.php?option=com_vikbooking&task=prices");
12893 }
12894
12895 public function canceliva() {
12896 $mainframe = JFactory::getApplication();
12897 $mainframe->redirect("index.php?option=com_vikbooking&task=iva");
12898 }
12899
12900 public function canceltrk() {
12901 $mainframe = JFactory::getApplication();
12902 $mainframe->redirect("index.php?option=com_vikbooking&task=trackings");
12903 }
12904
12905 public function canceldash() {
12906 $mainframe = JFactory::getApplication();
12907 $mainframe->redirect("index.php?option=com_vikbooking");
12908 }
12909
12910 public function cancelinvoice() {
12911 $mainframe = JFactory::getApplication();
12912 $pgoto = VikRequest::getString('goto', '', 'request', VIKREQUEST_ALLOWRAW);
12913 if (!empty($pgoto)) {
12914 $mainframe->redirect(base64_decode($pgoto));
12915 exit;
12916 }
12917 $mainframe->redirect("index.php?option=com_vikbooking&task=invoices");
12918 }
12919
12920 /**
12921 * AJAX upload the customer documents.
12922 *
12923 * @return void
12924 *
12925 * @throws Exception
12926 */
12927 public function upload_customer_document()
12928 {
12929 $input = JFactory::getApplication()->input;
12930 $dbo = JFactory::getDbo();
12931
12932 $customer_id = $input->getUint('customer', 0);
12933
12934 $result = new stdClass;
12935 $result->status = 0;
12936
12937 try
12938 {
12939 $q = $dbo->getQuery(true)
12940 ->select($dbo->qn(array(
12941 'id',
12942 'first_name',
12943 'last_name',
12944 'email',
12945 'docsfolder',
12946 )))
12947 ->from($dbo->qn('#__vikbooking_customers'))
12948 ->where($dbo->qn('id') . ' = ' . $customer_id);
12949
12950 $dbo->setQuery($q, 0, 1);
12951 $dbo->execute();
12952
12953 if (!$dbo->getNumRows())
12954 {
12955 throw new Exception(sprintf('Customer [%d] not found', $customer_id), 404);
12956 }
12957
12958 $customer = $dbo->loadObject();
12959
12960 // fetch documents folder path
12961 $dirpath = VBO_CUSTOMERS_PATH . DIRECTORY_SEPARATOR;
12962
12963 // check if we have a valid directory
12964 if (empty($customer->docsfolder) || !is_dir($dirpath . $customer->docsfolder))
12965 {
12966 // randomize string
12967 $customer->seed = uniqid();
12968
12969 // create blocks for hashed folder
12970 $parts = [
12971 $customer->first_name,
12972 $customer->last_name,
12973 md5(serialize($customer)),
12974 ];
12975
12976 // join fetched parts
12977 $customer->docsfolder = JFilterOutput::stringURLSafe(implode('-', array_filter($parts)));
12978
12979 if (strlen($customer->docsfolder) < 16)
12980 {
12981 throw new Exception('Possible security breach. Please specify the most details as possible.', 400);
12982 }
12983
12984 jimport('joomla.filesystem.folder');
12985
12986 // create a folder for this customer
12987 $created = JFolder::create($dirpath . $customer->docsfolder);
12988
12989 if (!$created)
12990 {
12991 throw new Exception(sprintf('Unable to create the folder [%s]', $dirpath . $customer->docsfolder), 403);
12992 }
12993
12994 unset($customer->seed);
12995
12996 // update docs folder
12997 $dbo->updateObject('#__vikbooking_customers', $customer, 'id');
12998 }
12999
13000 // get file from request
13001 $file = $input->files->get('file', array(), 'array');
13002
13003 // try to upload the file
13004 $result = VikBooking::uploadFileFromRequest($file, $dirpath . $customer->docsfolder, "/(image\/.+)|(application\/(zip|rar|pdf|msword|vnd.*?))|(text\/(plain|markdown|csv))$/i");
13005 $result->status = 1;
13006
13007 $result->size = JHtml::fetch('number.bytes', filesize($result->path), 'auto', 0);
13008 $result->url = str_replace(DIRECTORY_SEPARATOR, '/', str_replace(VBO_CUSTOMERS_PATH . DIRECTORY_SEPARATOR, VBO_CUSTOMERS_URI, $result->path));
13009 }
13010 catch (Exception $e)
13011 {
13012 $result->error = $e->getMessage();
13013 $result->code = $e->getCode();
13014 }
13015
13016 echo json_encode($result);
13017 exit;
13018 }
13019
13020 /**
13021 * AJAX delete the customer documents.
13022 *
13023 * @return void
13024 *
13025 * @throws Exception
13026 */
13027 public function delete_customer_document()
13028 {
13029 $input = JFactory::getApplication()->input;
13030 $dbo = JFactory::getDbo();
13031
13032 $customer_id = $input->getUint('customer', 0);
13033
13034 $result = new stdClass;
13035 $result->status = 0;
13036
13037 $q = $dbo->getQuery(true)
13038 ->select($dbo->qn('docsfolder'))
13039 ->from($dbo->qn('#__vikbooking_customers'))
13040 ->where($dbo->qn('id') . ' = ' . $customer_id);
13041
13042 $dbo->setQuery($q, 0, 1);
13043 $dbo->execute();
13044
13045 if (!$dbo->getNumRows())
13046 {
13047 throw new Exception(sprintf('Customer [%d] not found', $customer_id), 404);
13048 }
13049
13050 $folder = $dbo->loadResult();
13051
13052 if (!$folder)
13053 {
13054 throw new Exception('The customer does not have any documents', 500);
13055 }
13056
13057 $file = $input->getString('file');
13058
13059 if (!$file)
13060 {
13061 throw new Exception('File to remove not specified', 400);
13062 }
13063
13064 $path = implode(DIRECTORY_SEPARATOR, array(VBO_CUSTOMERS_PATH, $folder, $file));
13065
13066 if (!is_file($path))
13067 {
13068 throw new Exception(sprintf('File [%s] not found', $path), 404);
13069 }
13070
13071 jimport('joomla.filesystem.file');
13072
13073 $removed = JFile::delete($path);
13074
13075 echo json_encode(array('status' => (int) $removed));
13076 exit;
13077 }
13078
13079 /**
13080 * AJAX task to invoke a specific report and obtain information.
13081 *
13082 * @since 1.3.0
13083 */
13084 public function get_report_data()
13085 {
13086 $report_name = VikRequest::getString('report_name', '', 'request');
13087 $current_fest = VikRequest::getString('current_fest', '', 'request');
13088 $current_fromdate = VikRequest::getString('current_fromdate', '', 'request');
13089 $current_todate = VikRequest::getString('current_todate', '', 'request');
13090 $step = VikRequest::getString('step', 'weekend', 'request');
13091 $direction = VikRequest::getString('direction', 'load', 'request');
13092 $period = VikRequest::getString('period', 'full', 'request');
13093 $krsort = VikRequest::getString('krsort', 'occupancy', 'request');
13094 $krorder = VikRequest::getString('krorder', 'DESC', 'request');
13095 $chart_datatype = VikRequest::getVar('chart_datatype', array(), 'request');
13096 $chart_meta_data = VikRequest::getString('chart_meta_data', '', 'request', VIKREQUEST_ALLOWRAW);
13097 $chart_meta_data = !empty($chart_meta_data) ? json_decode($chart_meta_data, true) : array();
13098 // idroom can be an array of IDs or just one ID as int/string
13099 $idroom = VikRequest::getVar('idroom', null, 'request');
13100 //
13101
13102 if (empty($report_name) || empty($current_fromdate) || empty($current_todate)) {
13103 throw new Exception("Missing request data", 400);
13104 }
13105
13106 // get requested report instance
13107 $report = VikBooking::getReportInstance($report_name);
13108 if (!$report) {
13109 throw new Exception("Report not found", 404);
13110 }
13111
13112 // chart data
13113 if (empty($chart_datatype)) {
13114 $chart_datatype = array(
13115 'type' => 'doughnut',
13116 'depth' => 1,
13117 'keys' => array($krsort),
13118 );
13119 }
13120
13121 // website date format
13122 $df = $report->getDateFormat();
13123
13124 // prepare request params for the report
13125 $rparams = array(
13126 'fromdate' => $current_fromdate,
13127 'todate' => $current_todate,
13128 'period' => $period,
13129 'krsort' => $krsort,
13130 'krorder' => $krorder,
13131 'idroom' => $idroom,
13132 );
13133
13134 // starting dates info and timestamps
13135 $from_ts = VikBooking::getDateTimestamp($current_fromdate, 0, 0, 0);
13136 $to_ts = VikBooking::getDateTimestamp($current_todate, 23, 59, 59);
13137 $from_info = getdate($from_ts);
13138 $to_info = getdate($to_ts);
13139
13140 // the name of the period requested and whether it's a fest
13141 $period_name = '';
13142 $is_fest = null;
13143
13144 if ($direction == 'prev' || $direction == 'next') {
13145 // calculate prev or next dates
13146 if ($step == 'weekend') {
13147 $period_name = JText::translate('VBOWEEKND');
13148 if ($direction == 'next') {
13149 // next weekend from current end date
13150 $next_ts = strtotime("next friday", $to_ts);
13151 } else {
13152 // prev weekend from current start date
13153 $next_ts = strtotime("previous friday", $from_ts);
13154 }
13155 $next_info = getdate($next_ts);
13156 $new_from_ts = $next_ts;
13157 $new_to_ts = mktime(23, 59, 59, $next_info['mon'], ($next_info['mday'] + 1), $next_info['year']);
13158 $rparams['fromdate'] = date($df, $new_from_ts);
13159 $rparams['todate'] = date($df, $new_to_ts);
13160 } elseif ($step == 'week') {
13161 $period_name = JText::translate('VBOWEEK');
13162 if ($direction == 'next') {
13163 // start next week from the current end date
13164 $new_from_ts = $to_ts;
13165 $new_to_ts = mktime(23, 59, 59, $to_info['mon'], ($to_info['mday'] + 7), $to_info['year']);
13166 $rparams['fromdate'] = $rparams['todate'];
13167 $rparams['todate'] = date($df, $new_to_ts);
13168 } else {
13169 // end prev week from the current from date
13170 $new_from_ts = mktime(0, 0, 0, $from_info['mon'], ($from_info['mday'] - 7), $from_info['year']);
13171 $new_to_ts = $from_ts;
13172 $rparams['todate'] = $rparams['fromdate'];
13173 $rparams['fromdate'] = date($df, $new_from_ts);
13174 }
13175 } else {
13176 // month
13177 $period_name = JText::translate('VBPVIEWRESTRICTIONSTWO');
13178 if ($direction == 'next') {
13179 // next month from the current from date
13180 $nextmonts = mktime(0, 0, 0, ($from_info['mon'] + 1), 1, $from_info['year']);
13181 $new_from_ts = $nextmonts;
13182 $new_to_ts = mktime(23, 59, 59, ($from_info['mon'] + 1), date('t', $nextmonts), $from_info['year']);
13183 $rparams['fromdate'] = date($df, $new_from_ts);
13184 $rparams['todate'] = date($df, $new_to_ts);
13185 } else {
13186 // prev month from the current from date
13187 $nextmonts = mktime(0, 0, 0, ($from_info['mon'] - 1), 1, $from_info['year']);
13188 $new_from_ts = $nextmonts;
13189 $new_to_ts = mktime(23, 59, 59, ($from_info['mon'] - 1), date('t', $nextmonts), $from_info['year']);
13190 $rparams['fromdate'] = date($df, $new_from_ts);
13191 $rparams['todate'] = date($df, $new_to_ts);
13192 }
13193 }
13194
13195 // get the next festivities
13196 $fests = VikBooking::getFestivitiesInstance();
13197 $next_fests = $fests->loadFestDates();
13198 if (count($next_fests)) {
13199 // check whether a festivity should be displayed rather than the calculated period of dates
13200 foreach ($next_fests as $fest) {
13201 $fest_found = false;
13202 if ($direction == 'next' && $fest['festinfo'][0]->from_ts > $from_ts && $fest['festinfo'][0]->from_ts <= $new_to_ts) {
13203 $fest_found = true;
13204 } elseif ($direction == 'prev' && $fest['festinfo'][0]->from_ts < $to_ts && $fest['festinfo'][0]->from_ts >= $new_from_ts) {
13205 $fest_found = true;
13206 }
13207 if ($fest_found && (string)$fest['festinfo'][0]->next_ts != $current_fest) {
13208 // festivity found before next calculated period
13209 $is_fest = $fest['festinfo'][0]->next_ts;
13210 $period_name = $fest['festinfo'][0]->trans_name;
13211 $new_from_ts = $fest['festinfo'][0]->from_ts;
13212 $new_to_ts = $fest['festinfo'][0]->to_ts;
13213 $rparams['fromdate'] = date($df, $new_from_ts);
13214 $rparams['todate'] = date($df, $new_to_ts);
13215 break;
13216 }
13217 }
13218 }
13219 } else {
13220 // load requested dates by skipping the festivities
13221 $new_from_ts = $from_ts;
13222 $new_to_ts = $to_ts;
13223 }
13224
13225 // invoke report
13226 $report->injectParams($rparams);
13227 $report_values = $report->getReportValues(1);
13228 $report_cols = $report->getColumnsValues();
13229 $report_chart = null;
13230 $report_chart_metas = array();
13231 $chart_meta_data = array(
13232 'keys' => array(
13233 'occupancy',
13234 'tot_bookings',
13235 'nights_booked',
13236 ),
13237 );
13238 $error = null;
13239
13240 if (!count($report_values)) {
13241 $error = strlen($report->getError()) ? $report->getError() : JText::translate('VBNOTRACKINGS');
13242 } else {
13243 // get doughnut Chart for the requested key
13244 $report_chart = $report->getChart($chart_datatype);
13245
13246 // get Chart meta data
13247 $all_chart_metas = $report->getChartMetaData(null, $chart_meta_data);
13248 if (count($all_chart_metas)) {
13249 // merge all positions into one array
13250 foreach ($all_chart_metas as $pos_metas) {
13251 $report_chart_metas = array_merge($report_chart_metas, $pos_metas);
13252 }
13253 }
13254
13255 if (empty($period_name)) {
13256 $period_name = $report->getProperty('chartTitle');
13257 }
13258 }
13259
13260 // build response
13261 $response = new stdClass;
13262 $response->error = $error;
13263 $response->fromdate = $rparams['fromdate'];
13264 $response->todate = $rparams['todate'];
13265 $response->in_days = $report->countDaysTo($new_from_ts);
13266 $response->in_days_to = $report->countDaysTo($new_to_ts);
13267 $response->in_days_avg = $report->countAverageDays($response->in_days, $response->in_days_to);
13268 $response->period_name = $period_name;
13269 $response->period_date = count($report_values) && isset($report_values['day']) ? $report_values['day']['display_value'] : '';
13270 $response->is_fest = $is_fest;
13271 $response->report_chart = $report_chart;
13272 $response->report_cols = $report_cols;
13273 $response->report_values = $report_values;
13274 $response->report_script = $report->getScript();
13275 $response->chart_labels = $report->getProperty('chartJsLabels');
13276 $response->dataset_label = $report->getProperty('chartJsDataSetLabel');
13277 $response->chart_colors = $report->getProperty('chartJsColors');
13278 $response->chart_data = $report->getProperty('chartJsData');
13279 $response->report_chart_metas = $report_chart_metas;
13280
13281 echo json_encode($response);
13282 exit;
13283 }
13284
13285 /**
13286 * Go to the previous booking.
13287 *
13288 * @uses navigateToBooking()
13289 *
13290 * @since 1.3.0
13291 */
13292 public function prev_booking()
13293 {
13294 $this->navigateToBooking('prev');
13295 }
13296
13297 /**
13298 * Go to the next booking.
13299 *
13300 * @uses navigateToBooking()
13301 *
13302 * @since 1.3.0
13303 */
13304 public function next_booking()
13305 {
13306 $this->navigateToBooking('next');
13307 }
13308
13309 /**
13310 * Given the current booking ID in the request, we navigate
13311 * either to the next or to the previous reservation (if any).
13312 *
13313 * @param string $direction either next or prev.
13314 *
13315 * @return void
13316 *
13317 * @since 1.3.0
13318 */
13319 private function navigateToBooking($direction = 'next')
13320 {
13321 $bid = VikRequest::getInt('whereup', 0, 'request');
13322 if (empty($bid) || $bid < 1 || !in_array($direction, array('prev', 'next'))) {
13323 throw new Exception("Invalid request", 400);
13324 }
13325
13326 $dbo = JFactory::getDbo();
13327 $app = JFactory::getApplication();
13328
13329 $q = "SELECT `id` FROM `#__vikbooking_orders` WHERE `id`" . ($direction == 'next' ? '>' : '<') . "{$bid} ORDER BY `id` " . ($direction == 'next' ? 'ASC' : 'DESC');
13330 $dbo->setQuery($q, 0, 1);
13331 $dbo->execute();
13332 if (!$dbo->getNumRows()) {
13333 VikError::raiseWarning('', JText::translate('VBPEDITBUSYONE'));
13334 $app->redirect("index.php?option=com_vikbooking&task=orders");
13335 exit;
13336 }
13337
13338 $app->redirect("index.php?option=com_vikbooking&task=editorder&cid[]=" . $dbo->loadResult());
13339 exit;
13340 }
13341
13342 /**
13343 * AJAX request: from a list of reservation IDs, we return the ones
13344 * that have a review with the related review ID on VCM.
13345 *
13346 * @since 1.13
13347 */
13348 public function bookings_have_reviews()
13349 {
13350 $dbo = JFactory::getDbo();
13351 $bids = VikRequest::getVar('bids', array(), 'request', 'array');
13352 $vcm_installed = is_file(VCM_SITE_PATH . DIRECTORY_SEPARATOR . 'helpers' . DIRECTORY_SEPARATOR . 'lib.vikchannelmanager.php');
13353 $withreviews = array();
13354
13355 if ($vcm_installed && is_array($bids) && count($bids)) {
13356 try {
13357 $q = "SELECT `id`, `idorder` FROM `#__vikchannelmanager_otareviews` WHERE `idorder` IN (" . implode(', ', $bids) . ");";
13358 $dbo->setQuery($q);
13359 $dbo->execute();
13360 if ($dbo->getNumRows()) {
13361 $reviews = $dbo->loadAssocList();
13362 foreach ($reviews as $r) {
13363 $withreviews[$r['idorder']] = $r['id'];
13364 }
13365 }
13366 } catch (Exception $e) {
13367 // do nothing, outdated version
13368 }
13369 }
13370
13371 echo json_encode($withreviews);
13372 exit;
13373 }
13374
13375 /**
13376 * AJAX request for adding a new room-day note.
13377 *
13378 * @return void
13379 *
13380 * @since 1.13.5
13381 */
13382 public function add_roomdaynote()
13383 {
13384 $dt = VikRequest::getString('dt', '', 'request');
13385 $idroom = VikRequest::getInt('idroom', 0, 'request');
13386 $subunit = VikRequest::getInt('subunit', 0, 'request');
13387 $type = VikRequest::getString('type', '', 'request');
13388 $type = empty($type) ? 'custom' : $type;
13389 $name = VikRequest::getString('name', '', 'request');
13390 $descr = VikRequest::getString('descr', '', 'request');
13391 $cdays = VikRequest::getInt('cdays', 0, 'request');
13392 $cdays = $cdays < 0 ? 0 : $cdays;
13393 $cdays = $cdays > 365 ? 365 : $cdays;
13394 if (empty($idroom) || empty($dt) || !strtotime($dt)) {
13395 echo 'e4j.error.1';
13396 exit;
13397 }
13398
13399 // reload end date
13400 $end_date = $dt;
13401
13402 // build critical date object
13403 $new_note = array(
13404 'name' => $name,
13405 'type' => $type,
13406 'descr' => $descr,
13407 );
13408
13409 // get object
13410 $notes = VikBooking::getCriticalDatesInstance();
13411
13412 // store the notes for all consecutive dates
13413 for ($i = 0; $i <= $cdays; $i++) {
13414 $store_dt = $dt;
13415 if ($i > 0) {
13416 $dt_info = getdate(strtotime($store_dt));
13417 $store_dt = date('Y-m-d', mktime(0, 0, 0, $dt_info['mon'], ($dt_info['mday'] + $i), $dt_info['year']));
13418 $end_date = $store_dt;
13419 }
13420 $result = $notes->storeDayNote($new_note, $store_dt, $idroom, $subunit);
13421 if (!$result) {
13422 echo 'e4j.error.2';
13423 exit;
13424 }
13425 }
13426
13427 // reload all room day notes for this day for the AJAX response
13428 $all_notes = $notes->loadRoomDayNotes($dt, $end_date, $idroom, $subunit);
13429
13430 if (!$all_notes || !count($all_notes)) {
13431 // no notes found even after storing it
13432 echo 'e4j.error.3';
13433 exit;
13434 }
13435
13436 echo json_encode($all_notes);
13437 exit;
13438 }
13439
13440 /**
13441 * AJAX request for removing a room day note.
13442 *
13443 * @return void
13444 *
13445 * @since 1.13.5
13446 */
13447 public function remove_roomdaynote()
13448 {
13449 $dt = VikRequest::getString('dt', '', 'request');
13450 $idroom = VikRequest::getInt('idroom', 0, 'request');
13451 $subunit = VikRequest::getInt('subunit', 0, 'request');
13452 $type = VikRequest::getString('type', '', 'request');
13453 $type = empty($type) ? 'custom' : $type;
13454 $ind = VikRequest::getInt('ind', 0, 'request');
13455 if (empty($dt) || !strtotime($dt)) {
13456 echo 'e4j.error.1';
13457 exit;
13458 }
13459
13460 $notes = VikBooking::getCriticalDatesInstance();
13461 $result = $notes->deleteDayNote($ind, $dt, $idroom, $subunit, $type);
13462 if (!$result) {
13463 echo 'e4j.error.2';
13464 exit;
13465 }
13466
13467 echo 'e4j.ok';
13468 exit;
13469 }
13470
13471 /**
13472 * AJAX request for storing an event for a booking.
13473 * Firstly developed for the VCM Reporting API - Guest Misconduct,
13474 * but it can be used for any other purpose.
13475 *
13476 * @return void
13477 *
13478 * @since 1.13.5
13479 */
13480 public function store_booking_history_event()
13481 {
13482 $bid = VikRequest::getInt('bid', 0, 'request');
13483 $event = VikRequest::getString('event', '', 'request');
13484 $descr = VikRequest::getString('descr', '', 'request');
13485
13486 if (empty($bid) || empty($event)) {
13487 throw new Exception("Missing required information", 500);
13488 }
13489
13490 // Booking History
13491 VikBooking::getBookingHistoryInstance()->setBid($bid)->store($event, $descr);
13492 //
13493
13494 echo 'e4j.ok';
13495 exit;
13496 }
13497
13498 /**
13499 * AJAX request for updating an option/extra service.
13500 * Firstly developed for the VCM Vacation Rentals Essentials API - Damage Deposit,
13501 * but it can be used for any other purpose.
13502 *
13503 * @return void
13504 *
13505 * @since 1.13.5
13506 */
13507 public function update_option_params()
13508 {
13509 $optid = VikRequest::getInt('optid', 0, 'request');
13510 $oparams = VikRequest::getVar('oparams', array(), 'request', 'array');
13511
13512 if (empty($optid) || !is_array($oparams) || empty($oparams)) {
13513 throw new Exception("Missing required information", 500);
13514 }
13515
13516 $dbo = JFactory::getDbo();
13517 $q = "SELECT `oparams` FROM `#__vikbooking_optionals` WHERE `id`=" . (int)$optid . ";";
13518 $dbo->setQuery($q);
13519 $dbo->execute();
13520 if (!$dbo->getNumRows()) {
13521 throw new Exception("Option not found", 404);
13522 }
13523 $cur_params = $dbo->loadResult();
13524 $cur_params = !empty($cur_params) ? json_decode($cur_params, true) : array();
13525 $cur_params = !is_array($cur_params) ? array() : $cur_params;
13526
13527 foreach ($oparams as $k => $v) {
13528 if (empty($k)) {
13529 continue;
13530 }
13531 $cur_params[$k] = $v;
13532 }
13533
13534 $q = "UPDATE `#__vikbooking_optionals` SET `oparams`=" . $dbo->quote(json_encode($cur_params)) ." WHERE `id`=" . (int)$optid . ";";
13535 $dbo->setQuery($q);
13536 $dbo->execute();
13537
13538 echo 'e4j.ok';
13539 exit;
13540 }
13541
13542 /**
13543 * Hidden task to clean up duplicate records in certain database tables
13544 * due to a double execution of the installation queries. Ghost records,
13545 * if any, are also removed to clean up issues with hanging records.
13546 *
13547 * @since November 4th 2020
13548 * @since 1.16.3 (J) - 1.6.3 (WP)
13549 */
13550 public function clean_duplicate_records()
13551 {
13552 $dbo = JFactory::getDbo();
13553
13554 $tables_with_duplicates = [
13555 '#__vikbooking_config' => [
13556 'id_key' => 'id',
13557 'compare_key' => 'param',
13558 ],
13559 '#__vikbooking_countries' => [
13560 'id_key' => 'id',
13561 'compare_key' => 'country_3_code',
13562 ],
13563 '#__vikbooking_custfields' => [
13564 'id_key' => 'id',
13565 'compare_key' => 'name',
13566 ],
13567 '#__vikbooking_texts' => [
13568 'id_key' => 'id',
13569 'compare_key' => 'param',
13570 ],
13571 ];
13572
13573 foreach ($tables_with_duplicates as $tblname => $data) {
13574 $doubles = [];
13575 $storage = [];
13576 $rmlist = [];
13577
13578 $q = "SELECT * FROM `{$tblname}` ORDER BY `{$data['id_key']}` DESC;";
13579 $dbo->setQuery($q);
13580 $rows = $dbo->loadAssocList();
13581 if (!$rows) {
13582 echo "<p>No records found in table {$tblname}</p>";
13583 continue;
13584 }
13585
13586 foreach ($rows as $row) {
13587 if (!isset($doubles[$row[$data['compare_key']]])) {
13588 $doubles[$row[$data['compare_key']]] = 0;
13589 }
13590 $doubles[$row[$data['compare_key']]]++;
13591 if (!isset($storage[$row[$data['compare_key']]])) {
13592 $storage[$row[$data['compare_key']]] = [];
13593 }
13594 array_push($storage[$row[$data['compare_key']]], $row[$data['id_key']]);
13595 }
13596
13597 foreach ($doubles as $paramkey => $paramcount) {
13598 if ($paramcount < 2 || !isset($storage[$paramkey]) || count($storage[$paramkey]) < 2 || $paramcount != count($storage[$paramkey])) {
13599 continue;
13600 }
13601 $exceeding = $paramcount - 1;
13602 for ($x = 0; $x < $exceeding; $x++) {
13603 array_push($rmlist, $storage[$paramkey][$x]);
13604 }
13605 }
13606
13607 echo "<p>Total records found in table {$tblname}: " . count($rows) . "</p>";
13608 echo '<p>Total records to remove: ' . count($rmlist) . '</p>';
13609 echo '<pre style="display: none;">'.print_r($rmlist, true).'</pre><br/>';
13610
13611 if (count($rmlist)) {
13612 $q = "DELETE FROM `{$tblname}` WHERE `{$data['id_key']}` IN (" . implode(', ', $rmlist) . ");";
13613 $dbo->setQuery($q);
13614 $dbo->execute();
13615 }
13616 }
13617
13618 /**
13619 * Clean up busy records where the busy relations contain empty booking IDs.
13620 */
13621 $hanging_busy_ids = [];
13622
13623 $q = "SELECT `idbusy` FROM `#__vikbooking_ordersbusy` WHERE `idorder` = 0 OR `idorder` IS NULL;";
13624 $dbo->setQuery($q);
13625 $removelist = $dbo->loadAssocList();
13626 if ($removelist) {
13627 foreach ($removelist as $hanging_busy) {
13628 $hanging_busy_id = (int)$hanging_busy['idbusy'];
13629 if (!in_array($hanging_busy_id, $hanging_busy_ids)) {
13630 array_push($hanging_busy_ids, $hanging_busy_id);
13631 }
13632 }
13633 }
13634
13635 // let's check also for ghost records that only occupy the room
13636 $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);";
13637 $dbo->setQuery($q);
13638 $removelist = $dbo->loadAssocList();
13639 if ($removelist) {
13640 foreach ($removelist as $hanging_busy) {
13641 $hanging_busy_id = (int)$hanging_busy['id'];
13642 if (!in_array($hanging_busy_id, $hanging_busy_ids)) {
13643 array_push($hanging_busy_ids, $hanging_busy_id);
13644 }
13645 }
13646 }
13647
13648 if ($hanging_busy_ids) {
13649 $q = "DELETE FROM `#__vikbooking_busy` WHERE `id` IN (" . implode(', ', $hanging_busy_ids) . ");";
13650 $dbo->setQuery($q);
13651 $dbo->execute();
13652 }
13653
13654 echo "<p>Total ghost records removed: " . count($hanging_busy_ids) . "</p>";
13655
13656 return;
13657 }
13658
13659 /**
13660 * Loads a specific admin widget ID and executes the requested method.
13661 * Useful for loading a newly added widget, or to execute custom methods.
13662 *
13663 * @see this is an AJAX endpoint.
13664 *
13665 * @since 1.14 (J) - 1.4.0 (WP)
13666 * @since 1.15 (J) - 1.5.0 (WP) widget callback can return values rather than just echoing.
13667 */
13668 public function exec_admin_widget()
13669 {
13670 if (!JSession::checkToken()) {
13671 // missing CSRF-proof token
13672 VBOHttpDocument::getInstance()->close(403, JText::translate('JINVALID_TOKEN'));
13673 }
13674
13675 $widget_id = VikRequest::getString('widget_id', '', 'request');
13676 $call = VikRequest::getString('call', '', 'request');
13677 $return = VikRequest::getInt('return', 0, 'request');
13678 $vbo_page = VikRequest::getString('vbo_page', '', 'request');
13679 $vbo_uri = VikRequest::getString('vbo_uri', '', 'request');
13680 $multitask = VikRequest::getInt('multitask', 0, 'request');
13681
13682 if (empty($widget_id)) {
13683 VBOHttpDocument::getInstance()->close(500, 'Empty Admin Widget ID');
13684 }
13685
13686 if (empty($call) || !is_string($call)) {
13687 VBOHttpDocument::getInstance()->close(500, 'Empty Admin Widget Callback');
13688 }
13689
13690 // invoke admin widgets helper
13691 $widgets_helper = VikBooking::getAdminWidgetsInstance();
13692 $widget = $widgets_helper->getWidget($widget_id);
13693
13694 if ($widget === false) {
13695 VBOHttpDocument::getInstance()->close(404, 'Requested Admin Widget not found');
13696 }
13697
13698 if (!method_exists($widget, $call) || !is_callable(array($widget, $call))) {
13699 VBOHttpDocument::getInstance()->close(403, 'Admin Widget Callback not found or not callable');
13700 }
13701
13702 // check if arguments should be passed
13703 $call_args = [];
13704 if ($multitask && $call === 'render') {
13705 // build the multitask data object and inject it to the args
13706 $call_args[] = VBOMultitaskParser::getInstance($vbo_page, $vbo_uri)->getData();
13707 }
13708
13709 if ($return) {
13710 // invoke the widget's method and get the value returned
13711 $widget_response = count($call_args) ? call_user_func_array([$widget, $call], $call_args) : $widget->{$call}();
13712 } else {
13713 // invoke the widget's method within a buffer
13714 ob_start();
13715 if (count($call_args)) {
13716 $res = call_user_func_array([$widget, $call], $call_args);
13717 } else {
13718 $widget->{$call}();
13719 }
13720 $widget_response = ob_get_contents();
13721 ob_end_clean();
13722 }
13723
13724 // prepare response object with a property equal to the called method
13725 $response = new stdClass;
13726 $response->{$call} = $widget_response;
13727
13728 // output the JSON encoded response and exit
13729 VBOHttpDocument::getInstance()->json($response);
13730 }
13731
13732 /**
13733 * Updates the map of admin widgets.
13734 *
13735 * @throws Exception this is an AJAX endpoint.
13736 *
13737 * @since 1.4.0
13738 */
13739 public function save_admin_widgets()
13740 {
13741 if (!JSession::checkToken()) {
13742 // missing CSRF-proof token
13743 VBOHttpDocument::getInstance()->close(403, JText::translate('JINVALID_TOKEN'));
13744 }
13745
13746 // make sure permissions are sufficient
13747 if (!JFactory::getUser()->authorise('core.vbo.global', 'com_vikbooking')) {
13748 VBOHttpDocument::getInstance()->close(403, 'You are not authorized to modify the widgets.');
13749 }
13750
13751 $psections = VikRequest::getVar('sections', array(), 'request', 'array');
13752 if (!is_array($psections) || !count($psections)) {
13753 VBOHttpDocument::getInstance()->close(500, 'No sections found in map');
13754 }
13755
13756 // request values are all converted to arrays, so restore the object styling
13757 $psections = json_decode(json_encode($psections));
13758
13759 // update map
13760 $result = VikBooking::getAdminWidgetsInstance()->updateWidgetsMap($psections);
13761
13762 $response = new stdClass;
13763 $response->status = (int)$result;
13764
13765 // output the JSON encoded response and exit
13766 VBOHttpDocument::getInstance()->json($response);
13767 }
13768
13769 /**
13770 * Restores the default admin widgets map.
13771 *
13772 * @since 1.4.0
13773 */
13774 public function reset_admin_widgets()
13775 {
13776 // reset map and redirect to dashboard
13777 VikBooking::getAdminWidgetsInstance()->restoreDefaultWidgetsMap();
13778
13779 JFactory::getApplication()->redirect('index.php?option=com_vikbooking');
13780 exit;
13781 }
13782
13783 /**
13784 * Updates the welcome message status for the widget's customizer via AJAX.
13785 *
13786 * @since 1.4.0
13787 */
13788 public function admin_widgets_welcome()
13789 {
13790 if (!JSession::checkToken()) {
13791 // missing CSRF-proof token
13792 VBOHttpDocument::getInstance()->close(403, JText::translate('JINVALID_TOKEN'));
13793 }
13794
13795 $hide_welcome = VikRequest::getInt('hide_welcome', 0, 'request');
13796 // update configuration value
13797 VikBooking::getAdminWidgetsInstance()->updateWelcome($hide_welcome);
13798
13799 $response = new stdClass;
13800 $response->status = $hide_welcome;
13801
13802 // output the JSON encoded response and exit
13803 VBOHttpDocument::getInstance()->json($response);
13804 }
13805
13806 public function newcondtext()
13807 {
13808 VikBookingHelper::printHeader("11");
13809
13810 VikRequest::setVar('view', VikRequest::getCmd('view', 'managecondtext'));
13811
13812 parent::display();
13813
13814 if (VikBooking::showFooter()) {
13815 VikBookingHelper::printFooter();
13816 }
13817 }
13818
13819 public function editcondtext()
13820 {
13821 VikBookingHelper::printHeader("11");
13822
13823 VikRequest::setVar('view', VikRequest::getCmd('view', 'managecondtext'));
13824
13825 parent::display();
13826
13827 if (VikBooking::showFooter()) {
13828 VikBookingHelper::printFooter();
13829 }
13830 }
13831
13832 public function cancelcondtext()
13833 {
13834 JFactory::getApplication()->redirect('index.php?option=com_vikbooking&task=config&tab=7');
13835 }
13836
13837 public function createcondtext()
13838 {
13839 if (!JSession::checkToken()) {
13840 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
13841 }
13842 $this->_doCreateCondText();
13843 }
13844
13845 public function createcondtextstay()
13846 {
13847 if (!JSession::checkToken()) {
13848 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
13849 }
13850 $this->_doCreateCondText(true);
13851 }
13852
13853 private function _doCreateCondText($stay = false)
13854 {
13855 $dbo = JFactory::getDbo();
13856 $app = JFactory::getApplication();
13857 $rules_helper = VikBooking::getConditionalRulesInstance();
13858 $rules_list = $rules_helper->composeRulesParamsFromRequest();
13859
13860 $condtextname = VikRequest::getString('condtextname', '', 'request');
13861 $condtexttkn = VikRequest::getString('condtexttkn', '', 'request');
13862 $msg = VikRequest::getString('msg', '', 'request', VIKREQUEST_ALLOWRAW);
13863 $debug = VikRequest::getInt('debug', 0, 'request');
13864 if (empty($condtextname)) {
13865 $condtextname = date('Y-m-dHis');
13866 $condtexttkn = '{condition: ' . date('YmdHis') . '}';
13867 }
13868
13869 $existing_tokens = $rules_helper->getSpecialTags();
13870 if (count($existing_tokens) && isset($existing_tokens[$condtexttkn])) {
13871 VikError::raiseWarning('', 'Another conditional text with the same special tag already exists');
13872 $app->redirect('index.php?option=com_vikbooking&task=newcondtext');
13873 exit;
13874 }
13875
13876 $data = new stdClass;
13877 $data->name = $condtextname;
13878 $data->token = $condtexttkn;
13879 $data->rules = json_encode($rules_list);
13880 $data->msg = $msg;
13881 $data->lastupd = JDate::getInstance()->toSql();
13882 $data->debug = $debug;
13883
13884 $dbo->insertObject('#__vikbooking_condtexts', $data, 'id');
13885
13886 if (isset($data->id)) {
13887 $app->enqueueMessage(JText::translate('VBSEASONUPDATED'));
13888 }
13889
13890 if (!$stay || !isset($data->id)) {
13891 $this->cancelcondtext();
13892 exit;
13893 }
13894
13895 $app->redirect('index.php?option=com_vikbooking&task=editcondtext&cid[]=' . $data->id);
13896 }
13897
13898 public function updatecondtext()
13899 {
13900 if (!JSession::checkToken()) {
13901 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
13902 }
13903 $this->_doUpdateCondText();
13904 }
13905
13906 public function updatecondtextstay()
13907 {
13908 if (!JSession::checkToken()) {
13909 throw new Exception(JText::translate('JINVALID_TOKEN'), 403);
13910 }
13911 $this->_doUpdateCondText(true);
13912 }
13913
13914 private function _doUpdateCondText($stay = false)
13915 {
13916 $dbo = JFactory::getDbo();
13917 $app = JFactory::getApplication();
13918 $rules_helper = VikBooking::getConditionalRulesInstance();
13919 $rules_list = $rules_helper->composeRulesParamsFromRequest();
13920
13921 $pwhere = VikRequest::getInt('where', '', 'request');
13922 $condtextname = VikRequest::getString('condtextname', '', 'request');
13923 $condtexttkn = VikRequest::getString('condtexttkn', '', 'request');
13924 $msg = VikRequest::getString('msg', '', 'request', VIKREQUEST_ALLOWRAW);
13925 $debug = VikRequest::getInt('debug', 0, 'request');
13926 if (empty($condtextname)) {
13927 $condtextname = date('Y-m-dHis');
13928 $condtexttkn = '{condition: ' . date('YmdHis') . '}';
13929 }
13930
13931 $existing_tokens = $rules_helper->getSpecialTags();
13932 if (count($existing_tokens) && isset($existing_tokens[$condtexttkn]) && ($existing_tokens[$condtexttkn]['id'] != $pwhere)) {
13933 VikError::raiseWarning('', 'Another conditional text with the same special tag already exists (' . $existing_tokens[$condtexttkn]['name'] . ')');
13934 $app->redirect('index.php?option=com_vikbooking&task=editcondtext&cid[]=' . $pwhere);
13935 exit;
13936 }
13937
13938 $data = new stdClass;
13939 $data->id = $pwhere;
13940 $data->name = $condtextname;
13941 $data->token = $condtexttkn;
13942 $data->rules = json_encode($rules_list);
13943 $data->msg = $msg;
13944 $data->lastupd = JDate::getInstance()->toSql();
13945 $data->debug = $debug;
13946
13947 $dbo->updateObject('#__vikbooking_condtexts', $data, 'id');
13948
13949 $app->enqueueMessage(JText::translate('VBSEASONUPDATED'));
13950
13951 if (!$stay) {
13952 $this->cancelcondtext();
13953 exit;
13954 }
13955
13956 $app->redirect('index.php?option=com_vikbooking&task=editcondtext&cid[]=' . $data->id);
13957 }
13958
13959 public function removecondtext()
13960 {
13961 $dbo = JFactory::getDbo();
13962 $ids = VikRequest::getVar('cid', array());
13963
13964 VikBooking::getConditionalRulesInstance(true);
13965 $templates = VikBookingHelperConditionalRules::getTemplateFilesPaths();
13966
13967 foreach ($ids as $d) {
13968 $q = "SELECT `token` FROM `#__vikbooking_condtexts` WHERE `id`=" . (int)$d . ";";
13969 $dbo->setQuery($q);
13970 $dbo->execute();
13971 if (!$dbo->getNumRows()) {
13972 continue;
13973 }
13974 $special_tag = $dbo->loadResult();
13975
13976 // remove the token from each template file if it was used before
13977 if (!empty($special_tag)) {
13978 // remove token from all template files
13979 foreach ($templates as $tkey => $tpath) {
13980 // get requested file content
13981 $fcontent = VikBookingHelperConditionalRules::getTemplateFileCode($tkey);
13982 if (empty($fcontent) || !is_string($fcontent)) {
13983 break;
13984 }
13985 // remove tag from code content
13986 $fcontent = str_replace($special_tag, '', $fcontent);
13987 // update the file code
13988 VikBookingHelperConditionalRules::writeTemplateFileCode($tkey, $fcontent);
13989 }
13990 }
13991
13992 // delete the record
13993 $q = "DELETE FROM `#__vikbooking_condtexts` WHERE `id`=" . (int)$d . ";";
13994 $dbo->setQuery($q);
13995 $dbo->execute();
13996 }
13997
13998 $this->cancelcondtext();
13999 }
14000
14001 /**
14002 * AJAX endpoint to update one template file with the given tag or styles.
14003 * A JSON response will be echoed by exiting the process.
14004 */
14005 public function condtext_update_tmpl()
14006 {
14007 VikBooking::getConditionalRulesInstance(true);
14008
14009 $tagaction = VikRequest::getString('tagaction', '', 'request');
14010 $tag = VikRequest::getString('tag', '', 'request');
14011 $file = VikRequest::getString('file', '', 'request', VIKREQUEST_ALLOWRAW);
14012 $newcontent = VikRequest::getString('newcontent', '', 'request', VIKREQUEST_ALLOWRAW);
14013 $custom_classes = VikRequest::getVar('custom_classes', array(), 'request', 'array');
14014
14015 $allowed_actions = array(
14016 'add',
14017 'remove',
14018 'styles',
14019 'restore',
14020 );
14021
14022 if (empty($tagaction) || empty($file) || !in_array($tagaction, $allowed_actions)) {
14023 throw new Exception("Invalid request submitted", 500);
14024 }
14025
14026 if (in_array($tagaction, array('add', 'remove')) && empty($tag)) {
14027 throw new Exception("Invalid request submitted - missing tag", 500);
14028 }
14029
14030 if (in_array($tagaction, array('add', 'styles')) && empty($newcontent)) {
14031 throw new Exception("Invalid request submitted - missing new HTML content", 500);
14032 }
14033
14034 if ($tagaction == 'styles' && (!is_array($custom_classes) || !count($custom_classes))) {
14035 throw new Exception("No custom CSS classes to parse", 500);
14036 }
14037
14038 if ($tagaction == 'restore') {
14039 // immediately restore the requested file to avoid script interruptions
14040 VikBookingHelperConditionalRules::restoreTemplateFileCode($file);
14041 }
14042
14043 // get requested file content
14044 $fcontent = VikBookingHelperConditionalRules::getTemplateFileCode($file);
14045 if (empty($fcontent) || !is_string($fcontent)) {
14046 throw new Exception("File not found or its code is unreadable", 404);
14047 }
14048
14049 if ($tagaction == 'remove') {
14050 // remove tag from code content
14051 $fcontent = str_replace($tag, '', $fcontent);
14052 } elseif ($tagaction == 'add') {
14053 // add tag to code content in the same exact position
14054 $fcontent = VikBookingHelperConditionalRules::addTagByComparingSources($tag, $file, $newcontent, $fcontent);
14055 } elseif ($tagaction == 'styles') {
14056 // apply the same styling rules
14057 $fcontent = VikBookingHelperConditionalRules::addStylesByComparingSources($custom_classes, $file, $newcontent, $fcontent);
14058 }
14059
14060 // update the file code
14061 $res = VikBookingHelperConditionalRules::writeTemplateFileCode($file, $fcontent);
14062
14063 if (!$res) {
14064 throw new Exception("Could not update the source code of the template file", 500);
14065 }
14066
14067 // parse new HTML content
14068 $newhtmls = VikBookingHelperConditionalRules::getTemplateFilesContents($file);
14069 if (!is_array($newhtmls) || !isset($newhtmls[$file])) {
14070 throw new Exception("Could not parse new template file content", 404);
14071 }
14072
14073 // trigger backup/mirroring, if available
14074 if (defined('ABSPATH')) {
14075 VikBookingUpdateManager::storeTemplateContent($file, $newhtmls[$file]);
14076 }
14077
14078 // build output
14079 $output = new stdClass;
14080 $output->newhtml = $newhtmls[$file];
14081 $output->log = VikBookingHelperConditionalRules::getEditingLog();
14082
14083 echo json_encode($output);
14084 exit;
14085 }
14086
14087 /**
14088 * AJAX endpoint to invoke methods of the geocoding helper.
14089 */
14090 public function geocoding_endpoint()
14091 {
14092 $geo = VikBooking::getGeocodingInstance();
14093 $callback = VikRequest::getString('callback', '', 'request');
14094
14095 if (empty($callback) || !method_exists($geo, $callback) || !is_callable(array($geo, $callback))) {
14096 throw new Exception("Callback not available", 403);
14097 }
14098
14099 // invoke requested method
14100 $res = $geo->{$callback}();
14101
14102 // prepare response
14103 $response = new stdClass;
14104 $response->{$callback} = $res;
14105
14106 echo json_encode($response);
14107 exit;
14108 }
14109
14110 public function refundtn()
14111 {
14112 //modal box, so we do not set menu or footer
14113
14114 VikRequest::setVar('view', VikRequest::getCmd('view', 'refundtn'));
14115
14116 parent::display();
14117 }
14118
14119 public function do_refundtn()
14120 {
14121 $dbo = JFactory::getDbo();
14122 $app = JFactory::getApplication();
14123
14124 $bid = VikRequest::getInt('bid', 0, 'request');
14125 $amount = VikRequest::getFloat('amount', 0, 'request');
14126 $refund_reason = VikRequest::getString('refund_reason', '', 'request');
14127 $tmpl = VikRequest::getString('tmpl', '', 'request');
14128 $nav_suffix = $tmpl == 'component' ? '&tmpl=component' : '';
14129
14130 $currencysymb = VikBooking::getCurrencySymb();
14131
14132 if (empty($bid) || $amount <= 0) {
14133 VikError::raiseWarning('', JText::translate('VBO_PLEASE_FILL_FIELDS'));
14134 $app->redirect('index.php?option=com_vikbooking');
14135 exit;
14136 }
14137
14138 $q = "SELECT * FROM `#__vikbooking_orders` WHERE `id`=" . $bid . " AND `status`!='standby';";
14139 $dbo->setQuery($q);
14140 $dbo->execute();
14141 if ($dbo->getNumRows() < 1) {
14142 VikError::raiseWarning('', 'Booking not found');
14143 $app->redirect('index.php?option=com_vikbooking');
14144 exit;
14145 }
14146 $row = $dbo->loadAssoc();
14147
14148 // get booking history instance
14149 $history_obj = VikBooking::getBookingHistoryInstance();
14150 $history_obj->setBid($row['id']);
14151
14152 // get payment information
14153 $payment = VikBooking::getPayment($row['idpayment']);
14154 $tn_driver = is_array($payment) ? $payment['file'] : null;
14155
14156 // transaction data validation callback
14157 $tn_data_callback = function($data) use ($tn_driver) {
14158 return (is_object($data) && isset($data->driver) && basename($data->driver, '.php') == basename($tn_driver, '.php'));
14159 };
14160 // get previous transactions
14161 $prev_tn_data = $history_obj->getEventsWithData(array('P0', 'PN'), $tn_data_callback);
14162
14163 if (!is_array($prev_tn_data) || !count($prev_tn_data)) {
14164 // no previous transactions found
14165 VikError::raiseWarning('', 'No previous transactions found, unable to issue the refund');
14166 $app->redirect('index.php?option=com_vikbooking&task=refundtn&cid[]=' . $row['id'] . $nav_suffix);
14167 exit;
14168 }
14169
14170 // push refund information for the payment gateway
14171 $row['total_to_refund'] = $amount;
14172 $row['transaction'] = $prev_tn_data;
14173 $row['refund_reason'] = $refund_reason;
14174
14175 // push the transaction currency information
14176 $row['transaction_currency'] = VikBooking::getCurrencyCodePp();
14177
14178 /**
14179 * @wponly The payment gateway is loaded
14180 * through the apposite dispatcher.
14181 */
14182 JLoader::import('adapter.payment.dispatcher');
14183 $obj = JPaymentDispatcher::getInstance('vikbooking', $payment['file'], $row, $payment['params']);
14184
14185 if (!method_exists($obj, 'isRefundSupported') || !$obj->isRefundSupported()) {
14186 // refund not supported
14187 VikError::raiseWarning('', 'The selected payment method does not support refunds');
14188 $app->redirect('index.php?option=com_vikbooking&task=refundtn&cid[]=' . $row['id'] . $nav_suffix);
14189 exit;
14190 }
14191
14192 // perform the refund transaction
14193 $array_result = $obj->refund();
14194
14195 if ($array_result['verified'] != 1) {
14196 // raise warning by getting the message
14197 if (!empty($array_result['log']) && is_string($array_result['log'])) {
14198 VikError::raiseWarning('', $array_result['log']);
14199 } else {
14200 VikError::raiseWarning('', 'Operation failed');
14201 }
14202 $app->redirect('index.php?option=com_vikbooking&task=refundtn&cid[]=' . $row['id'] . $nav_suffix);
14203 exit;
14204 }
14205
14206 /**
14207 * New payment plugins can return the total amount refunded ('tot_paid').
14208 *
14209 * @since 1.15.4 (J) - 1.5.10 (WP)
14210 */
14211 if (!empty($array_result['tot_paid'])) {
14212 // overwrite the requested amount with the returned one
14213 $amount = (float)$array_result['tot_paid'];
14214 }
14215
14216 // update total paid, total and refund columns for the booking
14217 $booking = new stdClass;
14218 $booking->id = $row['id'];
14219 if ($row['totpaid'] > 0) {
14220 $booking->totpaid = $row['totpaid'] - $amount;
14221 }
14222 if ($row['total'] > 0) {
14223 $booking->total = $row['total'] - $amount;
14224 }
14225 $booking->refund = (float)$row['refund'] + $amount;
14226 // update record in db
14227 $dbo->updateObject('#__vikbooking_orders', $booking, 'id');
14228
14229 // store the refund event
14230 $event_descr = array(
14231 '(' . $payment['name'] . ')',
14232 $refund_reason,
14233 $currencysymb . ' ' . VikBooking::numberFormat($amount),
14234 );
14235 $history_obj->store('RF', implode("\n", $event_descr));
14236
14237 // display success message and redirect
14238 $app->enqueueMessage(JText::translate('VBO_REFUND_SUCCESS'));
14239 $app->redirect('index.php?option=com_vikbooking&task=refundtn&cid[]=' . $row['id'] . '&success=1' . $nav_suffix);
14240 exit;
14241 }
14242
14243 /**
14244 * AJAX upload endpoint for media files.
14245 *
14246 * @return void
14247 *
14248 * @throws Exception
14249 *
14250 * @since 1.15.0 (J) - 1.5.0 (WP)
14251 */
14252 public function upload_media_file()
14253 {
14254 $input = JFactory::getApplication()->input;
14255
14256 // allowed types
14257 $type = $input->getString('type', '');
14258 $mask = "/(image\/.+)|(application\/(zip|rar|pdf|msword|vnd.*?))|(text\/(plain|markdown|csv))$/i";
14259 if ($type == 'image') {
14260 $mask = "/(image\/.+)$/i";
14261 }
14262
14263 // response object
14264 $result = new stdClass;
14265 $result->status = 0;
14266
14267 try
14268 {
14269 // get file from request
14270 $file = $input->files->get('file', array(), 'array');
14271
14272 // try to upload the file
14273 $result = VikBooking::uploadFileFromRequest($file, VBO_MEDIA_PATH, $mask);
14274 $result->status = 1;
14275
14276 $result->size = JHtml::fetch('number.bytes', filesize($result->path), 'auto', 0);
14277 $result->url = str_replace(DIRECTORY_SEPARATOR, '/', str_replace(VBO_MEDIA_PATH . DIRECTORY_SEPARATOR, VBO_MEDIA_URI, $result->path));
14278 }
14279 catch (Exception $e)
14280 {
14281 $result->error = $e->getMessage();
14282 $result->code = $e->getCode();
14283 }
14284
14285 echo json_encode($result);
14286 exit;
14287 }
14288
14289 /**
14290 * AJAX endpoint to invoke a report object's method.
14291 *
14292 * @return void
14293 *
14294 * @throws Exception
14295 *
14296 * @since 1.15.0 (J) - 1.5.0 (WP)
14297 */
14298 public function invoke_report()
14299 {
14300 $report_name = VikRequest::getString('report', '', 'request');
14301 $report_call = VikRequest::getString('call', '', 'request');
14302 $params = VikRequest::getVar('params', array(), 'request', 'array');
14303
14304 if (empty($report_name)) {
14305 VBOHttpDocument::getInstance()->close(400, 'Missing report name');
14306 }
14307
14308 if (empty($report_call)) {
14309 VBOHttpDocument::getInstance()->close(400, 'Missing report call');
14310 }
14311
14312 // get requested report instance
14313 $report = VikBooking::getReportInstance($report_name);
14314 if (!$report) {
14315 VBOHttpDocument::getInstance()->close(404, 'Report not found');
14316 }
14317
14318 if (!method_exists($report, $report_call) || !is_callable(array($report, $report_call))) {
14319 VBOHttpDocument::getInstance()->close(403, sprintf('Cannot call [%s] on report', $report_call));
14320 }
14321
14322 // call on report's method
14323 $result = $report->{$report_call}($params);
14324
14325 if (is_null($result)) {
14326 VBOHttpDocument::getInstance()->close(400, 'Null response');
14327 }
14328
14329 if (is_scalar($result)) {
14330 // wrap result within an array for a JSON encoded response
14331 VBOHttpDocument::getInstance()->json([$result]);
14332 }
14333
14334 // output the JSON encoded array/object returned
14335 VBOHttpDocument::getInstance()->json($result);
14336 }
14337
14338 /**
14339 * Handles requests for the multitask widgets panel.
14340 *
14341 * @see this is an AJAX endpoint.
14342 *
14343 * @since 1.15.0 (J) - 1.5.0 (WP)
14344 */
14345 public function exec_multitask_widgets()
14346 {
14347 if (!JSession::checkToken()) {
14348 // missing CSRF-proof token
14349 VBOHttpDocument::getInstance()->close(403, JText::translate('JINVALID_TOKEN'));
14350 }
14351
14352 $call = VikRequest::getString('call', '', 'request');
14353 $call_args = VikRequest::getVar('call_args', array(), 'request', 'array');
14354
14355 if (empty($call)) {
14356 VBOHttpDocument::getInstance()->close(500, 'Empty Admin Widget Callback');
14357 }
14358
14359 // invoke admin widgets helper
14360 $widgets_helper = VikBooking::getAdminWidgetsInstance();
14361
14362 if (!method_exists($widgets_helper, $call) || !is_callable(array($widgets_helper, $call))) {
14363 VBOHttpDocument::getInstance()->close(403, 'Admin Widgets Callback not found or not callable');
14364 }
14365
14366 // invoke the helper's method and get the value returned
14367 if (is_array($call_args) && count($call_args)) {
14368 $result = call_user_func_array(array($widgets_helper, $call), $call_args);
14369 } else {
14370 $result = $widgets_helper->{$call}();
14371 }
14372
14373 // prepare response object with a property equal to the called method
14374 $response = new stdClass;
14375 $response->result = $result;
14376
14377 // output the JSON response and exit
14378 VBOHttpDocument::getInstance()->json($response);
14379 }
14380
14381 /**
14382 * Handles requests for displaying a browser notification being dispatched.
14383 *
14384 * @see this is an AJAX endpoint.
14385 *
14386 * @since 1.15.0 (J) - 1.5.0 (WP)
14387 */
14388 public function notification_displayer()
14389 {
14390 $payload_str = VikRequest::getString('payload', '', 'request', VIKREQUEST_ALLOWRAW);
14391
14392 if (empty($payload_str)) {
14393 VBOHttpDocument::getInstance()->close(500, 'Empty notification payload');
14394 }
14395
14396 // attempt to decode the notification payload
14397 $payload = json_decode($payload_str);
14398
14399 if (!is_object($payload)) {
14400 VBOHttpDocument::getInstance()->close(500, 'Could not decode notification payload: ' . $payload_str);
14401 }
14402
14403 // get notification displayer for this type of notification
14404 $displayer = VBONotificationBuilder::getInstance($payload)->getDisplayer();
14405 if (!$displayer) {
14406 VBOHttpDocument::getInstance()->close(500, 'Could not build notification display data from payload: ' . $payload_str);
14407 }
14408
14409 // compose the notification display data object
14410 $notif_data = $displayer->getData();
14411
14412 // output the JSON response and exit
14413 VBOHttpDocument::getInstance()->json($notif_data);
14414 }
14415
14416 /**
14417 * Handles requests for watching widgets data and getting
14418 * new events to trigger browser notifications.
14419 *
14420 * @see this is an AJAX endpoint.
14421 *
14422 * @since 1.15.0 (J) - 1.5.0 (WP)
14423 */
14424 public function widgets_watch_data()
14425 {
14426 if (!JSession::checkToken()) {
14427 // missing CSRF-proof token
14428 VBOHttpDocument::getInstance()->close(403, JText::translate('JINVALID_TOKEN'));
14429 }
14430
14431 $watch_data_str = VikRequest::getString('watch_data', '', 'request', VIKREQUEST_ALLOWRAW);
14432
14433 if (empty($watch_data_str)) {
14434 VBOHttpDocument::getInstance()->close(500, 'Empty watch-data payload');
14435 }
14436
14437 // attempt to decode the watch-data payload
14438 $watch_data = json_decode($watch_data_str, true);
14439
14440 if (!is_array($watch_data) || !count($watch_data)) {
14441 VBOHttpDocument::getInstance()->close(500, 'Could not decode watch-data payload: ' . $watch_data_str);
14442 }
14443
14444 // container for new notifications
14445 $notifs_pool = [];
14446
14447 // get admin widgets helper
14448 $widgets_helper = VikBooking::getAdminWidgetsInstance();
14449
14450 foreach ($watch_data as $widget_id => $data) {
14451 // invoke admin widget (with no pre-loading)
14452 $widget_instance = $widgets_helper->getWidget($widget_id);
14453 if (!$widget_instance) {
14454 continue;
14455 }
14456
14457 // build the widget watch data object
14458 $widget_watch_data = VBONotificationWatchdata::getInstance($data);
14459
14460 // check if the widget needs to emit browser notifications
14461 list($watch_next, $notifications) = $widget_instance->getNotifications($widget_watch_data);
14462
14463 if ($watch_next) {
14464 // update next watch-data object for this widget
14465 $watch_data[$widget_id] = $watch_next;
14466 }
14467
14468 if (is_array($notifications) && count($notifications)) {
14469 $notifs_pool = array_merge($notifs_pool, $notifications);
14470 }
14471 }
14472
14473 // build the response object
14474 $response = new stdClass;
14475 $response->watch_data = $watch_data;
14476 $response->notifications = $notifs_pool;
14477
14478 // output the JSON response and exit
14479 VBOHttpDocument::getInstance()->json($response);
14480 }
14481
14482 /**
14483 * Outputs a list of CSS assets required to render the admin widgets
14484 * externally from Vik Booking. Useful i.e. to Vik Channel Manager.
14485 *
14486 * @see this is an AJAX endpoint.
14487 *
14488 * @since 1.16.0 (J) - 1.6.0 (WP)
14489 */
14490 public function widgets_get_assets()
14491 {
14492 // list of needed CSS asset details
14493 $assets_pool = [];
14494
14495 // appearance preference assets (one or none)
14496 $app_pref_asset = VikBooking::loadAppearancePreferenceAssets($get_info = true);
14497
14498 if (defined('ABSPATH') && function_exists('wp_die')) {
14499 // WordPress (main CSS)
14500 $assets_pool[] = [
14501 'rel' => 'stylesheet',
14502 'id' => 'vbo-style-css',
14503 'href' => VIKBOOKING_ADMIN_ASSETS_URI . 'vikbooking.css?ver=' . VIKBOOKING_SOFTWARE_VERSION,
14504 'media' => 'all',
14505 ];
14506
14507 if (is_array($app_pref_asset) && !empty($app_pref_asset['href'])) {
14508 // appearance preference CSS
14509 $assets_pool[] = [
14510 'rel' => 'stylesheet',
14511 'id' => (!empty($app_pref_asset['id']) ? $app_pref_asset['id'] : rand()),
14512 'href' => $app_pref_asset['href'] . '?ver=' . VIKBOOKING_SOFTWARE_VERSION,
14513 'media' => 'all',
14514 ];
14515 }
14516 } else {
14517 // Joomla (main CSS)
14518 $assets_pool[] = [
14519 'rel' => 'stylesheet',
14520 'id' => 'vbo-style-css',
14521 'href' => VBO_ADMIN_URI . 'vikbooking.css?' . VIKBOOKING_SOFTWARE_VERSION,
14522 'media' => 'all',
14523 ];
14524
14525 if (is_array($app_pref_asset) && !empty($app_pref_asset['href'])) {
14526 // appearance preference CSS
14527 $assets_pool[] = [
14528 'rel' => 'stylesheet',
14529 'id' => (!empty($app_pref_asset['id']) ? $app_pref_asset['id'] : rand()),
14530 'href' => $app_pref_asset['href'] . '?' . VIKBOOKING_SOFTWARE_VERSION,
14531 'media' => 'all',
14532 ];
14533 }
14534 }
14535
14536 // output the JSON response and exit
14537 VBOHttpDocument::getInstance()->json($assets_pool);
14538 }
14539 }
14540