danielebarchiesi@4: $data) { danielebarchiesi@4: // Convert named placeholders to anonymous placeholders, since the menu danielebarchiesi@4: // system stores paths using anonymous placeholders. danielebarchiesi@4: $replacements = array_fill_keys(array_keys($data['arguments'][0]), '%'); danielebarchiesi@4: $data['parent'] = strtr($data['parent'], $replacements); danielebarchiesi@4: $new_map[strtr($path, $replacements)] = $data; danielebarchiesi@4: } danielebarchiesi@4: $expand_map = $new_map; danielebarchiesi@4: unset($new_map); danielebarchiesi@4: danielebarchiesi@4: // Retrieve dynamic menu link tree for the expansion mappings. danielebarchiesi@4: // @todo Skip entire processing if initial $expand_map is empty and directly danielebarchiesi@4: // return $tree? danielebarchiesi@4: if (!empty($expand_map)) { danielebarchiesi@4: $tree_dynamic = admin_menu_tree_dynamic($expand_map); danielebarchiesi@4: } danielebarchiesi@4: else { danielebarchiesi@4: $tree_dynamic = array(); danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: // Merge local tasks with static menu tree. danielebarchiesi@4: $tree = menu_tree_all_data($menu_name); danielebarchiesi@4: admin_menu_merge_tree($tree, $tree_dynamic, array()); danielebarchiesi@4: danielebarchiesi@4: return $tree; danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Load menu link trees for router paths containing dynamic arguments. danielebarchiesi@4: * danielebarchiesi@4: * @param $expand_map danielebarchiesi@4: * An array containing menu router path placeholder expansion argument danielebarchiesi@4: * mappings. danielebarchiesi@4: * danielebarchiesi@4: * @return danielebarchiesi@4: * An associative array whose keys are the parent paths of the menu router danielebarchiesi@4: * paths given in $expand_map as well as the parent paths of any child link danielebarchiesi@4: * deeper down the tree. The parent paths are used in admin_menu_merge_tree() danielebarchiesi@4: * to check whether anything needs to be merged. danielebarchiesi@4: * danielebarchiesi@4: * @see hook_admin_menu_map() danielebarchiesi@4: */ danielebarchiesi@4: function admin_menu_tree_dynamic(array $expand_map) { danielebarchiesi@4: $p_columns = array(); danielebarchiesi@4: for ($i = 1; $i <= MENU_MAX_DEPTH; $i++) { danielebarchiesi@4: $p_columns[] = 'p' . $i; danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: // Fetch p* columns for all router paths to expand. danielebarchiesi@4: $router_paths = array_keys($expand_map); danielebarchiesi@4: $plids = db_select('menu_links', 'ml') danielebarchiesi@4: ->fields('ml', $p_columns) danielebarchiesi@4: ->condition('router_path', $router_paths) danielebarchiesi@4: ->execute() danielebarchiesi@4: ->fetchAll(PDO::FETCH_ASSOC); danielebarchiesi@4: danielebarchiesi@4: // Unlikely, but possible. danielebarchiesi@4: if (empty($plids)) { danielebarchiesi@4: return array(); danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: // Use queried plid columns to query sub-trees for the router paths. danielebarchiesi@4: $query = db_select('menu_links', 'ml'); danielebarchiesi@4: $query->join('menu_router', 'm', 'ml.router_path = m.path'); danielebarchiesi@4: $query danielebarchiesi@4: ->fields('ml') danielebarchiesi@4: ->fields('m', array_diff(drupal_schema_fields_sql('menu_router'), drupal_schema_fields_sql('menu_links'))); danielebarchiesi@4: danielebarchiesi@4: // The retrieved menu link trees have to be ordered by depth, so parents danielebarchiesi@4: // always come before their children for the storage logic below. danielebarchiesi@4: foreach ($p_columns as $column) { danielebarchiesi@4: $query->orderBy($column, 'ASC'); danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: $db_or = db_or(); danielebarchiesi@4: foreach ($plids as $path_plids) { danielebarchiesi@4: $db_and = db_and(); danielebarchiesi@4: // plids with value 0 may be ignored. danielebarchiesi@4: foreach (array_filter($path_plids) as $column => $plid) { danielebarchiesi@4: $db_and->condition($column, $plid); danielebarchiesi@4: } danielebarchiesi@4: $db_or->condition($db_and); danielebarchiesi@4: } danielebarchiesi@4: $query->condition($db_or); danielebarchiesi@4: $result = $query danielebarchiesi@4: ->execute() danielebarchiesi@4: ->fetchAllAssoc('mlid', PDO::FETCH_ASSOC); danielebarchiesi@4: danielebarchiesi@4: // Store dynamic links grouped by parent path for later merging and assign danielebarchiesi@4: // placeholder expansion arguments. danielebarchiesi@4: $tree_dynamic = array(); danielebarchiesi@4: foreach ($result as $mlid => $link) { danielebarchiesi@4: // If contained in $expand_map, then this is a (first) parent, and we need danielebarchiesi@4: // to store by the defined 'parent' path for later merging, as well as danielebarchiesi@4: // provide the expansion map arguments to apply to the dynamic tree. danielebarchiesi@4: if (isset($expand_map[$link['path']])) { danielebarchiesi@4: $parent_path = $expand_map[$link['path']]['parent']; danielebarchiesi@4: $link['expand_map'] = $expand_map[$link['path']]['arguments']; danielebarchiesi@4: } danielebarchiesi@4: // Otherwise, just store this link keyed by its parent path; the expand_map danielebarchiesi@4: // is automatically derived from parent paths. danielebarchiesi@4: else { danielebarchiesi@4: $parent_path = $result[$link['plid']]['path']; danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: $tree_dynamic[$parent_path][] = $link; danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: return $tree_dynamic; danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Walk through the entire menu tree and merge in expanded dynamic menu links. danielebarchiesi@4: * danielebarchiesi@4: * @param &$tree danielebarchiesi@4: * A menu tree structure as returned by menu_tree_all_data(). danielebarchiesi@4: * @param $tree_dynamic danielebarchiesi@4: * A dynamic menu tree structure as returned by admin_menu_tree_dynamic(). danielebarchiesi@4: * @param $expand_map danielebarchiesi@4: * An array containing menu router path placeholder expansion argument danielebarchiesi@4: * mappings. danielebarchiesi@4: * danielebarchiesi@4: * @see hook_admin_menu_map() danielebarchiesi@4: * @see admin_menu_tree_dynamic() danielebarchiesi@4: * @see menu_tree_all_data() danielebarchiesi@4: */ danielebarchiesi@4: function admin_menu_merge_tree(array &$tree, array $tree_dynamic, array $expand_map) { danielebarchiesi@4: foreach ($tree as $key => $data) { danielebarchiesi@4: $path = $data['link']['router_path']; danielebarchiesi@4: danielebarchiesi@4: // Recurse into regular menu tree. danielebarchiesi@4: if ($tree[$key]['below']) { danielebarchiesi@4: admin_menu_merge_tree($tree[$key]['below'], $tree_dynamic, $expand_map); danielebarchiesi@4: } danielebarchiesi@4: // Nothing to merge, if this parent path is not in our dynamic tree. danielebarchiesi@4: if (!isset($tree_dynamic[$path])) { danielebarchiesi@4: continue; danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: // Add expanded dynamic items. danielebarchiesi@4: foreach ($tree_dynamic[$path] as $link) { danielebarchiesi@4: // If the dynamic item has custom placeholder expansion parameters set, danielebarchiesi@4: // use them, otherwise keep current. danielebarchiesi@4: if (isset($link['expand_map'])) { danielebarchiesi@4: // If there are currently no expansion parameters, we may use the new danielebarchiesi@4: // set immediately. danielebarchiesi@4: if (empty($expand_map)) { danielebarchiesi@4: $current_expand_map = $link['expand_map']; danielebarchiesi@4: } danielebarchiesi@4: else { danielebarchiesi@4: // Otherwise we need to filter out elements that differ from the danielebarchiesi@4: // current set, i.e. that are not in the same path. danielebarchiesi@4: $current_expand_map = array(); danielebarchiesi@4: foreach ($expand_map as $arguments) { danielebarchiesi@4: foreach ($arguments as $placeholder => $value) { danielebarchiesi@4: foreach ($link['expand_map'] as $new_arguments) { danielebarchiesi@4: // Skip the new argument if it doesn't contain the current danielebarchiesi@4: // replacement placeholders or if their values differ. danielebarchiesi@4: if (!isset($new_arguments[$placeholder]) || $new_arguments[$placeholder] != $value) { danielebarchiesi@4: continue; danielebarchiesi@4: } danielebarchiesi@4: $current_expand_map[] = $new_arguments; danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: else { danielebarchiesi@4: $current_expand_map = $expand_map; danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: // Skip dynamic items without expansion parameters. danielebarchiesi@4: if (empty($current_expand_map)) { danielebarchiesi@4: continue; danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: // Expand anonymous to named placeholders. danielebarchiesi@4: // @see _menu_load_objects() danielebarchiesi@4: $path_args = explode('/', $link['path']); danielebarchiesi@4: $load_functions = unserialize($link['load_functions']); danielebarchiesi@4: if (is_array($load_functions)) { danielebarchiesi@4: foreach ($load_functions as $index => $function) { danielebarchiesi@4: if ($function) { danielebarchiesi@4: if (is_array($function)) { danielebarchiesi@4: list($function,) = each($function); danielebarchiesi@4: } danielebarchiesi@4: // Add the loader function name minus "_load". danielebarchiesi@4: $placeholder = '%' . substr($function, 0, -5); danielebarchiesi@4: $path_args[$index] = $placeholder; danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: $path_dynamic = implode('/', $path_args); danielebarchiesi@4: danielebarchiesi@4: // Create new menu items using expansion arguments. danielebarchiesi@4: foreach ($current_expand_map as $arguments) { danielebarchiesi@4: // Create the cartesian product for all arguments and create new danielebarchiesi@4: // menu items for each generated combination thereof. danielebarchiesi@4: foreach (admin_menu_expand_args($arguments) as $replacements) { danielebarchiesi@4: $newpath = strtr($path_dynamic, $replacements); danielebarchiesi@4: // Skip this item, if any placeholder could not be replaced. danielebarchiesi@4: // Faster than trying to invoke _menu_translate(). danielebarchiesi@4: if (strpos($newpath, '%') !== FALSE) { danielebarchiesi@4: continue; danielebarchiesi@4: } danielebarchiesi@4: $map = explode('/', $newpath); danielebarchiesi@4: $item = admin_menu_translate($link, $map); danielebarchiesi@4: // Skip this item, if the current user does not have access. danielebarchiesi@4: if (empty($item)) { danielebarchiesi@4: continue; danielebarchiesi@4: } danielebarchiesi@4: // Build subtree using current replacement arguments. danielebarchiesi@4: $new_expand_map = array(); danielebarchiesi@4: foreach ($replacements as $placeholder => $value) { danielebarchiesi@4: $new_expand_map[$placeholder] = array($value); danielebarchiesi@4: } danielebarchiesi@4: admin_menu_merge_tree($item, $tree_dynamic, array($new_expand_map)); danielebarchiesi@4: $tree[$key]['below'] += $item; danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: // Sort new subtree items. danielebarchiesi@4: ksort($tree[$key]['below']); danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Translate an expanded router item into a menu link suitable for rendering. danielebarchiesi@4: * danielebarchiesi@4: * @param $router_item danielebarchiesi@4: * A menu router item. danielebarchiesi@4: * @param $map danielebarchiesi@4: * A path map with placeholders replaced. danielebarchiesi@4: */ danielebarchiesi@4: function admin_menu_translate($router_item, $map) { danielebarchiesi@4: _menu_translate($router_item, $map, TRUE); danielebarchiesi@4: danielebarchiesi@4: // Run through hook_translated_menu_link_alter() to add devel information, danielebarchiesi@4: // if configured. danielebarchiesi@4: $router_item['menu_name'] = 'management'; danielebarchiesi@4: // @todo Invoke as usual like _menu_link_translate(). danielebarchiesi@4: admin_menu_translated_menu_link_alter($router_item, NULL); danielebarchiesi@4: danielebarchiesi@4: if ($router_item['access']) { danielebarchiesi@4: // Override mlid to make this item unique; since these items are expanded danielebarchiesi@4: // from dynamic items, the mlid is always the same, so each item would danielebarchiesi@4: // replace any other. danielebarchiesi@4: // @todo Doing this instead leads to plenty of duplicate links below danielebarchiesi@4: // admin/structure/menu; likely a hidden recursion problem. danielebarchiesi@4: // $router_item['mlid'] = $router_item['href'] . $router_item['mlid']; danielebarchiesi@4: $router_item['mlid'] = $router_item['href']; danielebarchiesi@4: // Turn menu callbacks into regular menu items to make them visible. danielebarchiesi@4: if ($router_item['type'] == MENU_CALLBACK) { danielebarchiesi@4: $router_item['type'] = MENU_NORMAL_ITEM; danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: // @see _menu_tree_check_access() danielebarchiesi@4: $key = (50000 + $router_item['weight']) . ' ' . $router_item['title'] . ' ' . $router_item['mlid']; danielebarchiesi@4: return array($key => array( danielebarchiesi@4: 'link' => $router_item, danielebarchiesi@4: 'below' => array(), danielebarchiesi@4: )); danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: return array(); danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Create the cartesian product of multiple varying sized argument arrays. danielebarchiesi@4: * danielebarchiesi@4: * @param $arguments danielebarchiesi@4: * A two dimensional array of arguments. danielebarchiesi@4: * danielebarchiesi@4: * @see hook_admin_menu_map() danielebarchiesi@4: */ danielebarchiesi@4: function admin_menu_expand_args($arguments) { danielebarchiesi@4: $replacements = array(); danielebarchiesi@4: danielebarchiesi@4: // Initialize line cursors, move out array keys (placeholders) and assign danielebarchiesi@4: // numeric keys instead. danielebarchiesi@4: $i = 0; danielebarchiesi@4: $placeholders = array(); danielebarchiesi@4: $new_arguments = array(); danielebarchiesi@4: foreach ($arguments as $placeholder => $values) { danielebarchiesi@4: // Skip empty arguments. danielebarchiesi@4: if (empty($values)) { danielebarchiesi@4: continue; danielebarchiesi@4: } danielebarchiesi@4: $cursor[$i] = 0; danielebarchiesi@4: $placeholders[$i] = $placeholder; danielebarchiesi@4: $new_arguments[$i] = $values; danielebarchiesi@4: $i++; danielebarchiesi@4: } danielebarchiesi@4: $arguments = $new_arguments; danielebarchiesi@4: unset($new_arguments); danielebarchiesi@4: danielebarchiesi@4: if ($rows = count($arguments)) { danielebarchiesi@4: do { danielebarchiesi@4: // Collect current argument from each row. danielebarchiesi@4: $row = array(); danielebarchiesi@4: for ($i = 0; $i < $rows; ++$i) { danielebarchiesi@4: $row[$placeholders[$i]] = $arguments[$i][$cursor[$i]]; danielebarchiesi@4: } danielebarchiesi@4: $replacements[] = $row; danielebarchiesi@4: danielebarchiesi@4: // Increment cursor position. danielebarchiesi@4: $j = $rows - 1; danielebarchiesi@4: $cursor[$j]++; danielebarchiesi@4: while (!array_key_exists($cursor[$j], $arguments[$j])) { danielebarchiesi@4: // No more arguments left: reset cursor, go to next line and increment danielebarchiesi@4: // that cursor instead. Repeat until argument found or out of rows. danielebarchiesi@4: $cursor[$j] = 0; danielebarchiesi@4: if (--$j < 0) { danielebarchiesi@4: // We're done. danielebarchiesi@4: break 2; danielebarchiesi@4: } danielebarchiesi@4: $cursor[$j]++; danielebarchiesi@4: } danielebarchiesi@4: } while (1); danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: return $replacements; danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Build the administration menu as renderable menu links. danielebarchiesi@4: * danielebarchiesi@4: * @param $tree danielebarchiesi@4: * A data structure representing the administration menu tree as returned from danielebarchiesi@4: * menu_tree_all_data(). danielebarchiesi@4: * danielebarchiesi@4: * @return danielebarchiesi@4: * The complete administration menu, suitable for theme_admin_menu_links(). danielebarchiesi@4: * danielebarchiesi@4: * @see theme_admin_menu_links() danielebarchiesi@4: * @see admin_menu_menu_alter() danielebarchiesi@4: */ danielebarchiesi@4: function admin_menu_links_menu($tree) { danielebarchiesi@4: $links = array(); danielebarchiesi@4: foreach ($tree as $data) { danielebarchiesi@4: // Skip items that are inaccessible, invisible, or link to their parent. danielebarchiesi@4: // (MENU_DEFAULT_LOCAL_TASK), and MENU_CALLBACK-alike items that should only danielebarchiesi@4: // appear in the breadcrumb. danielebarchiesi@4: if (!$data['link']['access'] || $data['link']['type'] & MENU_LINKS_TO_PARENT || $data['link']['type'] == MENU_VISIBLE_IN_BREADCRUMB || $data['link']['hidden'] == 1) { danielebarchiesi@4: continue; danielebarchiesi@4: } danielebarchiesi@4: // Hide 'Administer' and make child links appear on this level. danielebarchiesi@4: // @todo Make this configurable. danielebarchiesi@4: if ($data['link']['router_path'] == 'admin') { danielebarchiesi@4: if ($data['below']) { danielebarchiesi@4: $links = array_merge($links, admin_menu_links_menu($data['below'])); danielebarchiesi@4: } danielebarchiesi@4: continue; danielebarchiesi@4: } danielebarchiesi@4: // Omit alias lookups. danielebarchiesi@4: $data['link']['localized_options']['alias'] = TRUE; danielebarchiesi@4: // Remove description to prevent mouseover tooltip clashes. danielebarchiesi@4: unset($data['link']['localized_options']['attributes']['title']); danielebarchiesi@4: danielebarchiesi@4: // Make action links (typically "Add ...") appear first in dropdowns. danielebarchiesi@4: // They might appear first already, but only as long as there is no link danielebarchiesi@4: // that comes alphabetically first (e.g., a node type with label "Ad"). danielebarchiesi@4: if ($data['link']['type'] & MENU_IS_LOCAL_ACTION) { danielebarchiesi@4: $data['link']['weight'] -= 1000; danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: $links[$data['link']['href']] = array( danielebarchiesi@4: '#title' => $data['link']['title'], danielebarchiesi@4: '#href' => $data['link']['href'], danielebarchiesi@4: '#options' => $data['link']['localized_options'], danielebarchiesi@4: '#weight' => $data['link']['weight'], danielebarchiesi@4: ); danielebarchiesi@4: danielebarchiesi@4: // Recurse to add any child links. danielebarchiesi@4: $children = array(); danielebarchiesi@4: if ($data['below']) { danielebarchiesi@4: $children = admin_menu_links_menu($data['below']); danielebarchiesi@4: $links[$data['link']['href']] += $children; danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: // Handle links pointing to category/overview pages. danielebarchiesi@4: if ($data['link']['page_callback'] == 'system_admin_menu_block_page' || $data['link']['page_callback'] == 'system_admin_config_page') { danielebarchiesi@4: // Apply a marker for others to consume. danielebarchiesi@4: $links[$data['link']['href']]['#is_category'] = TRUE; danielebarchiesi@4: // Automatically hide empty categories. danielebarchiesi@4: // Check for empty children first for performance. Only when non-empty danielebarchiesi@4: // (typically 'admin/config'), check whether children are accessible. danielebarchiesi@4: if (empty($children) || !element_get_visible_children($children)) { danielebarchiesi@4: $links[$data['link']['href']]['#access'] = FALSE; danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: return $links; danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Build icon menu links; mostly containing maintenance helpers. danielebarchiesi@4: * danielebarchiesi@4: * @see theme_admin_menu_links() danielebarchiesi@4: */ danielebarchiesi@4: function admin_menu_links_icon() { danielebarchiesi@4: $destination = drupal_get_destination(); danielebarchiesi@4: danielebarchiesi@4: $links = array( danielebarchiesi@4: '#theme' => 'admin_menu_links', danielebarchiesi@4: '#wrapper_attributes' => array('id' => 'admin-menu-icon'), danielebarchiesi@4: '#weight' => -100, danielebarchiesi@4: ); danielebarchiesi@4: $links['icon'] = array( danielebarchiesi@4: '#title' => theme('admin_menu_icon'), danielebarchiesi@4: '#attributes' => array('class' => array('admin-menu-icon')), danielebarchiesi@4: '#href' => '', danielebarchiesi@4: '#options' => array( danielebarchiesi@4: 'html' => TRUE, danielebarchiesi@4: ), danielebarchiesi@4: ); danielebarchiesi@4: // Add link to manually run cron. danielebarchiesi@4: $links['icon']['cron'] = array( danielebarchiesi@4: '#title' => t('Run cron'), danielebarchiesi@4: '#weight' => 50, danielebarchiesi@4: '#access' => user_access('administer site configuration'), danielebarchiesi@4: '#href' => 'admin/reports/status/run-cron', danielebarchiesi@4: ); danielebarchiesi@4: // Add link to run update.php. danielebarchiesi@4: $links['icon']['update'] = array( danielebarchiesi@4: '#title' => t('Run updates'), danielebarchiesi@4: '#weight' => 50, danielebarchiesi@4: // @see update_access_allowed() danielebarchiesi@4: '#access' => $GLOBALS['user']->uid == 1 || !empty($GLOBALS['update_free_access']) || user_access('administer software updates'), danielebarchiesi@4: '#href' => base_path() . 'update.php', danielebarchiesi@4: '#options' => array( danielebarchiesi@4: 'external' => TRUE, danielebarchiesi@4: ), danielebarchiesi@4: ); danielebarchiesi@4: // Add link to drupal.org. danielebarchiesi@4: $links['icon']['drupal.org'] = array( danielebarchiesi@4: '#title' => 'Drupal.org', danielebarchiesi@4: '#weight' => 100, danielebarchiesi@4: '#access' => user_access('display drupal links'), danielebarchiesi@4: '#href' => 'http://drupal.org', danielebarchiesi@4: ); danielebarchiesi@4: // Add links to project issue queues. danielebarchiesi@4: foreach (module_list(FALSE, TRUE) as $module) { danielebarchiesi@4: $info = drupal_parse_info_file(drupal_get_path('module', $module) . '/' . $module . '.info'); danielebarchiesi@4: if (!isset($info['project']) || isset($links['icon']['drupal.org'][$info['project']])) { danielebarchiesi@4: continue; danielebarchiesi@4: } danielebarchiesi@4: $links['icon']['drupal.org'][$info['project']] = array( danielebarchiesi@4: '#title' => t('@project issue queue', array('@project' => $info['name'])), danielebarchiesi@4: '#weight' => ($info['project'] == 'drupal' ? -10 : 0), danielebarchiesi@4: '#href' => 'http://drupal.org/project/issues/' . $info['project'], danielebarchiesi@4: '#options' => array( danielebarchiesi@4: 'query' => array('version' => (isset($info['core']) ? $info['core'] : 'All')), danielebarchiesi@4: ), danielebarchiesi@4: ); danielebarchiesi@4: } danielebarchiesi@4: // Add items to flush caches. danielebarchiesi@4: $links['icon']['flush-cache'] = array( danielebarchiesi@4: '#title' => t('Flush all caches'), danielebarchiesi@4: '#weight' => 20, danielebarchiesi@4: '#access' => user_access('flush caches'), danielebarchiesi@4: '#href' => 'admin_menu/flush-cache', danielebarchiesi@4: '#options' => array( danielebarchiesi@4: 'query' => $destination + array('token' => drupal_get_token('admin_menu/flush-cache')), danielebarchiesi@4: ), danielebarchiesi@4: ); danielebarchiesi@4: $caches = module_invoke_all('admin_menu_cache_info'); danielebarchiesi@4: foreach ($caches as $name => $cache) { danielebarchiesi@4: $links['icon']['flush-cache'][$name] = array( danielebarchiesi@4: '#title' => $cache['title'], danielebarchiesi@4: '#href' => 'admin_menu/flush-cache/' . $name, danielebarchiesi@4: '#options' => array( danielebarchiesi@4: 'query' => $destination + array('token' => drupal_get_token('admin_menu/flush-cache/' . $name)), danielebarchiesi@4: ), danielebarchiesi@4: ); danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: // Add link to toggle developer modules (performance). danielebarchiesi@4: $saved_state = variable_get('admin_menu_devel_modules_enabled', NULL); danielebarchiesi@4: $links['icon']['toggle-modules'] = array( danielebarchiesi@4: '#title' => isset($saved_state) ? t('Enable developer modules') : t('Disable developer modules'), danielebarchiesi@4: '#weight' => 88, danielebarchiesi@4: '#access' => user_access('administer modules'), danielebarchiesi@4: '#href' => 'admin_menu/toggle-modules', danielebarchiesi@4: '#options' => array( danielebarchiesi@4: 'query' => $destination + array('token' => drupal_get_token('admin_menu/toggle-modules')), danielebarchiesi@4: ), danielebarchiesi@4: ); danielebarchiesi@4: danielebarchiesi@4: // Add Devel module menu links. danielebarchiesi@4: if (module_exists('devel')) { danielebarchiesi@4: $devel_tree = menu_build_tree('devel'); danielebarchiesi@4: $devel_links = admin_menu_links_menu($devel_tree); danielebarchiesi@4: if (element_get_visible_children($devel_links)) { danielebarchiesi@4: $links['icon']['devel'] = array( danielebarchiesi@4: '#title' => t('Development'), danielebarchiesi@4: '#weight' => 30, danielebarchiesi@4: ) + $devel_links; danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: return $links; danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Builds the account links. danielebarchiesi@4: * danielebarchiesi@4: * @see theme_admin_menu_links() danielebarchiesi@4: */ danielebarchiesi@4: function admin_menu_links_account() { danielebarchiesi@4: $links = array( danielebarchiesi@4: '#theme' => 'admin_menu_links', danielebarchiesi@4: '#wrapper_attributes' => array('id' => 'admin-menu-account'), danielebarchiesi@4: '#weight' => 100, danielebarchiesi@4: ); danielebarchiesi@4: $links['account'] = array( danielebarchiesi@4: '#title' => format_username($GLOBALS['user']), danielebarchiesi@4: '#weight' => -99, danielebarchiesi@4: '#attributes' => array('class' => array('admin-menu-action', 'admin-menu-account')), danielebarchiesi@4: '#href' => 'user/' . $GLOBALS['user']->uid, danielebarchiesi@4: ); danielebarchiesi@4: $links['logout'] = array( danielebarchiesi@4: '#title' => t('Log out'), danielebarchiesi@4: '#weight' => -100, danielebarchiesi@4: '#attributes' => array('class' => array('admin-menu-action')), danielebarchiesi@4: '#href' => 'user/logout', danielebarchiesi@4: ); danielebarchiesi@4: // Add Devel module switch user links. danielebarchiesi@4: $switch_links = module_invoke('devel', 'switch_user_list'); danielebarchiesi@4: if (!empty($switch_links) && count($switch_links) > 1) { danielebarchiesi@4: foreach ($switch_links as $uid => $link) { danielebarchiesi@4: $links['account'][$link['title']] = array( danielebarchiesi@4: '#title' => $link['title'], danielebarchiesi@4: '#description' => $link['attributes']['title'], danielebarchiesi@4: '#href' => $link['href'], danielebarchiesi@4: '#options' => array( danielebarchiesi@4: 'query' => $link['query'], danielebarchiesi@4: 'html' => !empty($link['html']), danielebarchiesi@4: ), danielebarchiesi@4: ); danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: return $links; danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Builds user counter. danielebarchiesi@4: * danielebarchiesi@4: * @see theme_admin_menu_links() danielebarchiesi@4: */ danielebarchiesi@4: function admin_menu_links_users() { danielebarchiesi@4: $links = array( danielebarchiesi@4: '#theme' => 'admin_menu_links', danielebarchiesi@4: '#wrapper_attributes' => array('id' => 'admin-menu-users'), danielebarchiesi@4: '#weight' => 150, danielebarchiesi@4: ); danielebarchiesi@4: // Add link to show current authenticated/anonymous users. danielebarchiesi@4: $links['user-counter'] = array( danielebarchiesi@4: '#title' => admin_menu_get_user_count(), danielebarchiesi@4: '#description' => t('Current anonymous / authenticated users'), danielebarchiesi@4: '#weight' => -90, danielebarchiesi@4: '#attributes' => array('class' => array('admin-menu-action', 'admin-menu-users')), danielebarchiesi@4: '#href' => (user_access('administer users') ? 'admin/people/people' : 'user'), danielebarchiesi@4: ); danielebarchiesi@4: return $links; danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Build search widget. danielebarchiesi@4: * danielebarchiesi@4: * @see theme_admin_menu_links() danielebarchiesi@4: */ danielebarchiesi@4: function admin_menu_links_search() { danielebarchiesi@4: $links = array( danielebarchiesi@4: '#theme' => 'admin_menu_links', danielebarchiesi@4: '#wrapper_attributes' => array('id' => 'admin-menu-search'), danielebarchiesi@4: '#weight' => 180, danielebarchiesi@4: ); danielebarchiesi@4: $links['search'] = array( danielebarchiesi@4: '#type' => 'textfield', danielebarchiesi@4: '#title' => t('Search'), danielebarchiesi@4: '#title_display' => 'attribute', danielebarchiesi@4: '#attributes' => array( danielebarchiesi@4: 'placeholder' => t('Search'), danielebarchiesi@4: 'class' => array('admin-menu-search'), danielebarchiesi@4: ), danielebarchiesi@4: ); danielebarchiesi@4: return $links; danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Form builder function for module settings. danielebarchiesi@4: */ danielebarchiesi@4: function admin_menu_theme_settings() { danielebarchiesi@4: $form['admin_menu_margin_top'] = array( danielebarchiesi@4: '#type' => 'checkbox', danielebarchiesi@4: '#title' => t('Adjust top margin'), danielebarchiesi@4: '#default_value' => variable_get('admin_menu_margin_top', 1), danielebarchiesi@4: '#description' => t('Shifts the site output down by approximately 20 pixels from the top of the viewport. If disabled, absolute- or fixed-positioned page elements may be covered by the administration menu.'), danielebarchiesi@4: ); danielebarchiesi@4: $form['admin_menu_position_fixed'] = array( danielebarchiesi@4: '#type' => 'checkbox', danielebarchiesi@4: '#title' => t('Keep menu at top of page'), danielebarchiesi@4: '#default_value' => variable_get('admin_menu_position_fixed', 1), danielebarchiesi@4: '#description' => t('Displays the administration menu always at the top of the browser viewport (even when scrolling the page).'), danielebarchiesi@4: ); danielebarchiesi@4: // @todo Re-confirm this with latest browser versions. danielebarchiesi@4: $form['admin_menu_position_fixed']['#description'] .= '
' . t('In some browsers, this setting may result in a malformed page, an invisible cursor, non-selectable elements in forms, or other issues.') . ''; danielebarchiesi@4: danielebarchiesi@4: $form['advanced'] = array( danielebarchiesi@4: '#type' => 'vertical_tabs', danielebarchiesi@4: '#title' => t('Advanced settings'), danielebarchiesi@4: ); danielebarchiesi@4: danielebarchiesi@4: $form['plugins'] = array( danielebarchiesi@4: '#type' => 'fieldset', danielebarchiesi@4: '#title' => t('Plugins'), danielebarchiesi@4: '#group' => 'advanced', danielebarchiesi@4: ); danielebarchiesi@4: $form['plugins']['admin_menu_components'] = array( danielebarchiesi@4: '#type' => 'checkboxes', danielebarchiesi@4: '#title' => t('Enabled components'), danielebarchiesi@4: '#options' => array( danielebarchiesi@4: 'admin_menu.icon' => t('Icon menu'), danielebarchiesi@4: 'admin_menu.menu' => t('Administration menu'), danielebarchiesi@4: 'admin_menu.search' => t('Search bar'), danielebarchiesi@4: 'admin_menu.users' => t('User counts'), danielebarchiesi@4: 'admin_menu.account' => t('Account links'), danielebarchiesi@4: ), danielebarchiesi@4: ); danielebarchiesi@4: $form['plugins']['admin_menu_components']['#default_value'] = array_keys(array_filter(variable_get('admin_menu_components', $form['plugins']['admin_menu_components']['#options']))); danielebarchiesi@4: danielebarchiesi@4: $process = element_info_property('checkboxes', '#process', array()); danielebarchiesi@4: $form['plugins']['admin_menu_components']['#process'] = array_merge(array('admin_menu_settings_process_components'), $process); danielebarchiesi@4: $form['#attached']['js'][] = drupal_get_path('module', 'admin_menu') . '/admin_menu.admin.js'; danielebarchiesi@4: danielebarchiesi@4: $form['tweaks'] = array( danielebarchiesi@4: '#type' => 'fieldset', danielebarchiesi@4: '#title' => t('System tweaks'), danielebarchiesi@4: '#group' => 'advanced', danielebarchiesi@4: ); danielebarchiesi@4: $form['tweaks']['admin_menu_tweak_modules'] = array( danielebarchiesi@4: '#type' => 'checkbox', danielebarchiesi@4: '#title' => t('Collapse module groups on the %modules page', array( danielebarchiesi@4: '%modules' => t('Modules'), danielebarchiesi@4: '!modules-url' => url('admin/modules'), danielebarchiesi@4: )), danielebarchiesi@4: '#default_value' => variable_get('admin_menu_tweak_modules', 0), danielebarchiesi@4: ); danielebarchiesi@4: if (module_exists('util')) { danielebarchiesi@4: $form['tweaks']['admin_menu_tweak_modules']['#description'] .= '
' . t('If the Utility module was installed for this purpose, it can be safely disabled and uninstalled.') . ''; danielebarchiesi@4: } danielebarchiesi@4: $form['tweaks']['admin_menu_tweak_permissions'] = array( danielebarchiesi@4: '#type' => 'checkbox', danielebarchiesi@4: '#title' => t('Collapse module groups on the %permissions page', array( danielebarchiesi@4: '%permissions' => t('Permissions'), danielebarchiesi@4: '@permissions-url' => url('admin/people/permissions'), danielebarchiesi@4: )), danielebarchiesi@4: '#default_value' => variable_get('admin_menu_tweak_permissions', 0), danielebarchiesi@4: ); danielebarchiesi@4: $form['tweaks']['admin_menu_tweak_tabs'] = array( danielebarchiesi@4: '#type' => 'checkbox', danielebarchiesi@4: '#title' => t('Move local tasks into menu'), danielebarchiesi@4: '#default_value' => variable_get('admin_menu_tweak_tabs', 0), danielebarchiesi@4: '#description' => t('Moves the tabs on all pages into the administration menu. Only possible for themes using the CSS classes tabs primary and tabs secondary.'), danielebarchiesi@4: ); danielebarchiesi@4: danielebarchiesi@4: $form['performance'] = array( danielebarchiesi@4: '#type' => 'fieldset', danielebarchiesi@4: '#title' => t('Performance'), danielebarchiesi@4: '#group' => 'advanced', danielebarchiesi@4: ); danielebarchiesi@4: $form['performance']['admin_menu_cache_client'] = array( danielebarchiesi@4: '#type' => 'checkbox', danielebarchiesi@4: '#title' => t('Cache menu in client-side browser'), danielebarchiesi@4: '#default_value' => variable_get('admin_menu_cache_client', 1), danielebarchiesi@4: ); danielebarchiesi@4: // Fetch all available modules manually, since module_list() only returns danielebarchiesi@4: // currently enabled modules, which makes this setting pointless if developer danielebarchiesi@4: // modules are currently disabled. danielebarchiesi@4: $all_modules = array(); danielebarchiesi@4: $result = db_query("SELECT name, filename, info FROM {system} WHERE type = 'module' ORDER BY name ASC"); danielebarchiesi@4: foreach ($result as $module) { danielebarchiesi@4: if (file_exists($module->filename)) { danielebarchiesi@4: $info = unserialize($module->info); danielebarchiesi@4: $all_modules[$module->name] = $info['name']; danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: $devel_modules = variable_get('admin_menu_devel_modules', _admin_menu_developer_modules()); danielebarchiesi@4: $devel_modules = array_intersect_key($all_modules, array_flip($devel_modules)); danielebarchiesi@4: $form['performance']['admin_menu_devel_modules_skip'] = array( danielebarchiesi@4: '#type' => 'checkboxes', danielebarchiesi@4: '#title' => t('Developer modules to keep enabled'), danielebarchiesi@4: '#default_value' => variable_get('admin_menu_devel_modules_skip', array()), danielebarchiesi@4: '#options' => $devel_modules, danielebarchiesi@4: '#access' => !empty($devel_modules), danielebarchiesi@4: '#description' => t('The selected modules will not be disabled when the link %disable-developer-modules below the icon in the menu is invoked.', array( danielebarchiesi@4: '%disable-developer-modules' => t('Disable developer modules'), danielebarchiesi@4: )), danielebarchiesi@4: ); danielebarchiesi@4: danielebarchiesi@4: return system_settings_form($form); danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * #process callback for component plugin form element in admin_menu_theme_settings(). danielebarchiesi@4: */ danielebarchiesi@4: function admin_menu_settings_process_components($element) { danielebarchiesi@4: // Assign 'rel' attributes to all options to achieve a live preview. danielebarchiesi@4: // Unfortunately, #states relies on wrapping .form-wrapper classes, so it danielebarchiesi@4: // cannot be used here. danielebarchiesi@4: foreach ($element['#options'] as $key => $label) { danielebarchiesi@4: if (!isset($element[$key]['#attributes']['rel'])) { danielebarchiesi@4: $id = preg_replace('/[^a-z]/', '-', $key); danielebarchiesi@4: $element[$key]['#attributes']['rel'] = '#' . $id; danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: return $element; danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Form validation handler for admin_menu_theme_settings(). danielebarchiesi@4: */ danielebarchiesi@4: function admin_menu_theme_settings_validate(&$form, &$form_state) { danielebarchiesi@4: // Change the configured components to Boolean values. danielebarchiesi@4: foreach ($form_state['values']['admin_menu_components'] as $component => &$enabled) { danielebarchiesi@4: $enabled = (bool) $enabled; danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Implementation of hook_form_FORM_ID_alter(). danielebarchiesi@4: * danielebarchiesi@4: * Extends Devel module with Administration menu developer settings. danielebarchiesi@4: */ danielebarchiesi@4: function _admin_menu_form_devel_admin_settings_alter(&$form, $form_state) { danielebarchiesi@4: // Shift system_settings_form buttons. danielebarchiesi@4: $weight = isset($form['buttons']['#weight']) ? $form['buttons']['#weight'] : 0; danielebarchiesi@4: $form['buttons']['#weight'] = $weight + 1; danielebarchiesi@4: danielebarchiesi@4: $form['admin_menu'] = array( danielebarchiesi@4: '#type' => 'fieldset', danielebarchiesi@4: '#title' => t('Administration menu settings'), danielebarchiesi@4: '#collapsible' => TRUE, danielebarchiesi@4: '#collapsed' => TRUE, danielebarchiesi@4: ); danielebarchiesi@4: $display_options = array('mid', 'weight', 'pid'); danielebarchiesi@4: $display_options = array(0 => t('None'), 'mlid' => t('Menu link ID'), 'weight' => t('Weight'), 'plid' => t('Parent link ID')); danielebarchiesi@4: $form['admin_menu']['admin_menu_display'] = array( danielebarchiesi@4: '#type' => 'radios', danielebarchiesi@4: '#title' => t('Display additional data for each menu item'), danielebarchiesi@4: '#default_value' => variable_get('admin_menu_display', 0), danielebarchiesi@4: '#options' => $display_options, danielebarchiesi@4: '#description' => t('Display the selected items next to each menu item link.'), danielebarchiesi@4: ); danielebarchiesi@4: $form['admin_menu']['admin_menu_show_all'] = array( danielebarchiesi@4: '#type' => 'checkbox', danielebarchiesi@4: '#title' => t('Display all menu items'), danielebarchiesi@4: '#default_value' => variable_get('admin_menu_show_all', 0), danielebarchiesi@4: '#description' => t('If enabled, all menu items are displayed regardless of your site permissions. Note: Do not enable on a production site.'), danielebarchiesi@4: ); danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Menu callback; Enable/disable developer modules. danielebarchiesi@4: * danielebarchiesi@4: * This can save up to 150ms on each uncached page request. danielebarchiesi@4: */ danielebarchiesi@4: function admin_menu_toggle_modules() { danielebarchiesi@4: if (!isset($_GET['token']) || !drupal_valid_token($_GET['token'], current_path())) { danielebarchiesi@4: return MENU_ACCESS_DENIED; danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: $rebuild = FALSE; danielebarchiesi@4: $saved_state = variable_get('admin_menu_devel_modules_enabled', NULL); danielebarchiesi@4: if (isset($saved_state)) { danielebarchiesi@4: // Re-enable modules that were enabled before. danielebarchiesi@4: module_enable($saved_state); danielebarchiesi@4: variable_del('admin_menu_devel_modules_enabled'); danielebarchiesi@4: drupal_set_message(t('Enabled these modules: !module-list.', array('!module-list' => implode(', ', $saved_state)))); danielebarchiesi@4: $rebuild = TRUE; danielebarchiesi@4: } danielebarchiesi@4: else { danielebarchiesi@4: // Allow site admins to override this variable via settings.php. danielebarchiesi@4: $devel_modules = variable_get('admin_menu_devel_modules', _admin_menu_developer_modules()); danielebarchiesi@4: // Store currently enabled modules in a variable. danielebarchiesi@4: $devel_modules = array_intersect(module_list(FALSE, FALSE), $devel_modules); danielebarchiesi@4: $devel_modules = array_diff($devel_modules, variable_get('admin_menu_devel_modules_skip', array())); danielebarchiesi@4: if (!empty($devel_modules)) { danielebarchiesi@4: variable_set('admin_menu_devel_modules_enabled', $devel_modules); danielebarchiesi@4: // Disable developer modules. danielebarchiesi@4: module_disable($devel_modules); danielebarchiesi@4: drupal_set_message(t('Disabled these modules: !module-list.', array('!module-list' => implode(', ', $devel_modules)))); danielebarchiesi@4: $rebuild = TRUE; danielebarchiesi@4: } danielebarchiesi@4: else { danielebarchiesi@4: drupal_set_message(t('No developer modules are enabled.')); danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: if ($rebuild) { danielebarchiesi@4: // Make sure everything is rebuilt, basically a combination of the calls danielebarchiesi@4: // from system_modules() and system_modules_submit(). danielebarchiesi@4: drupal_theme_rebuild(); danielebarchiesi@4: menu_rebuild(); danielebarchiesi@4: cache_clear_all('schema', 'cache'); danielebarchiesi@4: cache_clear_all(); danielebarchiesi@4: drupal_clear_css_cache(); danielebarchiesi@4: drupal_clear_js_cache(); danielebarchiesi@4: // Synchronize to catch any actions that were added or removed. danielebarchiesi@4: actions_synchronize(); danielebarchiesi@4: // Finally, flush admin_menu's cache. danielebarchiesi@4: admin_menu_flush_caches(); danielebarchiesi@4: } danielebarchiesi@4: drupal_goto(); danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Helper function to return a default list of developer modules. danielebarchiesi@4: */ danielebarchiesi@4: function _admin_menu_developer_modules() { danielebarchiesi@4: return array( danielebarchiesi@4: 'admin_devel', danielebarchiesi@4: 'cache_disable', danielebarchiesi@4: 'coder', danielebarchiesi@4: 'content_copy', danielebarchiesi@4: 'context_ui', danielebarchiesi@4: 'debug', danielebarchiesi@4: 'delete_all', danielebarchiesi@4: 'demo', danielebarchiesi@4: 'devel', danielebarchiesi@4: 'devel_node_access', danielebarchiesi@4: 'devel_themer', danielebarchiesi@4: 'field_ui', danielebarchiesi@4: 'fontyourface_ui', danielebarchiesi@4: 'form_controller', danielebarchiesi@4: 'imagecache_ui', danielebarchiesi@4: 'journal', danielebarchiesi@4: 'l10n_client', danielebarchiesi@4: 'l10n_update', danielebarchiesi@4: 'macro', danielebarchiesi@4: 'rules_admin', danielebarchiesi@4: 'stringoverrides', danielebarchiesi@4: 'trace', danielebarchiesi@4: 'upgrade_status', danielebarchiesi@4: 'user_display_ui', danielebarchiesi@4: 'util', danielebarchiesi@4: 'views_ui', danielebarchiesi@4: 'views_theme_wizard', danielebarchiesi@4: ); danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Flush all caches or a specific one. danielebarchiesi@4: * danielebarchiesi@4: * @param $name danielebarchiesi@4: * (optional) Name of cache to flush. danielebarchiesi@4: */ danielebarchiesi@4: function admin_menu_flush_cache($name = NULL) { danielebarchiesi@4: if (!isset($_GET['token']) || !drupal_valid_token($_GET['token'], current_path())) { danielebarchiesi@4: return MENU_ACCESS_DENIED; danielebarchiesi@4: } danielebarchiesi@4: if (isset($name)) { danielebarchiesi@4: $caches = module_invoke_all('admin_menu_cache_info'); danielebarchiesi@4: if (!isset($caches[$name])) { danielebarchiesi@4: return MENU_NOT_FOUND; danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: else { danielebarchiesi@4: $caches[$name] = array( danielebarchiesi@4: 'title' => t('Every'), danielebarchiesi@4: 'callback' => 'drupal_flush_all_caches', danielebarchiesi@4: ); danielebarchiesi@4: } danielebarchiesi@4: // Pass the cache to flush forward to the callback. danielebarchiesi@4: $function = $caches[$name]['callback']; danielebarchiesi@4: $function($name); danielebarchiesi@4: danielebarchiesi@4: drupal_set_message(t('!title cache cleared.', array('!title' => $caches[$name]['title']))); danielebarchiesi@4: danielebarchiesi@4: // The JavaScript injects a destination request parameter pointing to the danielebarchiesi@4: // originating page, so the user is redirected back to that page. Without danielebarchiesi@4: // destination parameter, the redirect ends on the front page. danielebarchiesi@4: drupal_goto(); danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Implements hook_admin_menu_cache_info(). danielebarchiesi@4: */ danielebarchiesi@4: function admin_menu_admin_menu_cache_info() { danielebarchiesi@4: $caches['admin_menu'] = array( danielebarchiesi@4: 'title' => t('Administration menu'), danielebarchiesi@4: 'callback' => '_admin_menu_flush_cache', danielebarchiesi@4: ); danielebarchiesi@4: return $caches; danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Implements hook_admin_menu_cache_info() on behalf of System module. danielebarchiesi@4: */ danielebarchiesi@4: function system_admin_menu_cache_info() { danielebarchiesi@4: $caches = array( danielebarchiesi@4: 'assets' => t('CSS and JavaScript'), danielebarchiesi@4: 'cache' => t('Page and else'), danielebarchiesi@4: 'menu' => t('Menu'), danielebarchiesi@4: 'registry' => t('Class registry'), danielebarchiesi@4: 'theme' => t('Theme registry'), danielebarchiesi@4: ); danielebarchiesi@4: foreach ($caches as $name => $cache) { danielebarchiesi@4: $caches[$name] = array( danielebarchiesi@4: 'title' => $cache, danielebarchiesi@4: 'callback' => '_admin_menu_flush_cache', danielebarchiesi@4: ); danielebarchiesi@4: } danielebarchiesi@4: return $caches; danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Implements hook_admin_menu_cache_info() on behalf of Update module. danielebarchiesi@4: */ danielebarchiesi@4: function update_admin_menu_cache_info() { danielebarchiesi@4: $caches['update'] = array( danielebarchiesi@4: 'title' => t('Update data'), danielebarchiesi@4: 'callback' => '_update_cache_clear', danielebarchiesi@4: ); danielebarchiesi@4: return $caches; danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Flush all caches or a specific one. danielebarchiesi@4: * danielebarchiesi@4: * @param $name danielebarchiesi@4: * (optional) Name of cache to flush. danielebarchiesi@4: * danielebarchiesi@4: * @see system_admin_menu_cache_info() danielebarchiesi@4: */ danielebarchiesi@4: function _admin_menu_flush_cache($name = NULL) { danielebarchiesi@4: switch ($name) { danielebarchiesi@4: case 'admin_menu': danielebarchiesi@4: admin_menu_flush_caches(); danielebarchiesi@4: break; danielebarchiesi@4: danielebarchiesi@4: case 'menu': danielebarchiesi@4: menu_rebuild(); danielebarchiesi@4: break; danielebarchiesi@4: danielebarchiesi@4: case 'registry': danielebarchiesi@4: registry_rebuild(); danielebarchiesi@4: // Fall-through to clear cache tables, since registry information is danielebarchiesi@4: // usually the base for other data that is cached (e.g. SimpleTests). danielebarchiesi@4: case 'cache': danielebarchiesi@4: // Don't clear cache_form - in-progress form submissions may break. danielebarchiesi@4: // Ordered so clearing the page cache will always be the last action. danielebarchiesi@4: // @see drupal_flush_all_caches() danielebarchiesi@4: $core = array('cache', 'cache_bootstrap', 'cache_filter', 'cache_page'); danielebarchiesi@4: $cache_tables = array_merge(module_invoke_all('flush_caches'), $core); danielebarchiesi@4: foreach ($cache_tables as $table) { danielebarchiesi@4: cache_clear_all('*', $table, TRUE); danielebarchiesi@4: } danielebarchiesi@4: break; danielebarchiesi@4: danielebarchiesi@4: case 'assets': danielebarchiesi@4: // Change query-strings on css/js files to enforce reload for all users. danielebarchiesi@4: _drupal_flush_css_js(); danielebarchiesi@4: danielebarchiesi@4: drupal_clear_css_cache(); danielebarchiesi@4: drupal_clear_js_cache(); danielebarchiesi@4: danielebarchiesi@4: // Clear the page cache, since cached HTML pages might link to old CSS and danielebarchiesi@4: // JS aggregates. danielebarchiesi@4: cache_clear_all('*', 'cache_page', TRUE); danielebarchiesi@4: break; danielebarchiesi@4: danielebarchiesi@4: case 'theme': danielebarchiesi@4: system_rebuild_theme_data(); danielebarchiesi@4: drupal_theme_rebuild(); danielebarchiesi@4: break; danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Preprocesses variables for theme_admin_menu_icon(). danielebarchiesi@4: */ danielebarchiesi@4: function template_preprocess_admin_menu_icon(&$variables) { danielebarchiesi@4: // Image source might have been passed in as theme variable. danielebarchiesi@4: if (!isset($variables['src'])) { danielebarchiesi@4: if (theme_get_setting('toggle_favicon')) { danielebarchiesi@4: $variables['src'] = theme_get_setting('favicon'); danielebarchiesi@4: } danielebarchiesi@4: else { danielebarchiesi@4: $variables['src'] = base_path() . 'misc/favicon.ico'; danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: // Strip the protocol without delimiters for transient HTTP/HTTPS support. danielebarchiesi@4: // Since the menu is cached on the server-side and client-side, the cached danielebarchiesi@4: // version might contain a HTTP link, whereas the actual page is on HTTPS. danielebarchiesi@4: // Relative paths will work fine, but theme_get_setting() returns an danielebarchiesi@4: // absolute URI. danielebarchiesi@4: $variables['src'] = preg_replace('@^https?:@', '', $variables['src']); danielebarchiesi@4: $variables['src'] = check_plain($variables['src']); danielebarchiesi@4: $variables['alt'] = t('Home'); danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Renders an icon to display in the administration menu. danielebarchiesi@4: * danielebarchiesi@4: * @ingroup themeable danielebarchiesi@4: */ danielebarchiesi@4: function theme_admin_menu_icon($variables) { danielebarchiesi@4: return '' . $variables['alt'] . ''; danielebarchiesi@4: } danielebarchiesi@4: