PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.8.15
VikBooking Hotel Booking Engine & PMS v1.8.15
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 / helpers / widgets / arriving_today.php

arriving_today.php in VikBooking Hotel Booking Engine & PMS 1.8.15, at admin/helpers/widgets/arriving_today.php

439 lines 16.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package VikBooking
4 * @subpackage com_vikbooking
5 * @author Alessio Gaggii - e4j - Extensionsforjoomla.com
6 * @copyright Copyright (C) 2018 e4j - Extensionsforjoomla.com. All rights reserved.
7 * @license GNU General Public License version 2 or later; see LICENSE
8 * @link https://vikwp.com
9 */
10
11 defined('ABSPATH') or die('No script kiddies please!');
12
13 /**
14 * Class handler for admin widget "arriving today".
15 *
16 * @since 1.14 (J) - 1.4.0 (WP)
17 */
18 class VikBookingAdminWidgetArrivingToday extends VikBookingAdminWidget
19 {
20 /**
21 * The instance counter of this widget. Since we do not load individual parameters
22 * for each widget's instance, we use a static counter to determine its settings.
23 *
24 * @var int
25 */
26 protected static $instance_counter = -1;
27
28 /**
29 * Class constructor will define the widget name and identifier.
30 */
31 public function __construct()
32 {
33 // call parent constructor
34 parent::__construct();
35
36 $this->widgetName = JText::translate('VBO_W_ARRIVETOD_TITLE');
37 $this->widgetDescr = JText::translate('VBO_W_ARRIVETOD_DESCR');
38 $this->widgetId = basename(__FILE__, '.php');
39
40 /**
41 * Define widget and icon and style name.
42 *
43 * @since 1.15.0 (J) - 1.5.0 (WP)
44 */
45 $this->widgetIcon = '<i class="' . VikBookingIcons::i('plane-arrival') . '"></i>';
46 $this->widgetStyleName = 'light-red';
47 }
48
49 public function render(?VBOMultitaskData $data = null)
50 {
51 // increase widget's instance counter
52 static::$instance_counter++;
53
54 // check whether the widget is being rendered via AJAX when adding it through the customizer
55 $is_ajax = $this->isAjaxRendering();
56
57 // widget instance identifier
58 $widget_instance = $is_ajax ? -1 : static::$instance_counter;
59
60 // get arrivals for today
61 $checkin_today = $this->getArrivals();
62
63 // count arrivals
64 $tot_arrivals = 0;
65 foreach ($checkin_today as $in_today) {
66 if ($in_today['status'] == 'confirmed') {
67 $tot_arrivals++;
68 }
69 }
70
71 // render the necessary PHP/JS code for the modal window only once
72 if (!defined('VBO_JMODAL_CHECKIN_BOOKING')) {
73 define('VBO_JMODAL_CHECKIN_BOOKING', 1);
74 ?>
75 <script type="text/javascript">
76 function vboJModalShowCallback() {
77 if (typeof vbo_t_on == "undefined") {
78 return;
79 }
80 // simulate STOP click
81 if (vbo_t_on) {
82 vbo_t_on = false;
83 clearTimeout(vbo_t);
84 jQuery(".vbo-dashboard-refresh-play").fadeIn();
85 }
86 }
87 function vboJModalHideCallback() {
88 if (typeof vbo_t_on == "undefined") {
89 return;
90 }
91 // simulate PLAY click
92 if (!vbo_t_on) {
93 vboStartTimer();
94 jQuery(".vbo-dashboard-refresh-play").fadeOut();
95 }
96 }
97 </script>
98 <?php
99 echo $this->vbo_app->getJmodalScript('', 'vboJModalHideCallback();', 'vboJModalShowCallback();');
100 echo $this->vbo_app->getJmodalHtml('vbo-checkin-booking', JText::translate('VBOMANAGECHECKSINOUT'));
101 }
102
103 // prepare tristate toggle switch values
104 $multistate_vals = array(
105 'today',
106 'tomorrow',
107 'yesterday',
108 );
109 $multistate_lbls = array(
110 array(
111 'value' => JText::translate('VBTODAY'),
112 ),
113 array(
114 'value' => JText::translate('VBOTOMORROW'),
115 ),
116 array(
117 'value' => JText::translate('VBOYESTERDAY'),
118 ),
119 );
120 $multistate_attrs = array(
121 array(
122 'label_class' => 'vik-multiswitch-text vik-multiswitch-radiobtn-today',
123 'input' => array(
124 'onchange' => 'vboWidgetLoadArrivals(this.value, \'' . $widget_instance . '\')',
125 ),
126 ),
127 array(
128 'label_class' => 'vik-multiswitch-text vik-multiswitch-radiobtn-tomorrow',
129 'input' => array(
130 'onchange' => 'vboWidgetLoadArrivals(this.value, \'' . $widget_instance . '\')',
131 ),
132 ),
133 array(
134 'label_class' => 'vik-multiswitch-text vik-multiswitch-radiobtn-yesterday',
135 'input' => array(
136 'onchange' => 'vboWidgetLoadArrivals(this.value, \'' . $widget_instance . '\')',
137 ),
138 ),
139 );
140 $wrap_attrs = array(
141 'class' => 'vik-multiswitch-noanimation',
142 );
143
144 ?>
145 <div class="vbo-admin-widget-wrapper" id="vbo-widget-today-checkin-<?php echo $widget_instance; ?>">
146 <div class="vbo-admin-widget-head vbo-dashboard-today-checkin-head">
147 <div class="vbo-admin-widget-head-inline">
148 <h4>
149 <?php echo $this->widgetIcon; ?>
150 <span class="arrivals-when"><?php echo JText::translate('VBOARRIVING'); ?></span>
151 <span class="arrivals-tot"><?php echo $tot_arrivals; ?></span>
152 </h4>
153 <div class="vbo-dashboard-search-input vbo-dashboard-search-checkin">
154 <div class="btn-wrapper input-append pull-right">
155 <input type="text" class="checkin-search form-control" placeholder="<?php echo JText::translate('VBODASHSEARCHKEYS'); ?>">
156 <button type="button" class="btn" onclick="jQuery('.checkin-search').val('').trigger('keyup');"><i class="icon-remove"></i></button>
157 </div>
158 </div>
159 <div class="vbo-widget-today-checkin-tristate"><?php echo $this->vbo_app->multiStateToggleSwitchField('when_arriving' . $widget_instance, 'today', $multistate_vals, $multistate_lbls, $multistate_attrs, $wrap_attrs); ?></div>
160 </div>
161 </div>
162 <div class="vbo-dashboard-today-checkin table-responsive">
163 <table class="table vbo-table-search-cin">
164 <thead>
165 <tr class="vbo-dashboard-today-checkin-firstrow">
166 <th class="left"><?php echo JText::translate('VBDASHUPRESONE'); ?></th>
167 <th class="left"><?php echo JText::translate('VBCUSTOMERNOMINATIVE'); ?></th>
168 <th class="center"><?php echo JText::translate('VBDASHUPRESSIX'); ?></th>
169 <th class="center"><?php echo JText::translate('VBDASHUPRESTWO'); ?></th>
170 <th class="center"><?php echo JText::translate('VBDASHUPRESFOUR'); ?></th>
171 <th class="center"><?php echo JText::translate('VBDASHUPRESFIVE'); ?></th>
172 <th class="vbo-tdright"> </th>
173 </tr>
174 <tr class="warning no-results">
175 <td colspan="7"><i class="vboicn-warning"></i> <?php echo JText::translate('VBONORESULTS'); ?></td>
176 </tr>
177 </thead>
178 <tbody>
179 <?php
180 // render the rows for the arrivals (if any)
181 echo $this->buildArrivalRows($checkin_today);
182 ?>
183 </tbody>
184 </table>
185 </div>
186 </div>
187
188 <?php
189 if (static::$instance_counter === 0 || $is_ajax) {
190 ?>
191 <script type="text/javascript">
192 /**
193 * Retrieves the arrivals for the given day by making an AJAX request
194 */
195 function vboWidgetLoadArrivals(when, winstance) {
196 // the widget method to call
197 var call_method = 'loadArrivals';
198
199 // make a silent request to get the arrivals
200 VBOCore.doAjax(
201 "<?php echo $this->getExecWidgetAjaxUri(); ?>",
202 {
203 widget_id: "<?php echo $this->getIdentifier(); ?>",
204 call: call_method,
205 tmpl: "component",
206 when: when,
207 },
208 function(response) {
209 try {
210 var obj_res = typeof response === 'string' ? JSON.parse(response) : response;
211 if (!obj_res.hasOwnProperty(call_method)) {
212 console.error('Unexpected JSON response', obj_res);
213 return;
214 }
215
216 var widget_cont = jQuery('#vbo-widget-today-checkin-' + winstance);
217 if (!widget_cont || !widget_cont.length) {
218 console.error('Widget instance not found', winstance);
219 return;
220 }
221
222 // display the list of arrivals for the given day
223 widget_cont.find('table.vbo-table-search-cin tbody').html(obj_res[call_method]);
224
225 // update counter
226 var tot_arrivals = widget_cont.find('table.vbo-table-search-cin tbody').find('tr').not('.warning').length;
227 widget_cont.find('.arrivals-tot').text(tot_arrivals);
228 } catch(err) {
229 console.error('could not parse JSON response', err, response);
230 }
231
232 // in case of search keywords, trigger the keyup event after loading a new arrival type
233 setTimeout(() => {
234 jQuery(".checkin-search").trigger('keyup');
235 }, 200);
236 },
237 function(error) {
238 console.error(error);
239 }
240 );
241 }
242
243 jQuery(function() {
244 /* Attempt to append the modal container to the body for the multitask panel */
245 let modal_container = jQuery('[id*="vbo-checkin-booking"][class*="modal"]');
246 if (modal_container.length) {
247 modal_container.first().appendTo('body');
248 }
249
250 /* Check-in Search */
251 jQuery(".checkin-search").keyup(function() {
252 var inp_elem = jQuery(this);
253 var instance_elem = inp_elem.closest('.vbo-admin-widget-wrapper');
254 var searchTerm = inp_elem.val();
255 var listItem = instance_elem.find('.vbo-table-search-cin tbody').children('tr');
256 var searchSplit = searchTerm.replace(/ /g, "'):containsi('");
257 jQuery.extend(jQuery.expr[':'], {'containsi':
258 function(elem, i, match, array) {
259 return (elem.textContent || elem.innerText || '').toLowerCase().indexOf((match[3] || "").toLowerCase()) >= 0;
260 }
261 });
262 instance_elem.find(".vbo-table-search-cin tbody tr td.searchable").not(":containsi('" + searchSplit + "')").each(function(e) {
263 jQuery(this).parent('tr').attr('visible', 'false');
264 });
265 instance_elem.find(".vbo-table-search-cin tbody tr td.searchable:containsi('" + searchSplit + "')").each(function(e) {
266 jQuery(this).parent('tr').attr('visible', 'true');
267 });
268 var jobCount = parseInt(instance_elem.find('.vbo-table-search-cin tbody tr[visible="true"]').length);
269 instance_elem.find('.arrivals-tot').text(jobCount);
270 if (jobCount > 0) {
271 instance_elem.find('.vbo-table-search-cin').find('.no-results').hide();
272 } else {
273 instance_elem.find('.vbo-table-search-cin').find('.no-results').show();
274 }
275 });
276 });
277 </script>
278 <?php
279 }
280 }
281
282 /**
283 * Custom method for this widget only to load the arrivals for a given day.
284 * The method is called by the admin controller through an AJAX request.
285 * The visibility should be public, it should not exit the process, and
286 * any content sent to output will be returned to the AJAX response.
287 */
288 public function loadArrivals()
289 {
290 $when = VikRequest::getString('when', 'today', 'request');
291
292 echo $this->buildArrivalRows($this->getArrivals($when), $when);
293 }
294
295 /**
296 * Returns the list of arrivals for the given day.
297 *
298 * @param string $when either today, tomorrow, or yesterday.
299 *
300 * @return array list of arrivals, if any.
301 *
302 * @since 1.15.0 (J) - 1.5.0 (WP)
303 */
304 protected function getArrivals($when = 'today')
305 {
306 $dbo = JFactory::getDbo();
307
308 if ($when == 'tomorrow') {
309 $today_start_ts = mktime(0, 0, 0, date("n"), (date("j") + 1), date("Y"));
310 $today_end_ts = mktime(23, 59, 59, date("n"), (date("j") + 1), date("Y"));
311 } elseif ($when == 'yesterday') {
312 $today_start_ts = mktime(0, 0, 0, date("n"), (date("j") - 1), date("Y"));
313 $today_end_ts = mktime(23, 59, 59, date("n"), (date("j") - 1), date("Y"));
314 } else {
315 // today
316 $today_start_ts = mktime(0, 0, 0, date("n"), date("j"), date("Y"));
317 $today_end_ts = mktime(23, 59, 59, date("n"), date("j"), date("Y"));
318 }
319
320 $q = "SELECT `o`.`id`,`o`.`custdata`,`o`.`status`,`o`.`checkin`,`o`.`checkout`,`o`.`roomsnum`,`o`.`country`,`o`.`closure`,`o`.`checked`,`o`.`type`,(SELECT CONCAT_WS(' ',`or`.`t_first_name`,`or`.`t_last_name`) FROM `#__vikbooking_ordersrooms` AS `or` WHERE `or`.`idorder`=`o`.`id` LIMIT 1) AS `nominative`,(SELECT SUM(`or`.`adults`) FROM `#__vikbooking_ordersrooms` AS `or` WHERE `or`.`idorder`=`o`.`id`) AS `tot_adults`,(SELECT SUM(`or`.`children`) FROM `#__vikbooking_ordersrooms` AS `or` WHERE `or`.`idorder`=`o`.`id`) AS `tot_children` FROM `#__vikbooking_orders` AS `o` WHERE `o`.`checkin`>=" . $today_start_ts . " AND `o`.`checkin`<=" . $today_end_ts . " AND `o`.`status`=" . $dbo->q('confirmed') . " AND `o`.`closure`=0 ORDER BY `o`.`checkin` ASC;";
321
322 $dbo->setQuery($q);
323
324 return $dbo->loadAssocList();
325 }
326
327 /**
328 * Builds the HTML string for the given arrivals. We use a method
329 * so that the AJAX requests will be able to rely on this as well.
330 *
331 * @param array $arrivals the list of records found.
332 * @param string $when either today, tomorrow, or yesterday.
333 *
334 * @return string the composed HTML string.
335 *
336 * @since 1.15.0 (J) - 1.5.0 (WP)
337 */
338 protected function buildArrivalRows($arrivals, $when = 'today')
339 {
340 $rows = '';
341
342 $arrivals = !is_array($arrivals) ? array() : $arrivals;
343
344 // check permissions
345 $vbo_auth_bookings = JFactory::getUser()->authorise('core.vbo.bookings', 'com_vikbooking');
346
347 foreach ($arrivals as $ink => $intoday) {
348 $totpeople_str = $intoday['tot_adults']." ".($intoday['tot_adults'] > 1 ? JText::translate('VBMAILADULTS') : JText::translate('VBMAILADULT')).($intoday['tot_children'] > 0 ? ", ".$intoday['tot_children']." ".($intoday['tot_children'] > 1 ? JText::translate('VBMAILCHILDREN') : JText::translate('VBMAILCHILD')) : "");
349 $room_names = array();
350 $rooms = VikBooking::loadOrdersRoomsData($intoday['id']);
351 foreach ($rooms as $rr) {
352 $room_names[] = $rr['room_name'];
353 }
354 if ($intoday['roomsnum'] == 1) {
355 // parse distintive features
356 $unit_index = '';
357 if (strlen($rooms[0]['roomindex'] ?? '') && !empty($rooms[0]['params'])) {
358 $room_params = json_decode($rooms[0]['params'], true);
359 if (is_array($room_params) && array_key_exists('features', $room_params) && @count($room_params['features']) > 0) {
360 foreach ($room_params['features'] as $rind => $rfeatures) {
361 if ($rind == $rooms[0]['roomindex']) {
362 foreach ($rfeatures as $fname => $fval) {
363 if (strlen($fval)) {
364 $unit_index = ' #'.$fval;
365 break;
366 }
367 }
368 break;
369 }
370 }
371 }
372 }
373 //
374 $roomstr = '<span class="vbo-smalltext">' . ($room_names[0] ?? '') . $unit_index . '</span>';
375 } else {
376 $roomstr = '<span class="hasTooltip vbo-tip-small" title="'.implode(', ', $room_names).'">'.$intoday['roomsnum'].'</span><span class="hidden-for-search">'.implode(', ', $room_names).'</span>';
377 }
378 $act_status = '';
379 if ($intoday['status'] == 'confirmed') {
380 switch ($intoday['checked']) {
381 case -1:
382 $ord_status = '<span class="label label-error vbo-status-label">'.JText::translate('VBOCHECKEDSTATUSNOS').'</span>';
383 break;
384 case 1:
385 $ord_status = '<span class="label label-success vbo-status-label">'.JText::translate('VBOCHECKEDSTATUSIN').'</span>';
386 break;
387 case 2:
388 $ord_status = '<span class="label label-success vbo-status-label">'.JText::translate('VBOCHECKEDSTATUSOUT').'</span>';
389 break;
390 default:
391 $ord_status = '<span class="label label-success vbo-status-label">'.JText::translate('VBCONFIRMED').'</span>';
392 break;
393 }
394 if (!strcasecmp((string)$intoday['type'], 'overbooking')) {
395 $ord_status .= '<div class="vbo-orders-substatus"><span class="label label-error">' . JText::translate('VBO_BTYPE_OVERBOOKING') . '</span></div>';
396 }
397 if ($vbo_auth_bookings && $intoday['closure'] != 1) {
398 $act_status = '<button type="button" class="btn btn-small btn-primary" onclick="vboOpenJModal(\'vbo-checkin-booking\', \'index.php?option=com_vikbooking&task=bookingcheckin&cid[]='.$intoday['id'].'&tmpl=component\');">'.JText::translate('VBOMANAGECHECKIN').'</button>';
399 }
400 } elseif ($intoday['status'] == 'standby') {
401 $ord_status = '<span class="label label-warning vbo-status-label">'.JText::translate('VBSTANDBY').'</span>';
402 } else {
403 $ord_status = '<span class="label label-error vbo-status-label">'.JText::translate('VBCANCELLED').'</span>';
404 }
405 $nominative = strlen((string) $intoday['nominative']) > 1 ? $intoday['nominative'] : VikBooking::getFirstCustDataField($intoday['custdata']);
406 $country_flag = '';
407 if (file_exists(VBO_ADMIN_PATH.DS.'resources'.DS.'countries'.DS.$intoday['country'].'.png')) {
408 $country_flag = '<img src="'.VBO_ADMIN_URI.'resources/countries/'.$intoday['country'].'.png'.'" title="'.$intoday['country'].'" class="vbo-country-flag vbo-country-flag-left"/>';
409 }
410
411 $rows .= '<tr class="vbo-dashboard-today-checkin-rows">' . "\n";
412 $rows .= ' <td class="searchable left"><a href="index.php?option=com_vikbooking&amp;task=editorder&amp;cid[]=' . $intoday['id'] . '">' . $intoday['id'] . '</a></td>' . "\n";
413 $rows .= ' <td class="searchable left">' . $country_flag . $nominative . '</td>' . "\n";
414 $rows .= ' <td class="center">' . $totpeople_str . '</td>' . "\n";
415 $rows .= ' <td class="searchable center">' . $roomstr . '</td>' . "\n";
416 $rows .= ' <td class="searchable center">' . date(str_replace("/", $this->datesep, $this->df).' H:i', $intoday['checkout']) . '</td>' . "\n";
417 $rows .= ' <td class="searchable center" data-status="' . $intoday['id'] . '">' . $ord_status . '</td>' . "\n";
418 $rows .= ' <td class="vbo-tdright pro-feature">' . $act_status . '</td>' . "\n";
419 $rows .= '</tr>' . "\n";
420 }
421
422 if (!$arrivals) {
423 // display just the TR with the warning message
424 $no_arrivals_when = JText::translate('VBONOCHECKINSTODAY');
425 if ($when == 'yesterday') {
426 $no_arrivals_when = JText::translate('VBONOCHECKINSYESTERDAY');
427 } elseif ($when == 'tomorrow') {
428 $no_arrivals_when = JText::translate('VBONOCHECKINSTOMORROW');
429 }
430
431 $rows .= '<tr class="warning">' . "\n";
432 $rows .= ' <td colspan="7"><i class="vboicn-warning"></i> ' . $no_arrivals_when . '</td>' . "\n";
433 $rows .= '</tr>' . "\n";
434 }
435
436 return $rows;
437 }
438 }
439