diff options
-rw-r--r-- | CHANGELOG.txt | 2 | ||||
-rw-r--r-- | database/database.mysql | 16 | ||||
-rw-r--r-- | database/updates.inc | 24 | ||||
-rw-r--r-- | includes/menu.inc | 390 | ||||
-rw-r--r-- | index.php | 2 | ||||
-rw-r--r-- | misc/drupal.css | 5 | ||||
-rw-r--r-- | modules/blog.module | 2 | ||||
-rw-r--r-- | modules/blog/blog.module | 2 | ||||
-rw-r--r-- | modules/comment.module | 6 | ||||
-rw-r--r-- | modules/comment/comment.module | 6 | ||||
-rw-r--r-- | modules/filter.module | 2 | ||||
-rw-r--r-- | modules/filter/filter.module | 2 | ||||
-rw-r--r-- | modules/locale.module | 4 | ||||
-rw-r--r-- | modules/locale/locale.module | 4 | ||||
-rw-r--r-- | modules/menu.module | 417 | ||||
-rw-r--r-- | modules/menu/menu.module | 417 | ||||
-rw-r--r-- | modules/node.module | 4 | ||||
-rw-r--r-- | modules/node/node.module | 4 | ||||
-rw-r--r-- | modules/profile.module | 6 | ||||
-rw-r--r-- | modules/profile/profile.module | 6 | ||||
-rw-r--r-- | modules/taxonomy.module | 2 | ||||
-rw-r--r-- | modules/taxonomy/taxonomy.module | 2 | ||||
-rw-r--r-- | modules/title.module | 2 | ||||
-rw-r--r-- | modules/user.module | 10 | ||||
-rw-r--r-- | modules/user/user.module | 10 | ||||
-rw-r--r-- | modules/watchdog.module | 10 | ||||
-rw-r--r-- | modules/watchdog/watchdog.module | 10 |
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']); } @@ -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 = '- '. $title; + } + for ($i = 1; $i < $depth; $i++) { + $title = ' '. $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 = '- '. $title; + } + for ($i = 1; $i < $depth; $i++) { + $title = ' '. $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"); } } } |