You are here

admin_menu.module in Administration menu 5.3

Render an administrative menu as a dropdown menu at the top of the window.

Note: Most theme-functions in Administration Menu are not invoked via theme(), because we try to keep this module as fast as possible and chances are very small that someone wants to override those functions.

File

admin_menu.module
View source
<?php

/**
 * @file
 * Render an administrative menu as a dropdown menu at the top of the window.
 *
 * Note: Most theme-functions in Administration Menu are not invoked via theme(),
 * because we try to keep this module as fast as possible and chances are very
 * small that someone wants to override those functions.
 */

/**
 * Implementation of hook_help().
 */
function admin_menu_help($section) {
  switch ($section) {
    case 'admin/settings/admin_menu':
      return t('The administration menu module provides a dropdown menu arranged for one- or two-click access to most administrative tasks and other common destinations (to users with the proper permissions). Use the settings below to customize the appearance of the menu.');
    case 'admin/help#admin_menu':
      $output = '';
      $output .= '<p>' . t('The administration menu module provides a dropdown menu arranged for one- or two-click access to most administrative tasks and other common destinations (to users with the proper permissions). Administration menu also displays the number of anonymous and authenticated users, and allows modules to add their own custom menu items. Integration with the menu varies from module to module; the contributed module <a href="@drupal">Devel</a>, for instance, makes strong use of the administration menu module to provide quick access to development tools.', array(
        '@drupal' => 'http://drupal.org/project/devel',
      )) . '</p>';
      $output .= '<p>' . t('The administration menu <a href="@settings">settings page</a> allows you to modify some elements of the menu\'s behavior and appearance. Since the appearance of the menu is dependent on your site theme, substantial customizations require modifications to your site\'s theme and CSS files. See the advanced module README.txt file for more information on theme and CSS customizations.', array(
        '@settings' => url('admin/settings/admin_menu'),
      )) . '</p>';
      $output .= '<p>' . t('The menu items displayed in the administration menu depend upon the actual permissions of the viewer. First, the administration menu is only displayed to users in roles with the <em>Access administration menu</em> (admin_menu module) permission. Second, a user must be a member of a role with the <em>Access administration pages</em> (system module) permission to view administrative links. And, third, only currently permitted links are displayed; for example, if a user is not a member of a role with the permissions <em>Administer permissions</em> (user module) and <em>Administer users</em> (user module), the <em>User management</em> menu item is not displayed.') . '</p>';
      return $output;
  }
}

/**
 * Implementation of hook_perm().
 */
function admin_menu_perm() {
  return array(
    'access administration menu',
    'display drupal links',
  );
}

/**
 * Implementation of hook_menu().
 *
 * We can't move this into admin_menu_footer(), because PHP-only based themes
 * like chameleon load and output scripts and stylesheets in front of
 * theme_closure(), so we ensure Admin menu's styles and scripts are loaded on
 * all pages via hook_menu().
 */
function admin_menu_menu($may_cache) {
  $items = array();
  if ($may_cache) {

    // AJAX callback.
    $items[] = array(
      'path' => 'js/admin_menu/cache',
      'callback' => 'admin_menu_js_cache',
      'access' => user_access('access administration menu'),
      'type' => MENU_CALLBACK,
    );

    // Module settings.
    $items[] = array(
      'path' => 'admin/settings/admin_menu',
      'title' => t('Administration menu'),
      'description' => t('Adjust administration menu settings.'),
      'callback' => 'drupal_get_form',
      'callback arguments' => array(
        'admin_menu_theme_settings',
      ),
      'access' => user_access('administer site configuration'),
    );

    // Menu link callbacks.
    $items[] = array(
      'path' => 'admin_menu/toggle-modules',
      'callback' => 'admin_menu_toggle_modules',
      'access' => user_access('administer site configuration'),
      'type' => MENU_CALLBACK,
    );
    admin_menu_clear_cache();
    return $items;
  }
  if (!user_access('access administration menu') || admin_menu_suppress(FALSE)) {
    return $items;
  }

  // Performance: Skip this entirely for AJAX requests.
  if (strpos($_GET['q'], 'js/') === 0) {
    return $items;
  }
  global $user, $locale;
  $path = drupal_get_path('module', 'admin_menu');
  drupal_add_css($path . '/admin_menu.css', 'module', 'all', FALSE);
  if ($user->uid == 1) {
    drupal_add_css($path . '/admin_menu.uid1.css', 'module', 'all', FALSE);
  }

  // Performance: Defer execution.
  drupal_add_js($path . '/admin_menu.js', 'module', 'header', TRUE);

  // Destination query strings are applied via JS.
  // @see drupal_get_destination()
  $url_path = isset($_GET['q']) ? $_GET['q'] : '';
  $url_query = drupal_query_string_encode($_GET, array(
    'q',
  ));
  if ($url_query != '') {
    $url_path .= '?' . $url_query;
  }
  $settings['destination'] = 'destination=' . urlencode($url_path);

  // Hash for client-side HTTP/AJAX caching.
  $cid = 'admin_menu:' . $user->uid . ':' . $locale;
  if (!empty($_COOKIE['has_js']) && ($hash = admin_menu_cache_get($cid))) {
    $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
    // system configuration. url() already provides us the proper path and also
    // invokes potentially existing custom_url_rewrite() functions, which may
    // add further required components to the URL to provide context. Due to
    // those components, and since url('') returns only base_path() when clean
    // URLs are disabled, we need to use a replacement token as path.  Yuck.
    $settings['basePath'] = url('admin_menu');
  }
  $replacements = module_invoke_all('admin_menu_replacements');
  if (!empty($replacements)) {
    $settings['replacements'] = $replacements;
  }
  if ($setting = variable_get('admin_menu_margin_top', 1)) {
    $settings['margin_top'] = $setting;
  }
  if ($setting = variable_get('admin_menu_position_fixed', 0)) {
    $settings['position_fixed'] = $setting;
  }
  if ($setting = variable_get('admin_menu_tweak_tabs', 0)) {
    $settings['tweak_tabs'] = $setting;
  }
  if ($_GET['q'] == 'admin/build/menu' && variable_get('admin_menu_tweak_menu', 0)) {
    drupal_add_js($path . '/admin_menu.menu.js');
    drupal_add_js('misc/collapse.js');
  }
  if ($_GET['q'] == 'admin/build/modules' || strpos($_GET['q'], 'admin/build/modules/list') === 0) {
    $settings['tweak_modules'] = variable_get('admin_menu_tweak_modules', 0);
  }
  drupal_add_js(array(
    'admin_menu' => $settings,
  ), 'setting');
  if ($_GET['q'] == 'admin/settings/admin_menu' || $_GET['q'] == 'admin/settings/clean-urls' || $_GET['q'] == 'admin/settings/devel') {
    require_once $path . '/admin_menu.inc';
  }
  return $items;
}

/**
 * Suppress display of administration menu.
 *
 * This function should be called from within another module's page callback
 * (preferably using module_invoke()) when the menu should not be displayed.
 * This is useful for modules that implement popup pages or other special
 * pages where the menu would be distracting or break the layout.
 *
 * @param $set
 *   Defaults to TRUE. If called before hook_footer(), the menu will not be
 *   displayed. If FALSE is passed, the suppression state is returned.
 */
function admin_menu_suppress($set = TRUE) {
  static $suppress = FALSE;

  // drupal_add_js() must only be invoked once.
  if (!empty($set) && $suppress === FALSE) {
    $suppress = TRUE;
    drupal_add_js(array(
      'admin_menu' => array(
        'suppress' => 1,
      ),
    ), 'setting');
  }
  return $suppress;
}

/**
 * Implementation of hook_footer().
 */
function admin_menu_footer($main = 0) {
  return admin_menu_output();
}

/**
 * Implementation of hook_js().
 */
function admin_menu_js() {
  return array(
    'cache' => array(
      'callback' => 'admin_menu_js_cache',
      'includes' => array(
        'common',
        'theme',
        'unicode',
      ),
      'dependencies' => array(
        'devel',
        'filter',
        'user',
      ),
    ),
  );
}

/**
 * Retrieve a client-side cache hash from cache.
 *
 * The hash cache is consulted more than once per request; we therefore cache
 * the results statically to avoid multiple database requests.
 *
 * This should only be used for client-side cache hashes. Use cache_menu for
 * administration menu content.
 *
 * @param $cid
 *   The cache ID of the data to retrieve.
 */
function admin_menu_cache_get($cid) {
  static $cache = array();
  if (!variable_get('admin_menu_cache_client', TRUE)) {
    return FALSE;
  }
  if (!array_key_exists($cid, $cache)) {
    $cache[$cid] = cache_get($cid, 'cache_admin_menu');
    if ($cache[$cid] && isset($cache[$cid]->data)) {
      $cache[$cid] = $cache[$cid]->data;
    }
  }
  return $cache[$cid];
}

/**
 * Store a client-side cache hash in persistent cache.
 *
 * This should only be used for client-side cache hashes. Use cache_menu for
 * administration menu content.
 *
 * @param $cid
 *   The cache ID of the data to retrieve.
 */
function admin_menu_cache_set($cid, $data) {
  if (variable_get('admin_menu_cache_client', TRUE)) {
    cache_set($cid, 'cache_admin_menu', $data);
  }
}

/**
 * Menu callback; Output administration menu for HTTP caching via AJAX request.
 */
function admin_menu_js_cache($hash = NULL) {

  // Get the rendered menu.
  $content = admin_menu_output();

  // @todo According to http://www.mnot.net/blog/2006/05/11/browser_caching,
  //   IE will only cache the content when it is compressed.
  // Determine if the client accepts gzipped data.
  if (isset($_SERVER['HTTP_ACCEPT_ENCODING'])) {
    if (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'x-gzip') !== FALSE) {
      $encoding = 'x-gzip';
    }
    elseif (strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE) {
      $encoding = 'gzip';
    }

    // Perform gzip compression when:
    // 1) the user agent supports gzip compression.
    // 2) Drupal page compression is enabled. Sites may wish to perform the
    //    compression at the web server level (e.g. using mod_deflate).
    // 3) PHP's zlib extension is loaded, but zlib compression is disabled.
    if (isset($encoding) && variable_get('page_compression', TRUE) && extension_loaded('zlib') && zlib_get_coding_type() === FALSE) {

      // Use Vary header to tell caches to keep separate versions of the menu
      // based on user agent capabilities.
      header('Vary: Accept-Encoding');

      // Since we manually perform compression, we are also responsible to
      // send a proper encoding header.
      header('Content-Encoding: ' . $encoding);
      $content = gzencode($content, 9, FORCE_GZIP);
    }
  }
  $expires = time() + 3600 * 24 * 365;
  header('Expires: ' . gmdate('D, d M Y H:i:s', $expires) . ' GMT');
  header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
  header('Cache-Control: max-age=' . $expires);
  header('Content-Length: ' . strlen($content));

  // Suppress Devel module.
  $GLOBALS['devel_shutdown'] = FALSE;
  echo $content;
  exit;
}

/**
 * Implementation of hook_admin_menu_replacements().
 */
function admin_menu_admin_menu_replacements() {
  $items = array();
  if ($user_count = admin_menu_get_user_count()) {
    $items['.admin-menu-users a'] = $user_count;
  }
  return $items;
}

/**
 * Return count of online anonymous/authenticated users.
 *
 * @see user_block(), user.module
 */
function admin_menu_get_user_count() {
  $interval = time() - variable_get('user_block_seconds_online', 900);
  $count_anon = sess_count($interval);
  $count_auth = db_result(db_query("SELECT COUNT(DISTINCT uid) FROM {sessions} WHERE uid > 0 AND timestamp >= %d", $interval));
  return t('@count-anon / @count-auth', array(
    '@count-anon' => $count_anon,
    '@count-auth' => $count_auth,
  ));
}

/**
 * Build the administration menu output.
 */
function admin_menu_output() {
  if (!user_access('access administration menu') || admin_menu_suppress(FALSE)) {
    return;
  }
  global $user, $locale;
  $cache_server_enabled = variable_get('admin_menu_cache_server', TRUE);

  // Determine whether we need to rebuild.
  $rebuild = variable_get('admin_menu_rebuild_links', FALSE);
  $cid = 'admin_menu:' . $user->uid . ':' . $locale;

  // Do nothing at all here if the client supports client-side caching, no
  // rebuild is needed, the user has a hash, and is NOT requesting the cache
  // update path. Consult the hash cache last, since it requires a DB request.
  // @todo Implement a sanity-check to prevent permanent double requests; i.e.
  //   what if the client-side cache fails for any reason and performs a second
  //   request on every page?
  if (!empty($_COOKIE['has_js']) && !$rebuild && strpos($_GET['q'], 'js/admin_menu/cache') !== 0) {
    if (admin_menu_cache_get($cid)) {
      return;
    }
  }

  // Try to load and output administration menu from server-side cache.
  if ($cache_server_enabled) {
    $cache = cache_get($cid, 'cache_menu');
    if (!$rebuild && $cache && isset($cache->data)) {
      $content = $cache->data;
    }
  }

  // Rebuild the output.
  if (!isset($content)) {

    // Add site name as CSS class for development/staging theming purposes. We
    // leverage the cookie domain instead of HTTP_HOST to account for many (but
    // not all) multi-domain setups (e.g. language-based sub-domains).
    $class_site = 'admin-menu-site' . drupal_strtolower(preg_replace('/[^a-zA-Z0-9-]/', '-', $GLOBALS['cookie_domain']));
    $_admin_menu =& admin_menu_get_menu();

    // Allow other modules to integrate with admin_menu (uncached).
    foreach (module_implements('admin_menu') as $module) {
      $function = $module . '_admin_menu';
      $function($_admin_menu, FALSE);
    }
    $content = '<div id="admin-menu" class="' . $class_site . '">';
    $content .= theme_admin_menu_tree($_admin_menu['index']['admin']);
    $content .= '</div>';

    // Cache the menu for this user.
    if ($cache_server_enabled) {
      cache_set($cid, 'cache_menu', $content, time() + 60 * 60 * 24);
      variable_del('admin_menu_rebuild_links');
    }
  }

  // Store the new hash for this user.
  if (!empty($_COOKIE['has_js'])) {
    admin_menu_cache_set($cid, md5($content));
  }
  return $content;
}

/**
 * Return administration menu from cache or rebuild it.
 *
 * @return
 *   An array containing a complete menu structure of all cached administration
 *   menu items.
 */
function &admin_menu_get_menu() {
  static $_admin_menu;
  if (isset($_admin_menu)) {
    return $_admin_menu;
  }
  global $user, $locale;
  $cid = $user->uid . ':' . $locale . ':admin_menu';
  $cache = cache_get($cid, 'cache_menu');

  // Check if cache is an array needed to distinguish between v5.x-1.2 and later
  // versions.
  if ($cache && substr($cache->data, 0, 1) == 'a') {
    $_admin_menu = unserialize($cache->data);
  }
  else {
    require_once drupal_get_path('module', 'admin_menu') . '/admin_menu.inc';

    // Ensure all modules are loaded when we need to rebuild.
    drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
    module_list(TRUE, FALSE, FALSE);
    menu_get_menu();
    admin_menu_build($_admin_menu);
    cache_set($cid, 'cache_menu', serialize($_admin_menu), time() + 60 * 60 * 24);
  }
  return $_admin_menu;
}

/**
 * Return a rendered menu tree.
 *
 * @param $pid
 *   The menu item id to use for the administration menu.
 *
 * @return string
 *   The complete, rendered administration menu.
 */
function theme_admin_menu_tree($pid = 5) {
  $_admin_menu = admin_menu_get_menu();
  $output = '';
  if (!empty($_admin_menu[$pid]['children'])) {
    foreach ($_admin_menu[$pid]['children'] as $mid) {
      $output .= theme_admin_menu_item($mid, theme_admin_menu_tree($mid), empty($_admin_menu[$mid]['children']));
    }
  }
  return $output ? "\n<ul>" . $output . '</ul>' : '';
}

/**
 * High-performance implementation of theme_menu_item().
 *
 * This saves us a theme() call and does only the absolute minimum to get
 * the admin menu links rendered.
 *
 * @param $mid
 *   The menu id of the item.
 * @param $children
 *   A string containing any rendered child items of this menu.
 * @param $leaf
 *   A boolean indicating whether this menu item is a leaf.
 */
function theme_admin_menu_item($mid, $children = '', $leaf = TRUE) {
  static $display_option, $destination;
  $_admin_menu = admin_menu_get_menu();
  $item = $_admin_menu[$mid];
  if (!isset($display_option)) {
    $display_option = variable_get('admin_menu_display', 0);
    $destination = drupal_get_destination();
  }

  // Display extra information about menu items if enabled (devel).
  if ($display_option) {
    if ($display_option == 'mid') {
      $item['title'] = $item['title'] . ' (' . $mid . ')';
    }
    else {
      if (isset($item[$display_option])) {
        $item['title'] = $item['title'] . ' (' . $item[$display_option] . ')';
      }
    }
  }
  $class = array();
  if (!$leaf) {
    $class[] = 'expandable';
  }
  if (isset($item['class'])) {
    $class[] = $item['class'];
  }

  // Strip destination query string from href attribute and apply a CSS class
  // for our JavaScript behavior instead.
  $path = preg_replace('/[\\?|&]' . preg_quote($destination, '/') . '/', '', $item['path']);
  if ($path != $item['path']) {
    if (!empty($item['attributes']['class'])) {
      $item['attributes']['class'] .= ' admin-menu-destination';
    }
    else {
      $item['attributes']['class'] = 'admin-menu-destination';
    }
  }
  $output = '<li' . (!empty($class) ? ' class="' . implode(' ', $class) . '"' : '') . '>';
  $output .= '<a href="' . check_url($path) . '"' . drupal_attributes($item['attributes']) . '>' . filter_xss_admin($item['title']) . '</a>' . $children . '</li>';
  return $output;
}

/**
 * Comparator routine for use in sorting menu items.
 */
function _admin_menu_sort($a, $b) {
  $_admin_menu = admin_menu_get_menu();
  $a = $_admin_menu[$a];
  $b = $_admin_menu[$b];
  if ($a['weight'] < $b['weight']) {
    return -1;
  }
  elseif ($a['weight'] > $b['weight']) {
    return 1;
  }
  elseif (isset($a['title']) && isset($b['title'])) {
    return strnatcasecmp($a['title'], $b['title']);
  }
  else {
    return 1;
  }
}

/**
 * Adjust the menu item path.
 *
 * Adjust the path of local tasks and let them point to their parent item.
 * Finally build the url. These functions have been moved here to be able
 * to cache the final results.
 *
 * @param &$item
 *   An admin menu item.
 */
function admin_menu_item_url(&$_admin_menu, $mid) {
  $link_item = $mid;
  while ($_admin_menu[$link_item]['type'] & MENU_LINKS_TO_PARENT) {
    $link_item = $_admin_menu[$link_item]['pid'];
  }
  if (!isset($_admin_menu[$link_item]['processed'])) {
    $_admin_menu[$mid]['path'] = url($_admin_menu[$link_item]['path'], isset($_admin_menu[$mid]['query']) ? $_admin_menu[$mid]['query'] : NULL);
    $_admin_menu[$link_item]['processed'] = TRUE;
  }
  else {

    // Copy the already processed path of the parent item to the
    // default local task.
    $_admin_menu[$mid]['path'] = $_admin_menu[$link_item]['path'];
  }
}

/**
 * Add a custom menu item.
 *
 * @param $_admin_menu
 *   An array containing the complete administration menu structure, passed by
 *   reference.
 * @param $pid
 *   The parent menu item id.
 * @param $item
 *   An menu item array for the menu system. May contain the key 'weight' to
 *   adjust the item's weight.
 * @param $mid
 *   (Optional) The menu item id to use.  Should be specified for already
 *   existing menu items that are copied/relocated elsewhere.
 *
 * @return
 *   The id of the new menu item.
 */
function admin_menu_add_item(&$_admin_menu, $pid, $item, $mid = NULL) {
  static $custom_mid;
  if (empty($item['path'])) {
    return FALSE;
  }
  $item['pid'] = $pid;
  $item['children'] = array();
  if (!isset($custom_mid)) {
    $custom_mid = max(array_keys($_admin_menu)) + 10000;
  }
  if (!isset($mid)) {
    $mid = $custom_mid++;
  }
  else {

    // Ensure we have an integer.
    $mid = (int) $mid;
  }
  $_admin_menu[$mid] = $item;
  $_admin_menu[$pid]['children'][] = $mid;
  $_admin_menu['index'][$item['path']] = $mid;
  admin_menu_item_url($_admin_menu, $mid);

  // Sort items.
  usort($_admin_menu[$pid]['children'], '_admin_menu_sort');
  return $mid;
}

/**
 * Implementation of hook_admin_menu().
 *
 * @param array $admin_menu
 *   An array containing the complete administration menu structure, passed by
 *   reference.
 * @param bool $may_cache
 *   Whether changes will be cached. If new menu items contain dynamic
 *   information, such as query strings or user-related data, these should be
 *   added on each page request ($may_cache = FALSE).
 */
function admin_menu_admin_menu(&$admin_menu, $may_cache) {
  if (!$may_cache) {

    // Add count of active anonymous/authenticated users.
    $mid_admin = $admin_menu['index']['admin'];
    admin_menu_add_item($admin_menu, $mid_admin, array(
      'title' => admin_menu_get_user_count(),
      'description' => t('Current anonymous / authenticated users'),
      'path' => 'user',
      'weight' => -90,
      'class' => 'admin-menu-action admin-menu-users',
    ));
  }
}

/**
 * Implementation of hook_admin_menu() for Devel module (temporary).
 *
 * - Adds most used functions 'empty cache' and 'variable editor' to the menu in
 *   Administration Menu's icon.
 * - Adds links to switch to a different user to the logout button.
 */
if (!function_exists('devel_admin_menu')) {
  function devel_admin_menu(&$admin_menu, $may_cache) {
    $access_devel = user_access('access devel information');
    $access_switch = user_access('switch users');
    if (!$access_devel && !$access_switch) {
      return;
    }
    $mid_icon = $admin_menu['index']['admin_menu_icon'];
    if ($may_cache) {

      // Add variable editor.
      if ($access_devel) {
        admin_menu_add_item($admin_menu, $mid_icon, array(
          'title' => t('Variable editor'),
          'path' => 'devel/variable',
          'weight' => 20,
        ));
      }
    }
    else {

      // Add clear-cache.
      if ($access_devel) {
        admin_menu_add_item($admin_menu, $mid_icon, array(
          'title' => t('Empty cache'),
          'path' => 'devel/cache/clear',
          'weight' => 20,
          'query' => drupal_get_destination(),
        ));
      }

      // Add switch_user items.
      if ($access_switch && ($devel_user_links = module_invoke('devel', 'switch_user_list'))) {
        global $user;
        $mid_user = $admin_menu['index']["user/{$user->uid}"];
        foreach ($devel_user_links as $link) {
          if (is_array($link)) {
            admin_menu_add_item($admin_menu, $mid_user, array(
              'title' => $link['title'],
              'description' => $link['attributes']['title'],
              'path' => $link['href'],
              'query' => $link['query'],
            ));
          }
          elseif (preg_match('!href="' . base_path() . '([^\\?]+)\\?([^"]+)" title="([^"]+)">((<em>)?[^<]+(</em>)?)!', $link, $match)) {
            admin_menu_add_item($admin_menu, $mid_user, array(
              'title' => $match[4],
              'description' => $match[3],
              'path' => urldecode($match[1]),
              'query' => $match[2],
            ));
          }
        }
      }
    }
  }
}

/**
 * Clear the cached admin menu tree.
 */
function admin_menu_clear_cache() {

  // Flush cached menu tree.
  // cache_clear_all() does not support a leading wildcard.
  db_query("DELETE FROM {cache_menu} WHERE cid LIKE '%%:admin_menu'");
  variable_set('admin_menu_rebuild_links', TRUE);

  // Flush cached output of admin_menu.
  cache_clear_all('admin_menu:', 'cache_menu', TRUE);

  // Flush client-side cache hashes.
  cache_clear_all('*', 'cache_admin_menu', TRUE);
}

/**
 * Implementation of hook_panels_cache().
 *
 * We're misusing the panels_cache hook here: whenever called, check if the
 * current request has a POST payload, and clear the cached admin menu.
 * This can easily be seen as a hack, as it will happen way too often when
 * working on the panels admin pages.
 */
function admin_menu_panels_cache() {
  if (!empty($_POST)) {
    admin_menu_clear_cache();
  }
}

/**
 * Menu callback; Enable/disable developer modules.
 */
function admin_menu_toggle_modules() {
  require_once drupal_get_path('module', 'admin_menu') . '/admin_menu.inc';
  _admin_menu_toggle_modules();
}

Functions

Namesort descending Description
admin_menu_add_item Add a custom menu item.
admin_menu_admin_menu Implementation of hook_admin_menu().
admin_menu_admin_menu_replacements Implementation of hook_admin_menu_replacements().
admin_menu_cache_get Retrieve a client-side cache hash from cache.
admin_menu_cache_set Store a client-side cache hash in persistent cache.
admin_menu_clear_cache Clear the cached admin menu tree.
admin_menu_footer Implementation of hook_footer().
admin_menu_get_menu Return administration menu from cache or rebuild it.
admin_menu_get_user_count Return count of online anonymous/authenticated users.
admin_menu_help Implementation of hook_help().
admin_menu_item_url Adjust the menu item path.
admin_menu_js Implementation of hook_js().
admin_menu_js_cache Menu callback; Output administration menu for HTTP caching via AJAX request.
admin_menu_menu Implementation of hook_menu().
admin_menu_output Build the administration menu output.
admin_menu_panels_cache Implementation of hook_panels_cache().
admin_menu_perm Implementation of hook_perm().
admin_menu_suppress Suppress display of administration menu.
admin_menu_toggle_modules Menu callback; Enable/disable developer modules.
theme_admin_menu_item High-performance implementation of theme_menu_item().
theme_admin_menu_tree Return a rendered menu tree.
_admin_menu_sort Comparator routine for use in sorting menu items.