'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_form_alter() for system_admin_theme_settings.
*/
function admin_form_system_admin_theme_settings_alter(&$form) {
// Add in our stealth theme as an option
$form['admin_theme']['#options']['admin'] = t('Admin');
}
/**
* Implementation of hook_form_alter() for node_filter_form.
*/
function admin_form_node_admin_content_alter(&$form) {
// If the admin theme has been inited, do some additional work.
global $theme;
if ($theme == 'admin') {
unset($form['admin']['options']['#type']);
unset($form['admin']['options']['#prefix']);
unset($form['admin']['options']['#suffix']);
$form['admin']['options']['#theme'] = 'admin_manage_options';
}
}
function admin_form_user_admin_account_alter(&$form) {
// If the admin theme has been inited, do some additional work.
global $theme;
if ($theme == 'admin') {
unset($form['options']['#type']);
unset($form['options']['#prefix']);
unset($form['options']['#suffix']);
$form['options']['#theme'] = 'admin_manage_options';
}
}
/**
* 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) {
$items = array();
$items['admin_toolbar'] = array(
'arguments' => array('tree' => array()),
'template' => 'admin-toolbar',
'path' => drupal_get_path('module', 'admin') .'/toolbar',
'file' => 'theme.inc',
);
$items['admin_links'] = array(
'arguments' => array('links' => array()),
'template' => 'admin-links',
'path' => drupal_get_path('module', 'admin') .'/toolbar',
'file' => 'theme.inc',
);
$items['admin_manage_options'] = array(
'arguments' => array('form' => array()),
'path' => drupal_get_path('module', 'admin') .'/theme',
'file' => 'template.php',
);
return $items;
}
/**
* Set wrapper around admin_links_cache().
*/
function admin_links_set($type, $id, $link) {
admin_links_cache('set', $type, $id, $link);
}
/**
* Get wrapper around admin_links_cache().
*/
function admin_links_get($type, $id) {
return admin_links_cache('get', $type, $id);
}
/**
* Static cache function which allows different parts of the page load
* to add contextual admin links to different object types (nodes,
* blocks, etc). They are retrieved all at once at the final "rendering"
* stages.
*/
function admin_links_cache($op = 'set', $type, $id, $link = NULL) {
static $cache;
if (!isset($cache)) {
$cache = array();
}
switch ($op) {
case 'set':
if (!isset($cache[$type])) {
$cache[$type] = array();
}
if (!isset($cache[$type][$id])) {
$cache[$type][$id] = array();
}
if ($link) {
$cache[$type][$id][] = $link;
}
break;
case 'get':
if (isset($cache[$type][$id])) {
return $cache[$type][$id];
}
else {
return array();
}
break;
}
}
/**
* Helper function which centralizes link creation for different object
* types. Not actually sure if this is a good idea -- may split up.
*/
function admin_admin_link($hook, $params = array()) {
$options = array('query' => 'destination='. $_GET['q']);
switch ($hook) {
case 'node':
if (user_access('administer nodes')) {
$edit = $delete = $translate = $options;
$output = '';
if (isset($params['node']->translation)) {
$output .= l(t('Translate'), 'node/'. $params['node']->nid .'/translation', $options);
}
$edit['attributes'] = array('class' => 'icon-edit');
$output .= l(t('Edit'), "node/{$params['node']->nid}/edit", $edit);
$delete['attributes'] = array('class' => 'icon-delete');
$output .= l(t('Delete'), "node/{$params['node']->nid}/delete", $delete);
return $output;
}
break;
case 'block':
if (user_access('administer blocks')) {
$configure = $options;
$configure['attributes'] = array('class' => 'icon-configure');
return l(t('Configure'), "admin/build/block/configure/{$params['module']}/{$params['delta']}", $configure);
}
break;
case 'nodequeue':
if (user_access('manipulate queues')) {
return l(t("Manage queue"), "admin/content/nodequeue/". $params['qid'] ."/view", $options);
}
break;
case 'views':
if (user_access('administer views')) {
$edit['attributes'] = array('class' => 'icon-edit');
return l(t("Edit view"), "admin/build/views/edit/{$params['view']}", $edit);
}
break;
}
return '';
}
/**
* Implementation of hook_views_pre_view().
*/
function admin_views_pre_view(&$view, $display_id, $args) {
if (user_access('admin inline')) {
$links = array();
// Default view links (edit view)
$links[] = admin_admin_link('views', array('view' => $view->name));
// Helper nodequeue link for administrators
if (module_exists('nodequeue') && user_access("manipulate queues")) {
$display_id = $view->current_display;
$relationships = $view->display[$display_id]->handler->get_option('relationships');
if (isset($relationships['nodequeue_rel']) && isset($relationships['nodequeue_rel']['qids']) && count($relationships['nodequeue_rel']['qids'])) {
reset($relationships['nodequeue_rel']['qids']);
$qid = current($relationships['nodequeue_rel']['qids']);
$links[] = admin_admin_link('nodequeue', array('qid' => $qid));
}
}
$row_plugin = $view->display_handler->get_option('row_plugin');
// Bail on attachment views
if (get_class($view->display_handler) === 'views_plugin_display_attachment') {
return;
}
// If this is a block view, merge links into the respective block
else if (get_class($view->display_handler) === 'views_plugin_display_block') {
foreach ($links as $link) {
admin_links_set('block', "views-{$view->name}-{$view->current_display}", $link);
}
}
// Ensure the view popups and node popups don't collide
else if ($row_plugin != 'node') {
foreach ($links as $link) {
admin_links_set('views', $view->name .'-'. $view->current_display, $link);
}
}
}
}
/**
* Implementation of hook_theme_registry_alter().
*/
function admin_theme_registry_alter(&$theme_registry) {
$hooks = array(
'page',
'block',
'views_view',
'views_view_table',
'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 (user_access('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) {
if (user_access('admin inline')) {
// Retrieve link cache
$vid = $vars['view']->name .'-'. $vars['view']->current_display;
$links = admin_links_get('views', $vid);
if ($links) {
// Add admin links
$vars['pager'] .= theme('admin_links', $links);
}
$vars['admin_links'] = '';
$vars['admin_links_raw'] = '';
}
}
/**
* Implementation of hook_preprocess_block().
*/
function admin_preprocess_block(&$vars) {
if (user_access('admin inline')) {
if (!empty($vars['block']->module) && !empty($vars['block']->delta)) {
$bid = $vars['block']->module .'-'. $vars['block']->delta;
// If this is a custom block, we need to catch it here + add links!
switch ($vars['block']->module) {
case 'block':
$link = admin_admin_link('block', array('module' => 'block', 'delta' => $vars['block']->delta));
admin_links_set('block', $bid, $link);
break;
case 'menu':
$link = l(t('Edit menu'), "admin/build/menu-customize/{$vars['block']->delta}", array('query' => "destination={$_GET['q']}"));
admin_links_set('block', $bid, $link);
break;
}
// Retrieve link cache
$links = admin_links_get('block', $bid);
// Add admin links
$vars['block']->content .= theme('admin_links', $links);
}
}
}
/**
* Implementation of hook_preprocess_node().
*/
function admin_preprocess_node(&$vars) {
if (user_access('admin inline')) {
// Set link cache
$link = admin_admin_link('node', array('node' => $vars['node']));
admin_links_set('node', $vars['node']->nid, $link);
// Retrieve link cache
$links = admin_links_get('node', $vars['nid']);
$vars['content'] .= theme('admin_links', $links);
}
}
/**
* Retrieve a hierarchy of links representing select portions of the
* 'admin' branch of the navigation menu.
*/
function admin_menu_tree() {
$parents = array();
$trail = menu_get_active_trail();
foreach ($trail as $item) {
if (!empty($item['mlid'])) {
$parents[] = $item['mlid'];
}
}
$tree = menu_tree_data(db_query("
SELECT m.load_functions, m.to_arg_functions, m.access_callback, m.access_arguments, m.page_callback, m.page_arguments, m.title, m.title_callback, m.title_arguments, m.type, m.description, ml.*
FROM {menu_links} ml LEFT JOIN {menu_router} m ON m.path = ml.router_path
WHERE ml.menu_name = '%s'
AND ml.link_path LIKE 'admin%'
AND ml.depth > 1
AND ml.depth < 4
ORDER BY p1 ASC, p2 ASC, p3 ASC, p4 ASC, p5 ASC, p6 ASC, p7 ASC, p8 ASC, p9 ASC", 'navigation'), $parents);
// @TODO: Cache here!
menu_tree_check_access($tree);
$links = array();
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 ($item['link']['in_active_trail']) {
$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);
}
}
}
}
/**
* 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);
}
}