PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.8.16
VikBooking Hotel Booking Engine & PMS v1.8.16
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 / departing_today.php

departing_today.php in VikBooking Hotel Booking Engine & PMS 1.8.16, at admin/helpers/widgets/departing_today.php

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