Commit f3cd2da1 authored by Steven Wittens's avatar Steven Wittens

#130991: Custom menu items, part 1

parent c504141f
......@@ -2292,22 +2292,3 @@ function element_child($key) {
function element_children($element) {
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;
}
......@@ -312,4 +312,3 @@ function db_escape_table($string) {
* @} End of "defgroup database".
*/
......@@ -167,7 +167,27 @@
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))) {
// We need to access check the parents to match the navigation tree
// 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;
while ($item->access && ($parent = db_fetch_object($result))) {
$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] : '');
// If callback returned an error or there is no callback, trigger 404.
if ($return === FALSE) {
return array(FALSE, FALSE, '');
$item->access = FALSE;
return FALSE;
}
$map[$index] = $return;
}
......@@ -414,7 +437,9 @@ function _menu_translate(&$item, $map, $operation = MENU_HANDLE_REQUEST) {
*/
function menu_tree() {
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;
}
}
......@@ -552,8 +577,11 @@ function menu_rebuild() {
// TODO: split menu and menu links storage.
db_query('DELETE FROM {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;
// First pass: separate callbacks from pathes, making pathes ready for
// matching. Calculate fitness, and fill some default values.
foreach ($menu as $path => $item) {
......@@ -626,15 +654,21 @@ function menu_rebuild() {
$menu_path_map[$path] = $new_path;
$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[''] = '';
// Second pass: prepare for sorting and find parents.
foreach ($menu as $path => $item) {
$item = &$menu[$path];
$number_parts = $item['_number_parts'];
if (isset($item['parent'])) {
$item['parent'] = $menu_path_map[$item['parent']];
if (isset($menu_path_map[$item['parent']])) {
$item['parent'] = $menu_path_map[$item['parent']];
}
$parent_parts = explode('/', $item['parent'], 6);
$slashes = count($parent_parts) - 1;
$slashes = count($parent_parts);
}
else {
$parent_parts = $item['_parts'];
......@@ -670,6 +704,7 @@ function menu_rebuild() {
unset($item);
}
array_multisort($sort, $menu);
// We are now sorted, so let's build the tree.
$children = array();
foreach ($menu as $path => $item) {
......@@ -678,6 +713,7 @@ function menu_rebuild() {
}
}
menu_renumber($menu);
// Apply inheritance rules.
foreach ($menu as $path => $item) {
$item = &$menu[$path];
......@@ -719,6 +755,9 @@ function menu_rebuild() {
if (is_bool($item['access callback'])) {
$item['access callback'] = intval($item['access callback']);
}
if (empty($item['page callback'])) {
$item['access callback'] = 0;
}
if ($item['_tab']) {
if (!isset($item['parent'])) {
$item['parent'] = implode('/', array_slice($item['_parts'], 0, $item['_number_parts'] - 1));
......@@ -764,7 +803,11 @@ function menu_rebuild() {
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} (
mid, pid, path, load_functions, to_arg_functions,
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;
}
......@@ -1989,6 +1989,26 @@ function comment_invoke_comment(&$comment, $op) {
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.
*/
......
This diff is collapsed.
......@@ -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));
}
if ($node->nid) {
if ($node && $node->nid) {
// Call the node specific callback (if any) and piggy-back the
// results to the node or overwrite some values.
if ($extra = node_invoke($node, 'load')) {
......
......@@ -378,7 +378,7 @@ function system_main_admin_page($arg = NULL) {
function system_admin_menu_block($item) {
$map = arg(NULL);
$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)) {
_menu_translate($item, $map, MENU_RENDER_LINK);
if (!$item->access) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment