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/vikbooking.php +207 -36 1.6.7 → 1.8.16 View file →
@@ -41,8 +41,9 @@
41 41 $admin_user = JFactory::getUser();
42 42
43 43 $has_vcm = is_file(VCM_SITE_PATH.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'lib.vikchannelmanager.php');
44 44 $backlogo = VikBooking::getBackendLogo();
45 + $vbo_auth_admin = $admin_user->authorise('core.admin', 'com_vikbooking');
45 46 $vbo_auth_global = $admin_user->authorise('core.vbo.global', 'com_vikbooking');
46 47 $vbo_auth_rateplans = $admin_user->authorise('core.vbo.rateplans', 'com_vikbooking');
47 48 $vbo_auth_rooms = $admin_user->authorise('core.vbo.rooms', 'com_vikbooking');
48 49 $vbo_auth_pricing = $admin_user->authorise('core.vbo.pricing', 'com_vikbooking');
@@ -49,8 +50,10 @@
49 50 $vbo_auth_bookings = $admin_user->authorise('core.vbo.bookings', 'com_vikbooking');
50 51 $vbo_auth_availability = $admin_user->authorise('core.vbo.availability', 'com_vikbooking');
51 52 $vbo_auth_management = $admin_user->authorise('core.vbo.management', 'com_vikbooking');
52 53 $vbo_auth_pms = $admin_user->authorise('core.vbo.pms', 'com_vikbooking');
54 + $vbo_auth_reports = $admin_user->authorise('core.vbo.pmsreports', 'com_vikbooking');
55 + $vbo_auth_tm = $admin_user->authorise('core.vbo.tm', 'com_vikbooking');
53 56 $reviews_dld = 0;
54 57
55 58 // check for stored quick actions only once
56 59 $admin_menu_actions_checked = $session->get('admin_menu.actions.check', null, 'vikbooking');
@@ -125,9 +128,9 @@
125 128 </li>
126 129 <?php endif; ?>
127 130 <?php if ($vbo_auth_global) : ?>
128 131 <li>
129 - <div class="<?php echo ($highlight == "11" || $highlight == 'backups' ? "vmenulinkactive" : "vmenulink"); ?>">
132 + <div class="<?php echo ($highlight == "11" || $highlight == 'backups' || $highlight == 'overrides' ? "vmenulinkactive" : "vmenulink"); ?>">
130 133 <a href="index.php?option=com_vikbooking&amp;task=config">
131 134 <?php VikBookingIcons::e('cogs'); ?>
132 135 <span class="vbo-submenu-item">
133 136 <span class="vbo-submenu-item-txt"><?php echo JText::translate('VBMENUTWELVE'); ?></span>
@@ -253,9 +256,9 @@
253 256 <ul class="vbo-submenu-ul" data-menu-scope="pricing">
254 257 <li>
255 258 <div class="<?php echo ($highlight == "fares" ? "vmenulinkactive" : "vmenulink"); ?>">
256 259 <a href="index.php?option=com_vikbooking&amp;task=tariffs">
257 - <?php VikBookingIcons::e('toolbox'); ?>
260 + <?php VikBookingIcons::e('filter-circle-dollar'); ?>
258 261 <span class="vbo-submenu-item">
259 262 <span class="vbo-submenu-item-txt"><?php echo JText::translate('VBMENUPRICESTABLE'); ?></span>
260 263 </span>
261 264 </a>
@@ -317,10 +320,20 @@
317 320 <span class="vbo-submenu-item">
318 321 <span class="vbo-submenu-item-txt"><?php echo JText::translate('VBMENUQUICKRES'); ?></span>
319 322 </span>
320 323 </a>
321 - </div>
322 - </li>
324 + </div>
325 + </li>
326 + <li>
327 + <div class="<?php echo ($highlight == "managequote" ? "vmenulinkactive" : "vmenulink"); ?>">
328 + <a href="index.php?option=com_vikbooking&amp;view=managequote">
329 + <?php VikBookingIcons::e('file-alt'); ?>
330 + <span class="vbo-submenu-item">
331 + <span class="vbo-submenu-item-txt"><?php echo JText::translate('VBO_CREATE_QUOTE'); ?></span>
332 + </span>
333 + </a>
334 + </div>
335 + </li>
323 336 <?php endif; ?>
324 337 <?php if ($vbo_auth_availability) : ?>
325 338 <li>
326 339 <div class="<?php echo ($highlight == "15" ? "vmenulinkactive" : "vmenulink"); ?>">
@@ -344,11 +357,11 @@
344 357 </a>
345 358 </div>
346 359 </li>
347 360 <?php endif; ?>
348 - <?php if ($has_vcm && ($vbo_auth_availability || $vbo_auth_bookings)) : ?>
349 - <li>
350 - <div class="vmenulink">
361 + <?php if (($has_vcm || VBOPlatformDetection::isWordPress()) && ($vbo_auth_availability || $vbo_auth_bookings)) : ?>
362 + <li class="vbo-menu-vcm-only">
363 + <div class="<?php echo ($highlight == 'vikchannelmanager' ? 'vmenulinkactive' : 'vmenulink'); ?>">
351 364 <a href="index.php?option=com_vikchannelmanager" class="vbo-menu-vcmlink">
352 365 <?php VikBookingIcons::e('cloud'); ?>
353 366 <span class="vbo-submenu-item">
354 367 <span class="vbo-submenu-item-txt"><?php echo JText::translate('VBMENUCHANNELMANAGER'); ?></span>
@@ -418,14 +431,15 @@
418 431 </ul>
419 432 </div>
420 433 </li><?php
421 434 }
422 - if ($vbo_auth_pms) {
435 + if ($vbo_auth_pms || $vbo_auth_reports || $vbo_auth_tm) {
423 436 ?><li class="vbo-menu-parent-li">
424 437 <span><?php VikBookingIcons::e('tasks'); ?><a><?php echo JText::translate('VBMENUPMS'); ?> <?php VikBookingIcons::e('chevron-down', 'vbo-submenu-chevron'); ?></a></span>
425 438 <div class="vbo-submenu-wrap">
426 - <ul class="vbo-submenu-ul" data-menu-scope="pms">
427 - <li>
439 + <ul class="vbo-submenu-ul" data-menu-scope="pms"><?php
440 + if ($vbo_auth_pms) {
441 + ?><li>
428 442 <div class="<?php echo ($highlight == "operators" ? "vmenulinkactive" : "vmenulink"); ?>">
429 443 <a href="index.php?option=com_vikbooking&amp;task=operators">
430 444 <?php VikBookingIcons::e('user-tie'); ?>
431 445 <span class="vbo-submenu-item">
@@ -442,10 +456,12 @@
442 456 <span class="vbo-submenu-item-txt"><?php echo JText::translate('VBMENUTABLEAUX'); ?></span>
443 457 </span>
444 458 </a>
445 459 </div>
446 - </li>
447 - <li>
460 + </li><?php
461 + }
462 + if ($vbo_auth_admin || $vbo_auth_reports) {
463 + ?><li>
448 464 <div class="<?php echo ($highlight == "pmsreports" ? "vmenulinkactive" : "vmenulink"); ?>">
449 465 <a href="index.php?option=com_vikbooking&amp;task=pmsreports">
450 466 <?php VikBookingIcons::e('cash-register'); ?>
451 467 <span class="vbo-submenu-item">
@@ -452,10 +468,12 @@
452 468 <span class="vbo-submenu-item-txt"><?php echo JText::translate('VBMENUPMSREPORTS'); ?></span>
453 469 </span>
454 470 </a>
455 471 </div>
456 - </li>
457 - <li>
472 + </li><?php
473 + }
474 + if ($vbo_auth_pms) {
475 + ?><li>
458 476 <div class="<?php echo ($highlight == "einvoicing" ? "vmenulinkactive" : "vmenulink"); ?>">
459 477 <a href="index.php?option=com_vikbooking&amp;task=einvoicing">
460 478 <?php VikBookingIcons::e('laptop-code'); ?>
461 479 <span class="vbo-submenu-item">
@@ -462,10 +480,23 @@
462 480 <span class="vbo-submenu-item-txt"><?php echo JText::translate('VBMENUEINVOICING'); ?></span>
463 481 </span>
464 482 </a>
465 483 </div>
466 - </li>
467 - </ul>
484 + </li><?php
485 + }
486 + if ($vbo_auth_admin || $vbo_auth_tm) {
487 + ?><li class="vbo-menu-vcm-only">
488 + <div class="<?php echo ($highlight == "taskmanager" ? "vmenulinkactive" : "vmenulink"); ?>">
489 + <a href="index.php?option=com_vikbooking&amp;view=taskmanager">
490 + <?php VikBookingIcons::e('tasks'); ?>
491 + <span class="vbo-submenu-item">
492 + <span class="vbo-submenu-item-txt"><?php echo JText::translate('VBO_TASK_MANAGER'); ?></span>
493 + </span>
494 + </a>
495 + </div>
496 + </li><?php
497 + }
498 + ?></ul>
468 499 </div>
469 500 </li><?php
470 501 }
471 502 ?>
@@ -483,9 +514,9 @@
483 514 <?php VikBookingIcons::e('rocket'); ?>
484 515 <span><?php echo JText::translate('VBOGOTOPROBTN'); ?></span>
485 516 </button>
486 517 <?php
487 - } else {
518 + } elseif ($vbo_auth_global) {
488 519 ?>
489 520 <button type="button" class="vbo-alreadypro" title="<?php echo addslashes(JText::translate('VBOISPROBTN')); ?>" onclick="document.location.href='admin.php?option=com_vikbooking&view=gotopro';">
490 521 <?php VikBookingIcons::e('trophy'); ?>
491 522 <span><?php echo JText::translate('VBOISPROBTN'); ?></span>
@@ -609,9 +640,9 @@
609 640 }
610 641 }
611 642 }
612 643
613 - if ($vbo_auth_management && in_array($highlight, array('18', '11', '8'))) {
644 + if ($vbo_auth_management && in_array($highlight, array('18', '11'))) {
614 645 // VCM Opportunities
615 646 $opp = VikBooking::getVcmOpportunityInstance();
616 647 if (!is_null($opp)) {
617 648 // download opportunities if it's time to do it
@@ -625,12 +656,12 @@
625 656 );
626 657 $new_opp_count = count($opp->loadOpportunities($opp_filters, null, null));
627 658 if ($new_opp_count > 0) {
628 659 ?>
629 - <button type="button" class="vbo-opportunities-btnbadge" data-opportunity-count="<?php echo $new_opp_count; ?>" title="<?php echo htmlspecialchars(JText::translate('VBOGOTOOPPORTUNITIES')); ?>" onclick="document.location.href='<?php echo VBOFactory::getPlatform()->getUri()->admin('index.php?option=com_vikchannelmanager&task=opportunities', false); ?>';">
660 + <!-- <button type="button" class="vbo-opportunities-btnbadge" data-opportunity-count="<?php echo $new_opp_count; ?>" title="<?php echo htmlspecialchars(JText::translate('VBOGOTOOPPORTUNITIES')); ?>" onclick="document.location.href='<?php echo VBOFactory::getPlatform()->getUri()->admin('index.php?option=com_vikchannelmanager&task=opportunities', false); ?>';">
630 661 <?php VikBookingIcons::e('crown'); ?>
631 662 <span><?php echo JText::translate('VBOGOTOOPPORTUNITIES'); ?></span>
632 - </button>
663 + </button> -->
633 664 <?php
634 665 }
635 666 }
636 667
@@ -636,14 +667,16 @@
636 667
637 668 // Guest Reviews
638 669 $reviews_dld = VikBooking::shouldDownloadReviews();
639 670 $base_lnk = VBOFactory::getPlatform()->getUri()->admin('index.php?option=com_vikchannelmanager&task=reviews', false);
640 - ?>
671 + if ($highlight == '18') {
672 + ?>
641 673 <button type="button" class="vbo-reviews-btnbadge" data-reviews-count="" title="<?php echo htmlspecialchars(JText::translate('VBOPANELREVIEWS')); ?>" onclick="<?php echo $reviews_dld >= 0 ? "window.open('{$base_lnk}', '_blank'); jQuery(this).removeClass('vbo-reviews-btnbadge-alert').attr('data-reviews-count', '');" : "alert(Joomla.JText._('VBOGUESTREVSVCMREQ'));"; ?>">
642 674 <?php VikBookingIcons::e('star'); ?>
643 675 <span><?php echo JText::translate('VBOPANELREVIEWS'); ?></span>
644 676 </button>
645 - <?php
677 + <?php
678 + }
646 679 }
647 680
648 681 /**
649 682 * Admin widgets multitasking side panel.
@@ -652,25 +685,59 @@
652 685 */
653 686 if ($view != 'dashboard') {
654 687 ?>
655 688 <button type="button" class="vbo-multitasking-apps" title="<?php echo htmlspecialchars(JText::translate('VBO_MULTITASK_PANEL'), ENT_QUOTES, 'UTF-8'); ?>">
656 - <?php VikBookingIcons::e('th'); ?>
689 + <?php VikBookingIcons::e('grip'); ?>
657 690 </button>
658 691
659 692 <?php
660 693 // prepare the layout data array
661 - $layout_data = array(
694 + $layout_data = [
662 695 'vbo_page' => (empty($view) ? VikRequest::getString('task', '') : $view),
663 696 'btn_trigger' => '.vbo-multitasking-apps',
664 - );
665 - echo JLayoutHelper::render('sidepanel.multitasking', $layout_data, null, [
666 - 'component' => 'com_vikbooking',
667 - 'client' => 'administrator',
668 - ]);
697 + ];
698 + // render the multitasking layout
699 + echo JLayoutHelper::render('sidepanel.multitasking', $layout_data);
669 700 ?>
670 701 <?php
671 702 }
672 - ?>
703 +
704 + /**
705 + * Notifications Center.
706 + *
707 + * @since 1.16.8 (J) - 1.6.8 (WP)
708 + */
709 + $ncInstance = VBOFactory::getNotificationCenter();
710 +
711 + // read "old" notifications
712 + $ncInstance->readOldNotifications();
713 +
714 + // check if notifications should be downloaded
715 + $ncInstance->downloadNotifications();
716 +
717 + // count unread notifications
718 + $unreadNotifs = $ncInstance->countUnread();
719 + $unreadNotifsRead = $unreadNotifs > 99 ? '99+' : $unreadNotifs;
720 + $unreadNotifsRead = !$unreadNotifsRead ? '' : $unreadNotifsRead;
721 + ?>
722 + <div class="vbo-notifications-center-container">
723 + <button type="button" class="vbo-notifications-center-handler" data-badge-count="<?php echo $unreadNotifs; ?>" data-badge-read="<?php echo $unreadNotifsRead; ?>" title="<?php echo htmlspecialchars(JText::translate('VBO_W_NOTIFSCENTER_TITLE'), ENT_QUOTES, 'UTF-8'); ?>">
724 + <?php VikBookingIcons::e('bell', 'can-shake'); ?>
725 + </button>
726 + <?php
727 + // prepare the layout data array
728 + $layout_data = [
729 + 'vbo_page' => (empty($view) ? VikRequest::getString('task', '') : $view),
730 + 'btn_trigger' => '.vbo-notifications-center-handler',
731 + 'badge_c_attr' => 'data-badge-count',
732 + 'badge_r_attr' => 'data-badge-read',
733 + 'badge_count' => $unreadNotifs,
734 + ];
735 + // render the notificationscenter layout
736 + echo JLayoutHelper::render('sidepanel.notificationscenter', $layout_data);
737 + ?>
738 + </div>
739 +
673 740 </div>
674 741 </div>
675 742 </div>
676 743
@@ -739,10 +806,15 @@
739 806 } catch(e) {
740 807 console.error(e);
741 808 }
742 809
743 - // proceed with the navigation
744 - window.location.href = jQuery(this).attr('href');
810 + if (e.metaKey) {
811 + // open link on new window
812 + window.open(jQuery(this).attr('href'), '_blank').focus();
813 + } else {
814 + // proceed with the navigation
815 + window.location.href = jQuery(this).attr('href');
816 + }
745 817
746 818 return true;
747 819 });
748 820
@@ -779,9 +851,15 @@
779 851 }
780 852
781 853 // check if menu actions should be merged with the fallback scope
782 854 if (scope != 'widgets' && menu_scope_actions[0].hasOwnProperty('fallback')) {
855 + let before_fill_length = menu_scope_actions.length;
783 856 menu_scope_actions = VBOCore.fillAdminMenuActions(menu_scope_actions, menu_widgets_actions, scope);
857 + let after_fill_length = menu_scope_actions.length;
858 + if (before_fill_length && after_fill_length > before_fill_length) {
859 + // update scope for the filled entries
860 + VBOCore.storageSetItem(VBOCore.getStorageScopeName(scope), menu_scope_actions);
861 + }
784 862 }
785 863
786 864 wrapper.addClass('vbo-submenu-wrap-multi');
787 865 let quick_actions = jQuery('<ul></ul>').addClass('vbo-submenu-helper-ul');
@@ -897,8 +975,14 @@
897 975 }
898 976 );
899 977 }, 300));
900 978
979 + // append shortcut to title
980 + jQuery('.vbo-multitasking-apps').attr('title',
981 + jQuery('.vbo-multitasking-apps').attr('title') + ' '
982 + + (navigator.platform.toUpperCase().indexOf('MAC') === 0 ? '⌘' : '⌃') + '⏎'
983 + );
984 +
901 985 // register shortcuts
902 986 var vbo_menu_last_keydown = null;
903 987 window.addEventListener('keydown', (e) => {
904 988 e = e || window.event;
@@ -904,26 +988,38 @@
904 988 e = e || window.event;
905 989 if (!e.key) {
906 990 return;
907 991 }
908 - if (e.key === 'Enter' && e.metaKey) {
992 +
993 + let modifier = 'ctrl';
994 +
995 + // change the modifier depending on the platform
996 + if (navigator.platform.toUpperCase().indexOf('MAC') === 0) {
997 + modifier = 'meta';
998 + }
999 +
1000 + if (e.shortcut([modifier, 13])) {
909 1001 // toggle multitask panel
910 1002 VBOCore.emitEvent(VBOCore.multitask_shortcut_event);
911 1003 return;
912 1004 }
913 - if (VBOCore.side_panel_on && e.key === 'f' && e.metaKey) {
1005 +
1006 + if (VBOCore.side_panel_on && e.shortcut([modifier, 'F'])) {
914 1007 // focus search admin widget in multitask panel
915 1008 VBOCore.emitEvent(VBOCore.multitask_searchfs_event);
916 1009 e.preventDefault();
1010 +
917 1011 return;
918 1012 }
919 - if (e.key === 'k' && e.metaKey) {
1013 +
1014 + if (e.shortcut([modifier, 'K'])) {
920 1015 // set special key listener for sequences of combos
921 1016 e.preventDefault();
922 1017 vbo_menu_last_keydown = 'k';
923 1018 return;
924 1019 }
925 - if (vbo_menu_last_keydown === 'k' && e.metaKey && ['a', 'd', 'l'].includes(e.key)) {
1020 +
1021 + if (vbo_menu_last_keydown === 'k' && (e.shortcut([modifier, 'A']) || e.shortcut([modifier, 'D']) || e.shortcut([modifier, 'L']))) {
926 1022 // trigger event to change color scheme preferences
927 1023 e.preventDefault();
928 1024 // unset special key
929 1025 vbo_menu_last_keydown = '';
@@ -935,8 +1031,9 @@
935 1031 };
936 1032 jQuery('.vbo-sidepanel-colorscheme-option[data-scheme="' + color_schemes[e.key] + '"]').trigger('click');
937 1033 return;
938 1034 }
1035 +
939 1036 // always unset last key if this point gets reached
940 1037 vbo_menu_last_keydown = '';
941 1038 }, true);
942 1039
@@ -991,8 +1088,70 @@
991 1088 }
992 1089 );
993 1090 }, 300);
994 1091 }
1092 +
1093 + // declare window resize handler for setting the position of sub-menus
1094 + const subMenuStylesPositioning = () => {
1095 + // get window width
1096 + let windowWidth = window.innerWidth;
1097 +
1098 + // scan all sub-menu entries
1099 + document.querySelectorAll('.vbo-submenu-wrap').forEach((submenu) => {
1100 + // remove the class to style the sub-menu "to left"
1101 + submenu.classList.remove('vbo-submenu-wrap-toleft');
1102 +
1103 + // get sub-menu width and offset left position values
1104 + let elemWidth = submenu.offsetWidth;
1105 + let elemOffLeft = submenu.getBoundingClientRect().left;
1106 +
1107 + if (elemWidth) {
1108 + // sub-menu visibility is hidden, but width has been computed
1109 + if ((elemWidth + elemOffLeft) > windowWidth) {
1110 + // add "to left" positioning class or the sub-menu would exceed the window
1111 + submenu.classList.add('vbo-submenu-wrap-toleft');
1112 + }
1113 + } else {
1114 + // on small screens, the sub-menu may be hidden, hence with no width
1115 + let parentmenu = submenu.closest('.vbo-menu-parent-li');
1116 +
1117 + // register listener for mouseover event
1118 + parentmenu.addEventListener('mouseover', (e) => {
1119 + setTimeout(() => {
1120 + let now_submenu = e.target.querySelector('.vbo-submenu-wrap');
1121 + if (!now_submenu) {
1122 + return;
1123 + }
1124 + if ((now_submenu.offsetWidth + now_submenu.getBoundingClientRect().left) > window.innerWidth) {
1125 + // add "to left" positioning class or the sub-menu would exceed the window
1126 + now_submenu.classList.add('vbo-submenu-wrap-toleft');
1127 + }
1128 + }, 0);
1129 + });
1130 +
1131 + // register listener for touchstart event
1132 + parentmenu.addEventListener('touchstart', (e) => {
1133 + let limenu = e.target;
1134 + if (!limenu.matches('.vbo-menu-parent-li')) {
1135 + limenu = limenu.closest('.vbo-menu-parent-li');
1136 + }
1137 + // propagate the mouseover event
1138 + limenu.dispatchEvent(new Event('mouseover'));
1139 + });
1140 + }
1141 + });
1142 + };
1143 +
1144 + // register listener for window resize event
1145 + window.addEventListener('resize', subMenuStylesPositioning);
1146 +
1147 + // trigger sub-menus styles positioning function on page load
1148 + setTimeout(() => {
1149 + subMenuStylesPositioning();
1150 + }, 0);
1151 +
1152 + // populate admin-dock
1153 + VBOAdminDock.getInstance();
995 1154 });
996 1155 </script>
997 1156 <?php
998 1157
@@ -1020,8 +1179,20 @@
1020 1179 });
1021 1180 </script>
1022 1181 <?php
1023 1182 }
1183 +
1184 + $helpWizardAjaxUrl = VBOFactory::getPlatform()->getUri()->ajax('index.php?option=com_vikbooking');
1185 + JHtml::fetch('script', VBO_ADMIN_URI . 'resources/helpwizard.js', ['version' => VIKBOOKING_SOFTWARE_VERSION]);
1186 + JText::script('VBSAVE');
1187 + JText::script('VBDISMISS');
1188 + JFactory::getDocument()->addScriptDeclaration(
1189 +<<<JAVASCRIPT
1190 +(function(w) {
1191 + window.VBO_HELP_WIZARD_AJAX_URL = '{$helpWizardAjaxUrl}';
1192 +})(window);
1193 +JAVASCRIPT
1194 + );
1024 1195 }
1025 1196
1026 1197 public static function printFooter()
1027 1198 {