| [ Index ] |
PHP Cross Reference of Drupal 6 (yi-drupal) |
[Summary view] [Print] [Text view]
1 <?php 2 // $Id: admin_menu.inc,v 1.11.2.26 2009/12/24 15:45:50 sun Exp $ 3 4 /** 5 * The key function that builds the menu links whenever there is a menu rebuild. 6 */ 7 function _admin_menu_rebuild_links() { 8 // Get the newly rebuilt menu. 9 $menu = menu_router_build(); 10 // Add normal and suggested items as links. 11 $menu_links = array(); 12 foreach ($menu as $path => $item) { 13 // Exclude menu callbacks, include items below admin/* and node/add/*. 14 if ($item['type'] != MENU_CALLBACK && (($item['_parts'][0] == 'admin' && count($item['_parts']) > 1) || (strpos($path, 'node/add') === 0))) { 15 // TODO: handle local tasks with wildcards 16 if (!strpos($path, '%')) { 17 $item = admin_menu_link_build($item); 18 $menu_links[$path] = $item; 19 $sort[$path] = $item['_number_parts']; 20 } 21 } 22 } 23 $deleted = admin_menu_adjust_items($menu_links, $sort); 24 if ($menu_links) { 25 // Make sure no child comes before its parent. 26 array_multisort($sort, SORT_NUMERIC, $menu_links); 27 28 foreach ($menu_links as $item) { 29 admin_menu_link_save($item); 30 } 31 } 32 // Allow modules to add more links. If you want to alter links saved by 33 // admin_menu, use hook_menu_link_alter() and look for 34 // $item['module'] == 'admin_menu' 35 $links = array(); 36 foreach (module_implements('admin_menu') as $module) { 37 $function = $module . '_admin_menu'; 38 $links = array_merge_recursive($links, $function($deleted)); 39 } 40 foreach ($links as $item) { 41 admin_menu_link_save($item); 42 } 43 } 44 45 /** 46 * Prepare a menu link from basic information formatted for a router item. 47 */ 48 function admin_menu_link_build($item) { 49 $item['module'] = 'admin_menu'; 50 $item['menu_name'] = 'admin_menu'; 51 $item += array( 52 'link_title' => $item['title'], 53 'link_path' => $item['path'], 54 'hidden' => 0, 55 'options' => array(), 56 ); 57 $item['options']['alter'] = TRUE; 58 // DAM does not output item descriptions to prevent mouseover clashes and 59 // increase page loading performance. However, the following code shows how 60 // link attributes can be added (for ajaxified DAM functionality later). 61 /* 62 if (!empty($item['description'])) { 63 $item['options']['attributes']['title'] = $item['description']; 64 } 65 */ 66 if (!empty($item['query'])) { 67 $item['options']['query'] = $item['query']; 68 } 69 return $item; 70 } 71 72 /** 73 * Convenience function that looks up the plid if $item['parent_path'] is set. 74 */ 75 function admin_menu_link_save($item) { 76 $item = admin_menu_link_build($item); 77 78 // Check whether we are able to update an existing item. 79 $existing_item = db_fetch_array(db_query("SELECT mlid, plid, has_children FROM {menu_links} WHERE link_path = '%s' AND menu_name = '%s'", $item['link_path'], 'admin_menu')); 80 if ($existing_item) { 81 $item['mlid'] = $existing_item['mlid']; 82 $item['plid'] = $existing_item['plid']; 83 $item['has_children'] = $existing_item['has_children']; 84 } 85 86 // Look up the parent path for both new and existing links, since the parent 87 // may change. 88 if (isset($item['parent_path'])) { 89 if ($item['parent_path'] == '<root>') { 90 // <root> means that we want the link at the top level. 91 $item['plid'] = 0; 92 } 93 else { 94 $plid = db_result(db_query("SELECT mlid from {menu_links} WHERE link_path = '%s' AND menu_name = '%s'", $item['parent_path'], 'admin_menu')); 95 if ($plid) { 96 $item['plid'] = $plid; 97 } 98 } 99 } 100 101 menu_link_save($item); 102 } 103 104 /** 105 * Implementation of hook_admin_menu(). 106 * 107 * @param &$deleted 108 * Array of links under admin/* that were removed by admin_menu_adjust_items(). 109 * If one of these links is added back, it should be removed from the array. 110 */ 111 function admin_menu_admin_menu(&$deleted) { 112 $links = array(); 113 $icon_path = '<front>'; 114 115 // Add link to manually run cron. 116 $links[] = array( 117 'title' => 'Run cron', 118 'path' => 'admin/reports/status/run-cron', 119 'weight' => 50, 120 'parent_path' => $icon_path, 121 ); 122 // Add link to run update.php. 123 $links[] = array( 124 'title' => 'Run updates', 125 'path' => 'update.php', 126 'weight' => 50, 127 'parent_path' => $icon_path, 128 'options' => array('external' => TRUE), 129 ); 130 131 // Move 'By module' item into Site configuration. 132 if (isset($deleted['admin/by-module'])) { 133 $deleted['admin/by-module']['parent_path'] = 'admin/settings'; 134 $deleted['admin/by-module']['weight'] = -10; 135 $links[] = $deleted['admin/by-module']; 136 unset($deleted['admin/by-module']); 137 } 138 139 // Add link to drupal.org. 140 $links[] = array( 141 'title' => 'Drupal.org', 142 'path' => 'http://drupal.org', 143 'weight' => 100, 144 'parent_path' => $icon_path, 145 ); 146 // Add links to project issue queues. 147 $links[] = array( 148 'title' => 'Drupal issue queue', 149 'path' => 'http://drupal.org/project/issues/drupal', 150 'weight' => -10, 151 'parent_path' => 'http://drupal.org', 152 ); 153 $projects = array(); 154 foreach (module_list(FALSE, FALSE, TRUE) as $module) { 155 $info = drupal_parse_info_file(drupal_get_path('module', $module) .'/'. $module .'.info'); 156 if (!isset($info['project']) || (isset($info['project']) && ($info['project'] == 'drupal' || isset($projects[$info['project']])))) { 157 continue; 158 } 159 $projects[$info['project']] = 1; 160 $url = 'http://drupal.org/project/issues/'. $info['project']; 161 // Filtering project versions via query string is not yet supported. 162 // @see http://drupal.org/node/97569 163 // $url .= !empty($info['version']) ? '/'. $info['version'] : ''; 164 $links[] = array( 165 'title' => check_plain($info['name']) . ' issue queue', 166 'path' => $url, 167 'parent_path' => 'http://drupal.org', 168 ); 169 } 170 171 // Add 'Create <content-type>' items to Content management menu. 172 if (isset($deleted['node/add'])) { 173 $deleted['node/add']['parent_path'] = 'admin/content'; 174 $deleted['node/add']['weight'] = 0; 175 $links[] = $deleted['node/add']; 176 unset($deleted['node/add']); 177 } 178 foreach($deleted as $path => $item) { 179 if (strpos($path, 'node/add') !== FALSE) { 180 $links[] = $deleted[$path]; 181 unset($deleted[$path]); 182 } 183 } 184 // Make sure longer paths are after shorter ones 185 ksort($deleted); 186 foreach (node_get_types('types', NULL, TRUE) as $type) { 187 $type_url_str = str_replace('_', '-', $type->type); 188 $type_path = 'admin/content/node-type/' . $type_url_str; 189 $links[$type_path] = array( 190 'title' => 'Edit !content-type', 191 'path' => $type_path, 192 'parent_path' => 'admin/content/types', 193 'options' => array('t' => array('!content-type' => $type->name)), 194 ); 195 unset($deleted[$type_path . '/edit']); 196 // CCK and other modules adding to node types handled here. 197 foreach($deleted as $path => $item) { 198 // Precise test needed to account for multiple content-types having the 199 // same prefix in their name. 200 if ($path === $type_path || strpos($path, $type_path . '/') === 0) { 201 // Logically, parent path can never go shorter than $type_path. 202 $i = $item['_number_parts'] - 1; 203 do { 204 $parent_path = implode('/', array_slice($item['_parts'], 0, $i)); 205 --$i; 206 } while (!isset($links[$parent_path]) && $i); 207 $item['parent_path'] = $parent_path; 208 $links[$path] = $item; 209 unset($deleted[$path]); 210 } 211 } 212 } 213 214 // Add clear-cache. 215 $links[] = array( 216 'title' => 'Flush all caches', 217 'path' => 'admin_menu/flush-cache', 218 'query' => 'destination', 219 'weight' => 20, 220 'parent_path' => $icon_path, 221 ); 222 $caches = array( 223 'admin_menu' => 'Administration menu', 224 'cache' => 'Cache tables', 225 'menu' => 'Menu', 226 'requisites' => 'Page requisites', 227 'theme' => 'Theme registry', 228 ); 229 foreach ($caches as $name => $title) { 230 $links[] = array( 231 'title' => $title, 232 'path' => 'admin_menu/flush-cache/' . $name, 233 'query' => 'destination', 234 'parent_path' => 'admin_menu/flush-cache', 235 ); 236 } 237 238 // Add devel module links 239 if (module_exists('devel')) { 240 // Add variable editor. 241 $links[] = array( 242 'title' => 'Variable editor', 243 'path' => 'devel/variable', 244 'weight' => 20, 245 'parent_path' => $icon_path, 246 ); 247 // Add switch_user items. 248 if ($devel_user_links = module_invoke('devel', 'switch_user_list')) { 249 foreach ($devel_user_links as $link) { 250 if (is_array($link)) { 251 $links[] = array( 252 'title' => $link['title'], 253 'description' => $link['attributes']['title'], 254 'path' => $link['href'], 255 'options' => array( 256 'query' => $link['query'], 257 'html' => !empty($link['html']), 258 ), 259 'parent_path' => 'logout', 260 ); 261 } 262 // @todo Remove when Devel 6.x-1.16 has been released. 263 elseif (preg_match('!href="' . base_path() . '([^\?]+)\?([^"]+)" title="([^"]+)">((<em>)?[^<]+(</em>)?)!', $link, $match)) { 264 $links[] = array( 265 'title' => $match[4], 266 'description' => $match[3], 267 'path' => urldecode($match[1]), 268 'weight' => 20, 269 'query' => 'destination', 270 'parent_path' => 'logout', 271 'options' => array('html' => TRUE), 272 ); 273 } 274 } 275 } 276 } 277 // Add developer modules toggle link. 278 $saved_state = variable_get('admin_menu_devel_modules_enabled', NULL); 279 $links[] = array( 280 'title' => isset($saved_state) ? t('Enable developer modules') : t('Disable developer modules'), 281 'path' => 'admin_menu/toggle-modules', 282 'weight' => 88, 283 'parent_path' => $icon_path, 284 'options' => array('query' => 'destination'), 285 ); 286 287 return $links; 288 } 289 290 /** 291 * Add some hard-coded features for better user experience. 292 * 293 * @param array $menu_links 294 * An array containing the complete administration menu structure, passed by 295 * reference. 296 * @param array $sort 297 * An array containing the # parts of each link - must be updated if a link 298 * is added. 299 * @return 300 * An array of links that were removed from $menu_links. 301 */ 302 function admin_menu_adjust_items(&$menu_links, &$sort) { 303 global $user; 304 $links = array(); 305 $deleted = array(); 306 307 // Change or remove items, or add new top-level items. 308 $deleted['admin/by-module'] = $menu_links['admin/by-module']; 309 unset($menu_links['admin/by-module'], $sort['admin/by-module']); 310 $deleted['admin/by-task'] = $menu_links['admin/by-task']; 311 unset($menu_links['admin/by-task'], $sort['admin/by-task']); 312 313 // Remove certain links to re-position them in admin_menu_admin_menu(). 314 foreach ($menu_links as $path => $link) { 315 // Remove links below 316 // - admin/content/node-type/* 317 // - node/add* 318 if (strpos($path, 'admin/content/node-type/') !== FALSE || strpos($path, 'node/add') !== FALSE) { 319 $deleted[$path] = $link; 320 unset($menu_links[$path], $sort[$path]); 321 } 322 } 323 // Add the icon containing special links. 324 $links[] = array( 325 'title' => theme('admin_menu_icon'), 326 'path' => '<front>', 327 'weight' => -100, 328 'parent_path' => '<root>', 329 'options' => array('extra class' => 'admin-menu-icon', 'html' => TRUE), 330 ); 331 // Add link to show current authenticated/anonymous users - we will add the 332 // data dynamically in the _alter hook. 333 $links[] = array( 334 'title' => 'icon_users', 335 'path' => 'user', 336 'weight' => -90, 337 'parent_path' => '<root>', 338 'options' => array('extra class' => 'admin-menu-action admin-menu-icon admin-menu-users', 'html' => TRUE), 339 ); 340 $links[] = array( 341 'title' => 'Log out @username', 342 'path' => 'logout', 343 'weight' => -100, 344 'parent_path' => '<root>', 345 // Note: @username is dynamically replaced by default, we just invoke 346 // replacement by setting the 't' key here. 347 'options' => array('extra class' => 'admin-menu-action admin-menu-logout', 't' => array()), 348 ); 349 foreach ($links as $item) { 350 $path = $item['path']; 351 $item = admin_menu_link_build($item); 352 $menu_links[$path] = $item; 353 $sort[$path] = 1; 354 } 355 356 return $deleted; 357 } 358 359 /** 360 * Form builder function for module settings. 361 */ 362 function admin_menu_theme_settings() { 363 $form['admin_menu_margin_top'] = array( 364 '#type' => 'checkbox', 365 '#title' => t('Adjust top margin'), 366 '#default_value' => variable_get('admin_menu_margin_top', 1), 367 '#description' => t('If enabled, the site output is shifted down approximately 20 pixels from the top of the viewport to display the administration menu. If disabled, some absolute- or fixed-positioned page elements may be covered by the administration menu.'), 368 ); 369 $form['admin_menu_position_fixed'] = array( 370 '#type' => 'checkbox', 371 '#title' => t('Keep menu at top of page'), 372 '#default_value' => variable_get('admin_menu_position_fixed', 0), 373 '#description' => t('If enabled, the administration menu is always displayed at the top of the browser viewport (even after the page is scrolled). <strong>Note: In some browsers, this setting results in a malformed page, an invisible cursor, non-selectable elements in forms, or other issues. Disable this option if these issues occur.</strong>'), 374 ); 375 $form['tweaks'] = array( 376 '#type' => 'fieldset', 377 '#title' => t('Advanced settings'), 378 ); 379 $form['tweaks']['admin_menu_tweak_modules'] = array( 380 '#type' => 'checkbox', 381 '#title' => t('Collapse fieldsets on modules page'), 382 '#default_value' => variable_get('admin_menu_tweak_modules', 0), 383 '#description' => t('If enabled, fieldsets on the <a href="!modules-url">modules</a> page are automatically collapsed when loading the page.', array('!modules-url' => url('admin/build/modules'))), 384 ); 385 if (module_exists('util')) { 386 $form['tweaks']['admin_menu_tweak_modules']['#description'] .= '<br /><strong>'. t('If the Utility module was installed for this purpose, it can be safely disabled and uninstalled.') .'</strong>'; 387 } 388 $form['tweaks']['admin_menu_tweak_tabs'] = array( 389 '#type' => 'checkbox', 390 '#title' => t('Move local tasks into menu'), 391 '#default_value' => variable_get('admin_menu_tweak_tabs', 0), 392 '#description' => t('If enabled, the tabs on the current page are moved into the administration menu. This feature is only available in themes that use the CSS classes <code>tabs primary</code> and <code>tabs secondary</code> for tabs.'), 393 ); 394 $form = system_settings_form($form); 395 $form['wipe description'] = array( 396 '#type' => 'item', 397 '#value' => t('If the administration menu displays duplicate menu items, you may need to rebuild your menu items using the <em>Wipe and rebuild</em> button.'), 398 ); 399 $form['wipe'] = array( 400 '#type' => 'submit', 401 '#value' => t('Wipe and rebuild'), 402 '#submit' => array('admin_menu_wipe'), 403 ); 404 405 return $form; 406 } 407 408 /** 409 * Wipe the menu so it can be rebuilt from scratch. 410 */ 411 function admin_menu_wipe() { 412 db_query("DELETE FROM {menu_links} WHERE menu_name = 'admin_menu'"); 413 menu_cache_clear('admin_menu'); 414 variable_set('admin_menu_rebuild_links', TRUE); 415 } 416 417 /** 418 * Helper function for admin_menu_form_devel_admin_settings_alter(). 419 * 420 * Extends Devel module with Administration Menu developer settings. 421 */ 422 function _admin_menu_devel_settings_form_alter(&$form, $form_state) { 423 // Shift system_settings_form buttons. 424 $weight = isset($form['buttons']['#weight']) ? $form['buttons']['#weight'] : 0; 425 $form['buttons']['#weight'] = $weight + 1; 426 427 $form['admin_menu'] = array( 428 '#type' => 'fieldset', 429 '#title' => t('Administration menu settings'), 430 '#collapsible' => TRUE, 431 '#collapsed' => TRUE, 432 ); 433 $display_options = array('mid', 'weight', 'pid'); 434 $display_options = array(0 => t('None'), 'mlid' => t('Menu link ID'), 'weight' => t('Weight'), 'plid' => t('Parent link ID')); 435 $form['admin_menu']['admin_menu_display'] = array( 436 '#type' => 'radios', 437 '#title' => t('Display additional data for each menu item'), 438 '#default_value' => variable_get('admin_menu_display', 0), 439 '#options' => $display_options, 440 '#description' => t('Display the selected items next to each menu item link.'), 441 ); 442 $form['admin_menu']['admin_menu_show_all'] = array( 443 '#type' => 'checkbox', 444 '#title' => t('Display all menu items'), 445 '#default_value' => variable_get('admin_menu_show_all', 0), 446 '#description' => t('If enabled, all menu items are displayed regardless of your site permissions. <em>Note: Do not enable on a production site.</em>'), 447 ); 448 } 449 450 /** 451 * Menu callback to enable/disable developer modules. 452 * 453 * This saves up to 150ms on each uncached page request. Not much, but 454 * on larger Drupal sites this is actually a 10% performance increase. 455 */ 456 function admin_menu_toggle_modules() { 457 $rebuild = FALSE; 458 $saved_state = variable_get('admin_menu_devel_modules_enabled', NULL); 459 if (isset($saved_state)) { 460 // Re-enable modules that were enabled before. 461 module_enable($saved_state); 462 variable_del('admin_menu_devel_modules_enabled'); 463 drupal_set_message(t('Enabled these modules: !module-list.', array('!module-list' => implode(', ', $saved_state)))); 464 $rebuild = TRUE; 465 } 466 else { 467 // Allow site admins to override this variable via settings.php. 468 $devel_modules = variable_get('admin_menu_devel_modules', array('cache_disable', 'coder', 'content_copy', 'debug', 'delete_all', 'demo', 'devel', 'devel_node_access', 'devel_themer', 'macro', 'form_controller', 'imagecache_ui', 'journal', 'trace', 'upgrade_status', 'user_display_ui', 'util', 'views_ui', 'views_theme_wizard')); 469 // Store currently enabled modules in a variable. 470 $devel_modules = array_intersect(module_list(FALSE, FALSE), $devel_modules); 471 if (!empty($devel_modules)) { 472 variable_set('admin_menu_devel_modules_enabled', $devel_modules); 473 // Disable developer modules. 474 module_disable($devel_modules); 475 drupal_set_message(t('Disabled these modules: !module-list.', array('!module-list' => implode(', ', $devel_modules)))); 476 $rebuild = TRUE; 477 } 478 else { 479 drupal_set_message(t('No developer modules are enabled.')); 480 } 481 } 482 if ($rebuild) { 483 // Make sure everything is rebuilt, basically a combination of the calls 484 // from system_modules() and system_modules_submit(). 485 drupal_rebuild_theme_registry(); 486 menu_rebuild(); 487 cache_clear_all('schema', 'cache'); 488 cache_clear_all(); 489 drupal_clear_css_cache(); 490 drupal_clear_js_cache(); 491 // Synchronize to catch any actions that were added or removed. 492 actions_synchronize(); 493 } 494 drupal_goto(''); 495 } 496 497 /** 498 * Flush all caches or a specific one. 499 * 500 * @param $name 501 * (optional) Name of cache to flush. 502 */ 503 function admin_menu_flush_cache($name = NULL) { 504 switch ($name) { 505 case 'admin_menu': 506 admin_menu_wipe(); 507 break; 508 509 case 'cache': 510 // Don't clear cache_form - in-progress form submissions may break. 511 // Ordered so clearing the page cache will always be the last action. 512 $core = array('cache', 'cache_block', 'cache_filter', 'cache_page'); 513 $cache_tables = array_merge(module_invoke_all('flush_caches'), $core); 514 foreach ($cache_tables as $table) { 515 cache_clear_all('*', $table, TRUE); 516 } 517 break; 518 519 case 'menu': 520 module_invoke('menu', 'rebuild'); 521 break; 522 523 case 'requisites': 524 // Change query-strings on css/js files to enforce reload for all users. 525 _drupal_flush_css_js(); 526 527 drupal_clear_css_cache(); 528 drupal_clear_js_cache(); 529 break; 530 531 case 'theme': 532 module_invoke('system', 'theme_data'); 533 drupal_rebuild_theme_registry(); 534 break; 535 536 default: 537 // Flush all caches; no need to re-implement this. 538 module_load_include('inc', 'system', 'system.admin'); 539 $form = $form_state = array(); 540 system_clear_cache_submit($form, $form_state); 541 break; 542 } 543 drupal_goto(); 544 } 545
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Mon Jul 9 18:01:44 2012 | Cross-referenced by PHPXref 0.7 |