summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.txt2
-rw-r--r--database/database.mysql16
-rw-r--r--database/updates.inc24
-rw-r--r--includes/menu.inc390
-rw-r--r--index.php2
-rw-r--r--misc/drupal.css5
-rw-r--r--modules/blog.module2
-rw-r--r--modules/blog/blog.module2
-rw-r--r--modules/comment.module6
-rw-r--r--modules/comment/comment.module6
-rw-r--r--modules/filter.module2
-rw-r--r--modules/filter/filter.module2
-rw-r--r--modules/locale.module4
-rw-r--r--modules/locale/locale.module4
-rw-r--r--modules/menu.module417
-rw-r--r--modules/menu/menu.module417
-rw-r--r--modules/node.module4
-rw-r--r--modules/node/node.module4
-rw-r--r--modules/profile.module6
-rw-r--r--modules/profile/profile.module6
-rw-r--r--modules/taxonomy.module2
-rw-r--r--modules/taxonomy/taxonomy.module2
-rw-r--r--modules/title.module2
-rw-r--r--modules/user.module10
-rw-r--r--modules/user/user.module10
-rw-r--r--modules/watchdog.module10
-rw-r--r--modules/watchdog/watchdog.module10
27 files changed, 1201 insertions, 166 deletions
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 6c350a50e..f924b0724 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -2,7 +2,7 @@ Drupal x.x.x, xxxx-xx-xx
------------------------
- profile module:
- * made it possible to administere profile fields.
+ * made it possible to administer profile fields.
* made it possible to browse the profiles by field.
Drupal 4.4.0, 2004-04-01 (release candidate)
diff --git a/database/database.mysql b/database/database.mysql
index fd7f22980..698d81d2d 100644
--- a/database/database.mysql
+++ b/database/database.mysql
@@ -236,6 +236,21 @@ CREATE TABLE locales (
) TYPE=MyISAM;
--
+-- Table structure for table 'menu'
+--
+
+CREATE TABLE menu (
+ mid int(10) unsigned NOT NULL default '0',
+ pid int(10) unsigned NOT NULL default '0',
+ path varchar(255) NOT NULL default '',
+ title varchar(255) NOT NULL default '',
+ weight tinyint(4) NOT NULL default '0',
+ visibility int(1) unsigned NOT NULL default '0',
+ status int(1) unsigned NOT NULL default '0',
+ PRIMARY KEY (mid)
+) TYPE=MyISAM;
+
+--
-- Table structure for table 'moderation_filters'
--
@@ -632,3 +647,4 @@ REPLACE variable SET name='theme_default', value='s:9:"xtemplate";';
REPLACE blocks SET module = 'user', delta = '0', status = '1';
REPLACE blocks SET module = 'user', delta = '1', status = '1';
+INSERT INTO sequences (name, id) VALUES ('menu_mid', 1);
diff --git a/database/updates.inc b/database/updates.inc
index 26f4da7ab..54ca79eb1 100644
--- a/database/updates.inc
+++ b/database/updates.inc
@@ -53,7 +53,8 @@ $sql_updates = array(
"2004-02-21" => "update_79",
"2004-03-11: first update since Drupal 4.4.0 release" => "update_80",
"2004-02-20" => "update_81",
- "2004-02-27" => "update_82"
+ "2004-02-27" => "update_82",
+ "2004-04-15" => "update_83"
);
function update_32() {
@@ -900,6 +901,27 @@ function update_82() {
return $ret;
}
+function update_83() {
+ $ret = array();
+ if ($GLOBALS["db_type"] == "mysql") {
+ $ret[] = update_sql("CREATE TABLE menu (
+ mid int(10) unsigned NOT NULL default '0',
+ pid int(10) unsigned NOT NULL default '0',
+ path varchar(255) NOT NULL default '',
+ title varchar(255) NOT NULL default '',
+ weight tinyint(4) NOT NULL default '0',
+ visibility int(1) unsigned NOT NULL default '0',
+ status int(1) unsigned NOT NULL default '0',
+ PRIMARY KEY (mid)
+ );");
+ $ret[] = update_sql("INSERT INTO sequences (name, id) VALUES ('menu_mid', 1)");
+ }
+ else {
+ /* Needs PostgreSQL equivalent */
+ }
+ return $ret;
+}
+
function update_sql($sql) {
$edit = $_POST["edit"];
$result = db_query($sql);
diff --git a/includes/menu.inc b/includes/menu.inc
index 1350d3580..9a7c7234d 100644
--- a/includes/menu.inc
+++ b/includes/menu.inc
@@ -10,6 +10,11 @@ define('MENU_SHOW', 0);
define('MENU_HIDE', 1);
define('MENU_HIDE_NOCHILD', 2);
+define('MENU_NORMAL', 0);
+define('MENU_MODIFIED', 1);
+define('MENU_LOCKED', 2);
+define('MENU_CUSTOM', 3);
+
/** @} */
/**
@@ -20,39 +25,82 @@ define('MENU_HIDE_NOCHILD', 2);
* @param $title The title of the menu item to show in the rendered menu.
* @param $callback The function to call when this is the active menu item.
* @param $weight Heavier menu items sink down the menu.
- * @param $hidden
- * - MENU_SHOW show the menu (default).
- * - MENU_HIDE hide the menu item, but register a callback.
- * - MENU_HIDE_NOCHILD hide the menu item when it has no children.
+ * @param $visibility
+ * - MENU_SHOW - Show the menu item (default).
+ * - MENU_HIDE - Hide the menu item, but register a callback.
+ * - MENU_HIDE_NOCHILD - Hide the menu item when it has no children.
+ * @param $status
+ * - MENU_NORMAL - The menu item can be moved (default).
+ * - MENU_MODIFIED - The administrator has moved or otherwise changed the menu item.
+ * - MENU_LOCKED - The administrator may not modify the item.
+ * - MENU_CUSTOM - The menu item was created by the administrator.
*/
-function menu($path, $title, $callback = NULL, $weight = 0, $hidden = MENU_SHOW) {
- global $_list;
+function menu($path, $title, $callback = NULL, $weight = 0, $visibility = MENU_SHOW, $status = MENU_NORMAL) {
+ global $_menu;
// add the menu to the flat list of menu items:
- $_list[$path] = array("title" => $title, "callback" => $callback, "weight" => $weight, "hidden" => $hidden);
+ $_menu['list'][$path] = array('title' => $title, 'callback' => $callback, 'weight' => $weight, 'visibility' => $visibility, 'status' => $status);
+}
+
+/**
+ * Return the menu data structure.
+ *
+ * The returned structure contains much information that is useful only
+ * internally in the menu system. External modules are likely to need only
+ * the ['visible'] element of the returned array. All menu items that are
+ * accessible to the current user and not hidden will be present here, so
+ * modules and themes can use this structure to build their own representations
+ * of the menu.
+ *
+ * $menu['visible'] will contain an associative array, the keys of which
+ * are menu IDs. The values of this array are themselves associative arrays,
+ * with the following key-value pairs defined:
+ * - 'title' - The displayed title of the menu or menu item. It will already
+ * have been translated by the locale system.
+ * - 'path' - The Drupal path to the menu item. A link to a particular item
+ * can thus be constructed with l($item['title'], $item['path']).
+ * - 'children' - A linear list of the menu ID's of this item's children.
+ *
+ * Menu ID 0 is the "root" of the menu. The children of this item are the
+ * menus themselves (they will have no associated path). Menu ID 1 will
+ * always be one of these children; it is the default "Navigation" menu.
+ */
+function menu_get_menu() {
+ global $_menu;
+ global $user;
+
+ if (!isset($_menu['items'])) {
+ $cache = cache_get('menu:'. $user->uid);
+ if ($cache) {
+ $_menu = unserialize($cache->data);
+ }
+ else {
+ menu_build();
+ cache_set('menu:'. $user->uid, serialize($_menu), 1);
+ }
+ }
+ return $_menu;
}
/**
* Returns an array with the menu items that lead to the specified path.
*/
function menu_get_trail($path) {
- global $_list;
+ $menu = menu_get_menu();
$trail = array();
- while ($path) {
- if ($_list[$path]) {
- array_unshift($trail, $path);
- }
-
- $path = substr($path, 0, strrpos($path, "/"));
+ $mid = menu_get_active_item();
+ while ($mid && $menu['items'][$mid]) {
+ array_unshift($trail, $mid);
+ $mid = $menu['items'][$mid]['pid'];
}
return $trail;
}
/**
- * Returns the path of the active menu item.
+ * Returns the ID of the active menu item.
* @ingroup menu
*/
function menu_get_active_item() {
@@ -64,34 +112,34 @@ function menu_get_active_item() {
* @ingroup menu
*/
function menu_set_active_item($path = NULL) {
- global $_list;
- static $stored_path;
+ static $stored_mid;
+ $menu = menu_get_menu();
- if (is_null($stored_path) || !empty($path)) {
+ if (is_null($stored_mid) || !empty($path)) {
if (empty($path)) {
- $path = $_GET["q"];
+ $path = $_GET['q'];
}
else {
$_GET['q'] = $path;
}
- while ($path && !$_list[$path]) {
- $path = substr($path, 0, strrpos($path, "/"));
+ while ($path && !$menu['path index'][$path]) {
+ $path = substr($path, 0, strrpos($path, '/'));
}
- $stored_path = $path;
+ $stored_mid = $menu['path index'][$path];
}
- return $stored_path;
+ return $stored_mid;
}
/**
* Returns the title of the active menu item.
*/
function menu_get_active_title() {
- global $_list;
+ $menu = menu_get_menu();
- if ($path = menu_get_active_item()) {
- return ucfirst($_list[$path]["title"]);
+ if ($mid = menu_get_active_item()) {
+ return ucfirst($menu['items'][$mid]['title']);
}
}
@@ -101,10 +149,10 @@ function menu_get_active_title() {
function menu_get_active_help() {
if (menu_active_handler_exists()) {
- $path = $_GET["q"];
- $output = "";
+ $path = $_GET['q'];
+ $output = '';
- $return = module_invoke_all("help", $path);
+ $return = module_invoke_all('help', $path);
foreach ($return as $item) {
if (!empty($item)) {
$output .= $item ."\n";
@@ -118,168 +166,282 @@ function menu_get_active_help() {
* Returns an array of rendered menu items in the active breadcrumb trail.
*/
function menu_get_active_breadcrumb() {
+ $menu = menu_get_menu();
- $links[] = l(t("Home"), "");
+ $links[] = l(t('Home'), '');
- $trail = menu_get_trail($_GET["q"]);
- foreach ($trail as $item) {
- $links[] = _render_item($item);
+ $trail = menu_get_trail($_GET['q']);
+ foreach ($trail as $mid) {
+ // Don't show menu items without valid link targets.
+ if ($menu['items'][$mid]['path'] != '') {
+ $links[] = _menu_render_item($mid);
+ }
}
return $links;
}
-
/**
* Execute the handler associated with the active menu item.
*/
function menu_execute_active_handler() {
- global $_list;
+ $menu = menu_get_menu();
- $path = menu_get_active_item();
+ $path = $_GET['q'];
+ while ($path && (!$menu['path index'][$path] || !$menu['items'][$menu['path index'][$path]]['callback'])) {
+ $path = substr($path, 0, strrpos($path, '/'));
+ }
+ $mid = $menu['path index'][$path];
- if ($_list[$path]["callback"]) {
- $arg = substr($_GET["q"], strlen($path) + 1);
+ if ($menu['items'][$mid]['callback']) {
+ $arg = substr($_GET['q'], strlen($menu['items'][$mid]['path']) + 1);
if (isset($arg)) {
- return call_user_func_array($_list[$path]["callback"], explode("/", $arg));
+ return call_user_func_array($menu['items'][$mid]['callback'], explode('/', $arg));
}
else {
- return call_user_func($_list[$path]["callback"]);
+ return call_user_func($menu['items'][$mid]['callback']);
}
}
}
+/**
+ * Return true if a valid callback can be called from the current path.
+ */
function menu_active_handler_exists() {
- global $_list;
+ $menu = menu_get_menu();
- $path = menu_get_active_item();
+ $path = $_GET['q'];
+ while ($path && (!$menu['path index'][$path] || !$menu['items'][$menu['path index'][$path]]['callback'])) {
+ $path = substr($path, 0, strrpos($path, '/'));
+ }
+ $mid = $menu['path index'][$path];
- return function_exists($_list[$path]["callback"]);
+ return function_exists($menu['items'][$mid]['callback']);
}
/**
* Returns true when the path is in the active trail.
*/
-function menu_in_active_trail($path) {
+function menu_in_active_trail($mid) {
static $trail;
if (empty($trail)) {
- $trail = menu_get_trail($_GET["q"]);
+ $trail = menu_get_trail($_GET['q']);
}
- return in_array($path, $trail);
+ return in_array($mid, $trail);
}
/**
- * Returns true when the menu has visisble children.
+ * Returns a rendered menu tree.
*/
-function menu_has_visible_children($item) {
- global $_list;
+function menu_tree($pid = 1) {
+ static $trail;
+ $menu = menu_get_menu();
+ $output = '';
- if ($_list[$item]['children']) {
- foreach ($_list[$item]['children'] as $child) {
- if ($_list[$child]['hidden'] == MENU_SHOW) {
- return true;
+ if (empty($trail)) {
+ $trail = menu_get_trail($_GET['q']);
+ }
+
+ if (isset($menu['visible'][$pid]) && $menu['visible'][$pid]['children']) {
+
+ foreach ($menu['visible'][$pid]['children'] as $mid) {
+ $style = (count($menu['visible'][$mid]['children']) ? (menu_in_active_trail($mid) ? 'expanded' : 'collapsed') : 'leaf');
+ $output .= "<li class=\"$style\">";
+ $output .= _menu_render_item($mid);
+ if (menu_in_active_trail($mid)) {
+ $output .= menu_tree($mid);
}
+ $output .= "</li>\n";
+ }
+
+ if ($output != '') {
+ $output = "\n<ul>\n$output\n</ul>\n";
}
}
- return false;
+ return $output;
}
/**
- * Returns a rendered menu tree.
+ * Build the menu by querying both modules and the database.
*/
-function menu_tree($parent = "", $hidden = 0) {
- global $_list;
- static $trail;
- $output = "";
+function menu_build() {
+ global $_menu;
+ global $user;
- if (empty($trail)) {
- $trail = menu_get_trail($_GET["q"]);
+ // Start from a clean slate.
+ $_menu = array();
+
+ // Build a sequential list of all menu items.
+ module_invoke_all('link', 'system');
+
+ $_menu['path index'] = array();
+ // Set up items array, including default "Navigation" menu.
+ $_menu['items'] = array(0 => array(), 1 => array('pid' => 0, 'title' => t('Navigation'), 'weight' => -50, 'visibility' => MENU_SHOW, 'status' => MENU_LOCKED));
+
+ // Menu items not in the DB get temporary negative IDs.
+ $temp_mid = -1;
+
+ foreach ($_menu['list'] as $path => $data) {
+ $mid = $temp_mid;
+ $_menu['items'][$mid] = array('path' => $path, 'title' => $data['title'], 'callback' => $data['callback'], 'weight' => $data['weight'], 'visibility' => $data['visibility'], 'status' => $data['status']);
+ $_menu['path index'][$path] = $mid;
+
+ $temp_mid--;
}
- if (isset($_list[$parent]) && $_list[$parent]["children"]) {
-
- usort($_list[$parent]["children"], "_menu_sort");
- foreach ($_list[$parent]["children"] as $item) {
- /*
- ** Don't render the menu when it is hidden, or when it has no call-back
- ** nor children. The latter check avoids that useless links are being
- ** rendered.
- */
- $visible = menu_has_visible_children($item);
- if (($_list[$item]["hidden"] == MENU_SHOW && $_list[$item]["callback"]) ||
- ($_list[$item]["hidden"] == MENU_SHOW && $visible) ||
- ($_list[$item]["hidden"] == MENU_HIDE_NOCHILD && $visible)) {
- $style = ($visible ? (menu_in_active_trail($item) ? "expanded" : "collapsed") : "leaf");
- $output .= "<li class=\"$style\">";
- $output .= _render_item($item);
- if (menu_in_active_trail($item)) {
- $output .= menu_tree($item);
+ // Now fetch items from the DB, reassigning menu IDs as needed.
+ if (module_exist('menu')) {
+ $result = db_query('SELECT * FROM {menu}');
+ while ($item = db_fetch_object($result)) {
+ // First, add any custom items added by the administrator.
+ if ($item->status == MENU_CUSTOM) {
+ $_menu['items'][$item->mid] = array('pid' => $item->pid, 'path' => $item->path, 'title' => $item->title, 'callback' => NULL, 'weight' => $item->weight, 'visibility' => MENU_SHOW, 'status' => MENU_CUSTOM);
+ $_menu['path index'][$item->path] = $item->mid;
+ }
+ // Don't display non-custom menu items if no module declared them.
+ else if ($old_mid = $_menu['path index'][$item->path]) {
+ $_menu['items'][$item->mid] = $_menu['items'][$old_mid];
+ unset($_menu['items'][$old_mid]);
+ $_menu['path index'][$item->path] = $item->mid;
+ // If administrator has changed item position, reflect the change.
+ if ($item->status == MENU_MODIFIED) {
+ $_menu['items'][$item->mid]['title'] = $item->title;
+ $_menu['items'][$item->mid]['pid'] = $item->pid;
+ $_menu['items'][$item->mid]['weight'] = $item->weight;
+ $_menu['items'][$item->mid]['visibility'] = $item->visibility;
+ $_menu['items'][$item->mid]['status'] = $item->status;
}
- $output .= "</li>\n";
}
- else if ($_list[$item]["hidden"] == MENU_HIDE && $_list[$item]["children"]) {
- $output .= menu_tree($item, 1);
+ }
+ }
+
+ // Establish parent-child relationships.
+ foreach ($_menu['items'] as $mid => $item) {
+ if (!isset($item['pid'])) {
+ // Parent's location has not been customized, so figure it out using the path.
+ $parent = $item['path'];
+ do {
+ $parent = substr($parent, 0, strrpos($parent, '/'));
}
+ while ($parent && !$_menu['path index'][$parent]);
+
+ $pid = $parent ? $_menu['path index'][$parent] : 1;
+ $_menu['items'][$mid]['pid'] = $pid;
+ }
+ else {
+ $pid = $item['pid'];
}
- if ($output != '' && $hidden != MENU_HIDE) {
- $output = "\n<ul>\n$output\n</ul>\n";
+ // Don't make root a child of itself.
+ if ($mid) {
+ if (isset ($_menu['items'][$pid])) {
+ $_menu['items'][$pid]['children'][] = $mid;
+ }
+ else {
+ // If parent is missing, it is a menu item that used to be defined
+ // but is no longer. Default to a root-level "Navigation" menu item.
+ $_menu['items'][1]['children'][] = $mid;
+ }
}
}
- return $output;
+ // Prepare to display trees to the user as required.
+ menu_build_visible_tree();
}
/**
- * Query to module to build the menu.
+ * Find all visible items in the menu tree, for ease in displaying to user.
+ *
+ * Since this is only for display, we only need title, path, and children
+ * for each item.
*/
-function menu_build($type) {
- /*
- ** Build a sequential list of all menus items.
- */
+function menu_build_visible_tree($pid = 0) {
+ global $_menu;
- module_invoke_all("link", $type);
+ if (isset($_menu['items'][$pid])) {
+ $parent = $_menu['items'][$pid];
- /*
- ** Tree-ify the sequential list of menu items by adding each
- ** menu item to the 'children' array of their direct parent.
- */
+ $children = array();
+ if ($parent['children']) {
+ usort($parent['children'], '_menu_sort');
+ foreach ($parent['children'] as $mid) {
+ $children = array_merge($children, menu_build_visible_tree($mid));
+ }
+ }
+ if (($parent['visibility'] == MENU_SHOW) ||
+ ($parent['visibility'] == MENU_HIDE_NOCHILD && count($children) > 1)) {
+ $_menu['visible'][$pid] = array('title' => $parent['title'], 'path' => $parent['path'], 'children' => $children);
+ return array($pid);
+ }
+ else {
+ return $children;
+ }
+ }
- global $_list;
+ return array();
+}
- foreach ($_list as $path => $data) {
+/**
+ * Populate the database representation of the menu.
+ *
+ * This need only be called at the start of pages that modify the menu.
+ */
+function menu_rebuild() {
+ cache_clear_all();
+ menu_build();
+ $menu = menu_get_menu();
+
+ $new_items = array();
+ foreach ($menu['items'] as $mid => $item) {
+ if ($mid < 0 && ($item->status != MENU_LOCKED)) {
+ $new_mid = db_next_id('menu_mid');
+ if (isset($new_items[$item['pid']])) {
+ $new_pid = $new_items[$item['pid']]['mid'];
+ }
+ else {
+ $new_pid = $item['pid'];
+ }
- /*
- ** Find $path's direct parent:
- */
- $parent = $path;
- do {
- $parent = substr($parent, 0, strrpos($parent, "/"));
- }
- while ($parent && !$_list[$parent]);
+ // Fix parent IDs for menu items already added.
+ if ($item['children']) {
+ foreach ($item['children'] as $child) {
+ if (isset($new_items[$child])) {
+ $new_items[$child]['pid'] = $new_mid;
+ }
+ }
+ }
- if ($path) {
- $_list[$parent]["children"][] = $path;
+ $new_items[$mid] = array('mid' => $new_mid, 'pid' => $new_pid, 'path' => $item['path'], 'title' => $item['title'], 'weight' => $item['weight'], 'visibility' => $item['visibility'], 'status' => $item['status']);
}
}
+
+ foreach ($new_items as $item) {
+ db_query('INSERT INTO {menu} (mid, pid, path, title, weight, visibility, status) VALUES (%d, %d, \'%s\', \'%s\', %d, %d, %d)', $item['mid'], $item['pid'], $item['path'], $item['title'], $item['weight'], $item['visibility'], $item['status']);
+ }
+
+ // Rebuild the menu to account for any changes.
+ menu_build();
}
+/**
+ * Comparator routine for use in sorting menu items.
+ */
function _menu_sort($a, $b) {
- global $_list;
+ $menu = menu_get_menu();
- $a = &$_list[$a];
- $b = &$_list[$b];
+ $a = &$menu['items'][$a];
+ $b = &$menu['items'][$b];
- return $a["weight"] < $b["weight"] ? -1 : ($a["weight"] > $b["weight"] ? 1 : ($a["title"] < $b["title"] ? -1 : 1));
+ return $a['weight'] < $b['weight'] ? -1 : ($a['weight'] > $b['weight'] ? 1 : ($a['title'] < $b['title'] ? -1 : 1));
}
-function _render_item($path) {
- global $_list;
+function _menu_render_item($mid) {
+ $menu = menu_get_menu();
- return l($_list[$path]["title"], $path);
+ return l($menu['items'][$mid]['title'], $menu['items'][$mid]['path']);
}
diff --git a/index.php b/index.php
index 4062ce5bb..24b787cd5 100644
--- a/index.php
+++ b/index.php
@@ -7,8 +7,6 @@ include_once "includes/common.inc";
fix_gpc_magic();
-menu_build("system");
-
if (menu_active_handler_exists()) {
menu_execute_active_handler();
}
diff --git a/misc/drupal.css b/misc/drupal.css
index b95367ef3..6d4a4468b 100644
--- a/misc/drupal.css
+++ b/misc/drupal.css
@@ -313,4 +313,7 @@ td.watchdog-httpd {
td.watchdog-error {
background: #e44;
border: 1px solid #c22;
-} \ No newline at end of file
+}
+td.menu-disabled {
+ background: #ccc;
+}
diff --git a/modules/blog.module b/modules/blog.module
index bd1c00fe7..796df58ab 100644
--- a/modules/blog.module
+++ b/modules/blog.module
@@ -219,7 +219,7 @@ function blog_link($type, $node = 0, $main) {
if ($type == "system") {
if (user_access("maintain personal blog")) {
menu("node/add/blog", t("blog entry"), "node_page", 0);
- menu("blog/". $user->uid, t("my blog"), "blog_page", 1);
+ menu("blog/". $user->uid, t("my blog"), "blog_page", 1, MENU_SHOW, MENU_LOCKED);
}
if (user_access("access content")) {
menu("blog", t("blogs"), "blog_page", 0, MENU_HIDE);
diff --git a/modules/blog/blog.module b/modules/blog/blog.module
index bd1c00fe7..796df58ab 100644
--- a/modules/blog/blog.module
+++ b/modules/blog/blog.module
@@ -219,7 +219,7 @@ function blog_link($type, $node = 0, $main) {
if ($type == "system") {
if (user_access("maintain personal blog")) {
menu("node/add/blog", t("blog entry"), "node_page", 0);
- menu("blog/". $user->uid, t("my blog"), "blog_page", 1);
+ menu("blog/". $user->uid, t("my blog"), "blog_page", 1, MENU_SHOW, MENU_LOCKED);
}
if (user_access("access content")) {
menu("blog", t("blogs"), "blog_page", 0, MENU_HIDE);
diff --git a/modules/comment.module b/modules/comment.module
index 24e2a232b..b99f7a269 100644
--- a/modules/comment.module
+++ b/modules/comment.module
@@ -794,8 +794,8 @@ function comment_link($type, $node = 0, $main = 0) {
menu("admin/comment/comments/0", t("new/updated"), "comment_admin", 1);
menu("admin/comment/comments/1", t("approval queue"), "comment_admin", 2);
menu("admin/comment/help", t("help"), "comment_help_page", 9);
- menu("admin/comment/edit", t("edit comment"), "comment_admin", 0, MENU_HIDE);
- menu("admin/comment/delete", t("delete comment"), "comment_admin", 0, MENU_HIDE);
+ menu("admin/comment/edit", t("edit comment"), "comment_admin", 0, MENU_HIDE, MENU_LOCKED);
+ menu("admin/comment/delete", t("delete comment"), "comment_admin", 0, MENU_HIDE, MENU_LOCKED);
if (module_exist('search')) {
menu("admin/comment/search", t("search"), "comment_admin", 8);
}
@@ -809,7 +809,7 @@ function comment_link($type, $node = 0, $main = 0) {
menu("admin/comment/moderation/roles", t("initial scores"), "comment_admin", 6);
}
}
- menu("comment", t("comments"), "comment_page", 0, MENU_HIDE);
+ menu("comment", t("comments"), "comment_page", 0, MENU_HIDE, MENU_LOCKED);
}
return $links;
diff --git a/modules/comment/comment.module b/modules/comment/comment.module
index 24e2a232b..b99f7a269 100644
--- a/modules/comment/comment.module
+++ b/modules/comment/comment.module
@@ -794,8 +794,8 @@ function comment_link($type, $node = 0, $main = 0) {
menu("admin/comment/comments/0", t("new/updated"), "comment_admin", 1);
menu("admin/comment/comments/1", t("approval queue"), "comment_admin", 2);
menu("admin/comment/help", t("help"), "comment_help_page", 9);
- menu("admin/comment/edit", t("edit comment"), "comment_admin", 0, MENU_HIDE);
- menu("admin/comment/delete", t("delete comment"), "comment_admin", 0, MENU_HIDE);
+ menu("admin/comment/edit", t("edit comment"), "comment_admin", 0, MENU_HIDE, MENU_LOCKED);
+ menu("admin/comment/delete", t("delete comment"), "comment_admin", 0, MENU_HIDE, MENU_LOCKED);
if (module_exist('search')) {
menu("admin/comment/search", t("search"), "comment_admin", 8);
}
@@ -809,7 +809,7 @@ function comment_link($type, $node = 0, $main = 0) {
menu("admin/comment/moderation/roles", t("initial scores"), "comment_admin", 6);
}
}
- menu("comment", t("comments"), "comment_page", 0, MENU_HIDE);
+ menu("comment", t("comments"), "comment_page", 0, MENU_HIDE, MENU_LOCKED);
}
return $links;
diff --git a/modules/filter.module b/modules/filter.module
index 3ff107f4d..4fa0547e5 100644
--- a/modules/filter.module
+++ b/modules/filter.module
@@ -47,7 +47,7 @@ function filter_link($type) {
menu("admin/system/filters", t("filters"), "filter_admin", 5);
menu("admin/system/filters/order", t("ordering"), "filter_admin", 5);
}
- menu("filter/tips", t("Compose tips"), "filter_tips_long", 0, MENU_HIDE);
+ menu("filter/tips", t("compose tips"), "filter_tips_long", 0, MENU_HIDE);
}
}
diff --git a/modules/filter/filter.module b/modules/filter/filter.module
index 3ff107f4d..4fa0547e5 100644
--- a/modules/filter/filter.module
+++ b/modules/filter/filter.module
@@ -47,7 +47,7 @@ function filter_link($type) {
menu("admin/system/filters", t("filters"), "filter_admin", 5);
menu("admin/system/filters/order", t("ordering"), "filter_admin", 5);
}
- menu("filter/tips", t("Compose tips"), "filter_tips_long", 0, MENU_HIDE);
+ menu("filter/tips", t("compose tips"), "filter_tips_long", 0, MENU_HIDE);
}
}
diff --git a/modules/locale.module b/modules/locale.module
index 907c99834..47706292f 100644
--- a/modules/locale.module
+++ b/modules/locale.module
@@ -60,8 +60,8 @@ function locale_link($type) {
menu("admin/locale", t("localization"), "locale_admin", 5);
menu("admin/locale/search", t("search string"), "locale_admin", 8);
menu("admin/locale/help", t("help"), "locale_help_page", 9);
- menu("admin/locale/edit", t("edit string"), "locale_admin", 0, MENU_HIDE);
- menu("admin/locale/delete", t("delete string"), "locale_admin", 0, MENU_HIDE);
+ menu("admin/locale/edit", t("edit string"), "locale_admin", 0, MENU_HIDE, MENU_LOCKED);
+ menu("admin/locale/delete", t("delete string"), "locale_admin", 0, MENU_HIDE, MENU_LOCKED);
foreach ($languages as $key => $value) {
menu("admin/locale/$key", "$value", "locale_admin");
diff --git a/modules/locale/locale.module b/modules/locale/locale.module
index 907c99834..47706292f 100644
--- a/modules/locale/locale.module
+++ b/modules/locale/locale.module
@@ -60,8 +60,8 @@ function locale_link($type) {
menu("admin/locale", t("localization"), "locale_admin", 5);
menu("admin/locale/search", t("search string"), "locale_admin", 8);
menu("admin/locale/help", t("help"), "locale_help_page", 9);
- menu("admin/locale/edit", t("edit string"), "locale_admin", 0, MENU_HIDE);
- menu("admin/locale/delete", t("delete string"), "locale_admin", 0, MENU_HIDE);
+ menu("admin/locale/edit", t("edit string"), "locale_admin", 0, MENU_HIDE, MENU_LOCKED);
+ menu("admin/locale/delete", t("delete string"), "locale_admin", 0, MENU_HIDE, MENU_LOCKED);
foreach ($languages as $key => $value) {
menu("admin/locale/$key", "$value", "locale_admin");
diff --git a/modules/menu.module b/modules/menu.module
new file mode 100644
index 000000000..236278950
--- /dev/null
+++ b/modules/menu.module
@@ -0,0 +1,417 @@
+<?php
+// $Id$
+
+/**
+ * Implementation of hook_link().
+ */
+function menu_link($type, $node = 0, $main) {
+ if ($type == 'system' && user_access('administer menu')) {
+ menu('admin/menu', t('menus'), 'menu_overview', 0, MENU_SHOW);
+ menu('admin/menu/reset', t('reset all menus'), 'menu_reset', 0, MENU_SHOW);
+ menu('admin/menu/menu/add', t('add menu'), 'menu_add_menu', 0, MENU_SHOW);
+ menu('admin/menu/item/add', t('add menu item'), 'menu_edit_item', 0, MENU_SHOW);
+ menu('admin/menu/item/edit', t('edit menu item'), 'menu_edit_item', 0, MENU_HIDE, MENU_LOCKED);
+ menu('admin/menu/item/reset', t('reset menu item'), 'menu_reset_item', 0, MENU_HIDE, MENU_LOCKED);
+ menu('admin/menu/item/disable', t('disable menu item'), 'menu_disable_item', 0, MENU_HIDE, MENU_LOCKED);
+ menu('admin/menu/item/delete', t('delete menu item'), 'menu_delete_item', 0, MENU_HIDE, MENU_LOCKED);
+ }
+}
+
+/**
+ * Implementation of hook_help().
+ */
+function menu_help($section) {
+ switch ($section) {
+ case 'admin/system/modules#description':
+ return t('Allows administrators to customize the site navigation menu.');
+ case 'admin/menu':
+ return t('Select an operation from the list to move, change, or delete a menu item. To add a new menu, add a new menu item, or reset all menu items to default values, choose an option from the main menu.');
+ case 'admin/menu/menu/add':
+ return t('Enter the name for your new menu. Remember to enable the newly created block in the %blocks administration page.', array('%blocks' => l(t('blocks'), 'admin/system/block')));
+ }
+}
+
+/**
+ * Implementation of hook_block().
+ */
+function menu_block($op = 'list', $delta = 0) {
+ $menu = menu_get_menu();
+
+ if ($op == 'list') {
+ $blocks = array();
+ foreach ($menu['items'][0]['children'] as $mid) {
+ // Default "Navigation" block is handled by user.module.
+ if ($mid != 1) {
+ $blocks[$mid]['info'] = $menu['items'][$mid]['title'];
+ }
+ }
+ return $blocks;
+ }
+ else {
+ $data['subject'] = $menu['items'][$delta]['title'];
+ $data['content'] = menu_tree($delta);
+ return $data;
+ }
+}
+
+/**
+ * Implementation of hook_perm().
+ */
+function menu_perm() {
+ return array('administer menu');
+}
+
+/**
+ * Present the main menu management page.
+ */
+function menu_overview() {
+ menu_rebuild();
+
+ print theme('page', menu_overview_tree());
+}
+
+/**
+ * Clear the database, resetting the menu to factory defaults.
+ */
+function menu_reset() {
+ $op = $_POST['op'];
+ switch ($op) {
+ case t('Reset'):
+ db_query('DELETE FROM {menu}');
+ menu_rebuild();
+ drupal_set_message(t('all menu items reset.'));
+ print theme('page', menu_overview_tree());
+ break;
+ case t('Cancel'):
+ print theme('page', menu_overview_tree());
+ break;
+ default:
+ $output = '<p>'. t('Are you sure you want to reset all menu items to their default settings? Any custom menu items will be lost.') .'</p>';
+ $output .= form(form_submit(t('Reset')) . form_submit(t('Cancel')));
+ print theme('page', $output);
+ }
+}
+
+/**
+ * Handle the adding of a new menu.
+ */
+function menu_add_menu() {
+ $op = $_POST['op'];
+ $edit = $_POST['edit'];
+ $output = '';
+
+ switch ($op) {
+ case t('Submit'):
+ menu_edit_item_save($edit);
+ $output .= menu_overview_tree();
+ break;
+ default:
+ $edit['pid'] = 0;
+ $edit['status'] = MENU_CUSTOM;
+ $output .= menu_edit_item_form($edit);
+ }
+
+ print theme('page', $output);
+}
+
+/**
+ * Reset a single modified item.
+ */
+function menu_reset_item($mid) {
+ $op = $_POST['op'];
+ switch ($op) {
+ case t('Reset'):
+ db_query('DELETE FROM {menu} WHERE mid = %d', $mid);
+ menu_rebuild();
+ drupal_set_message(t('menu item reset.'));
+ print theme('page', menu_overview_tree());
+ break;
+ case t('Cancel'):
+ print theme('page', menu_overview_tree());
+ break;
+ default:
+ $output = '<p>'. t('Are you sure you want to reset this item to its default values?') .'</p>';
+ $output .= form(form_submit(t('Reset')) . form_submit(t('Cancel')));
+ print theme('page', $output);
+ }
+}
+
+/**
+ * Delete a single custom item.
+ */
+function menu_delete_item($mid) {
+ $op = $_POST['op'];
+ switch ($op) {
+ case t('Delete'):
+ db_query('DELETE FROM {menu} WHERE mid = %d', $mid);
+ menu_rebuild();
+ drupal_set_message(t('menu item deleted.'));
+ print theme('page', menu_overview_tree());
+ break;
+ case t('Cancel'):
+ print theme('page', menu_overview_tree());
+ break;
+ default:
+ $output = '<p>'. t('Are you sure you want to delete this custom menu item?') .'</p>';
+ $output .= form(form_submit(t('Delete')) . form_submit(t('Cancel')));
+ print theme('page', $output);
+ }
+}
+
+/**
+ * Hide a menu item.
+ */
+function menu_disable_item($mid) {
+ db_query("UPDATE {menu} SET visibility = %d, status = %d WHERE mid = %d", MENU_HIDE, MENU_MODIFIED, $mid);
+ menu_rebuild();
+ drupal_set_message(t('menu item disabled.'));
+ print theme('page', menu_overview_tree());
+}
+
+/**
+ * Dispatch to the appropriate menu item edit function.
+ */
+function menu_edit_item($mid) {
+ $op = $_POST['op'];
+ $edit = $_POST['edit'];
+ $output = '';
+
+ switch ($op) {
+ case t('Submit'):
+ menu_edit_item_save($edit);
+ $output .= menu_overview_tree();
+ break;
+ case t('Delete'):
+ menu_edit_item_delete($edit);
+ $output .= menu_overview_tree();
+ break;
+ default:
+ if ($mid > 0) {
+ $item = db_fetch_object(db_query('SELECT * FROM {menu} WHERE mid = %d', $mid));
+
+ $edit['mid'] = $item->mid;
+ $edit['pid'] = $item->pid;
+ $edit['path'] = $item->path;
+ $edit['title'] = $item->title;
+ $edit['weight'] = $item->weight;
+ $edit['visibility'] = $item->visibility;
+ $edit['status'] = $item->status;
+ }
+ else {
+ $edit['mid'] = 0; // In case a negative ID was passed in.
+ $edit['pid'] = 1; // default to "Navigation" menu.
+ $edit['status'] = MENU_CUSTOM;
+ }
+ $output .= menu_edit_item_form($edit);
+ }
+
+ print theme('page', $output);
+}
+
+/**
+ * Present the menu item editing form.
+ */
+function menu_edit_item_form($edit) {
+ $menu = menu_get_menu();
+
+ $form .= form_textfield(t('Title'), 'title', $edit['title'], 60, 128);
+
+ if ($edit['pid'] == 0) {
+ // Display a limited set of fields for menus (not items).
+ $form .= form_hidden('path', '');
+ $form .= form_hidden('pid', 0);
+ $form .= form_hidden('weight', 0);
+ }
+ else {
+ if ($edit['status'] == MENU_CUSTOM) {
+ $form .= form_textfield(t('Path'), 'path', $edit['path'], 60, 128);
+ }
+ else {
+ $form .= form_item(t('Path'), l($edit['path'], $edit['path']));
+ }
+
+ // Generate a list of possible parents (not including this item or descendants).
+ $options = menu_parent_options($edit['mid']);
+ $form .= form_select(t('Parent item'), 'pid', $edit['pid'], $options);
+
+ $form .= form_weight(t('Weight'), 'weight', $edit['weight'], 10, t('Optional. In the menu, the heavier items will sink and the lighter items will be positioned nearer the top.'));
+ }
+
+ $form .= form_submit(t('Submit'));
+
+ $form .= form_hidden('mid', $edit['mid']);
+ $form .= form_hidden('status', $edit['status']);
+ if ($edit['visibility'] == MENU_HIDE) {
+ // always enable on edit
+ $form .= form_hidden('visibility', MENU_SHOW);
+ }
+ else {
+ $form .= form_hidden('visibility', $edit['visibility']);
+ }
+
+ return form($form);
+}
+
+/**
+ * Save changes to a menu item into the database.
+ */
+function menu_edit_item_save($edit) {
+ if ($edit['mid']) {
+ if ($edit['status'] == MENU_CUSTOM) {
+ db_query("UPDATE {menu} SET pid = %d, path = '%s', title = '%s', weight = %d, visibility = %d WHERE mid = %d", $edit['pid'], $edit['path'], $edit['title'], $edit['weight'], $edit['visibility'], $edit['mid']);
+ }
+ else {
+ db_query("UPDATE {menu} SET pid = %d, title = '%s', weight = %d, visibility = %d, status = %d WHERE mid = %d", $edit['pid'], $edit['title'], $edit['weight'], $edit['visibility'], MENU_MODIFIED, $edit['mid']);
+ }
+ drupal_set_message(t('updated menu item "%title".', array('%title' => $edit['title'])));
+ }
+ else {
+ $mid = db_next_id('menu_mid');
+ db_query("INSERT INTO {menu} (mid, pid, path, title, weight, visibility, status) VALUES (%d, %d, '%s', '%s', %d, %d, %d)", $mid, $edit['pid'], $edit['path'], $edit['title'], $edit['weight'], $edit['visibility'], $edit['status']);
+ drupal_set_message(t('created new menu item "%title".', array('%title' => $edit['title'])));
+ }
+
+ menu_rebuild();
+}
+
+/**
+ * Present the menu tree, rendered along with links to edit menu items.
+ */
+function menu_overview_tree() {
+ $menu = menu_get_menu();
+ $header = array(t('menu item'), array('data' => t('operations'), 'colspan' => 3));
+ $output = '';
+
+ foreach ($menu['items'][0]['children'] as $mid) {
+ $operations = array();
+ if ($menu['items'][$mid]['status'] != MENU_LOCKED) {
+ $operations[] = l(t('edit'), 'admin/menu/item/edit/'. $mid);
+ }
+ if ($menu['items'][$mid]['status'] == MENU_CUSTOM) {
+ $operations[] = l(t('delete'), 'admin/menu/item/delete/'. $mid);
+ }
+ $table = theme('item_list', $operations);
+ $table .= theme('table', $header, menu_overview_tree_rows($mid));
+ $output .= theme('box', $menu['items'][$mid]['title'], $table);
+ }
+ return $output;
+}
+
+function menu_overview_tree_rows($pid = 0, $depth = 0) {
+ $menu = menu_get_menu();
+
+ $rows = array();
+
+ if (isset($menu['items'][$pid]) && $menu['items'][$pid]['children']) {
+
+ usort($menu['items'][$pid]['children'], '_menu_sort');
+ foreach ($menu['items'][$pid]['children'] as $mid) {
+ // Populate the title field.
+ $title = '';
+ if ($pid == 0) {
+ // Top-level items are menu names, and don't have an associated path.
+ $title .= t($menu['items'][$mid]['title']);
+ }
+ else {
+ $title .= l(t($menu['items'][$mid]['title']), $menu['items'][$mid]['path']);
+ }
+ if ($depth > 0) {
+ $title = '-&nbsp;'. $title;
+ }
+ for ($i = 1; $i < $depth; $i++) {
+ $title = '&nbsp;&nbsp;'. $title;
+ }
+
+ // Populate the operations field.
+ $operations = array();
+ if ($menu['items'][$mid]['status'] == MENU_LOCKED) {
+ $operations[] = array('data' => t('locked'), 'colspan' => 3, 'align' => 'center');
+ }
+ else {
+ if ($menu['items'][$mid]['visibility'] == MENU_HIDE) {
+ $operations[] = array('data' => '');
+ $operations[] = array('data' => l(t('enable'), 'admin/menu/item/edit/'. $mid));
+ }
+ else {
+ $operations[] = array('data' => l(t('edit'), 'admin/menu/item/edit/'. $mid));
+ if ($pid == 0) {
+ // Disabling entire menus is done from block admin page.
+ $operations[] = array('data' => '');
+ }
+ else {
+ $operations[] = array('data' => l(t('disable'), 'admin/menu/item/disable/'. $mid));
+ }
+ }
+
+ if ($menu['items'][$mid]['status'] == MENU_MODIFIED) {
+ $operations[] = array('data' => l(t('reset'), 'admin/menu/item/reset/'. $mid));
+ }
+ else if ($menu['items'][$mid]['status'] == MENU_CUSTOM) {
+ $operations[] = array('data' => l(t('delete'), 'admin/menu/item/delete/'. $mid));
+ }
+ else {
+ $operations[] = array('data' => '');
+ }
+ }
+
+ // Call out disabled items.
+ if ($menu['items'][$mid]['visibility'] == MENU_HIDE) {
+ $title .= ' ('. t('disabled') .')';
+ $class = 'menu-disabled';
+ }
+ else {
+ $class = 'menu-enabled';
+ }
+
+ if ($menu['items'][$mid]['visibility'] == MENU_HIDE && $menu['items'][$mid]['status'] == MENU_LOCKED) {
+ // Skip items that are hidden and locked; admins will never care about them.
+ $rows = array_merge($rows, menu_overview_tree_rows($mid, $depth));
+ }
+ else {
+ $row = array(array('data' => $title, 'class' => $class));
+ foreach ($operations as $operation) {
+ $operation['class'] = $class;
+ $row[] = $operation;
+ }
+ $rows[] = $row;
+ $rows = array_merge($rows, menu_overview_tree_rows($mid, $depth + 1));
+ }
+ }
+
+ }
+
+ return $rows;
+}
+
+/**
+ * Return a list of menu items that are valid possible parents for the
+ * given menu item.
+ */
+function menu_parent_options($mid, $pid = 0, $depth = 0) {
+ $menu = menu_get_menu();
+
+ $options = array();
+
+ if (isset($menu['items'][$pid]) && $menu['items'][$pid]['children']) {
+ usort($menu['items'][$pid]['children'], '_menu_sort');
+ foreach ($menu['items'][$pid]['children'] as $child) {
+ if ($child != $mid) {
+ if ($child == 1 || ($child > 0 && $menu['items'][$child]['status'] != MENU_LOCKED)) {
+ $title = ' '. $menu['items'][$child]['title'];
+ for ($i = 0; $i < $depth; $i++) {
+ $title = '--'. $title;
+ }
+ if ($menu['items'][$child]['visibility'] == MENU_HIDE) {
+ $title .= ' ('. t('disabled') .')';
+ }
+ $options[$child] = $title;
+ }
+ $options += menu_parent_options($mid, $child, $depth + 1);
+ }
+ }
+ }
+
+ return $options;
+}
+
+?>
diff --git a/modules/menu/menu.module b/modules/menu/menu.module
new file mode 100644
index 000000000..236278950
--- /dev/null
+++ b/modules/menu/menu.module
@@ -0,0 +1,417 @@
+<?php
+// $Id$
+
+/**
+ * Implementation of hook_link().
+ */
+function menu_link($type, $node = 0, $main) {
+ if ($type == 'system' && user_access('administer menu')) {
+ menu('admin/menu', t('menus'), 'menu_overview', 0, MENU_SHOW);
+ menu('admin/menu/reset', t('reset all menus'), 'menu_reset', 0, MENU_SHOW);
+ menu('admin/menu/menu/add', t('add menu'), 'menu_add_menu', 0, MENU_SHOW);
+ menu('admin/menu/item/add', t('add menu item'), 'menu_edit_item', 0, MENU_SHOW);
+ menu('admin/menu/item/edit', t('edit menu item'), 'menu_edit_item', 0, MENU_HIDE, MENU_LOCKED);
+ menu('admin/menu/item/reset', t('reset menu item'), 'menu_reset_item', 0, MENU_HIDE, MENU_LOCKED);
+ menu('admin/menu/item/disable', t('disable menu item'), 'menu_disable_item', 0, MENU_HIDE, MENU_LOCKED);
+ menu('admin/menu/item/delete', t('delete menu item'), 'menu_delete_item', 0, MENU_HIDE, MENU_LOCKED);
+ }
+}
+
+/**
+ * Implementation of hook_help().
+ */
+function menu_help($section) {
+ switch ($section) {
+ case 'admin/system/modules#description':
+ return t('Allows administrators to customize the site navigation menu.');
+ case 'admin/menu':
+ return t('Select an operation from the list to move, change, or delete a menu item. To add a new menu, add a new menu item, or reset all menu items to default values, choose an option from the main menu.');
+ case 'admin/menu/menu/add':
+ return t('Enter the name for your new menu. Remember to enable the newly created block in the %blocks administration page.', array('%blocks' => l(t('blocks'), 'admin/system/block')));
+ }
+}
+
+/**
+ * Implementation of hook_block().
+ */
+function menu_block($op = 'list', $delta = 0) {
+ $menu = menu_get_menu();
+
+ if ($op == 'list') {
+ $blocks = array();
+ foreach ($menu['items'][0]['children'] as $mid) {
+ // Default "Navigation" block is handled by user.module.
+ if ($mid != 1) {
+ $blocks[$mid]['info'] = $menu['items'][$mid]['title'];
+ }
+ }
+ return $blocks;
+ }
+ else {
+ $data['subject'] = $menu['items'][$delta]['title'];
+ $data['content'] = menu_tree($delta);
+ return $data;
+ }
+}
+
+/**
+ * Implementation of hook_perm().
+ */
+function menu_perm() {
+ return array('administer menu');
+}
+
+/**
+ * Present the main menu management page.
+ */
+function menu_overview() {
+ menu_rebuild();
+
+ print theme('page', menu_overview_tree());
+}
+
+/**
+ * Clear the database, resetting the menu to factory defaults.
+ */
+function menu_reset() {
+ $op = $_POST['op'];
+ switch ($op) {
+ case t('Reset'):
+ db_query('DELETE FROM {menu}');
+ menu_rebuild();
+ drupal_set_message(t('all menu items reset.'));
+ print theme('page', menu_overview_tree());
+ break;
+ case t('Cancel'):
+ print theme('page', menu_overview_tree());
+ break;
+ default:
+ $output = '<p>'. t('Are you sure you want to reset all menu items to their default settings? Any custom menu items will be lost.') .'</p>';
+ $output .= form(form_submit(t('Reset')) . form_submit(t('Cancel')));
+ print theme('page', $output);
+ }
+}
+
+/**
+ * Handle the adding of a new menu.
+ */
+function menu_add_menu() {
+ $op = $_POST['op'];
+ $edit = $_POST['edit'];
+ $output = '';
+
+ switch ($op) {
+ case t('Submit'):
+ menu_edit_item_save($edit);
+ $output .= menu_overview_tree();
+ break;
+ default:
+ $edit['pid'] = 0;
+ $edit['status'] = MENU_CUSTOM;
+ $output .= menu_edit_item_form($edit);
+ }
+
+ print theme('page', $output);
+}
+
+/**
+ * Reset a single modified item.
+ */
+function menu_reset_item($mid) {
+ $op = $_POST['op'];
+ switch ($op) {
+ case t('Reset'):
+ db_query('DELETE FROM {menu} WHERE mid = %d', $mid);
+ menu_rebuild();
+ drupal_set_message(t('menu item reset.'));
+ print theme('page', menu_overview_tree());
+ break;
+ case t('Cancel'):
+ print theme('page', menu_overview_tree());
+ break;
+ default:
+ $output = '<p>'. t('Are you sure you want to reset this item to its default values?') .'</p>';
+ $output .= form(form_submit(t('Reset')) . form_submit(t('Cancel')));
+ print theme('page', $output);
+ }
+}
+
+/**
+ * Delete a single custom item.
+ */
+function menu_delete_item($mid) {
+ $op = $_POST['op'];
+ switch ($op) {
+ case t('Delete'):
+ db_query('DELETE FROM {menu} WHERE mid = %d', $mid);
+ menu_rebuild();
+ drupal_set_message(t('menu item deleted.'));
+ print theme('page', menu_overview_tree());
+ break;
+ case t('Cancel'):
+ print theme('page', menu_overview_tree());
+ break;
+ default:
+ $output = '<p>'. t('Are you sure you want to delete this custom menu item?') .'</p>';
+ $output .= form(form_submit(t('Delete')) . form_submit(t('Cancel')));
+ print theme('page', $output);
+ }
+}
+
+/**
+ * Hide a menu item.
+ */
+function menu_disable_item($mid) {
+ db_query("UPDATE {menu} SET visibility = %d, status = %d WHERE mid = %d", MENU_HIDE, MENU_MODIFIED, $mid);
+ menu_rebuild();
+ drupal_set_message(t('menu item disabled.'));
+ print theme('page', menu_overview_tree());
+}
+
+/**
+ * Dispatch to the appropriate menu item edit function.
+ */
+function menu_edit_item($mid) {
+ $op = $_POST['op'];
+ $edit = $_POST['edit'];
+ $output = '';
+
+ switch ($op) {
+ case t('Submit'):
+ menu_edit_item_save($edit);
+ $output .= menu_overview_tree();
+ break;
+ case t('Delete'):
+ menu_edit_item_delete($edit);
+ $output .= menu_overview_tree();
+ break;
+ default:
+ if ($mid > 0) {
+ $item = db_fetch_object(db_query('SELECT * FROM {menu} WHERE mid = %d', $mid));
+
+ $edit['mid'] = $item->mid;
+ $edit['pid'] = $item->pid;
+ $edit['path'] = $item->path;
+ $edit['title'] = $item->title;
+ $edit['weight'] = $item->weight;
+ $edit['visibility'] = $item->visibility;
+ $edit['status'] = $item->status;
+ }
+ else {
+ $edit['mid'] = 0; // In case a negative ID was passed in.
+ $edit['pid'] = 1; // default to "Navigation" menu.
+ $edit['status'] = MENU_CUSTOM;
+ }
+ $output .= menu_edit_item_form($edit);
+ }
+
+ print theme('page', $output);
+}
+
+/**
+ * Present the menu item editing form.
+ */
+function menu_edit_item_form($edit) {
+ $menu = menu_get_menu();
+
+ $form .= form_textfield(t('Title'), 'title', $edit['title'], 60, 128);
+
+ if ($edit['pid'] == 0) {
+ // Display a limited set of fields for menus (not items).
+ $form .= form_hidden('path', '');
+ $form .= form_hidden('pid', 0);
+ $form .= form_hidden('weight', 0);
+ }
+ else {
+ if ($edit['status'] == MENU_CUSTOM) {
+ $form .= form_textfield(t('Path'), 'path', $edit['path'], 60, 128);
+ }
+ else {
+ $form .= form_item(t('Path'), l($edit['path'], $edit['path']));
+ }
+
+ // Generate a list of possible parents (not including this item or descendants).
+ $options = menu_parent_options($edit['mid']);
+ $form .= form_select(t('Parent item'), 'pid', $edit['pid'], $options);
+
+ $form .= form_weight(t('Weight'), 'weight', $edit['weight'], 10, t('Optional. In the menu, the heavier items will sink and the lighter items will be positioned nearer the top.'));
+ }
+
+ $form .= form_submit(t('Submit'));
+
+ $form .= form_hidden('mid', $edit['mid']);
+ $form .= form_hidden('status', $edit['status']);
+ if ($edit['visibility'] == MENU_HIDE) {
+ // always enable on edit
+ $form .= form_hidden('visibility', MENU_SHOW);
+ }
+ else {
+ $form .= form_hidden('visibility', $edit['visibility']);
+ }
+
+ return form($form);
+}
+
+/**
+ * Save changes to a menu item into the database.
+ */
+function menu_edit_item_save($edit) {
+ if ($edit['mid']) {
+ if ($edit['status'] == MENU_CUSTOM) {
+ db_query("UPDATE {menu} SET pid = %d, path = '%s', title = '%s', weight = %d, visibility = %d WHERE mid = %d", $edit['pid'], $edit['path'], $edit['title'], $edit['weight'], $edit['visibility'], $edit['mid']);
+ }
+ else {
+ db_query("UPDATE {menu} SET pid = %d, title = '%s', weight = %d, visibility = %d, status = %d WHERE mid = %d", $edit['pid'], $edit['title'], $edit['weight'], $edit['visibility'], MENU_MODIFIED, $edit['mid']);
+ }
+ drupal_set_message(t('updated menu item "%title".', array('%title' => $edit['title'])));
+ }
+ else {
+ $mid = db_next_id('menu_mid');
+ db_query("INSERT INTO {menu} (mid, pid, path, title, weight, visibility, status) VALUES (%d, %d, '%s', '%s', %d, %d, %d)", $mid, $edit['pid'], $edit['path'], $edit['title'], $edit['weight'], $edit['visibility'], $edit['status']);
+ drupal_set_message(t('created new menu item "%title".', array('%title' => $edit['title'])));
+ }
+
+ menu_rebuild();
+}
+
+/**
+ * Present the menu tree, rendered along with links to edit menu items.
+ */
+function menu_overview_tree() {
+ $menu = menu_get_menu();
+ $header = array(t('menu item'), array('data' => t('operations'), 'colspan' => 3));
+ $output = '';
+
+ foreach ($menu['items'][0]['children'] as $mid) {
+ $operations = array();
+ if ($menu['items'][$mid]['status'] != MENU_LOCKED) {
+ $operations[] = l(t('edit'), 'admin/menu/item/edit/'. $mid);
+ }
+ if ($menu['items'][$mid]['status'] == MENU_CUSTOM) {
+ $operations[] = l(t('delete'), 'admin/menu/item/delete/'. $mid);
+ }
+ $table = theme('item_list', $operations);
+ $table .= theme('table', $header, menu_overview_tree_rows($mid));
+ $output .= theme('box', $menu['items'][$mid]['title'], $table);
+ }
+ return $output;
+}
+
+function menu_overview_tree_rows($pid = 0, $depth = 0) {
+ $menu = menu_get_menu();
+
+ $rows = array();
+
+ if (isset($menu['items'][$pid]) && $menu['items'][$pid]['children']) {
+
+ usort($menu['items'][$pid]['children'], '_menu_sort');
+ foreach ($menu['items'][$pid]['children'] as $mid) {
+ // Populate the title field.
+ $title = '';
+ if ($pid == 0) {
+ // Top-level items are menu names, and don't have an associated path.
+ $title .= t($menu['items'][$mid]['title']);
+ }
+ else {
+ $title .= l(t($menu['items'][$mid]['title']), $menu['items'][$mid]['path']);
+ }
+ if ($depth > 0) {
+ $title = '-&nbsp;'. $title;
+ }
+ for ($i = 1; $i < $depth; $i++) {
+ $title = '&nbsp;&nbsp;'. $title;
+ }
+
+ // Populate the operations field.
+ $operations = array();
+ if ($menu['items'][$mid]['status'] == MENU_LOCKED) {
+ $operations[] = array('data' => t('locked'), 'colspan' => 3, 'align' => 'center');
+ }
+ else {
+ if ($menu['items'][$mid]['visibility'] == MENU_HIDE) {
+ $operations[] = array('data' => '');
+ $operations[] = array('data' => l(t('enable'), 'admin/menu/item/edit/'. $mid));
+ }
+ else {
+ $operations[] = array('data' => l(t('edit'), 'admin/menu/item/edit/'. $mid));
+ if ($pid == 0) {
+ // Disabling entire menus is done from block admin page.
+ $operations[] = array('data' => '');
+ }
+ else {
+ $operations[] = array('data' => l(t('disable'), 'admin/menu/item/disable/'. $mid));
+ }
+ }
+
+ if ($menu['items'][$mid]['status'] == MENU_MODIFIED) {
+ $operations[] = array('data' => l(t('reset'), 'admin/menu/item/reset/'. $mid));
+ }
+ else if ($menu['items'][$mid]['status'] == MENU_CUSTOM) {
+ $operations[] = array('data' => l(t('delete'), 'admin/menu/item/delete/'. $mid));
+ }
+ else {
+ $operations[] = array('data' => '');
+ }
+ }
+
+ // Call out disabled items.
+ if ($menu['items'][$mid]['visibility'] == MENU_HIDE) {
+ $title .= ' ('. t('disabled') .')';
+ $class = 'menu-disabled';
+ }
+ else {
+ $class = 'menu-enabled';
+ }
+
+ if ($menu['items'][$mid]['visibility'] == MENU_HIDE && $menu['items'][$mid]['status'] == MENU_LOCKED) {
+ // Skip items that are hidden and locked; admins will never care about them.
+ $rows = array_merge($rows, menu_overview_tree_rows($mid, $depth));
+ }
+ else {
+ $row = array(array('data' => $title, 'class' => $class));
+ foreach ($operations as $operation) {
+ $operation['class'] = $class;
+ $row[] = $operation;
+ }
+ $rows[] = $row;
+ $rows = array_merge($rows, menu_overview_tree_rows($mid, $depth + 1));
+ }
+ }
+
+ }
+
+ return $rows;
+}
+
+/**
+ * Return a list of menu items that are valid possible parents for the
+ * given menu item.
+ */
+function menu_parent_options($mid, $pid = 0, $depth = 0) {
+ $menu = menu_get_menu();
+
+ $options = array();
+
+ if (isset($menu['items'][$pid]) && $menu['items'][$pid]['children']) {
+ usort($menu['items'][$pid]['children'], '_menu_sort');
+ foreach ($menu['items'][$pid]['children'] as $child) {
+ if ($child != $mid) {
+ if ($child == 1 || ($child > 0 && $menu['items'][$child]['status'] != MENU_LOCKED)) {
+ $title = ' '. $menu['items'][$child]['title'];
+ for ($i = 0; $i < $depth; $i++) {
+ $title = '--'. $title;
+ }
+ if ($menu['items'][$child]['visibility'] == MENU_HIDE) {
+ $title .= ' ('. t('disabled') .')';
+ }
+ $options[$child] = $title;
+ }
+ $options += menu_parent_options($mid, $child, $depth + 1);
+ }
+ }
+ }
+
+ return $options;
+}
+
+?>
diff --git a/modules/node.module b/modules/node.module
index bb487e077..12209ca0d 100644
--- a/modules/node.module
+++ b/modules/node.module
@@ -366,7 +366,7 @@ function node_load($conditions, $revision = -1) {
** Return the desired revision
*/
if ($revision != -1 && isset($node->revisions[$revision])) {
- $node = $node->revisions[$revision]['node'];
+ $node = $node->revisions[$revision]['node'];
}
return $node;
@@ -617,7 +617,7 @@ function node_link($type, $node = 0, $main = 0) {
if (user_access('administer nodes')) {
menu('admin/node', t('content'), 'node_admin');
menu('admin/node/help', t('help'), 'node_help_page', 9);
- menu('admin/node/edit', t('edit post'), 'node_admin', 0, MENU_HIDE);
+ menu('admin/node/edit', t('edit post'), 'node_admin', 0, MENU_HIDE, MENU_LOCKED);
menu('admin/node/settings', t('settings'), 'node_admin', 8);
if (module_exist('search')) {
menu('admin/node/search', t('search'), 'node_admin', 8);
diff --git a/modules/node/node.module b/modules/node/node.module
index bb487e077..12209ca0d 100644
--- a/modules/node/node.module
+++ b/modules/node/node.module
@@ -366,7 +366,7 @@ function node_load($conditions, $revision = -1) {
** Return the desired revision
*/
if ($revision != -1 && isset($node->revisions[$revision])) {
- $node = $node->revisions[$revision]['node'];
+ $node = $node->revisions[$revision]['node'];
}
return $node;
@@ -617,7 +617,7 @@ function node_link($type, $node = 0, $main = 0) {
if (user_access('administer nodes')) {
menu('admin/node', t('content'), 'node_admin');
menu('admin/node/help', t('help'), 'node_help_page', 9);
- menu('admin/node/edit', t('edit post'), 'node_admin', 0, MENU_HIDE);
+ menu('admin/node/edit', t('edit post'), 'node_admin', 0, MENU_HIDE, MENU_LOCKED);
menu('admin/node/settings', t('settings'), 'node_admin', 8);
if (module_exist('search')) {
menu('admin/node/search', t('search'), 'node_admin', 8);
diff --git a/modules/profile.module b/modules/profile.module
index 3a2ebe48a..cbeaccd1e 100644
--- a/modules/profile.module
+++ b/modules/profile.module
@@ -20,9 +20,9 @@ function profile_link($type) {
if (user_access('administer users')) {
menu('admin/system/modules/profile', t('profile'), 'profile_admin_overview');
- menu('admin/system/modules/profile/add', NULL, 'profile_admin_add', 0, MENU_HIDE);
- menu('admin/system/modules/profile/edit', NULL, 'profile_admin_edit', 0, MENU_HIDE);
- menu('admin/system/modules/profile/delete', NULL, 'profile_admin_delete', 0, MENU_HIDE);
+ menu('admin/system/modules/profile/add', NULL, 'profile_admin_add', 0, MENU_HIDE, MENU_LOCKED);
+ menu('admin/system/modules/profile/edit', NULL, 'profile_admin_edit', 0, MENU_HIDE, MENU_LOCKED);
+ menu('admin/system/modules/profile/delete', NULL, 'profile_admin_delete', 0, MENU_HIDE, MENU_LOCKED);
}
}
}
diff --git a/modules/profile/profile.module b/modules/profile/profile.module
index 3a2ebe48a..cbeaccd1e 100644
--- a/modules/profile/profile.module
+++ b/modules/profile/profile.module
@@ -20,9 +20,9 @@ function profile_link($type) {
if (user_access('administer users')) {
menu('admin/system/modules/profile', t('profile'), 'profile_admin_overview');
- menu('admin/system/modules/profile/add', NULL, 'profile_admin_add', 0, MENU_HIDE);
- menu('admin/system/modules/profile/edit', NULL, 'profile_admin_edit', 0, MENU_HIDE);
- menu('admin/system/modules/profile/delete', NULL, 'profile_admin_delete', 0, MENU_HIDE);
+ menu('admin/system/modules/profile/add', NULL, 'profile_admin_add', 0, MENU_HIDE, MENU_LOCKED);
+ menu('admin/system/modules/profile/edit', NULL, 'profile_admin_edit', 0, MENU_HIDE, MENU_LOCKED);
+ menu('admin/system/modules/profile/delete', NULL, 'profile_admin_delete', 0, MENU_HIDE, MENU_LOCKED);
}
}
}
diff --git a/modules/taxonomy.module b/modules/taxonomy.module
index 1c73ba543..e29359351 100644
--- a/modules/taxonomy.module
+++ b/modules/taxonomy.module
@@ -29,7 +29,7 @@ function taxonomy_link($type, $node = NULL) {
menu("admin/taxonomy/help", t("help"), "taxonomy_admin", 9);
}
if (user_access("access content")) {
- menu("taxonomy", t("taxonomy"), "taxonomy_page", 0, MENU_HIDE);
+ menu("taxonomy", t("taxonomy"), "taxonomy_page", 0, MENU_HIDE, MENU_LOCKED);
}
}
else if ($type == "taxonomy terms" && $node != NULL) {
diff --git a/modules/taxonomy/taxonomy.module b/modules/taxonomy/taxonomy.module
index 1c73ba543..e29359351 100644
--- a/modules/taxonomy/taxonomy.module
+++ b/modules/taxonomy/taxonomy.module
@@ -29,7 +29,7 @@ function taxonomy_link($type, $node = NULL) {
menu("admin/taxonomy/help", t("help"), "taxonomy_admin", 9);
}
if (user_access("access content")) {
- menu("taxonomy", t("taxonomy"), "taxonomy_page", 0, MENU_HIDE);
+ menu("taxonomy", t("taxonomy"), "taxonomy_page", 0, MENU_HIDE, MENU_LOCKED);
}
}
else if ($type == "taxonomy terms" && $node != NULL) {
diff --git a/modules/title.module b/modules/title.module
index fd02de0c7..df7e20b9e 100644
--- a/modules/title.module
+++ b/modules/title.module
@@ -16,7 +16,7 @@ function title_help($section) {
function title_link($type) {
if ($type == "system") {
if (user_access("access content")) {
- menu("title", t("search"), "title_page", 0, MENU_HIDE);
+ menu("title", t("search"), "title_page", 0, MENU_HIDE, MENU_LOCKED);
}
}
}
diff --git a/modules/user.module b/modules/user.module
index 01ba43601..e6a940f2c 100644
--- a/modules/user.module
+++ b/modules/user.module
@@ -539,8 +539,10 @@ function user_link($type) {
menu("logout", t("log out"), "user_logout", 10);
}
else {
- menu('user', t("my account"), "user_page", 8, MENU_HIDE);
+ menu("user/login", t("log in"), "user_page", 0, MENU_HIDE);
}
+ menu("user/password", t("e-mail new password"), "user_page", 0, MENU_HIDE);
+ menu("user/register", t("create new account"), "user_page", 0, MENU_HIDE);
if (user_access("administer users")) {
menu("admin/user", t("accounts"), "user_admin", 2);
@@ -551,7 +553,7 @@ function user_link($type) {
menu("admin/user/role", t("roles"), "user_admin", 4);
menu("admin/user/permission", t("permissions"), "user_admin", 5);
menu("admin/user/help", t("help"), "user_help_page", 9);
- menu("admin/user/edit", t("edit user account"), "user_admin", 0, MENU_HIDE);
+ menu("admin/user/edit", t("edit user account"), "user_admin", 0, MENU_HIDE, MENU_LOCKED);
if (module_exist('search')) {
menu("admin/user/search", t("search"), "user_admin", 8);
}
@@ -764,7 +766,7 @@ function user_login($edit = array(), $msg = "") {
$output = form_group(t('User login'), $output);
- return form($output, "post", url('user'));
+ return form($output, "post", url('user/login'));
}
function _user_authenticated_id() {
@@ -851,7 +853,7 @@ function user_pass($edit = array()) {
}
$output .= theme("item_list", $items);
$output = form_group(t('Request new password'), $output);
- return form($output, "post", url('user'));
+ return form($output, "post", url('user/password'));
}
}
diff --git a/modules/user/user.module b/modules/user/user.module
index 01ba43601..e6a940f2c 100644
--- a/modules/user/user.module
+++ b/modules/user/user.module
@@ -539,8 +539,10 @@ function user_link($type) {
menu("logout", t("log out"), "user_logout", 10);
}
else {
- menu('user', t("my account"), "user_page", 8, MENU_HIDE);
+ menu("user/login", t("log in"), "user_page", 0, MENU_HIDE);
}
+ menu("user/password", t("e-mail new password"), "user_page", 0, MENU_HIDE);
+ menu("user/register", t("create new account"), "user_page", 0, MENU_HIDE);
if (user_access("administer users")) {
menu("admin/user", t("accounts"), "user_admin", 2);
@@ -551,7 +553,7 @@ function user_link($type) {
menu("admin/user/role", t("roles"), "user_admin", 4);
menu("admin/user/permission", t("permissions"), "user_admin", 5);
menu("admin/user/help", t("help"), "user_help_page", 9);
- menu("admin/user/edit", t("edit user account"), "user_admin", 0, MENU_HIDE);
+ menu("admin/user/edit", t("edit user account"), "user_admin", 0, MENU_HIDE, MENU_LOCKED);
if (module_exist('search')) {
menu("admin/user/search", t("search"), "user_admin", 8);
}
@@ -764,7 +766,7 @@ function user_login($edit = array(), $msg = "") {
$output = form_group(t('User login'), $output);
- return form($output, "post", url('user'));
+ return form($output, "post", url('user/login'));
}
function _user_authenticated_id() {
@@ -851,7 +853,7 @@ function user_pass($edit = array()) {
}
$output .= theme("item_list", $items);
$output = form_group(t('Request new password'), $output);
- return form($output, "post", url('user'));
+ return form($output, "post", url('user/password'));
}
}
diff --git a/modules/watchdog.module b/modules/watchdog.module
index e0b1c38d2..e7ac001c1 100644
--- a/modules/watchdog.module
+++ b/modules/watchdog.module
@@ -52,13 +52,11 @@ function watchdog_perm() {
function watchdog_link($type) {
if ($type == "system") {
if (user_access("administer watchdog")) {
- if (arg(0) == 'admin') { // avoid SQL queries if possible
- menu("admin/watchdog", t("logs"), "watchdog_admin", 7);
- menu("admin/watchdog/view", t("view details"), "watchdog_admin", 0, MENU_HIDE);
+ menu("admin/watchdog", t("logs"), "watchdog_admin", 7);
+ menu("admin/watchdog/view", t("view details"), "watchdog_admin", 0, MENU_HIDE, MENU_LOCKED);
- foreach (_watchdog_get_message_types() as $type) {
- menu("admin/watchdog/$type", t($type), "watchdog_admin");
- }
+ foreach (_watchdog_get_message_types() as $type) {
+ menu("admin/watchdog/$type", t($type), "watchdog_admin");
}
}
}
diff --git a/modules/watchdog/watchdog.module b/modules/watchdog/watchdog.module
index e0b1c38d2..e7ac001c1 100644
--- a/modules/watchdog/watchdog.module
+++ b/modules/watchdog/watchdog.module
@@ -52,13 +52,11 @@ function watchdog_perm() {
function watchdog_link($type) {
if ($type == "system") {
if (user_access("administer watchdog")) {
- if (arg(0) == 'admin') { // avoid SQL queries if possible
- menu("admin/watchdog", t("logs"), "watchdog_admin", 7);
- menu("admin/watchdog/view", t("view details"), "watchdog_admin", 0, MENU_HIDE);
+ menu("admin/watchdog", t("logs"), "watchdog_admin", 7);
+ menu("admin/watchdog/view", t("view details"), "watchdog_admin", 0, MENU_HIDE, MENU_LOCKED);
- foreach (_watchdog_get_message_types() as $type) {
- menu("admin/watchdog/$type", t($type), "watchdog_admin");
- }
+ foreach (_watchdog_get_message_types() as $type) {
+ menu("admin/watchdog/$type", t($type), "watchdog_admin");
}
}
}