Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate KAM smartmenus to core #13582

Merged
merged 1 commit into from
Feb 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CRM/Admin/Form/Preferences/Display.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class CRM_Admin_Form_Preferences_Display extends CRM_Admin_Form_Preferences {
'ajaxPopupsEnabled' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
'display_name_format' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
'sort_name_format' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
'menubar_position' => CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
);

/**
Expand Down
81 changes: 61 additions & 20 deletions CRM/Admin/Page/AJAX.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,35 +37,76 @@
class CRM_Admin_Page_AJAX {

/**
* CRM-12337 Output navigation menu as executable javascript.
*
* @see smarty_function_crmNavigationMenu
* Outputs menubar data (json format) for the current user.
*/
public static function getNavigationMenu() {
$contactID = CRM_Core_Session::singleton()->get('userID');
if ($contactID) {
CRM_Core_Page_AJAX::setJsHeaders();
$smarty = CRM_Core_Smarty::singleton();
$smarty->assign('quicksearchOptions', self::getSearchOptions());
print $smarty->fetchWith('CRM/common/navigation.js.tpl', array(
'navigation' => CRM_Core_BAO_Navigation::createNavigation(),
));
public static function navMenu() {
if (CRM_Core_Session::getLoggedInContactID()) {

$menu = CRM_Core_BAO_Navigation::buildNavigationTree();
CRM_Core_BAO_Navigation::buildHomeMenu($menu);
CRM_Utils_Hook::navigationMenu($menu);
CRM_Core_BAO_Navigation::fixNavigationMenu($menu);
CRM_Core_BAO_Navigation::orderByWeight($menu);
CRM_Core_BAO_Navigation::filterByPermission($menu);
self::formatMenuItems($menu);

$output = [
'menu' => $menu,
'search' => CRM_Utils_Array::makeNonAssociative(self::getSearchOptions()),
];
// Encourage browsers to cache for a long time - 1 year
$ttl = 60 * 60 * 24 * 364;
CRM_Utils_System::setHttpHeader('Expires', gmdate('D, d M Y H:i:s \G\M\T', time() + $ttl));
CRM_Utils_System::setHttpHeader('Cache-Control', "max-age=$ttl, public");
CRM_Utils_System::setHttpHeader('Content-Type', 'application/json');
print (json_encode($output));
}
CRM_Utils_System::civiExit();
}

/**
* @param array $menu
*/
public static function formatMenuItems(&$menu) {
foreach ($menu as $key => &$item) {
$props = $item['attributes'];
unset($item['attributes']);
if (!empty($props['separator'])) {
$item['separator'] = ($props['separator'] == 1 ? 'bottom' : 'top');
}
if (!empty($props['icon'])) {
$item['icon'] = $props['icon'];
}
if (!empty($props['attr'])) {
$item['attr'] = $props['attr'];
}
if (!empty($props['url'])) {
$item['url'] = CRM_Utils_System::evalUrl(CRM_Core_BAO_Navigation::makeFullyFormedUrl($props['url']));
}
if (!empty($props['label'])) {
$item['label'] = ts($props['label'], ['context' => 'menu']);
}
$item['name'] = !empty($props['name']) ? $props['name'] : CRM_Utils_String::munge(CRM_Utils_Array::value('label', $props));
if (!empty($item['child'])) {
self::formatMenuItems($item['child']);
}
}
$menu = array_values($menu);
}

public static function getSearchOptions() {
$searchOptions = Civi::settings()->get('quicksearch_options');
$searchOptions[] = 'sort_name';
$searchOptions = array_intersect_key(CRM_Core_SelectValues::quicksearchOptions(), array_flip($searchOptions));
foreach ($searchOptions as $key => $label) {
$searchOptions = array_merge(['sort_name'], Civi::settings()->get('quicksearch_options'));
$labels = CRM_Core_SelectValues::quicksearchOptions();
$result = [];
foreach ($searchOptions as $key) {
$label = $labels[$key];
if (strpos($key, 'custom_') === 0) {
unset($searchOptions[$key]);
$id = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomField', substr($key, 7), 'id', 'name');
$searchOptions["custom_$id"] = $label;
$key = 'custom_' . CRM_Core_DAO::getFieldValue('CRM_Core_DAO_CustomField', substr($key, 7), 'id', 'name');
$label = array_slice(explode(': ', $label, 2), -1);
}
$result[$key] = $label;
}
return $searchOptions;
return $result;
}

/**
Expand Down
151 changes: 60 additions & 91 deletions CRM/Core/BAO/Navigation.php
Original file line number Diff line number Diff line change
Expand Up @@ -299,51 +299,6 @@ private static function buildTree($elements, $parentId = NULL) {
return $branch;
}

/**
* Build menu.
*
* @return string
*/
public static function buildNavigation() {
$navigations = self::buildNavigationTree();
$navigationString = '';

// run the Navigation through a hook so users can modify it
CRM_Utils_Hook::navigationMenu($navigations);
self::fixNavigationMenu($navigations);

// Hooks have added menu items in an arbitrary order. We need to order by
// weight again. I would put this function directly after
// CRM_Utils_Hook::navigationMenu but for some reason, fixNavigationMenu is
// moving items added by hooks on the end of the menu. Hence I do it
// afterwards
self::orderByWeight($navigations);

//skip children menu item if user don't have access to parent menu item
$skipMenuItems = array();
foreach ($navigations as $key => $value) {
// Home is a special case
if ($value['attributes']['name'] != 'Home') {
$name = self::getMenuName($value, $skipMenuItems);
if ($name) {
//separator before
if (isset($value['attributes']['separator']) && $value['attributes']['separator'] == 2) {
$navigationString .= '<li class="menu-separator"></li>';
}
$removeCharacters = array('/', '!', '&', '*', ' ', '(', ')', '.');
$navigationString .= '<li class="menumain crm-' . str_replace($removeCharacters, '_', $value['attributes']['label']) . '">' . $name;
}
}
self::recurseNavigation($value, $navigationString, $skipMenuItems);
}

// clean up - Need to remove empty <ul>'s, this happens when user don't have
// permission to access parent
$navigationString = str_replace('<ul></ul></li>', '', $navigationString);

return $navigationString;
}

/**
* buildNavigationTree retreives items in order. We call this function to
* ensure that any items added by the hook are also in the correct order.
Expand Down Expand Up @@ -560,52 +515,6 @@ public static function checkPermission($item) {
return TRUE;
}

/**
* Create navigation for CiviCRM Admin Menu.
*
* @return string
* returns navigation html
*/
public static function createNavigation() {
$navigation = self::buildNavigation();

if ($navigation) {

//add additional navigation items
$logoutURL = CRM_Utils_System::url('civicrm/logout', 'reset=1');

// get home menu from db
$homeParams = array('name' => 'Home');
$homeNav = array();
$homeIcon = '<span class="crm-logo-sm" ></span>';
self::retrieve($homeParams, $homeNav);
if ($homeNav) {
$homeURL = self::makeFullyFormedUrl($homeNav['url']);
$homeLabel = $homeNav['label'];
// CRM-6804 (we need to special-case this as we don’t ts()-tag variables)
if ($homeLabel == 'Home') {
$homeLabel = ts('CiviCRM Home');
}
}
else {
$homeURL = CRM_Utils_System::url('civicrm/dashboard', 'reset=1');
$homeLabel = ts('CiviCRM Home');
}
// Link to hide the menubar
$hideLabel = ts('Hide Menu');

$prepandString = "
<li class='menumain crm-link-home'>$homeIcon
<ul id='civicrm-home'>
<li><a href='$homeURL'>$homeLabel</a></li>
<li><a href='#' class='crm-hidemenu'>$hideLabel</a></li>
<li><a href='$logoutURL' class='crm-logout-link'>" . ts('Log out') . "</a></li>
</ul>";
// <li> tag doesn't need to be closed
}
return $prepandString . $navigation;
}

/**
* Turns relative URLs (like civicrm/foo/bar) into fully-formed
* ones (i.e. example.com/wp-admin?q=civicrm/dashboard).
Expand Down Expand Up @@ -1051,4 +960,64 @@ public static function getCacheKey($cid) {
return $key;
}

/**
* Unset menu items for disabled components and non-permissioned users
*
* @param $menu
*/
public static function filterByPermission(&$menu) {
foreach ($menu as $key => $item) {
if (
(array_key_exists('active', $item['attributes']) && !$item['attributes']['active']) ||
!CRM_Core_BAO_Navigation::checkPermission($item['attributes'])
) {
unset($menu[$key]);
continue;
}
if (!empty($item['child'])) {
self::filterByPermission($menu[$key]['child']);
}
}
}

/**
* @param array $menu
*/
public static function buildHomeMenu(&$menu) {
foreach ($menu as &$item) {
if (CRM_Utils_Array::value('name', $item['attributes']) === 'Home') {
unset($item['attributes']['label'], $item['attributes']['url']);
$item['attributes']['icon'] = 'crm-logo-sm';
$item['attributes']['attr']['accesskey'] = 'm';
$item['child'] = [
[
'attributes' => [
'label' => 'CiviCRM Home',
'name' => 'CiviCRM Home',
'url' => 'civicrm/dashboard?reset=1',
'weight' => 1,
]
],
[
'attributes' => [
'label' => 'Hide Menu',
'name' => 'Hide Menu',
'url' => '#hidemenu',
'weight' => 2,
]
],
[
'attributes' => [
'label' => 'Log out',
'name' => 'Log out',
'url' => 'civicrm/logout?reset=1',
'weight' => 3,
]
],
];
return;
}
}
}

}
30 changes: 24 additions & 6 deletions CRM/Core/Resources.php
Original file line number Diff line number Diff line change
Expand Up @@ -609,10 +609,6 @@ public function addCoreResources($region = 'html-header') {
'isFrontend' => $config->userFrameworkFrontend,
),
);
$contactID = CRM_Core_Session::getLoggedInContactID();
if ($contactID) {
$settings['config']['menuCacheCode'] = CRM_Core_BAO_Navigation::getCacheKey($contactID);
}
// Disable profile creation if user lacks permission
if (!CRM_Core_Permission::check('edit all contacts') && !CRM_Core_Permission::check('add contacts')) {
$settings['config']['entityRef']['contactCreate'] = FALSE;
Expand Down Expand Up @@ -685,6 +681,8 @@ public static function outputLocalizationJS() {
'ajaxPopupsEnabled' => self::singleton()->ajaxPopupsEnabled,
'allowAlertAutodismissal' => (bool) Civi::settings()->get('allow_alert_autodismissal'),
'resourceCacheCode' => self::singleton()->getCacheCode(),
'locale' => CRM_Core_I18n::getLocale(),
'cid' => (int) CRM_Core_Session::getLoggedInContactID(),
);
print CRM_Core_Smarty::singleton()->fetchWith('CRM/common/l10n.js.tpl', $vars);
CRM_Utils_System::civiExit();
Expand Down Expand Up @@ -746,11 +744,31 @@ public function coreResourceList($region) {
// These scripts are only needed by back-office users
if (CRM_Core_Permission::check('access CiviCRM')) {
$items[] = "packages/jquery/plugins/jquery.tableHeader.js";
$items[] = "packages/jquery/plugins/jquery.menu.min.js";
$items[] = "css/civicrmNavigation.css";
$items[] = "packages/jquery/plugins/jquery.notify.min.js";
}

$contactID = CRM_Core_Session::getLoggedInContactID();

// Menubar
$position = $contactID && CRM_Core_Permission::check('access CiviCRM') ? Civi::settings()->get('menubar_position') : 'none';
if ($position !== 'none' && !@constant('CIVICRM_DISABLE_DEFAULT_MENU') && !CRM_Core_Config::isUpgradeMode()) {
$cms = strtolower(CRM_Core_Config::singleton()->userFramework);
$cms = $cms === 'drupal' ? 'drupal7' : $cms;
$items[] = 'bower_components/smartmenus/dist/jquery.smartmenus.min.js';
$items[] = 'bower_components/smartmenus/dist/addons/keyboard/jquery.smartmenus.keyboard.min.js';
$items[] = 'js/crm.menubar.js';
$items[] = 'bower_components/smartmenus/dist/css/sm-core-css.css';
$items[] = 'css/crm-menubar.css';
$items[] = "css/menubar-$cms.css";
$items[] = [
'menubar' => [
'position' => $position ?: 'over-cms-menu',
'qfKey' => CRM_Core_Key::get('CRM_Contact_Controller_Search', TRUE),
'cacheCode' => CRM_Core_BAO_Navigation::getCacheKey($contactID),
],
];
}

// JS for multilingual installations
if (!empty($config->languageLimit) && count($config->languageLimit) > 1 && CRM_Core_Permission::check('translate CiviCRM')) {
$items[] = "js/crm.multilingual.js";
Expand Down
Loading