? grouping.patch
? menu.patch
? my_bug_fix.patch
? sites/menu
Index: includes/menu.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/menu.inc,v
retrieving revision 1.155
diff -u -p -r1.155 menu.inc
--- includes/menu.inc	8 Mar 2007 19:03:48 -0000	1.155
+++ includes/menu.inc	10 Mar 2007 23:10:09 -0000
@@ -76,13 +76,12 @@
 define('MENU_IS_ROOT', 0x0001);
 define('MENU_VISIBLE_IN_TREE', 0x0002);
 define('MENU_VISIBLE_IN_BREADCRUMB', 0x0004);
-define('MENU_VISIBLE_IF_HAS_CHILDREN', 0x0008);
+define('MENU_MODIFIED_BY_ADMIN', 0x0008);
 define('MENU_MODIFIABLE_BY_ADMIN', 0x0010);
-define('MENU_MODIFIED_BY_ADMIN', 0x0020);
-define('MENU_CREATED_BY_ADMIN', 0x0040);
-define('MENU_IS_LOCAL_TASK', 0x0080);
-define('MENU_EXPANDED', 0x0100);
-define('MENU_LINKS_TO_PARENT', 0x0200);
+define('MENU_CREATED_BY_ADMIN', 0x0020);
+define('MENU_IS_LOCAL_TASK', 0x0040);
+define('MENU_EXPANDED', 0x0080);
+define('MENU_LINKS_TO_PARENT', 0x00100);
 
 /**
  * @} End of "Menu flags".
@@ -103,25 +102,12 @@ define('MENU_LINKS_TO_PARENT', 0x0200);
 define('MENU_NORMAL_ITEM', MENU_VISIBLE_IN_TREE | MENU_VISIBLE_IN_BREADCRUMB | MENU_MODIFIABLE_BY_ADMIN);
 
 /**
- * Item groupings are used for pages like "node/add" that simply list
- * subpages to visit. They are distinguished from other pages in that they will
- * disappear from the menu if no subpages exist.
- */
-define('MENU_ITEM_GROUPING', MENU_VISIBLE_IF_HAS_CHILDREN | MENU_VISIBLE_IN_BREADCRUMB | MENU_MODIFIABLE_BY_ADMIN);
-
-/**
  * Callbacks simply register a path so that the correct function is fired
  * when the URL is accessed. They are not shown in the menu.
  */
 define('MENU_CALLBACK', MENU_VISIBLE_IN_BREADCRUMB);
 
 /**
- * Dynamic menu items change frequently, and so should not be stored in the
- * database for administrative customization.
- */
-define('MENU_DYNAMIC_ITEM', MENU_VISIBLE_IN_TREE | MENU_VISIBLE_IN_BREADCRUMB);
-
-/**
  * Modules may "suggest" menu items that the administrator may enable. They act
  * just as callbacks do until enabled, at which time they act like normal items.
  */
@@ -418,16 +404,15 @@ function _menu_translate($item, $map, $o
  * Returns a rendered menu tree.
  */
 function menu_tree() {
-  global $user;
   if ($item = menu_get_item()) {
     list(, $menu) = _menu_tree(db_query('SELECT * FROM {menu} WHERE pid IN ('. $item->parents .') AND visible = 1 ORDER BY mleft'));
     return $menu;
   }
 }
 
-function _menu_tree($result = NULL, $depth = 0, $link = array('link' => '', 'has_children' => FALSE)) {
+function _menu_tree($result = NULL, $depth = 0, $old_item = NULL) {
   static $map;
-  $remnant = array('link' => '', 'has_children' => FALSE);
+  $remnant = NULL;
   $tree = '';
   if (!isset($map)) {
     $map = arg(NULL);
@@ -438,50 +423,64 @@ function _menu_tree($result = NULL, $dep
     if (!$access) {
       continue;
     }
-    $menu_link = array('link' => l($item->title, $path), 'has_children' => $item->has_children);
+    if ($item->to_arg_functions) {
+      $item->link_path = $path;
+      $item->alias = FALSE;
+    }
+    else {
+      $item->alias = TRUE;
+    }
+    if ($item->attributes) {
+      $item->attributes = unserialize($item->attributes);
+    }
     if ($item->depth > $depth) {
-      list($remnant, $menu) = _menu_tree($result, $item->depth, $menu_link);
-      if ($menu) {
-        $tree .= theme('menu_tree', $link, $menu);
-      }
-      else {
-        $tree .= theme('menu_link', $link);
-      }
-      $link = $remnant;
-      $remnant = array('link' => '', 'has_children' => FALSE);
+      list($remnant, $menu) = _menu_tree($result, $item->depth, $item);
+      $tree .= theme('menu_item', $old_item, $menu);
+      $old_item = $remnant;
+      $remnant = NULL;
     }
     elseif ($item->depth == $depth) {
-      if ($link['link'] && !($old_type & MENU_VISIBLE_IF_HAS_CHILDREN)) {
-        $tree .= theme('menu_link', $link);
-      }
-      $link = $menu_link;
+      $tree .= theme('menu_item', $old_item);
+      $old_item = $item;
     }
     // it's the end of a submenu
     else {
-      $remnant = $menu_link;
+      $remnant = $item;
       break;
     }
-    $old_type = $item->type;
-  }
-  if ($link['link']) {
-    $tree .= theme('menu_link', $link);
   }
+  $tree .= theme('menu_item', $old_item);
   return array($remnant, $tree);
 }
 
 /**
- * Generate the HTML for a menu tree.
+ * Generate the HTML output for a single menu link.
  */
-function theme_menu_tree($link, $tree) {
-  $tree = '<ul class="menu">'. $tree .'</ul>';
-  return $link['link'] ? theme('menu_link', $link, $tree) : $tree;
+function theme_menu_item_link($item) {
+  $link = (array)$item;
+  return l($link['title'], $link['link_path'], $link);
 }
 
 /**
- * Generate the HTML for a menu link.
+ * Generate the HTML output for a menu tree
  */
-function theme_menu_link($link, $menu = '') {
-  return '<li class="'. ($menu ? 'expanded' : (empty($link['has_children']) ? 'leaf': 'collapsed')) .'">'. $link['link'] . $menu .'</li>' . "\n";
+function theme_menu_tree($tree) {
+  return '<ul class="menu">'. $tree .'</ul>';
+}
+
+/**
+ * Generate the HTML output for a menu item and submenu.
+ */
+function theme_menu_item($item, $menu = '') {
+  if ($menu) {
+    $menu = theme('menu_tree', $menu);
+    $class = 'expanded';
+  }
+  if (isset($item)) {
+    $class = empty($item->has_children) ? 'leaf': 'collapsed';
+    return '<li class="'. $class .'">'. theme('menu_item_link', $item) . $menu .'</li>' . "\n";
+  }
+  return $menu;
 }
 
 function theme_menu_local_task($link, $active = FALSE) {
@@ -699,14 +698,27 @@ function menu_rebuild() {
       'page callback' => '',
       '_mleft' => 0,
       '_mright' => 0,
+      'block callback' => '',
+      'description' => '',
+      'attributes' => '',
+      'query' => '',
+      'fragment' => '',
+      'absolute' => '',
+      'html' => '',
     );
+    $link_path = $item['to_arg_functions'] ? $path : drupal_get_path_alias($path);
+    if ($item['attributes']) {
+      $item['attributes'] = serialize($item['attributes']);
+    }
     db_query("INSERT INTO {menu} (
       mid, pid, path, load_functions, to_arg_functions,
       access_callback, access_arguments, page_callback, page_arguments, fit,
       number_parts, visible, parents, depth, has_children, tab, title, parent,
-      type, mleft, mright)
+      type, mleft, mright, block_callback, description,
+      link_path, attributes, query, fragment, absolute, html)
       VALUES (%d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d,
-      '%s', %d, %d, %d, '%s', '%s', '%s', %d, %d)",
+      '%s', %d, %d, %d, '%s', '%s', '%s', %d, %d, '%s', '%s',
+      '%s', '%s', '%s', '%s', %d, %d)",
       $item['_mid'], $item['_pid'], $path, $item['load_functions'],
       $item['to_arg_functions'], $item['access callback'],
       serialize($item['access arguments']), $item['page callback'],
@@ -714,7 +726,9 @@ function menu_rebuild() {
       $item['_number_parts'], $item['_visible'], $item['_parents'],
       $item['_depth'], !empty($item['_children']), $item['_tab'],
       $item['title'], $item['parent'], $item['type'], $item['_mleft'],
-      $item['_mright']);
+      $item['_mright'], $item['block callback'], $item['description'],
+      $link_path, $item['attributes'], $item['query'], $item['fragment'],
+      $item['absolute'], $item['html']);
   }
 }
 
Index: modules/aggregator/aggregator.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.module,v
retrieving revision 1.330
diff -u -p -r1.330 aggregator.module
--- modules/aggregator/aggregator.module	27 Feb 2007 12:29:22 -0000	1.330
+++ modules/aggregator/aggregator.module	10 Mar 2007 23:10:10 -0000
@@ -91,8 +91,7 @@ function aggregator_menu() {
   $items['aggregator/categories'] = array(
     'title' => t('Categories'),
     'page callback' => 'aggregator_page_categories',
-    'access arguments' => array('access news feeds'),
-    'type' => MENU_ITEM_GROUPING,
+    'access callback' => '_aggregator_has_categories',
   );
   $items['aggregator/rss'] = array(
     'title' => t('RSS feed'),
@@ -112,6 +111,7 @@ function aggregator_menu() {
     $items[$path] = array(
       'title' => $category['title'],
       'page callback' => 'aggregator_page_category',
+      'access callback' => 'user_access',
       'access arguments' => array('access news feeds'),
     );
     $items[$path .'/view'] = array(
@@ -181,6 +181,10 @@ function aggregator_init() {
   drupal_add_css(drupal_get_path('module', 'aggregator') .'/aggregator.css');
 }
 
+function _aggregator_has_categories() {
+  return user_access('access news feeds') && db_num_rows(db_query_range('SELECT 1 FROM {aggregator_category}', 0, 1));
+}
+
 function aggregator_admin_settings() {
   $items = array(0 => t('none')) + drupal_map_assoc(array(3, 5, 10, 15, 20, 25), '_aggregator_items');
   $period = drupal_map_assoc(array(3600, 10800, 21600, 32400, 43200, 86400, 172800, 259200, 604800, 1209600, 2419200, 4838400, 9676800), 'format_interval');
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.788
diff -u -p -r1.788 node.module
--- modules/node/node.module	7 Mar 2007 13:09:32 -0000	1.788
+++ modules/node/node.module	10 Mar 2007 23:10:10 -0000
@@ -1132,8 +1132,7 @@ function node_menu() {
   $items['node/add'] = array(
     'title' => t('Create content'),
     'page callback' => 'node_add',
-    'access callback' => 'user_access',
-    'access arguments' => array('access content'),
+    'access callback' => '_node_add_access',
     'weight' => 1,
   );
   $items['rss.xml'] = array(
@@ -2090,6 +2089,16 @@ function theme_node_form($form) {
   return $output;
 }
 
+function _node_add_access() {
+  $types = node_get_types();
+  foreach ($types as $type) {
+    if (function_exists($type->module .'_form') && node_access('create', $type->type)) {
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
 /**
  * Present a node submission form or a set of links to such forms.
  */
Index: modules/path/path.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/path/path.module,v
retrieving revision 1.108
diff -u -p -r1.108 path.module
--- modules/path/path.module	15 Feb 2007 11:40:18 -0000	1.108
+++ modules/path/path.module	10 Mar 2007 23:10:10 -0000
@@ -135,10 +135,12 @@ function path_admin_delete($pid = 0) {
 function path_set_alias($path = NULL, $alias = NULL, $pid = NULL) {
   if ($path && !$alias) {
     db_query("DELETE FROM {url_alias} WHERE src = '%s'", $path);
+    db_query("UPDATE {menu} SET link_path = path WHERE path = '%s'", $path);
     drupal_clear_path_cache();
   }
   else if (!$path && $alias) {
     db_query("DELETE FROM {url_alias} WHERE dst = '%s'", $alias);
+    db_query("UPDATE {menu} SET link_path = path WHERE link_path = '%s'", $alias);
     drupal_clear_path_cache();
   }
   else if ($path && $alias) {
@@ -147,29 +149,34 @@ function path_set_alias($path = NULL, $a
     $alias = urldecode($alias);
     $alias_count = db_result(db_query("SELECT COUNT(dst) FROM {url_alias} WHERE dst = '%s'", $alias));
 
-    // We have an insert:
-    if ($path_count == 0 && $alias_count == 0) {
-      db_query("INSERT INTO {url_alias} (src, dst) VALUES ('%s', '%s')", $path, $alias);
-      drupal_clear_path_cache();
-    }
-    else if ($path_count >= 1 && $alias_count == 0) {
-      if ($pid) {
+    // Alias count can only be 0 or 1.
+    if ($alias_count == 0) {
+      // New alias.
+      if ($path_count == 0 || $pid == 0) {
+        db_query("INSERT INTO {url_alias} (src, dst) VALUES ('%s', '%s')", $path, $alias);
+      }
+      // Updating existing alias.
+      else {
         db_query("UPDATE {url_alias} SET dst = '%s', src = '%s' WHERE pid = %d", $alias, $path, $pid);
       }
+    }
+    // The alias exists.
+    else {
+      // This path has no alias yet, so we redirect the alias here.
+      if ($path_count == 0) {
+        db_query("UPDATE {url_alias} SET src = '%s' WHERE dst = '%s'", $path, $alias);
+      }
       else {
-        db_query("INSERT INTO {url_alias} (src, dst) VALUES ('%s', '%s')", $path, $alias);
+        // This will delete the path that alias was originally pointing to.
+        path_set_alias(NULL, $alias);
+        // This will remove the current aliases of the path.
+        path_set_alias($path);
+        path_set_alias($path, $alias);
       }
-      drupal_clear_path_cache();
     }
-    else if ($path_count == 0 && $alias_count == 1) {
-      db_query("UPDATE {url_alias} SET src = '%s' WHERE dst = '%s'", $path, $alias);
+    if ($alias_count == 0 || $path_count == 0) {
       drupal_clear_path_cache();
-    }
-    else if ($path_count == 1 && $alias_count == 1) {
-      // This will delete the path that alias was originally pointing to:
-      path_set_alias(NULL, $alias);
-      path_set_alias($path);
-      path_set_alias($path, $alias);
+      db_query("UPDATE {menu} SET link_path = '%s' WHERE path = '%s'", $alias, $path);
     }
   }
 }
Index: modules/system/system.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.install,v
retrieving revision 1.82
diff -u -p -r1.82 system.install
--- modules/system/system.install	8 Mar 2007 19:03:48 -0000	1.82
+++ modules/system/system.install	10 Mar 2007 23:10:11 -0000
@@ -349,6 +349,14 @@ function system_install() {
         title varchar(255) NOT NULL default '',
         parent varchar(255) NOT NULL default '',
         type int NOT NULL default 0,
+        block_callback varchar(255) NOT NULL default '',
+        description varchar(255) NOT NULL default '',
+        link_path varchar(255) NOT NULL default '',
+        attributes varchar(255) NOT NULL default '',
+        query varchar(255) NOT NULL default '',
+        fragment varchar(255) NOT NULL default '',
+        absolute INT NOT NULL default 0,
+        html INT NOT NULL default 0,
         PRIMARY KEY  (path),
         KEY fit (fit),
         KEY visible (visible),
@@ -824,6 +832,14 @@ function system_install() {
         title varchar(255) NOT NULL default '',
         parent varchar(255) NOT NULL default '',
         type int NOT NULL default 0,
+        block_callback varchar(255) NOT NULL default '',
+        description varchar(255) NOT NULL default '',
+        link_path varchar(255) NOT NULL default '',
+        attributes varchar(255) NOT NULL default '',
+        query varchar(255) NOT NULL default '',
+        fragment varchar(255) NOT NULL default '',
+        absolute INT NOT NULL default 0,
+        html INT NOT NULL default 0,
         PRIMARY KEY (path)
       )");
 
