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
← All changes | admin/helpers/admin_widgets.php +127 -45 1.6.4 → 1.8.16 View file →
@@ -31,8 +31,17 @@
31 31 */
32 32 protected static $helper = null;
33 33
34 34 /**
35 + * List of preloaded widgets.
36 + *
37 + * @var array
38 + *
39 + * @since 1.18.3 (J) - 1.8.3 (WP)
40 + */
41 + protected static $preloaded = [];
42 +
43 + /**
35 44 * The database handler instance.
36 45 *
37 46 * @var object
38 47 */
@@ -45,8 +54,17 @@
45 54 */
46 55 protected $widgets;
47 56
48 57 /**
58 + * The list of widget positions in the multitask panel.
59 + *
60 + * @var array
61 + *
62 + * @since 1.16.10 (J) - 1.6.10 (WP)
63 + */
64 + protected $widgets_pos_list;
65 +
66 + /**
49 67 * Class constructor is protected.
50 68 *
51 69 * @see getInstance()
52 70 */
@@ -54,8 +72,9 @@
54 72 {
55 73 static::$helper = [];
56 74 $this->dbo = JFactory::getDbo();
57 75 $this->widgets = [];
76 + $this->widgets_pos_list = (array) VBOFactory::getConfig()->getArray('multitasking_wpos', []);
58 77 $this->load();
59 78 }
60 79
61 80 /**
@@ -143,10 +162,19 @@
143 162 if (class_exists($classname)) {
144 163 // instantiate widget object
145 164 $widget = new $classname();
146 165
147 - // push widget object
148 - array_push($this->widgets, $widget);
166 + /**
167 + * Call the widget's preflight method to see if it's compatible with the current environment.
168 + *
169 + * @since 1.16.10 (J) - 1.6.10 (WP)
170 + */
171 + if (!$widget->preflight()) {
172 + continue;
173 + }
174 +
175 + // push the installed widget object
176 + $this->widgets[] = $widget;
149 177 }
150 178 } catch (Exception $e) {
151 179 // do nothing
152 180 }
@@ -189,8 +217,9 @@
189 217 $container->size = 'small';
190 218 $container->widgets = [
191 219 'guest_messages',
192 220 'latest_from_guests',
221 + 'booking_details',
193 222 'visitors_counter',
194 223 ];
195 224 // push container
196 225 array_push($section->containers, $container);
@@ -197,8 +226,9 @@
197 226 // start container
198 227 $container = new stdClass;
199 228 $container->size = 'small';
200 229 $container->widgets = [
230 + 'aitools',
201 231 'forecast',
202 232 'bookings_calendar',
203 233 'reminders',
204 234 ];
@@ -247,8 +277,9 @@
247 277 $container = new stdClass;
248 278 $container->size = 'medium';
249 279 $container->widgets = [
250 280 'finance',
281 + 'inquiries_chat',
251 282 'currency_converter',
252 283 ];
253 284 // push container
254 285 array_push($section->containers, $container);
@@ -330,12 +361,11 @@
330 361 {
331 362 $id = $this->simplifyId($id);
332 363
333 364 foreach ($this->widgets as $widget) {
334 - if ($widget->getIdentifier() != $id) {
335 - continue;
365 + if ($widget->getIdentifier() == $id) {
366 + return $widget;
336 367 }
337 - return $widget;
338 368 }
339 369
340 370 return false;
341 371 }
@@ -367,30 +397,58 @@
367 397 $descr = $widget->getDescription();
368 398
369 399 if ($preload) {
370 400 // preload widget's CSS/JS assets (if any)
371 - $watch_data = $widget->preload();
401 + $watch_data = array_key_exists($id, static::$preloaded) ? static::$preloaded[$id] : $widget->preload();
402 +
372 403 if ($watch_data) {
373 404 // assign watching data to this widget
374 405 $watch[$id] = $watch_data;
375 406 }
407 +
408 + // overwrite cache for the preloaded widget result
409 + static::$preloaded[$id] = $watch_data;
376 410 }
377 411
378 412 // build widget info object
379 413 $wtdata = new stdClass;
380 - $wtdata->id = $id;
381 - $wtdata->name = $name;
382 - $wtdata->descr = $descr;
383 - $wtdata->icon = $widget->getIcon();
384 - $wtdata->style = str_replace(array(' ', '_'), '-', $widget->getStyleName());
414 + $wtdata->id = $id;
415 + $wtdata->name = $name;
416 + $wtdata->descr = $descr;
417 + $wtdata->icon = $widget->getIcon();
418 + $wtdata->style = str_replace(array(' ', '_'), '-', $widget->getStyleName());
419 + $wtdata->priority = $widget->getPriority();
385 420
386 421 // set object for sorting
387 - $names[$name] = $wtdata;
422 + $names[$name] = $wtdata;
388 423 }
389 424
390 425 // apply sorting by name
391 426 ksort($names);
392 427
428 + // apply sorting by priority
429 + usort($names, function($a, $b) {
430 + // the higher the priority is, the higher the position will be
431 + return $b->priority - $a->priority;
432 + });
433 +
434 + if ($this->widgets_pos_list) {
435 + // get the custom positions list
436 + $widgets_pos_list = $this->widgets_pos_list;
437 + // apply custom sorting
438 + usort($names, function($a, $b) use ($widgets_pos_list) {
439 + $wa_id = $a->id;
440 + $wb_id = $b->id;
441 +
442 + if (($widgets_pos_list[$wa_id] ?? null) && ($widgets_pos_list[$wb_id] ?? null)) {
443 + // the higher the custom position is, the lower the sorting position will be
444 + return $widgets_pos_list[$wa_id] > $widgets_pos_list[$wb_id] ? 1 : -1;
445 + }
446 +
447 + return 0;
448 + });
449 + }
450 +
393 451 // push sorted widgets to pool
394 452 foreach ($names as $wtdata) {
395 453 $pool[] = $wtdata;
396 454 }
@@ -398,9 +456,9 @@
398 456 /**
399 457 * In case some widgets were pre-loaded for watching certain
400 458 * events, enqueue the watch-data list to the document.
401 459 */
402 - if (count($watch)) {
460 + if ($watch) {
403 461 // schedule the browser notifications watching data
404 462 VBONotificationScheduler::getInstance()->registerWatchData($watch);
405 463 }
406 464
@@ -416,21 +474,21 @@
416 474 * containers and widgets.
417 475 */
418 476 public function getWidgetsMap()
419 477 {
420 - $q = "SELECT `setting` FROM `#__vikbooking_config` WHERE `param`='admin_widgets_map';";
421 - $this->dbo->setQuery($q);
422 - $this->dbo->execute();
423 - if ($this->dbo->getNumRows()) {
424 - $map = json_decode($this->dbo->loadResult());
478 + $config = VBOFactory::getConfig();
479 +
480 + $map = $config->get('admin_widgets_map', null);
481 +
482 + if ($map) {
483 + $map = json_decode($map);
425 484 return is_object($map) && !empty($map->sections) && is_array($map->sections) ? $map : $this->getDefaultWidgetsMap();
426 485 }
427 486
428 487 $default_map = $this->getDefaultWidgetsMap();
429 - $q = "INSERT INTO `#__vikbooking_config` (`param`,`setting`) VALUES ('admin_widgets_map', " . $this->dbo->quote(json_encode($default_map)) . ");";
430 - $this->dbo->setQuery($q);
431 - $this->dbo->execute();
432 488
489 + $config->set('admin_widgets_map', $default_map);
490 +
433 491 return $default_map;
434 492 }
435 493
436 494 /**
@@ -441,9 +499,9 @@
441 499 * @return bool True on success, false otherwise.
442 500 */
443 501 public function updateWidgetsMap($sections)
444 502 {
445 - if (!is_array($sections) || !count($sections)) {
503 + if (!is_array($sections) || !$sections) {
446 504 return false;
447 505 }
448 506
449 507 // prepare new map object
@@ -449,11 +507,9 @@
449 507 // prepare new map object
450 508 $map = new stdClass;
451 509 $map->sections = $sections;
452 510
453 - $q = "UPDATE `#__vikbooking_config` SET `setting`=" . $this->dbo->quote(json_encode($map)) . " WHERE `param`='admin_widgets_map';";
454 - $this->dbo->setQuery($q);
455 - $this->dbo->execute();
511 + VBOFactory::getConfig()->set('admin_widgets_map', $map);
456 512
457 513 return true;
458 514 }
459 515
@@ -476,25 +532,26 @@
476 532
477 533 /**
478 534 * Forces the rendering of a specific widget identifier.
479 535 *
480 - * @param string $id the widget identifier.
481 - * @param mixed $data anything to pass to the widget.
536 + * @param string $id the widget identifier.
537 + * @param ?VBOMultitaskData $data optional multitask data for the widget.
482 538 *
483 - * @return mixed void on success, false otherwise.
539 + * @return void
484 540 */
485 - public function renderWidget($id, $data = null)
541 + public function renderWidget($id, ?VBOMultitaskData $data = null)
486 542 {
487 543 $id = $this->simplifyId($id);
488 544
489 545 foreach ($this->widgets as $widget) {
490 - if ($widget->getIdentifier() != $id) {
491 - continue;
546 + if ($widget->getIdentifier() == $id) {
547 + // render the requested widget
548 + $widget->render($data);
549 +
550 + // return void
551 + return;
492 552 }
493 - return $widget->render($data);
494 553 }
495 -
496 - return false;
497 554 }
498 555
499 556 /**
500 557 * Maps the size identifier to a CSS class.
@@ -505,12 +562,12 @@
505 562 */
506 563 public function getContainerCssClass($size)
507 564 {
508 565 $css_size_map = [
509 - 'small' => 'vbo-admin-widgets-container-small',
566 + 'small' => 'vbo-admin-widgets-container-small',
510 567 'medium' => 'vbo-admin-widgets-container-medium',
511 - 'large' => 'vbo-admin-widgets-container-large',
512 - 'full' => 'vbo-admin-widgets-container-fullwidth',
568 + 'large' => 'vbo-admin-widgets-container-large',
569 + 'full' => 'vbo-admin-widgets-container-fullwidth',
513 570 ];
514 571
515 572 return isset($css_size_map[$size]) ? $css_size_map[$size] : $css_size_map['full'];
516 573 }
@@ -576,11 +633,10 @@
576 633 $tot_rooms_units = 0;
577 634
578 635 $q = "SELECT `id`,`name`,`units`,`params`,`avail` FROM `#__vikbooking_rooms`;";
579 636 $this->dbo->setQuery($q);
580 - $this->dbo->execute();
581 - if ($this->dbo->getNumRows() > 0) {
582 - $all_rooms = $this->dbo->loadAssocList();
637 + $all_rooms = $this->dbo->loadAssocList();
638 + if ($all_rooms) {
583 639 foreach ($all_rooms as $k => $r) {
584 640 if ($r['avail'] < 1) {
585 641 $unpublished_rooms[] = $r['id'];
586 642 } else {
@@ -587,9 +643,9 @@
587 643 $tot_rooms_units += $r['units'];
588 644 }
589 645 $all_rooms_ids[$r['id']] = $r['name'];
590 646 $all_rooms_units[$r['id']] = $r['units'];
591 - $rparams = json_decode($r['params'], true);
647 + $rparams = json_decode((string) $r['params'], true);
592 648 $all_rooms_features[$r['id']] = is_array($rparams) && array_key_exists('features', $rparams) && is_array($rparams['features']) ? $rparams['features'] : [];
593 649 }
594 650 }
595 651
@@ -613,9 +669,9 @@
613 669 if (empty($key)) {
614 670 return false;
615 671 }
616 672
617 - if (!count(static::$helper)) {
673 + if (!static::$helper) {
618 674 $this->loadRoomsData();
619 675 }
620 676
621 677 if (isset(static::$helper[$key])) {
@@ -661,11 +717,11 @@
661 717 public function showWelcome()
662 718 {
663 719 $q = "SELECT `setting` FROM `#__vikbooking_config` WHERE `param`='admin_widgets_welcome';";
664 720 $this->dbo->setQuery($q);
665 - $this->dbo->execute();
666 - if ($this->dbo->getNumRows()) {
667 - return ((int)$this->dbo->loadResult() < 1);
721 + $show_welcome = $this->dbo->loadResult();
722 + if ($show_welcome !== null) {
723 + return ((int)$show_welcome < 1);
668 724 }
669 725
670 726 $q = "INSERT INTO `#__vikbooking_config` (`param`,`setting`) VALUES ('admin_widgets_welcome', '0');";
671 727 $this->dbo->setQuery($q);
@@ -820,8 +876,34 @@
820 876 // update configuration record
821 877 VBOFactory::getConfig()->set('multitasking_map', json_encode($map));
822 878
823 879 return true;
880 + }
881 +
882 + /**
883 + * Sets the position for an admin widget in the multitask panel.
884 + *
885 + * @param array $pos_list Associative list of widget positions.
886 + *
887 + * @return array The updated widgets position list.
888 + *
889 + * @since 1.16.10 (J) - 1.6.10 (WP)
890 + */
891 + public function setMultitaskingWidgetPos($pos_list)
892 + {
893 + if (!is_array($pos_list)) {
894 + return false;
895 + }
896 +
897 + // turn all position values into integers
898 + $pos_list = array_map(function($pos) {
899 + return (int) $pos;
900 + }, $pos_list);
901 +
902 + // update configuration record
903 + VBOFactory::getConfig()->set('multitasking_wpos', $pos_list);
904 +
905 + return $pos_list;
824 906 }
825 907
826 908 /**
827 909 * Admin widgets used to be named as the entire file name,