diff -ruaN admin_menu.orig/admin_menu.api.php admin_menu/admin_menu.api.php
--- admin_menu.orig/admin_menu.api.php 2014-12-19 23:59:50.000000000 +0200
+++ admin_menu/admin_menu.api.php 2015-07-26 13:30:39.751637608 +0300
@@ -162,3 +162,21 @@
);
return $caches;
}
+
+/**
+ * Allows other modules to alter the configuration used to integrate with JS.
+ *
+ * Only is invoked if the JS module is available and enabled.
+ *
+ * @deprecated Please use JS 2.x if possible.
+ *
+ * @param array $config
+ * The configuration array as used in hook_js().
+ *
+ * @see hook_js()
+ * @link https://www.drupal.org/project/js
+ */
+function hook_admin_menu_hook_js_config_alter(&$config) {
+ // Add our own module to the dependencies.
+ $config['cache']['dependencies']['my_module'] = 'my_module';
+}
diff -ruaN admin_menu.orig/admin_menu.install admin_menu/admin_menu.install
--- admin_menu.orig/admin_menu.install 2014-12-19 23:59:50.000000000 +0200
+++ admin_menu/admin_menu.install 2015-07-26 13:30:39.755637589 +0300
@@ -45,6 +45,31 @@
variable_del('admin_menu_devel_modules');
variable_del('admin_menu_devel_modules_enabled');
variable_del('admin_menu_devel_modules_skip');
+ variable_del('admin_menu_js_dependencies');
+}
+
+/**
+ * Implements hook_requirements().
+ */
+function admin_menu_requirements($phase) {
+ $requirements = array();
+ $t = get_t();
+ switch ($phase) {
+ case 'runtime':
+ // Warn about 1.x version of JS.
+ if (module_exists('js')) {
+ $js_info = drupal_parse_info_file(drupal_get_path('module', 'js') . '/js.info');
+ if (!version_compare($js_info['version'], '7.x-2', '>=')) {
+ $requirements['admin_menu_js'] = array(
+ 'title' => $t(' Administration menu'),
+ 'description' => $t('Top avoid runtime issues you should upgrade to version 2.x of the High-performance JavaScript callback handler.'),
+ 'severity' => REQUIREMENT_INFO,
+ 'value' => $t('Please update to version 2.x of High-performance JavaScript callback handler'),
+ );
+ }
+ }
+ }
+ return $requirements;
}
/**
diff -ruaN admin_menu.orig/admin_menu.js admin_menu/admin_menu.js
--- admin_menu.orig/admin_menu.js 2014-12-19 23:59:50.000000000 +0200
+++ admin_menu/admin_menu.js 2015-07-26 13:30:39.756637584 +0300
@@ -123,10 +123,15 @@
}
$.ajax({
cache: true,
- type: 'GET',
+ type: 'POST',
dataType: 'text', // Prevent auto-evaluation of response.
global: false, // Do not trigger global AJAX events.
url: Drupal.settings.admin_menu.basePath.replace(/admin_menu/, 'js/admin_menu/cache/' + hash),
+ data: {
+ js_module: 'admin_menu',
+ js_callback: 'cache',
+ js_token: Drupal.settings.js && Drupal.settings.js.tokens && Drupal.settings.js.tokens['admin_menu-cache'] || ''
+ },
success: onSuccess,
complete: function (XMLHttpRequest, status) {
Drupal.admin.hashes.hash = status;
diff -ruaN admin_menu.orig/admin_menu.module admin_menu/admin_menu.module
--- admin_menu.orig/admin_menu.module 2014-12-19 23:59:50.000000000 +0200
+++ admin_menu/admin_menu.module 2015-07-26 13:32:11.546193261 +0300
@@ -64,7 +64,7 @@
// AJAX callback.
// @see http://drupal.org/project/js
$items['js/admin_menu/cache'] = array(
- 'page callback' => 'admin_menu_js_cache',
+ 'page callback' => 'admin_menu_js_callback_cache',
'delivery callback' => 'admin_menu_deliver',
'access arguments' => array('access administration menu'),
'type' => MENU_CALLBACK,
@@ -161,7 +161,7 @@
'#attached' => array(),
);
$attached = &$page['page_bottom']['admin_menu']['#attached'];
- $options = array('every_page' => TRUE);
+ $options = array('every_page' => TRUE, 'defer' => TRUE);
$attached['css'][$path . '/admin_menu.css'] = $options;
if ($user->uid == 1) {
@@ -186,6 +186,11 @@
// user, only output the hash for the client-side HTTP cache callback URL.
$cid = 'admin_menu:' . $user->uid . ':' . session_id() . ':' . $language->language;
if (!$complete && !empty($_COOKIE['has_js']) && ($hash = admin_menu_cache_get($cid))) {
+ // If the JS module is installed, invoke the function to generate a token
+ // so it is added via settings.
+ if (module_exists('js')) {
+ js_get_token('admin_menu', 'cache');
+ }
$settings['hash'] = $hash;
// The base path to use for cache requests depends on whether clean URLs
// are enabled, whether Drupal runs in a sub-directory, and on the language
@@ -264,18 +269,121 @@
/**
* Implements hook_js().
+ *
+ * For JS version 1.x
+ *
+ * @deprecated Please use JS 2.x if possible.
+ *
+ * @see admin_menu_hook_js_config()
+ * @see admin_menu_js_info()
*/
function admin_menu_js() {
+ $config = array();
+ // If we've the dependencies in the cache we might can skip a boot-level here.
+ // Not significantly faster unless used with in-memory caching e.g. redis.
+ if (($cache = cache_get('admin_menu_hook_js_config')) && !empty($cache->data)) {
+ $config = $cache->data;
+ }
+ // If not available from cache it has to be in the variables.
+ if (empty($config)) {
+ // Make sure we've variable support.
+ drupal_bootstrap(DRUPAL_BOOTSTRAP_VARIABLES);
+ $config = variable_get('admin_menu_hook_js_config', array());
+ // Store in cache.
+ cache_set('admin_menu_hook_js_config', $config);
+ }
+ return $config;
+}
+
+/**
+ * Implements hook_js_info().
+ *
+ * For JS version 2.x
+ *
+ * @see admin_menu_js()
+ */
+function admin_menu_js_info() {
+ // Build dependency list.
+ $module_data = system_rebuild_module_data();
+ $dependencies = array('devel' => 'devel', 'filter' => 'filter', 'user' => 'user');
+ // Ensure the "on behalf of" hooks are available too.
+ module_load_include('inc', 'admin_menu', 'admin_menu.map');
+ foreach (module_implements('admin_menu_map') as $module) {
+ if (!isset($dependencies[$module])) {
+ $dependencies[$module] = $module;
+ if (isset($module_data[$module]->requires)) {
+ $dependencies += array_combine(array_keys($module_data[$module]->requires), array_keys($module_data[$module]->requires));
+ }
+ }
+ }
+
return array(
'cache' => array(
- 'callback' => 'admin_menu_js_cache',
+ 'delivery callback' => 'admin_menu_deliver',
+ 'dependencies' => $dependencies,
'includes' => array('common', 'theme', 'unicode'),
- 'dependencies' => array('devel', 'filter', 'user'),
+ 'methods' => array('POST'),
),
);
}
/**
+ * Builds the config for the hook_js() implementation.
+ *
+ * Allows other modules to alter the configuration by using
+ * hook_admin_menu__hook_js_config_alter(&$config)
+ *
+ * @deprecated Please use JS 2.x if possible.
+ */
+function admin_menu_hook_js_config() {
+ if (module_exists('js')) {
+ // Build dependency list.
+ $module_data = system_rebuild_module_data();
+ $dependencies = array();
+ // Ensure the "on behalf of" hooks are available too.
+ module_load_include('inc', 'admin_menu', 'admin_menu.map');
+ foreach (module_implements('admin_menu_map') as $module) {
+ if (!isset($dependencies[$module])) {
+ $dependencies[$module] = $module;
+ if (isset($module_data[$module]->requires)) {
+ $dependencies += array_combine(array_keys($module_data[$module]->requires), array_keys($module_data[$module]->requires));
+ }
+ }
+ }
+ // Basic configuration.
+ $config = array(
+ 'cache' => array(
+ 'callback' => 'admin_menu_js_callback_cache',
+ 'includes' => array('path', 'theme', 'language', 'menu'),
+ 'dependencies' => $dependencies,
+ 'access arguments' => array('access administration menu'),
+ ),
+ );
+ drupal_alter('admin_menu_hook_js_config', $config);
+ variable_set('admin_menu_hook_js_config', $config);
+ // Ensure the config is available in the cache. Not significantly faster
+ // unless used with in-memory caching e.g. redis.
+ cache_set('admin_menu_hook_js_config', $config);
+ }
+}
+
+/**
+ * Implements hook_modules_enabled().
+ */
+function admin_menu_modules_enabled($modules) {
+ // Rebuild the JS menu configuration.
+ admin_menu_hook_js_config();
+}
+
+/**
+ * Implements hook_modules_disabled().
+ */
+function admin_menu_modules_disabled($modules) {
+ // Rebuild the JS menu configuration.
+ admin_menu_hook_js_config();
+}
+
+/**
* Retrieve a client-side cache hash from cache.
*
* The hash cache is consulted more than once per request; we therefore cache
@@ -323,7 +431,7 @@
*
* @see admin_menu_deliver()
*/
-function admin_menu_js_cache() {
+function admin_menu_js_callback_cache() {
global $conf;
// Suppress Devel module.
@@ -359,14 +467,15 @@
drupal_add_http_header('Expires', gmdate(DATE_RFC1123, REQUEST_TIME + $max_age));
drupal_add_http_header('Cache-Control', 'private, max-age=' . $max_age);
- // Retrieve and return the rendered menu.
- return admin_menu_output();
+ // Retrieve and output the rendered menu.
+ print admin_menu_output();
+ exit;
}
/**
* Delivery callback for client-side HTTP caching.
*
- * @see admin_menu_js_cache()
+ * @see admin_menu_js_callback_cache()
*/
function admin_menu_deliver($page_callback_result) {
drupal_add_http_header('Content-Type', 'text/html; charset=utf-8');
@@ -375,9 +484,10 @@
global $language;
drupal_add_http_header('Content-Language', $language->language);
- // The page callback is always admin_menu_js_cache(), which always returns a
- // string, and is only accessed when the user actually has access to it.
- // Therefore, we do not care for the other possible page callback results.
+ // The page callback is always admin_menu_js_callback_cache(), which always
+ // returns a string, and is only accessed when the user actually has access
+ // to it. Therefore, we do not care for the other possible page callback
+ // results.
print $page_callback_result;
// Perform end-of-request tasks. The page cache is created here.
@@ -473,6 +583,10 @@
// Rebuild the output.
if (!isset($content)) {
+ // Note: 'admin_menu' uses theme() function to render own links through 'theme_admin_menu_links()'
+ // and icon through 'theme_admin_menu_icon()'. It requires to use 'DRUPAL_BOOTSTRAP_FULL'.
+ drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
+
// Retrieve enabled components to display and make them available for others.
$components = variable_get('admin_menu_components', array());
$components += array(
@@ -799,6 +913,9 @@
if (db_table_exists('cache_admin_menu')) {
cache_clear_all(isset($uid) ? $cid : '*', 'cache_admin_menu', TRUE);
}
+
+ // Rebuild the JS menu configuration.
+ admin_menu_hook_js_config();
}
/**