Merge lp:~pressflow/pressflow/menu-tng into lp:pressflow

Proposed by David Strauss
Status: Rejected
Rejected by: David Strauss
Proposed branch: lp:~pressflow/pressflow/menu-tng
Merge into: lp:pressflow
Diff against target: 538 lines (+304/-52)
2 files modified
includes/menu.inc (+302/-50)
modules/book/book.module (+2/-2)
To merge this branch: bzr merge lp:~pressflow/pressflow/menu-tng
Reviewer Review Type Date Requested Status
Pressflow Administrators Pending
Review via email: mp+15439@code.launchpad.net
To post a comment you must log in.

Unmerged revisions

65. By David Strauss

Initial (seemingly working) Menu-TNG system.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'includes/menu.inc'
--- includes/menu.inc 2009-04-30 00:36:53 +0000
+++ includes/menu.inc 2009-11-30 19:05:26 +0000
@@ -285,7 +285,7 @@
285}285}
286286
287/**287/**
288 * Get a router item.288 * Get a router item. Pressflow-optimized.
289 *289 *
290 * @param $path290 * @param $path
291 * The path, for example node/5. The function will find the corresponding291 * The path, for example node/5. The function will find the corresponding
@@ -293,13 +293,14 @@
293 * @param $router_item293 * @param $router_item
294 * Internal use only.294 * Internal use only.
295 * @return295 * @return
296 * The router item, an associate array corresponding to one row in the296 * The router item, an associative array corresponding to one menu item.
297 * menu_router table. The value of key map holds the loaded objects. The297 * The value of key map holds the loaded objects. The value of key access
298 * value of key access is TRUE if the current user can access this page.298 * is TRUE if the current user can access this page.
299 * The values for key title, page_arguments, access_arguments will be
300 * filled in based on the database values and the objects loaded.
301 */299 */
302function menu_get_item($path = NULL, $router_item = NULL) {300function menu_get_item($path = NULL, $router_item = NULL) {
301 static $tree = NULL;
302
303 $start = microtime(TRUE);
303 static $router_items;304 static $router_items;
304 if (!isset($path)) {305 if (!isset($path)) {
305 $path = $_GET['q'];306 $path = $_GET['q'];
@@ -310,28 +311,63 @@
310 if (!isset($router_items[$path])) {311 if (!isset($router_items[$path])) {
311 $original_map = arg(NULL, $path);312 $original_map = arg(NULL, $path);
312 $parts = array_slice($original_map, 0, MENU_MAX_PARTS);313 $parts = array_slice($original_map, 0, MENU_MAX_PARTS);
313 list($ancestors, $placeholders) = menu_get_ancestors($parts);314
314315 if (!$tree) {
315 if ($router_item = db_fetch_array(db_query_range('SELECT * FROM {menu_router} WHERE path IN ('. implode (',', $placeholders) .') ORDER BY fit DESC', $ancestors, 0, 1))) {316 $tree = menu_get_tree();
316 $map = _menu_translate($router_item, $original_map);317 }
317 if ($map === FALSE) {318 $cursor =& $tree;
319
320 foreach ($parts as $element) {
321 // Try the best fit first.
322 if (isset($cursor[$element])) {
323 $cursor =& $cursor[$element];
324 }
325 // Then try a placeholder fit.
326 else if (isset($cursor['%'])) {
327 $cursor =& $cursor['%'];
328 }
329 // Check if there's a leaf available.
330 else if (isset($cursor['#leaf'])) {
331 break;
332 }
333 // If there's no fit, there's no matching item.
334 else {
318 $router_items[$path] = FALSE;335 $router_items[$path] = FALSE;
319 return FALSE;336 return FALSE;
320 }337 }
321 if ($router_item['access']) {338 }
322 $router_item['map'] = $map;339
323 $router_item['page_arguments'] = array_merge(menu_unserialize($router_item['page_arguments'], $map), array_slice($map, $router_item['number_parts']));340 // At this point, there should be a leaf.
324 }341 if (!isset($cursor['#leaf'])) {
325 }342 $router_items[$path] = FALSE;
343 return FALSE;
344 }
345
346 $router_item = $cursor['#leaf'];
347
348 //echo "router_item:\n";
349 //print_r($router_item);
350
351 $map = _menu_translate($router_item, $original_map);
352 if ($map === FALSE) {
353 $router_items[$path] = FALSE;
354 return FALSE;
355 }
356 if ($router_item['access']) {
357 $router_item['map'] = $map;
358 $router_item['page_arguments'] = array_merge(menu_unserialize($router_item['page_arguments'], $map), array_slice($map, $router_item['number_parts']));
359 }
360
326 $router_items[$path] = $router_item;361 $router_items[$path] = $router_item;
327 }362 }
363 header('X-Profile-' . str_replace('/', '-', $path) . ': ' . number_format(microtime(TRUE) - $start, 10));
328 return $router_items[$path];364 return $router_items[$path];
329}365}
330366
331/**367/**
332 * Execute the page callback associated with the current path368 * Execute the page callback associated with the current path
333 */369 */
334function menu_execute_active_handler($path = NULL) {370function menu_execute_active_handler($path = NULL, $old = FALSE) {
335 if (_menu_site_is_offline()) {371 if (_menu_site_is_offline()) {
336 return MENU_SITE_OFFLINE;372 return MENU_SITE_OFFLINE;
337 }373 }
@@ -340,7 +376,8 @@
340 if (variable_get('menu_rebuild_needed', FALSE) || !variable_get('menu_masks', array())) {376 if (variable_get('menu_rebuild_needed', FALSE) || !variable_get('menu_masks', array())) {
341 menu_rebuild();377 menu_rebuild();
342 }378 }
343 if ($router_item = menu_get_item($path)) {379
380 if ((!$old && $router_item = menu_get_item($path)) || ($old && $router_item = menu_get_item_old($path))) {
344 if ($router_item['access']) {381 if ($router_item['access']) {
345 if ($router_item['file']) {382 if ($router_item['file']) {
346 require_once($router_item['file']);383 require_once($router_item['file']);
@@ -434,6 +471,7 @@
434 * $item['access'] becomes TRUE if the item is accessible, FALSE otherwise.471 * $item['access'] becomes TRUE if the item is accessible, FALSE otherwise.
435 */472 */
436function _menu_check_access(&$item, $map) {473function _menu_check_access(&$item, $map) {
474 //print_r($item);
437 // Determine access callback, which will decide whether or not the current475 // Determine access callback, which will decide whether or not the current
438 // user has access to this path.476 // user has access to this path.
439 $callback = empty($item['access_callback']) ? 0 : trim($item['access_callback']);477 $callback = empty($item['access_callback']) ? 0 : trim($item['access_callback']);
@@ -443,6 +481,9 @@
443 }481 }
444 else {482 else {
445 $arguments = menu_unserialize($item['access_arguments'], $map);483 $arguments = menu_unserialize($item['access_arguments'], $map);
484
485 //print_r($arguments);
486
446 // As call_user_func_array is quite slow and user_access is a very common487 // As call_user_func_array is quite slow and user_access is a very common
447 // callback, it is worth making a special case for it.488 // callback, it is worth making a special case for it.
448 if ($callback == 'user_access') {489 if ($callback == 'user_access') {
@@ -823,12 +864,11 @@
823 $parents = array();864 $parents = array();
824 }865 }
825 array_unshift($args, $menu_name);866 array_unshift($args, $menu_name);
826 // Select the links from the table, and recursively build the tree. We867 // Select the links from the table, and recursively build the tree. Loading data for
827 // LEFT JOIN since there is no match in {menu_router} for an external868 // internal links (formerly from {menu_router}) has moved to _menu_tree_data() in Pressflow.
828 // link.
829 $data['tree'] = menu_tree_data(db_query("869 $data['tree'] = menu_tree_data(db_query("
830 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.*870 SELECT ml.*
831 FROM {menu_links} ml LEFT JOIN {menu_router} m ON m.path = ml.router_path871 FROM {menu_links} ml
832 WHERE ml.menu_name = '%s'". $where ."872 WHERE ml.menu_name = '%s'". $where ."
833 ORDER BY p1 ASC, p2 ASC, p3 ASC, p4 ASC, p5 ASC, p6 ASC, p7 ASC, p8 ASC, p9 ASC", $args), $parents);873 ORDER BY p1 ASC, p2 ASC, p3 ASC, p4 ASC, p5 ASC, p6 ASC, p7 ASC, p8 ASC, p9 ASC", $args), $parents);
834 $data['node_links'] = array();874 $data['node_links'] = array();
@@ -930,12 +970,10 @@
930 $placeholders = '%d';970 $placeholders = '%d';
931 $parents = array();971 $parents = array();
932 }972 }
933 // Select the links from the table, and recursively build the tree. We973 // Select the links from the table, and recursively build the tree.
934 // LEFT JOIN since there is no match in {menu_router} for an external
935 // link.
936 $data['tree'] = menu_tree_data(db_query("974 $data['tree'] = menu_tree_data(db_query("
937 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.*975 SELECT ml.*
938 FROM {menu_links} ml LEFT JOIN {menu_router} m ON m.path = ml.router_path976 FROM {menu_links} ml
939 WHERE ml.menu_name = '%s' AND ml.plid IN (". $placeholders .")977 WHERE ml.menu_name = '%s' AND ml.plid IN (". $placeholders .")
940 ORDER BY p1 ASC, p2 ASC, p3 ASC, p4 ASC, p5 ASC, p6 ASC, p7 ASC, p8 ASC, p9 ASC", $args), $parents);978 ORDER BY p1 ASC, p2 ASC, p3 ASC, p4 ASC, p5 ASC, p6 ASC, p7 ASC, p8 ASC, p9 ASC", $args), $parents);
941 $data['node_links'] = array();979 $data['node_links'] = array();
@@ -1067,6 +1105,26 @@
1067 $remnant = NULL;1105 $remnant = NULL;
1068 $tree = array();1106 $tree = array();
1069 while ($item = db_fetch_array($result)) {1107 while ($item = db_fetch_array($result)) {
1108
1109 // Load additional data for the menu item.
1110 $menu_item = menu_get_item($item['router_path']);
1111 if ($menu_item) {
1112 $menu_item_filter_keys = array(
1113 'load_functions',
1114 'to_arg_functions',
1115 'access_callback',
1116 'access_arguments',
1117 'page_callback',
1118 'page_arguments',
1119 'title',
1120 'title_callback',
1121 'title_arguments',
1122 'type',
1123 'description',
1124 );
1125 $item += array_intersect_key($menu_item, array_fill_keys($menu_item_filter_keys, TRUE));
1126 }
1127
1070 // We need to determine if we're on the path to root so we can later build1128 // We need to determine if we're on the path to root so we can later build
1071 // the correct active trail and breadcrumb.1129 // the correct active trail and breadcrumb.
1072 $item['in_active_trail'] = in_array($item['mlid'], $parents);1130 $item['in_active_trail'] = in_array($item['mlid'], $parents);
@@ -1297,6 +1355,14 @@
1297 return $links;1355 return $links;
1298}1356}
12991357
1358function _menu_sort_callback($item1, $item2) {
1359 if ($item1['weight'] != $item2['weight']) {
1360 return ($item1['weight'] < $item2['weight']) ? -1 : 1;
1361 }
1362
1363 return ($item1['title'] < $item2['title']) ? -1 : 1;
1364}
1365
1300/**1366/**
1301 * Collects the local tasks (tabs) for a given level.1367 * Collects the local tasks (tabs) for a given level.
1302 *1368 *
@@ -1321,13 +1387,34 @@
1321 return '';1387 return '';
1322 }1388 }
1323 // Get all tabs and the root page.1389 // Get all tabs and the root page.
1324 $result = db_query("SELECT * FROM {menu_router} WHERE tab_root = '%s' ORDER BY weight, title", $router_item['tab_root']);1390 $menu_tree =& menu_get_tree();
1391 $items = array();
1392 $cursor =& $menu_tree;
1393 $parts = explode('/', $router_item['tab_root']);
1394 foreach ($parts as $part) {
1395 if (isset($cursor[$part])) {
1396 $cursor = $cursor[$part];
1397 }
1398 else if (isset($cursor['%'])) {
1399 $cursor = $cursor['%'];
1400 }
1401 else {
1402 $cursor = array();
1403 }
1404 }
1405 foreach ($cursor as $key => $item) {
1406 if ($key != '#leaf') {
1407 $items[] = $item;
1408 }
1409 }
1410 usort($items, '_menu_sort_callback');
1411
1325 $map = arg();1412 $map = arg();
1326 $children = array();1413 $children = array();
1327 $tasks = array();1414 $tasks = array();
1328 $root_path = $router_item['path'];1415 $root_path = $router_item['path'];
13291416
1330 while ($item = db_fetch_array($result)) {1417 foreach ($items as $item) {
1331 _menu_translate($item, $map, TRUE);1418 _menu_translate($item, $map, TRUE);
1332 if ($item['tab_parent']) {1419 if ($item['tab_parent']) {
1333 // All tabs, but not the root page.1420 // All tabs, but not the root page.
@@ -1627,7 +1714,11 @@
1627 * rendering.1714 * rendering.
1628 */1715 */
1629function menu_link_load($mlid) {1716function menu_link_load($mlid) {
1630 if (is_numeric($mlid) && $item = db_fetch_array(db_query("SELECT m.*, ml.* FROM {menu_links} ml LEFT JOIN {menu_router} m ON m.path = ml.router_path WHERE ml.mlid = %d", $mlid))) {1717 if (is_numeric($mlid) && $item = db_fetch_array(db_query("SELECT ml.* FROM {menu_links} ml WHERE ml.mlid = %d", $mlid))) {
1718 $menu_item = menu_get_item($item['router_path']);
1719 if ($menu_item) {
1720 $item += $menu_item;
1721 }
1631 _menu_link_translate($item);1722 _menu_link_translate($item);
1632 return $item;1723 return $item;
1633 }1724 }
@@ -1648,6 +1739,7 @@
1648 register_shutdown_function('cache_clear_all', 'links:'. $menu_name .':', 'cache_menu', TRUE);1739 register_shutdown_function('cache_clear_all', 'links:'. $menu_name .':', 'cache_menu', TRUE);
1649 $cache_cleared[$menu_name] = 2;1740 $cache_cleared[$menu_name] = 2;
1650 }1741 }
1742 menu_rebuild();
1651}1743}
16521744
1653/**1745/**
@@ -1656,12 +1748,13 @@
1656 */1748 */
1657function menu_cache_clear_all() {1749function menu_cache_clear_all() {
1658 cache_clear_all('*', 'cache_menu', TRUE);1750 cache_clear_all('*', 'cache_menu', TRUE);
1751 menu_rebuild();
1659}1752}
16601753
1661/**1754/**
1662 * (Re)populate the database tables used by various menu functions.1755 * (Re)populate the data used by various menu functions.
1663 *1756 *
1664 * This function will clear and populate the {menu_router} table, add entries1757 * This function will clear and populate the menu tree, add entries
1665 * to {menu_links} for new router items, then remove stale items from1758 * to {menu_links} for new router items, then remove stale items from
1666 * {menu_links}. If called from update.php or install.php, it will also1759 * {menu_links}. If called from update.php or install.php, it will also
1667 * schedule a call to itself on the first real page load from1760 * schedule a call to itself on the first real page load from
@@ -1669,15 +1762,9 @@
1669 * is different and leaves stale data in the menu tables.1762 * is different and leaves stale data in the menu tables.
1670 */1763 */
1671function menu_rebuild() {1764function menu_rebuild() {
1672 variable_del('menu_rebuild_needed');1765 // Note the current time of the rebuild request. This timestamp is guaranteed consistent across the cluster.
1673 $menu = menu_router_build(TRUE);1766 // The rebuild request is stored for up to a day.
1674 _menu_navigation_links_rebuild($menu);1767 cache_set('menu_tree_rebuild', $_SERVER['REQUEST_TIME'], 'cache', $_SERVER['REQUEST_TIME'] + 86400);
1675 // Clear the menu, page and block caches.
1676 menu_cache_clear_all();
1677 _menu_clear_page_cache();
1678 if (defined('MAINTENANCE_MODE')) {
1679 variable_set('menu_rebuild_needed', TRUE);
1680 }
1681}1768}
16821769
1683/**1770/**
@@ -1730,7 +1817,7 @@
1730 $item['hidden'] = 1;1817 $item['hidden'] = 1;
1731 }1818 }
1732 // Note, we set this as 'system', so that we can be sure to distinguish all1819 // Note, we set this as 'system', so that we can be sure to distinguish all
1733 // the menu links generated automatically from entries in {menu_router}.1820 // the menu links generated automatically from entries in the menu tree.
1734 $item['module'] = 'system';1821 $item['module'] = 'system';
1735 $item += array(1822 $item += array(
1736 'menu_name' => 'navigation',1823 'menu_name' => 'navigation',
@@ -2056,15 +2143,16 @@
2056 // $menu will only have data during a menu rebuild.2143 // $menu will only have data during a menu rebuild.
2057 $menu = _menu_router_cache();2144 $menu = _menu_router_cache();
20582145
2059 $router_path = $link_path;
2060 $parts = explode('/', $link_path, MENU_MAX_PARTS);
2061 list($ancestors, $placeholders) = menu_get_ancestors($parts);
2062
2063 if (empty($menu)) {2146 if (empty($menu)) {
2064 // Not during a menu rebuild, so look up in the database.2147 // Not during a menu rebuild, so look up in the database.
2065 $router_path = (string)db_result(db_query_range('SELECT path FROM {menu_router} WHERE path IN ('. implode (',', $placeholders) .') ORDER BY fit DESC', $ancestors, 0, 1));2148 $menu_item = menu_get_item($link_path);
2149 $router_path = $menu_item['path'];
2066 }2150 }
2067 elseif (!isset($menu[$router_path])) {2151 elseif (!isset($menu[$router_path])) {
2152 $router_path = $link_path;
2153 $parts = explode('/', $link_path, MENU_MAX_PARTS);
2154 list($ancestors, $placeholders) = menu_get_ancestors($parts);
2155
2068 // Add an empty path as a fallback.2156 // Add an empty path as a fallback.
2069 $ancestors[] = '';2157 $ancestors[] = '';
2070 foreach ($ancestors as $key => $router_path) {2158 foreach ($ancestors as $key => $router_path) {
@@ -2231,7 +2319,7 @@
2231 }2319 }
2232}2320}
22332321
2234/**2322 /**
2235 * Helper function to build the router table based on the data from hook_menu.2323 * Helper function to build the router table based on the data from hook_menu.
2236 */2324 */
2237function _menu_router_build($callbacks) {2325function _menu_router_build($callbacks) {
@@ -2492,7 +2580,7 @@
2492 }2580 }
2493 elseif (preg_match('/\/\%/', $path)) {2581 elseif (preg_match('/\/\%/', $path)) {
2494 // Path is dynamic (ie 'user/%'), so check directly against menu_router table.2582 // Path is dynamic (ie 'user/%'), so check directly against menu_router table.
2495 if ($item = db_fetch_array(db_query("SELECT * FROM {menu_router} where path = '%s' ", $path))) {2583 if ($item = menu_get_item($path)) {
2496 $item['link_path'] = $form_item['link_path'];2584 $item['link_path'] = $form_item['link_path'];
2497 $item['link_title'] = $form_item['link_title'];2585 $item['link_title'] = $form_item['link_title'];
2498 $item['external'] = FALSE;2586 $item['external'] = FALSE;
@@ -2507,6 +2595,170 @@
2507 return $item && $item['access'];2595 return $item && $item['access'];
2508}2596}
25092597
2598/*
2599 * Returns a structured array with all menu items. Pressflow-specific.
2600 *
2601 * @returns A structured array with all menu items.
2602 */
2603function menu_get_tree() {
2604 // Attempt to load the tree from cache.
2605 $cache_hit = FALSE;
2606 $rebuild = FALSE;
2607 $write_to_cache = TRUE;
2608 if (function_exists('apc_fetch')) {
2609 $cache_item = apc_fetch('menu_tree', $cache_hit);
2610
2611 if ($cache_hit) {
2612 // Check if there is a recent rebuild request.
2613 $rebuild_request = cache_get('menu_tree_rebuild');
2614
2615 // Check if the rebuild request postdates the locally cached menu tree.
2616 if ($rebuild_request && $rebuild_request->data > $cache_item->created) {
2617 // We need to rebuild the locally cached menu tree. Attempt to grab a semaphore.
2618 $rebuild = apc_add('menu_tree_semaphore', TRUE, 86400);
2619
2620 if (!$rebuild) {
2621 // If the semaphore grab was unsuccessful, return the current (slightly stale) menu tree.
2622 $tree =& $cache_item->data;
2623 }
2624 }
2625 else {
2626 $tree =& $cache_item->data;
2627 }
2628
2629 header('X-APC-Menu-Cache: HIT');
2630 }
2631 else {
2632 header('X-APC-Menu-Cache: MISS');
2633 }
2634 }
2635 else {
2636 $cache_item = cache_get('menu_tree', 'cache');
2637 if ($cache_item) {
2638 $cache_hit = TRUE;
2639 $tree = $cache_item->data;
2640 }
2641 }
2642
2643 // On miss, rebuild the tree.
2644 if (!$cache_hit || $rebuild) {
2645 // Build a fresh menu.
2646 $menu = menu_router_build(TRUE);
2647
2648 // Run the rest of the legacy menu_rebuild().
2649 // TODO: Obsolete this code and anything relying on {menu_*} tables.
2650 _menu_navigation_links_rebuild($menu);
2651 menu_cache_clear_all();
2652 _menu_clear_page_cache();
2653
2654 // Return to the Pressflow rebuild.
2655 $tree = array();
2656 foreach ($menu as $path => $item) {
2657
2658 $item = array(
2659 'path' => $item['path'],
2660 'load_functions' => $item['load_functions'],
2661 'to_arg_functions' => $item['to_arg_functions'],
2662 'access_callback' => $item['access callback'],
2663 'access_arguments' => serialize($item['access arguments']),
2664 'page_callback' => $item['page callback'],
2665 'page_arguments' => serialize($item['page arguments']),
2666 'fit' => $item['_fit'],
2667 'number_parts' => count($item['_parts']),
2668 'tab_parent' => $item['tab_parent'],
2669 'tab_root' => $item['tab_root'],
2670 'title' => $item['title'],
2671 'title_callback' => $item['title callback'],
2672 'title_arguments' => $item['title arguments'] ? serialize($item['title arguments']) : '',
2673 'type' => $item['type'],
2674 'block_callback' => $item['block callback'],
2675 'description' => $item['description'],
2676 'position' => $item['position'],
2677 'weight' => $item['weight'],
2678 'file' => $item['include file'],
2679 'href' => $item['href'],
2680 'options' => $item['options'],
2681 );
2682
2683 $path = explode('/', $path);
2684
2685 // Ensure the route to the item is initialized.
2686 $cursor =& $tree;
2687 foreach ($path as $element) {
2688 if (!isset($cursor[$element])) {
2689 $cursor[$element] = array();
2690 }
2691 $cursor =& $cursor[$element];
2692 }
2693
2694 $cursor['#leaf'] = $item;
2695 }
2696
2697 if ($write_to_cache) {
2698 // Use APC if possible.
2699 if (function_exists('apc_store')) {
2700 $cache_item = new stdClass();
2701 $cache_item->data = $tree;
2702 $cache_item->created = $_SERVER['REQUEST_TIME'];
2703
2704 // TODO: Make the maximum age a variable or constant.
2705 apc_store('menu_tree', $cache_item, 86400);
2706 header('X-APC-Menu-Cache-Write: DONE');
2707 apc_delete('menu_tree_semaphore');
2708 if (defined('MAINTENANCE_MODE')) {
2709 apc_add('menu_tree_rebuild', TRUE);
2710 }
2711 else {
2712 apc_delete('menu_tree_rebuild');
2713 }
2714 }
2715 // Otherwise use the internal cache.
2716 else {
2717 cache_set('menu_tree', $tree, 'cache', $_SERVER['REQUEST_TIME'] + 86400);
2718 if (defined('MAINTENANCE_MODE')) {
2719 cache_set('menu_tree_rebuild', TRUE, 'cache');
2720 }
2721 else {
2722 cache_clear_all('menu_tree_rebuild', 'cache');
2723 }
2724 }
2725 }
2726 }
2727
2728 return $tree;
2729}
2730
2731function menu_get_item_old($path = NULL, $router_item = NULL) {
2732 static $router_items;
2733 if (!isset($path)) {
2734 $path = $_GET['q'];
2735 }
2736 if (isset($router_item)) {
2737 $router_items[$path] = $router_item;
2738 }
2739 if (!isset($router_items[$path])) {
2740 $original_map = arg(NULL, $path);
2741 $parts = array_slice($original_map, 0, MENU_MAX_PARTS);
2742 list($ancestors, $placeholders) = menu_get_ancestors($parts);
2743
2744 if ($router_item = db_fetch_array(db_query_range('SELECT * FROM {menu_router} WHERE path IN ('. implode (',', $placeholders) .') ORDER BY fit DESC', $ancestors, 0, 1))) {
2745 //echo "old router_item:\n";
2746 //print_r($router_item);
2747 $map = _menu_translate($router_item, $original_map);
2748 if ($map === FALSE) {
2749 $router_items[$path] = FALSE;
2750 return FALSE;
2751 }
2752 if ($router_item['access']) {
2753 $router_item['map'] = $map;
2754 $router_item['page_arguments'] = array_merge(menu_unserialize($router_item['page_arguments'], $map), array_slice($map, $router_item['number_parts']));
2755 }
2756 }
2757 $router_items[$path] = $router_item;
2758 }
2759 return $router_items[$path];
2760}
2761
2510/**2762/**
2511 * @} End of "defgroup menu".2763 * @} End of "defgroup menu".
2512 */2764 */
25132765
=== modified file 'modules/book/book.module'
--- modules/book/book.module 2009-02-25 22:33:09 +0000
+++ modules/book/book.module 2009-11-30 19:05:26 +0000
@@ -1068,8 +1068,8 @@
1068 $i++;1068 $i++;
1069 }1069 }
1070 $sql = "1070 $sql = "
1071 SELECT b.*, 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, ml.*1071 SELECT b.*, ml.*
1072 FROM {menu_links} ml INNER JOIN {menu_router} m ON m.path = ml.router_path1072 FROM {menu_links} ml
1073 INNER JOIN {book} b ON ml.mlid = b.mlid1073 INNER JOIN {book} b ON ml.mlid = b.mlid
1074 WHERE ". implode(' AND ', $match) ."1074 WHERE ". implode(' AND ', $match) ."
1075 ORDER BY p1 ASC, p2 ASC, p3 ASC, p4 ASC, p5 ASC, p6 ASC, p7 ASC, p8 ASC, p9 ASC";1075 ORDER BY p1 ASC, p2 ASC, p3 ASC, p4 ASC, p5 ASC, p6 ASC, p7 ASC, p8 ASC, p9 ASC";

Subscribers

People subscribed via source and target branches

to status/vote changes: