From 7353869752836eeff00ab68234f0d64303cfd713 Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Mon, 25 Nov 2013 20:49:09 -0800 Subject: [PATCH] CRM-12337 - Convert navigation script to ajax with browser caching --- CRM/Admin/Page/AJAX.php | 30 ++++++- CRM/Core/BAO/Navigation.php | 90 +++++++++---------- .../plugins/function.crmNavigationMenu.php | 18 +++- CRM/Core/xml/Menu/Admin.xml | 5 ++ templates/CRM/common/Navigation.tpl | 8 +- 5 files changed, 90 insertions(+), 61 deletions(-) diff --git a/CRM/Admin/Page/AJAX.php b/CRM/Admin/Page/AJAX.php index 0f0427c164..4588d0c8a9 100644 --- a/CRM/Admin/Page/AJAX.php +++ b/CRM/Admin/Page/AJAX.php @@ -39,7 +39,32 @@ class CRM_Admin_Page_AJAX { /** - * Function to build menu tree + * CRM-12337 Output navigation menu as executable javascript + * @see smarty_function_crmNavigationMenu + */ + static function getNavigationMenu() { + $session = CRM_Core_Session::singleton(); + $contactID = $session->get('userID'); + if ($contactID) { + // Set headers to encourage browsers to cache for a long time + // If we want to refresh the menu we will send a different url + // @see smarty_function_crmNavigationMenu() + $year = 60*60*24*364; + header('Expires: '.gmdate('D, d M Y H:i:s \G\M\T', time() + $year)); + header('Content-Type: application/javascript'); + header("Cache-Control: max-age=$year, public"); + + // Render template as a javascript file + $smarty = CRM_Core_Smarty::singleton(); + $navigation = CRM_Core_BAO_Navigation::createNavigation($contactID); + $smarty->assign('navigation', $navigation); + print $smarty->fetch('CRM/common/Navigation.tpl'); + } + exit(); + } + + /** + * Return menu tree as json data for editing */ static function getNavigationList() { echo CRM_Core_BAO_Navigation::buildNavigation(TRUE, FALSE); @@ -50,8 +75,7 @@ class CRM_Admin_Page_AJAX { * Function to process drag/move action for menu tree */ static function menuTree() { - echo CRM_Core_BAO_Navigation::processNavigation($_GET); - CRM_Utils_System::civiExit(); + CRM_Core_BAO_Navigation::processNavigation($_GET); } /** diff --git a/CRM/Core/BAO/Navigation.php b/CRM/Core/BAO/Navigation.php index 3ba44506d0..361bef7f8a 100644 --- a/CRM/Core/BAO/Navigation.php +++ b/CRM/Core/BAO/Navigation.php @@ -34,6 +34,9 @@ */ class CRM_Core_BAO_Navigation extends CRM_Core_DAO_Navigation { + // Number of characters in the menu js cache key + const CACHE_KEY_STRLEN = 8; + /** * class constructor */ @@ -568,29 +571,9 @@ ORDER BY parent_id, weight"; static function createNavigation($contactID) { $config = CRM_Core_Config::singleton(); - // if on frontend, do not create navigation menu items, CRM-5349 - if ($config->userFrameworkFrontend) { - return ""; - } + $navigation = self::buildNavigation(); - $navParams = array('contact_id' => $contactID); - - $navigation = CRM_Core_BAO_Setting::getItem( - CRM_Core_BAO_Setting::PERSONAL_PREFERENCES_NAME, - 'navigation', - NULL, - NULL, - $contactID - ); - - // FIXME: hack for CRM-5027: we need to prepend the navigation string with - // (HTML-commented-out) locale info so that we rebuild menu on locale changes - if ( - !$navigation || - substr($navigation, 0, 14) != "" - ) { - //retrieve navigation if it's not cached. - $navigation = self::buildNavigation(); + if ($navigation) { //add additional navigation items $logoutURL = CRM_Utils_System::url('civicrm/logout', 'reset=1'); @@ -629,16 +612,32 @@ ORDER BY parent_id, weight"; $prepandString = "
  • " . $homeLabel . "
  • "; } - // prepend the navigation with locale info for CRM-5027 - $navigation = "" . $prepandString . $navigation . $appendSring; + $navigation = $prepandString . $navigation . $appendSring; + } + return $navigation; + } + /** + * Reset navigation for all contacts or a specified contact + * + * @param integer $contactID - reset only entries belonging to that contact ID + * @return string + */ + static function resetNavigation($contactID = NULL) { + $newKey = CRM_Utils_String::createRandom(self::CACHE_KEY_STRLEN, CRM_Utils_String::ALPHANUMERIC); + if (!$contactID) { + $query = "UPDATE civicrm_setting SET value = '$newKey' WHERE name='navigation' AND contact_id IS NOT NULL"; + CRM_Core_DAO::executeQuery($query); + CRM_Core_BAO_Cache::deleteGroup('navigation'); + } + else { // before inserting check if contact id exists in db - // this is to handle wierd case when contact id is in session but not in db + // this is to handle weird case when contact id is in session but not in db $contact = new CRM_Contact_DAO_Contact(); $contact->id = $contactID; if ($contact->find(TRUE)) { CRM_Core_BAO_Setting::setItem( - $navigation, + $newKey, CRM_Core_BAO_Setting::PERSONAL_PREFERENCES_NAME, 'navigation', NULL, @@ -647,30 +646,11 @@ ORDER BY parent_id, weight"; ); } } - return $navigation; - } - - /** - * Reset navigation for all contacts - * - * @param integer $contactID - reset only entries belonging to that contact ID - */ - static function resetNavigation($contactID = NULL) { - $params = array(); - $query = "UPDATE civicrm_setting SET value = NULL WHERE name='navigation'"; - if ($contactID) { - $query .= " AND contact_id = %1"; - $params[1] = array($contactID, 'Integer'); - } - else { - $query .= " AND contact_id IS NOT NULL"; - } - - CRM_Core_DAO::executeQuery($query, $params); - CRM_Core_BAO_Cache::deleteGroup('navigation'); - // also reset the dashlet cache in case permissions have changed etc + // FIXME: decouple this CRM_Core_BAO_Dashboard::resetDashletCache($contactID); + + return $newKey; } /** @@ -824,5 +804,19 @@ ORDER BY parent_id, weight"; $dao->save(); } } + + static function getCacheKey($cid) { + $key = CRM_Core_BAO_Setting::getItem( + CRM_Core_BAO_Setting::PERSONAL_PREFERENCES_NAME, + 'navigation', + NULL, + '', + $cid + ); + if (strlen($key) !== self::CACHE_KEY_STRLEN) { + $key = self::resetNavigation($cid); + } + return $key; + } } diff --git a/CRM/Core/Smarty/plugins/function.crmNavigationMenu.php b/CRM/Core/Smarty/plugins/function.crmNavigationMenu.php index 0f02e19cf6..e38d8f0a34 100644 --- a/CRM/Core/Smarty/plugins/function.crmNavigationMenu.php +++ b/CRM/Core/Smarty/plugins/function.crmNavigationMenu.php @@ -34,7 +34,7 @@ */ /** - * Generate the nav menu + * Output navigation script tag * * @param array $params * - is_default: bool, true if this is normal/default instance of the menu (which may be subject to CIVICRM_DISABLE_DEFAULT_MENU) @@ -43,18 +43,28 @@ * @return string HTML */ function smarty_function_crmNavigationMenu($params, &$smarty) { + $config = CRM_Core_Config::singleton(); //check if logged in user has access CiviCRM permission and build menu $buildNavigation = !CRM_Core_Config::isUpgradeMode() && CRM_Core_Permission::check('access CiviCRM'); if (defined('CIVICRM_DISABLE_DEFAULT_MENU') && CRM_Utils_Array::value('is_default', $params, FALSE)) { $buildNavigation = FALSE; } + if ($config->userFrameworkFrontend) { + $buildNavigation = FALSE; + } if ($buildNavigation) { $session = CRM_Core_Session::singleton(); $contactID = $session->get('userID'); if ($contactID) { - $navigation = CRM_Core_BAO_Navigation::createNavigation($contactID); - $smarty->assign('navigation', $navigation); - return $smarty->fetch('CRM/common/Navigation.tpl'); + // These params force the browser to refresh the js file when switching user, domain, or language + // We don't put them as a query string because some browsers will refuse to cache a page with a ? in the url + // We end the string with .js to trick apache mods into sending pro-caching headers + // @see CRM_Admin_Page_AJAX::getNavigationMenu + $lang = $config->lcMessages; + $domain = CRM_Core_Config::domainID(); + $key = CRM_Core_BAO_Navigation::getCacheKey($contactID); + $src = CRM_Utils_System::url("civicrm/ajax/menujs/$contactID/$lang/$domain/$key.js"); + return ''; } } return ''; diff --git a/CRM/Core/xml/Menu/Admin.xml b/CRM/Core/xml/Menu/Admin.xml index f56b9d8302..187a8796f5 100644 --- a/CRM/Core/xml/Menu/Admin.xml +++ b/CRM/Core/xml/Menu/Admin.xml @@ -658,6 +658,11 @@ Option Values CRM_Admin_Page_OptionValue + + civicrm/ajax/menujs + CRM_Admin_Page_AJAX::getNavigationMenu + access CiviCRM + civicrm/ajax/menu CRM_Admin_Page_AJAX::getNavigationList diff --git a/templates/CRM/common/Navigation.tpl b/templates/CRM/common/Navigation.tpl index 5e981612df..92d7cdce00 100644 --- a/templates/CRM/common/Navigation.tpl +++ b/templates/CRM/common/Navigation.tpl @@ -53,9 +53,7 @@ {/if} {$navigation} -{/strip}{/capture} -{literal} - -{/literal} + })(cj);{/literal} -- 2.25.1