$item) { if (strpos($path, 'admin') === 0) { $items[$path]['menu_name'] = 'admin'; } } // Move admin theme settings to theme local task. $items['admin/build/themes/admin'] = $items['admin/settings/admin']; $items['admin/build/themes/admin']['type'] = MENU_LOCAL_TASK; $items['admin/build/themes/admin']['weight'] = 10; unset($items['admin/settings/admin']); // Gather site settings under local tasks $items['admin/settings/site'] = $items['admin/settings/site/information'] = $items['admin/settings/site-information']; unset($items['admin/settings/site-information']); $items['admin/settings/site']['title'] = 'Site settings'; $items['admin/settings/site/information']['title'] = 'Information'; $items['admin/settings/site/information']['type'] = MENU_DEFAULT_LOCAL_TASK; $items['admin/settings/site/clean-urls'] = $items['admin/settings/clean-urls']; $items['admin/settings/site/clean-urls']['type'] = MENU_LOCAL_TASK; $items['admin/settings/site/clean-urls']['weight'] = 10; unset($items['admin/settings/clean-urls']); $items['admin/settings/site/error-reporting'] = $items['admin/settings/error-reporting']; $items['admin/settings/site/error-reporting']['type'] = MENU_LOCAL_TASK; $items['admin/settings/site/error-reporting']['weight'] = 10; unset($items['admin/settings/error-reporting']); $items['admin/settings/site/file-system'] = $items['admin/settings/file-system']; $items['admin/settings/site/file-system']['type'] = MENU_LOCAL_TASK; $items['admin/settings/site/file-system']['weight'] = 10; unset($items['admin/settings/file-system']); // Generate additional items for use in the menu $items = array_merge($items, admin_menu_clone_items('node/add', 'admin/content/add', $items)); $items = array_merge($items, admin_menu_clone_items('admin/build/themes', 'admin/themes', $items)); $items = array_merge($items, admin_menu_clone_items('admin/build/modules', 'admin/modules', $items)); // Expose a small subset of the most usable core admin pages. // Other pages can be exposed simply by adding ['options']['admin'] = TRUE // to items in hook_menu(). $include = array( 'admin/content' => 'Content', 'admin/content/add' => 'Add', 'admin/content/node' => 'Edit', 'admin/build' => 'Structure', 'admin/build/views' => '', 'admin/build/block' => '', 'admin/build/menu' => '', 'admin/user' => 'People', 'admin/user/permissions' => '', 'admin/user/user' => '', 'admin/settings' => 'Configuration', 'admin/settings/date-time' => '', 'admin/settings/filters' => '', 'admin/settings/language' => '', 'admin/settings/performance' => '', 'admin/settings/site' => '', 'admin/themes' => 'Appearance', 'admin/modules' => '', ); foreach ($include as $path => $title) { if (!empty($items[$path])) { $items[$path]['title'] = !empty($title) ? $title : $items[$path]['title']; $items[$path]['options']['admin'] = TRUE; } } // Apparently node/add has no description. Add one. $items['admin/content/add']['description'] = 'Create new content on your site.'; $items['admin/content/add']['weight'] = -20; $items['admin/content/node']['weight'] = -19; } /** * Helper to clone portions of the menu tree to a duplicate location. */ function admin_menu_clone_items($search, $replace, $items) { $offset = count(explode('/', $replace)) - count(explode('/', $search)); $clone = array(); foreach ($items as $path => $item) { if (strpos($path, $search) === 0) { $clone_path = str_replace($search, $replace, $path); // Adjust argument offsets if the search and replace paths have a // different arg counts. if ($offset != 0) { foreach (array('page arguments', 'access arguments', 'load arguments', 'title arguments') as $arg_key) { if (!empty($item[$arg_key])) { foreach ($item[$arg_key] as $k => $v) { if (is_numeric($v)) { $item[$arg_key][$k] = $v + $offset; } } } } } $clone[$clone_path] = $item; } } return $clone; } /** * Implementation of hook_system_info_alter(). * Throw a flag that tells us we need to reinstantiate the admin theme. */ function admin_system_info_alter(&$info, &$theme) { static $once; if (!isset($once)) { $once = TRUE; variable_set('admin_theme_invalidated', TRUE); } } /** * Implementation of hook_perm(). */ function admin_perm() { return array('admin menu', 'admin inline'); } /** * Implementation of hook_theme(). */ function admin_theme($cache, $type, $theme, $path) { $path = drupal_get_path('module', 'admin'); $items['admin_menu_overview_form'] = array( 'arguments' => array('form' => array()), ); $items['admin_toolbar'] = array( 'arguments' => array('tree' => array()), 'template' => 'admin-toolbar', 'path' => $path . '/toolbar', 'file' => 'theme.inc', ); $items['admin_links'] = array( 'arguments' => array('links' => array()), 'template' => 'admin-links', 'path' => $path . '/toolbar', 'file' => 'theme.inc', ); $items['admin_manage_options'] = array( 'arguments' => array('form' => array()), 'path' => $path . '/theme', 'file' => 'template.php', ); return $items; } /** * Wrapper to check whether various admin features are accessible to the * current user and compatible with the current theme. */ function admin_is_enabled($op = 'admin menu') { if (user_access($op)) { global $theme_info; // If the theme does not specify some flag for this feature, assume // it is compatible. if (!isset($theme_info->info['admin'][$op]) || (isset($theme_info->info['admin'][$op]) && !empty($theme_info->info['admin'][$op]))) { return TRUE; } } return FALSE; } /** * Retrieve the admin links for a given object. */ function admin_get_links($type, $object) { $links = array(); if (admin_is_enabled('admin inline')) { $links = module_invoke_all('admin_link', $type, $object); drupal_alter('admin_link', $links, $type, $object); } return $links; } /** * Implementation of hook_admin_link() on behalf of the node module. */ function node_admin_link($type, $object) { $links = array(); if ($type == 'node') { if (node_access('update', $object)) { $links['node-edit'] = array( 'title' => t('Edit'), 'href' => "node/{$object->nid}/edit", 'attributes' => array('class' => 'icon-edit'), 'query' => array('destination' => $_GET['q']), ); } if (node_access('delete', $object)) { $links['node-delete'] = array( 'title' => t('Delete'), 'href' => "node/{$object->nid}/delete", 'attributes' => array('class' => 'icon-delete'), 'query' => array('destination' => $_GET['q']), ); } } return $links; } /** * Implementation of hook_admin_link() on behalf of the block module. */ function block_admin_link($type, $object) { $links = array(); if ($type == 'block') { if (user_access('administer blocks')) { $links['block-configure'] = array( 'title' => t('Configure'), 'href' => "admin/build/block/configure/{$object->module}/{$object->delta}", 'attributes' => array('class' => 'icon-configure'), 'query' => array('destination' => $_GET['q']), ); } } return $links; } /** * Implementation of hook_admin_link() on behalf of the views module. */ function views_admin_link($type, $object) { $links = array(); $view_name = ''; if (user_access('administer views')) { switch ($type) { case 'block': // If this is a Views block and not a special (exposed filter, etc.) block... if ($object->module == 'views' && strpos($object->delta, '-') !== 0) { $split = explode('-', $object->delta); $view_name = array_shift($split); } break; case 'views': // Bail on block/attachment views or views using the node row plugin to prevent collisions. if ($object->display_handler->get_option('row_plugin') != 'node' && !in_array(get_class($object->display_handler), array('views_plugin_display_attachment', 'views_plugin_display_block'))) { $view_name = $object->name; } break; } if (!empty($view_name)) { $links['views-edit'] = array( 'title' => t('Edit view'), 'href' => "admin/build/views/edit/{$view_name}", 'attributes' => array('class' => 'icon-edit'), 'query' => array('destination' => $_GET['q']), ); } } return $links; } /** * Implementation of hook_theme_registry_alter(). */ function admin_theme_registry_alter(&$theme_registry) { $hooks = array( 'page', 'block', 'views_view', 'node', ); foreach ($hooks as $hook) { if (empty($theme_registry[$hook]['preprocess functions']) || !in_array('admin_preprocess_'. $hook, $theme_registry[$hook]['preprocess functions'])) { $theme_registry[$hook]['preprocess functions'][] = 'admin_preprocess_'. $hook; } } // If the admin theme has been inited, do some additional work. global $theme; if ($theme == 'admin') { // Slap a preprocessor on at the very front of the stack for rebuilding the admin theme. if (!in_array('admin_page_alter', $theme_registry['page']['preprocess functions'])) { array_unshift($theme_registry['page']['preprocess functions'], 'admin_page_alter'); } $overrides = array('fieldset', 'node_form', 'system_settings_form', 'admin_block_content'); foreach ($overrides as $hook) { $theme_registry[$hook]['function'] = 'admin_'. $hook; } } } /** * Page preprocessor that runs before any others (including template_preprocess_page()). * Check the theme rebuild flag and do so if necessary. */ function admin_page_alter(&$vars) { _admin_theme_rebuild(); } /** * Implementation of hook_preprocess_page(). */ function admin_preprocess_page(&$vars) { // @TODO: merge multiple menus rather than just using the first if (admin_is_enabled('admin menu')) { $links = admin_menu_tree(); $links = theme('admin_toolbar', $links); $vars['admin'] = $links; } else { $vars['admin'] = ''; } } /** * Implementation of hook_preprocess_views_view(). */ function admin_preprocess_views_view(&$vars) { $admin_links = theme('admin_links', admin_get_links('views', $vars['view'])); if ($admin_links) { $vars['pager'] .= $admin_links; } // Disable the Views admin links stack to prevent clutter. $vars['admin_links'] = ''; $vars['admin_links_raw'] = ''; } /** * Implementation of hook_preprocess_block(). */ function admin_preprocess_block(&$vars) { $vars['block']->content .= theme('admin_links', admin_get_links('block', $vars['block'])); } /** * Implementation of hook_preprocess_node(). */ function admin_preprocess_node(&$vars) { $vars['content'] .= theme('admin_links', admin_get_links('node', $vars['node'])); } /** * Helper for returning a selectively flattened version of the admin menu. */ function admin_get_menu_tree($method = 'all', $reset = FALSE) { $tree = ($method == 'all' ? menu_tree_all_data('admin') : menu_tree_page_data('admin')); foreach ($tree as $k => $item) { if ($item['link']['link_path'] == 'admin' && !empty($item['below'])) { unset($tree[$k]); $tree = array_merge($tree, $item['below']); } } return $tree; } /** * Retrieve a hierarchy of links representing select portions of the * 'admin' branch of the navigation menu. */ function admin_menu_tree() { $links = array(); // Retrieve the admin menu from the database. $tree = admin_get_menu_tree(); admin_menu_tree_links($tree, $links); // Add user-specific links global $user; $user_links = array(); $user_links[] = array( 'title' => t('Hello !username', array('!username' => $user->name)), 'href' => 'user', 'html' => TRUE ); $user_links[] = array('title' => t('Logout'), 'href' => "logout"); $links[0]['user'] = $user_links; return $links; } /** * Generate a links array from a menu tree array. */ function admin_menu_navigation_links($tree, $admin_only = FALSE) { $links = array(); foreach ($tree as $item) { if (!$item['link']['hidden'] && (!$admin_only || !empty($item['link']['options']['admin']))) { $class = ''; $id = str_replace('/', '-', $item['link']['href']); $l = $item['link']['localized_options']; $l['href'] = $item['link']['href']; $l['title'] = "". $item['link']['title']; $l['attributes'] = array('id' => 'admin-link-'. $id); $l['html'] = TRUE; $class = ' path-'. $id; if (admin_in_active_trail($item['link']['href'])) { $class .= ' active-trail'; } // Keyed with the unique mlid to generate classes in theme_links(). $links['menu-'. $item['link']['mlid'] . $class] = $l; } } return $links; } /** * Build a hierarchy of $links arrays suitable for theme_links() from a * menu tree. */ function admin_menu_tree_links($tree, &$links, $parent = 'admin', $depth = 0) { // Create a single level of links. $links[$depth][$parent] = array(); $l = admin_menu_navigation_links($tree, TRUE); if (!empty($l)) { $links[$depth][$parent] = $l; } // Recurse foreach ($tree as $item) { if (!$item['link']['hidden'] && !empty($item['link']['options']['admin'])) { if (!empty($item['below'])) { admin_menu_tree_links($item['below'], $links, $item['link']['href'], $depth + 1); } } } } /** * Checks whether an item is in the active trail. Useful when using * a menu generated by menu_tree_all_data() which does not set the * 'in_active_trail' flag on items. */ function admin_in_active_trail($path, $reset = FALSE) { // Gather active paths static $active_paths; if (!isset($active_paths) || $reset) { $active_paths = array(); $trail = menu_get_active_trail(); foreach ($trail as $item) { if (!empty($item['href'])) { $active_paths[] = $item['href']; } } } return in_array($path, $active_paths); } /** * Rebuild the admin theme entry in the database. */ function _admin_theme_rebuild($force = FALSE) { if (arg(0) == 'admin') { $exists = db_result(db_query("SELECT count(*) FROM {system} WHERE name = 'admin' AND type = 'theme'")); $force = !$exists ? TRUE : $force; } if ($force || variable_get('admin_theme_invalidated', FALSE)) { $path = drupal_get_path('module', 'admin') .'/theme'; $theme = new StdClass(); $theme->name = 'admin'; $theme->filename = "{$path}/admin.theme.info"; $theme->engine = 'phptemplate'; $theme->owner = drupal_get_path('theme_engine', 'phptemplate') .'/phptemplate.engine'; $theme->info = system_theme_default(); db_query("DELETE FROM {system} WHERE name = 'admin' AND type = 'theme'"); db_query("INSERT INTO {system} (name, owner, info, type, filename, status, throttle, bootstrap) VALUES ('%s', '%s', '%s', '%s', '%s', %d, %d, %d)", $theme->name, $theme->owner, serialize($theme->info), 'theme', $theme->filename, isset($theme->status) ? $theme->status : 0, 0, 0); variable_set('admin_theme_invalidated', FALSE); } }