#130991: Custom menu items, part 1

6.x
Steven Wittens 2007-04-06 04:39:51 +00:00
parent c504141f45
commit f3cd2da113
7 changed files with 560 additions and 530 deletions

View File

@ -2292,22 +2292,3 @@ function element_child($key) {
function element_children($element) { function element_children($element) {
return array_filter(array_keys((array) $element), 'element_child'); return array_filter(array_keys((array) $element), 'element_child');
} }
/**
* Generate vancode.
*
* Consists of a leading character indicating length, followed by N digits
* with a numerical value in base 36. Vancodes can be sorted as strings
* without messing up numerical order.
*
* It goes:
* 00, 01, 02, ..., 0y, 0z,
* 110, 111, ... , 1zy, 1zz,
* 2100, 2101, ..., 2zzy, 2zzz,
* 31000, 31001, ...
*/
function int2vancode($i = 0) {
$num = base_convert((int)$i, 10, 36);
$length = strlen($num);
return chr($length + ord('0') - 1) . $num;
}

View File

@ -312,4 +312,3 @@ function db_escape_table($string) {
* @} End of "defgroup database". * @} End of "defgroup database".
*/ */

View File

@ -167,7 +167,27 @@ define('MENU_HANDLE_REQUEST', 0);
define('MENU_RENDER_LINK', 1); define('MENU_RENDER_LINK', 1);
/** /**
* @} End of "Menu helper directions * @} End of "Menu operations."
*/
/**
* @Name Menu alterations
* @{
* Menu alter phases
*/
/**
* Alter the menu as defined in modules, keys are like user/%user.
*/
define('MENU_ALTER_MODULE_DEFINED', 0);
/**
* Alter the menu after the first preprocessing phase, keys are like user/%.
*/
define('MENU_ALTER_PREPROCESSED', 1);
/**
* @} End of "Menu alterations".
*/ */
/** /**
@ -290,7 +310,9 @@ function menu_get_item($path = NULL, $item = NULL) {
if ($item = db_fetch_object(db_query_range('SELECT * FROM {menu} WHERE path IN ('. implode (',', $placeholders) .') ORDER BY fit DESC', $ancestors, 0, 1))) { if ($item = db_fetch_object(db_query_range('SELECT * FROM {menu} WHERE path IN ('. implode (',', $placeholders) .') ORDER BY fit DESC', $ancestors, 0, 1))) {
// We need to access check the parents to match the navigation tree // We need to access check the parents to match the navigation tree
// behaviour. The last parent is always the item itself. // behaviour. The last parent is always the item itself.
$result = db_query('SELECT * FROM {menu} WHERE mid IN ('. $item->parents .') ORDER BY mleft'); $args = explode(',', $item->parents);
$placeholders = implode(', ', array_fill(0, count($args), '%d'));
$result = db_query('SELECT * FROM {menu} WHERE mid IN ('. $placeholders .') ORDER BY mleft', $args);
$item->access = TRUE; $item->access = TRUE;
while ($item->access && ($parent = db_fetch_object($result))) { while ($item->access && ($parent = db_fetch_object($result))) {
$map = _menu_translate($parent, $original_map); $map = _menu_translate($parent, $original_map);
@ -379,7 +401,8 @@ function _menu_translate(&$item, $map, $operation = MENU_HANDLE_REQUEST) {
$return = $load_function(isset($path_map[$index]) ? $path_map[$index] : ''); $return = $load_function(isset($path_map[$index]) ? $path_map[$index] : '');
// If callback returned an error or there is no callback, trigger 404. // If callback returned an error or there is no callback, trigger 404.
if ($return === FALSE) { if ($return === FALSE) {
return array(FALSE, FALSE, ''); $item->access = FALSE;
return FALSE;
} }
$map[$index] = $return; $map[$index] = $return;
} }
@ -414,7 +437,9 @@ function _menu_translate(&$item, $map, $operation = MENU_HANDLE_REQUEST) {
*/ */
function menu_tree() { function menu_tree() {
if ($item = menu_get_item()) { if ($item = menu_get_item()) {
list(, $menu) = _menu_tree(db_query('SELECT * FROM {menu} WHERE pid IN ('. $item->parents .') AND visible = 1 ORDER BY mleft')); $args = explode(',', $item->parents);
$placeholders = implode(', ', array_fill(0, count($args), '%d'));
list(, $menu) = _menu_tree(db_query('SELECT * FROM {menu} WHERE pid IN ('. $placeholders .') AND visible = 1 ORDER BY mleft', $args));
return $menu; return $menu;
} }
} }
@ -552,8 +577,11 @@ function menu_rebuild() {
// TODO: split menu and menu links storage. // TODO: split menu and menu links storage.
db_query('DELETE FROM {menu}'); db_query('DELETE FROM {menu}');
$menu = module_invoke_all('menu'); $menu = module_invoke_all('menu');
drupal_alter('menu', $menu);
// Alter the menu as defined in modules, keys are like user/%user.
drupal_alter('menu', $menu, MENU_ALTER_MODULE_DEFINED);
$mid = 1; $mid = 1;
// First pass: separate callbacks from pathes, making pathes ready for // First pass: separate callbacks from pathes, making pathes ready for
// matching. Calculate fitness, and fill some default values. // matching. Calculate fitness, and fill some default values.
foreach ($menu as $path => $item) { foreach ($menu as $path => $item) {
@ -626,15 +654,21 @@ function menu_rebuild() {
$menu_path_map[$path] = $new_path; $menu_path_map[$path] = $new_path;
$menu[$new_path] = $item; $menu[$new_path] = $item;
} }
// Alter the menu after the first preprocessing phase, keys are like user/%.
drupal_alter('menu', $menu, MENU_ALTER_PREPROCESSED);
$menu_path_map[''] = ''; $menu_path_map[''] = '';
// Second pass: prepare for sorting and find parents. // Second pass: prepare for sorting and find parents.
foreach ($menu as $path => $item) { foreach ($menu as $path => $item) {
$item = &$menu[$path]; $item = &$menu[$path];
$number_parts = $item['_number_parts']; $number_parts = $item['_number_parts'];
if (isset($item['parent'])) { if (isset($item['parent'])) {
if (isset($menu_path_map[$item['parent']])) {
$item['parent'] = $menu_path_map[$item['parent']]; $item['parent'] = $menu_path_map[$item['parent']];
}
$parent_parts = explode('/', $item['parent'], 6); $parent_parts = explode('/', $item['parent'], 6);
$slashes = count($parent_parts) - 1; $slashes = count($parent_parts);
} }
else { else {
$parent_parts = $item['_parts']; $parent_parts = $item['_parts'];
@ -670,6 +704,7 @@ function menu_rebuild() {
unset($item); unset($item);
} }
array_multisort($sort, $menu); array_multisort($sort, $menu);
// We are now sorted, so let's build the tree. // We are now sorted, so let's build the tree.
$children = array(); $children = array();
foreach ($menu as $path => $item) { foreach ($menu as $path => $item) {
@ -678,6 +713,7 @@ function menu_rebuild() {
} }
} }
menu_renumber($menu); menu_renumber($menu);
// Apply inheritance rules. // Apply inheritance rules.
foreach ($menu as $path => $item) { foreach ($menu as $path => $item) {
$item = &$menu[$path]; $item = &$menu[$path];
@ -719,6 +755,9 @@ function menu_rebuild() {
if (is_bool($item['access callback'])) { if (is_bool($item['access callback'])) {
$item['access callback'] = intval($item['access callback']); $item['access callback'] = intval($item['access callback']);
} }
if (empty($item['page callback'])) {
$item['access callback'] = 0;
}
if ($item['_tab']) { if ($item['_tab']) {
if (!isset($item['parent'])) { if (!isset($item['parent'])) {
$item['parent'] = implode('/', array_slice($item['_parts'], 0, $item['_number_parts'] - 1)); $item['parent'] = implode('/', array_slice($item['_parts'], 0, $item['_number_parts'] - 1));
@ -764,7 +803,11 @@ function menu_rebuild() {
break; break;
} }
} }
// We remove disabled items here -- this way they will be numbered in the
// tree so the menu overview screen can show them.
if (!empty($item['disabled'])) {
$item['_visible'] = FALSE;
}
db_query("INSERT INTO {menu} ( db_query("INSERT INTO {menu} (
mid, pid, path, load_functions, to_arg_functions, mid, pid, path, load_functions, to_arg_functions,
access_callback, access_arguments, page_callback, page_arguments, fit, access_callback, access_arguments, page_callback, page_arguments, fit,
@ -914,3 +957,23 @@ function menu_get_active_title() {
} }
} }
} }
/**
* Get a menu item by its mid, access checked and link translated for
* rendering.
*
* @param $mid
* The mid of the menu item.
* @return
* A menu object, with $item->access filled and link translated for
* rendering.
*/
function menu_get_item_by_mid($mid) {
if ($item = db_fetch_object(db_query('SELECT * FROM {menu} WHERE mid = %d', $mid))) {
_menu_translate($item, arg(), MENU_RENDER_LINK);
if ($item->access) {
return $item;
}
}
return FALSE;
}

View File

@ -1989,6 +1989,26 @@ function comment_invoke_comment(&$comment, $op) {
return $return; return $return;
} }
/**
* Generate vancode.
*
* Consists of a leading character indicating length, followed by N digits
* with a numerical value in base 36. Vancodes can be sorted as strings
* without messing up numerical order.
*
* It goes:
* 00, 01, 02, ..., 0y, 0z,
* 110, 111, ... , 1zy, 1zz,
* 2100, 2101, ..., 2zzy, 2zzz,
* 31000, 31001, ...
*/
function int2vancode($i = 0) {
$num = base_convert((int)$i, 10, 36);
$length = strlen($num);
return chr($length + ord('0') - 1) . $num;
}
/** /**
* Decode vancode back to an integer. * Decode vancode back to an integer.
*/ */

File diff suppressed because it is too large Load Diff

View File

@ -527,7 +527,7 @@ function node_load($param = array(), $revision = NULL, $reset = NULL) {
$node = db_fetch_object(db_query('SELECT n.nid, n.vid, n.type, n.status, n.created, n.changed, n.comment, n.promote, n.sticky, r.timestamp AS revision_timestamp, r.title, r.body, r.teaser, r.log, r.format, u.uid, u.name, u.picture, u.data FROM {node} n INNER JOIN {users} u ON u.uid = n.uid INNER JOIN {node_revisions} r ON r.vid = n.vid WHERE '. $cond, $arguments)); $node = db_fetch_object(db_query('SELECT n.nid, n.vid, n.type, n.status, n.created, n.changed, n.comment, n.promote, n.sticky, r.timestamp AS revision_timestamp, r.title, r.body, r.teaser, r.log, r.format, u.uid, u.name, u.picture, u.data FROM {node} n INNER JOIN {users} u ON u.uid = n.uid INNER JOIN {node_revisions} r ON r.vid = n.vid WHERE '. $cond, $arguments));
} }
if ($node->nid) { if ($node && $node->nid) {
// Call the node specific callback (if any) and piggy-back the // Call the node specific callback (if any) and piggy-back the
// results to the node or overwrite some values. // results to the node or overwrite some values.
if ($extra = node_invoke($node, 'load')) { if ($extra = node_invoke($node, 'load')) {

View File

@ -378,7 +378,7 @@ function system_main_admin_page($arg = NULL) {
function system_admin_menu_block($item) { function system_admin_menu_block($item) {
$map = arg(NULL); $map = arg(NULL);
$content = array(); $content = array();
$result = db_query('SELECT * FROM {menu} WHERE depth = %d AND %d < mleft AND mright < %d ORDER BY mleft', $item->depth + 1, $item->mleft, $item->mright); $result = db_query('SELECT * FROM {menu} WHERE depth = %d AND %d < mleft AND mright < %d AND visible = 1 ORDER BY mleft', $item->depth + 1, $item->mleft, $item->mright);
while ($item = db_fetch_object($result)) { while ($item = db_fetch_object($result)) {
_menu_translate($item, $map, MENU_RENDER_LINK); _menu_translate($item, $map, MENU_RENDER_LINK);
if (!$item->access) { if (!$item->access) {