Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.1205
diff -u -p -r1.1205 common.inc
--- includes/common.inc	14 Aug 2010 03:15:01 -0000	1.1205
+++ includes/common.inc	16 Aug 2010 15:27:22 -0000
@@ -230,7 +230,7 @@ function drupal_get_profile() {
 function drupal_set_breadcrumb($breadcrumb = NULL) {
   $stored_breadcrumb = &drupal_static(__FUNCTION__);
 
-  if (!is_null($breadcrumb)) {
+  if (isset($breadcrumb)) {
     $stored_breadcrumb = $breadcrumb;
   }
   return $stored_breadcrumb;
@@ -242,7 +242,7 @@ function drupal_set_breadcrumb($breadcru
 function drupal_get_breadcrumb() {
   $breadcrumb = drupal_set_breadcrumb();
 
-  if (is_null($breadcrumb)) {
+  if (!isset($breadcrumb)) {
     $breadcrumb = menu_get_active_breadcrumb();
   }
 
Index: includes/menu.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/menu.inc,v
retrieving revision 1.404
diff -u -p -r1.404 menu.inc
--- includes/menu.inc	5 Aug 2010 07:56:50 -0000	1.404
+++ includes/menu.inc	16 Aug 2010 15:27:22 -0000
@@ -795,6 +795,7 @@ function _menu_link_translate(&$item) {
     $item['localized_options'] = $item['options'];
   }
   else {
+    // Complete the path of the menu link with elements from the current path.
     $map = explode('/', $item['link_path']);
     if (!empty($item['to_arg_functions'])) {
       _menu_link_map_translate($map, $item['to_arg_functions']);
@@ -1077,50 +1078,27 @@ function menu_tree_page_data($menu_name,
         // If the item for the current page is accessible, build the tree
         // parameters accordingly.
         if ($item['access']) {
-          // Check whether a menu link exists that corresponds to the current path.
-          $args[] = $item['href'];
-          if (drupal_is_front_page()) {
-            $args[] = '<front>';
-          }
-          $active_link = db_select('menu_links')
-            ->fields('menu_links', array(
-              'p1',
-              'p2',
-              'p3',
-              'p4',
-              'p5',
-              'p6',
-              'p7',
-              'p8',
-            ))
-            ->condition('menu_name', $menu_name)
-            ->condition('link_path', $args, 'IN')
-            ->execute()->fetchAssoc();
-
-          if (empty($active_link)) {
-            // If no link exists, we may be on a local task that's not in the links.
-            // TODO: Handle the case like a local task on a specific node in the menu.
-            $active_link = db_select('menu_links')
-              ->fields('menu_links', array(
-                'p1',
-                'p2',
-                'p3',
-                'p4',
-                'p5',
-                'p6',
-                'p7',
-                'p8',
-              ))
-              ->condition('menu_name', $menu_name)
-              ->condition('link_path', $item['tab_root'])
-              ->execute()->fetchAssoc();
-          }
+          // Parent mlids.
+          $active_link = array();
+
+          // Find a menu link corresponding to the current path.
+          $top_link = menu_link_get_preferred();
 
+          if ($top_link) {
+            // Use all the coordinates, except the last one because there
+            // can be no child beyond the last column.
+            for ($i = 1; $i < MENU_MAX_DEPTH; $i++) {
+              if ($top_link['p' . $i]) {
+                $active_link[] = $top_link['p' . $i];
+              }
+            }
+          }
+          
           // We always want all the top-level links with plid == 0.
           $active_link[] = '0';
 
           // Use array_values() so that the indices are numeric.
-          $parents = $active_link = array_unique(array_values($active_link));
+          $parents = $active_link = array_values(array_unique($active_link));
 
           $expanded = variable_get('menu_expanded', array());
           // Check whether the current menu has any links set to be expanded.
@@ -1726,6 +1704,7 @@ function menu_local_tasks($level = 0) {
     // If this router item points to its parent, start from the parents to
     // compute tabs and actions.
     if ($router_item && ($router_item['type'] & MENU_LINKS_TO_PARENT)) {
+      // FIXME: $router_item['tab_parent'] is not a href, but a wildcard path.
       $router_item = menu_get_item($router_item['tab_parent']);
     }
 
@@ -2116,53 +2095,22 @@ function menu_set_active_trail($new_trai
   elseif (!isset($trail)) {
     $trail = array();
     $trail[] = array('title' => t('Home'), 'href' => '<front>', 'localized_options' => array(), 'type' => 0);
-    $item = menu_get_item();
 
-    // Check whether the current item is a local task (displayed as a tab).
-    if ($item['tab_parent']) {
-      // The title of a local task is used for the tab, never the page title.
-      // Thus, replace it with the item corresponding to the root path to get
-      // the relevant href and title. For example, the menu item corresponding
-      // to 'admin' is used when on the 'By module' tab at 'admin/by-module'.
-      $parts = explode('/', $item['tab_root']);
-      $args = arg();
-      // Replace wildcards in the root path using the current path.
-      foreach ($parts as $index => $part) {
-        if ($part == '%') {
-          $parts[$index] = $args[$index];
-        }
-      }
-      // Retrieve the menu item using the root path after wildcard replacement.
-      $root_item = menu_get_item(implode('/', $parts));
-      if ($root_item && $root_item['access']) {
-        $item = $root_item;
-      }
+    $preferred_link = menu_link_get_preferred();
+
+    if ($preferred_link) {
+      $tree = menu_tree_page_data($preferred_link['menu_name']);
+      list($key, $curr) = each($tree);
     }
-    $menu_names = menu_get_active_menu_names();
-    $curr = FALSE;
-    // Determine if the current page is a link in any of the active menus.
-    if ($menu_names) {
-      $query = db_select('menu_links', 'ml');
-      $query->fields('ml', array('menu_name'));
-      $query->condition('ml.link_path', $item['href']);
-      $query->condition('ml.menu_name', $menu_names, 'IN');
-      $result = $query->execute();
-      $found = array();
-      foreach ($result as $menu) {
-        $found[] = $menu->menu_name;
-      }
-      // The $menu_names array is ordered, so take the first one that matches.
-      $found_menu_names = array_intersect($menu_names, $found);
-      $name = current($found_menu_names);
-      if ($name !== FALSE) {
-        $tree = menu_tree_page_data($name);
-        list($key, $curr) = each($tree);
-      }
+    else {
+      $preferred_link = menu_get_item();
+      $key = NULL;
+      $curr = NULL;
     }
 
     while ($curr) {
       // Terminate the loop when we find the current path in the active trail.
-      if ($curr['link']['href'] == $item['href']) {
+      if ($curr['link']['href'] == $preferred_link['href']) {
         $trail[] = $curr['link'];
         $curr = FALSE;
       }
@@ -2178,14 +2126,98 @@ function menu_set_active_trail($new_trai
     // Make sure the current page is in the trail (needed for the page title),
     // but exclude tabs and the front page.
     $last = count($trail) - 1;
-    if ($trail[$last]['href'] != $item['href'] && !(bool) ($item['type'] & MENU_IS_LOCAL_TASK) && !drupal_is_front_page()) {
-      $trail[] = $item;
+    if ($trail[$last]['href'] != $preferred_link['href'] && !(bool)($preferred_link['type'] & MENU_IS_LOCAL_TASK) && !drupal_is_front_page()) {
+      $trail[] = $preferred_link;
     }
   }
   return $trail;
 }
 
 /**
+ * Load the preferred menu link for a given path.
+ *
+ * @param $path
+ *   The path, for example node/5. The function will find the corresponding
+ *   menu link (node/5 if it exists, or fallback to node/%).
+ * @return
+ *   A fully translated menu link, or NULL if not matching menu link was
+ *   found. The most specific menu link (node/5 preferred over node/%) in the
+ *   most preferred menu (as defined by menu_get_active_menu_names()) is returned.
+ */
+function menu_link_get_preferred($href = NULL, $check_access = TRUE) {
+  $preferred_links = &drupal_static(__FUNCTION__);
+
+  if (!isset($href)) {
+    $href = $_GET['q'];
+  }
+
+  if (!isset($preferred_links[$href])) {
+    $item = menu_get_item($href);
+
+    // We look for the correct menu link by building a list of candidate
+    // paths. We pick the most relevant path in the preferred menu.
+    $path_candidates = array();
+    // 1. The current item href.
+    $path_candidates[] = $item['href'];
+    // 2. The current item path (with wildcards).
+    $path_candidates[] = $item['path'];
+    if ($item['tab_parent']) {
+      // FIXME: tab_root is not a href, but a wildcard path.
+      $tab_item = menu_get_item($item['tab_root']);
+      // 3. The href of the current item tab root (if its exists).
+      $path_candidates[] = $tab_item['href'];
+      // 4. The path of the current item tab root (if its exists).
+      $path_candidates[] = $tab_item['path'];
+    }
+
+    // The list of preferred menu names, in preference order.
+    $menu_names = menu_get_active_menu_names();
+
+    // Build the query.
+    $query = db_select('menu_links', 'ml', array('fetch' => PDO::FETCH_ASSOC));
+    $query->leftJoin('menu_router', 'm', 'm.path = ml.router_path');
+    $query->fields('ml');
+    // Weight should be taken from {menu_links}, not {menu_router}.
+    $query->fields('m', array_diff(drupal_schema_fields_sql('menu_router'), array('weight')));
+    $query->condition('ml.link_path', $path_candidates, 'IN');
+    $query->condition('ml.menu_name', $menu_names, 'IN');
+
+    // Sort candidates by link path and menu name.
+    $candidates = array();
+    foreach ($query->execute() as $candidate) {
+      $candidates[$candidate['link_path']][$candidate['menu_name']] = $candidate;
+    }
+
+    // Pick the most specific link, in the preferred menu.
+    $preferred_links[$href] = NULL;
+    foreach ($path_candidates as $path) {
+      if (!isset($candidates[$path])) {
+        continue;
+      }
+      foreach ($menu_names as $menu_name) {
+        if (!isset($candidates[$path][$menu_name])) {
+          continue;
+        }
+
+        $candidate_item = $candidates[$path][$menu_name];
+
+        $map = explode('/', $href);
+        _menu_translate($candidate_item, $map);
+        if (!$candidate_item['access']) {
+          die();
+          continue;
+        }
+
+        $preferred_links[$href] = $candidate_item;
+        break 2;
+      }
+    }
+  }
+
+  return $preferred_links[$href];
+}
+
+/**
  * Gets the active trail (path to root menu root) of the current page.
  *
  * See menu_set_active_trail() for details of return value.
Index: modules/field/modules/options/options.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/modules/options/options.test,v
retrieving revision 1.15
diff -u -p -r1.15 options.test
--- modules/field/modules/options/options.test	5 Aug 2010 23:53:37 -0000	1.15
+++ modules/field/modules/options/options.test	16 Aug 2010 15:27:22 -0000
@@ -77,7 +77,7 @@ class OptionsWidgetsTestCase extends Fie
     field_test_entity_save($entity);
 
     // With no field data, no buttons are checked.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid .'/edit');
     $this->assertNoFieldChecked("edit-card-1-$langcode-0");
     $this->assertNoFieldChecked("edit-card-1-$langcode-1");
     $this->assertNoFieldChecked("edit-card-1-$langcode-2");
@@ -89,7 +89,7 @@ class OptionsWidgetsTestCase extends Fie
     $this->assertFieldValues($entity_init, 'card_1', $langcode, array(0));
 
     // Check that the selected button is checked.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid .'/edit');
     $this->assertFieldChecked("edit-card-1-$langcode-0");
     $this->assertNoFieldChecked("edit-card-1-$langcode-1");
     $this->assertNoFieldChecked("edit-card-1-$langcode-2");
@@ -104,7 +104,7 @@ class OptionsWidgetsTestCase extends Fie
     field_update_field($this->card_1);
     $instance['required'] = TRUE;
     field_update_instance($instance);
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid .'/edit');
     $this->assertFieldChecked("edit-card-1-$langcode-99");
   }
 
@@ -134,7 +134,7 @@ class OptionsWidgetsTestCase extends Fie
     field_test_entity_save($entity);
 
     // Display form: with no field data, nothing is checked.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid .'/edit');
     $this->assertNoFieldChecked("edit-card-2-$langcode-0");
     $this->assertNoFieldChecked("edit-card-2-$langcode-1");
     $this->assertNoFieldChecked("edit-card-2-$langcode-2");
@@ -150,7 +150,7 @@ class OptionsWidgetsTestCase extends Fie
     $this->assertFieldValues($entity_init, 'card_2', $langcode, array(0, 2));
 
     // Display form: check that the right options are selected.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid .'/edit');
     $this->assertFieldChecked("edit-card-2-$langcode-0");
     $this->assertNoFieldChecked("edit-card-2-$langcode-1");
     $this->assertFieldChecked("edit-card-2-$langcode-2");
@@ -165,7 +165,7 @@ class OptionsWidgetsTestCase extends Fie
     $this->assertFieldValues($entity_init, 'card_2', $langcode, array(0));
 
     // Display form: check that the right options are selected.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid .'/edit');
     $this->assertFieldChecked("edit-card-2-$langcode-0");
     $this->assertNoFieldChecked("edit-card-2-$langcode-1");
     $this->assertNoFieldChecked("edit-card-2-$langcode-2");
@@ -194,7 +194,7 @@ class OptionsWidgetsTestCase extends Fie
     field_update_field($this->card_2);
     $instance['required'] = TRUE;
     field_update_instance($instance);
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid .'/edit');
     $this->assertFieldChecked("edit-card-2-$langcode-99");
   }
 
@@ -221,7 +221,7 @@ class OptionsWidgetsTestCase extends Fie
     field_test_entity_save($entity);
 
     // Display form: with no field data, nothing is selected.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid .'/edit');
     $this->assertNoOptionSelected("edit-card-1-$langcode", 0);
     $this->assertNoOptionSelected("edit-card-1-$langcode", 1);
     $this->assertNoOptionSelected("edit-card-1-$langcode", 2);
@@ -233,20 +233,20 @@ class OptionsWidgetsTestCase extends Fie
     $this->assertFieldValues($entity_init, 'card_1', $langcode, array(0));
 
     // Display form: check that the right options are selected.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid .'/edit');
     $this->assertOptionSelected("edit-card-1-$langcode", 0);
     $this->assertNoOptionSelected("edit-card-1-$langcode", 1);
     $this->assertNoOptionSelected("edit-card-1-$langcode", 2);
 
     // Submit form: Unselect the option.
     $edit = array("card_1[$langcode]" => '_none');
-    $this->drupalPost('test-entity/' . $entity->ftid .'/edit', $edit, t('Save'));
+    $this->drupalPost('test-entity/manage/' . $entity->ftid .'/edit', $edit, t('Save'));
     $this->assertFieldValues($entity_init, 'card_1', $langcode, array());
 
     // A required select list does not have an empty key.
     $instance['required'] = TRUE;
     field_update_instance($instance);
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid .'/edit');
     $this->assertFalse($this->xpath('//select[@id=:id]//option[@value=""]', array(':id' => 'edit-card-1-' . $langcode)), t('A required select list does not have an empty key.'));
 
     // We do not have to test that a required select list with one option is
@@ -261,7 +261,7 @@ class OptionsWidgetsTestCase extends Fie
     field_update_instance($instance);
 
     // Display form: with no field data, nothing is selected
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid .'/edit');
     $this->assertNoOptionSelected("edit-card-1-$langcode", 0);
     $this->assertNoOptionSelected("edit-card-1-$langcode", 1);
     $this->assertNoOptionSelected("edit-card-1-$langcode", 2);
@@ -274,14 +274,14 @@ class OptionsWidgetsTestCase extends Fie
     $this->assertFieldValues($entity_init, 'card_1', $langcode, array(0));
 
     // Display form: check that the right options are selected.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid .'/edit');
     $this->assertOptionSelected("edit-card-1-$langcode", 0);
     $this->assertNoOptionSelected("edit-card-1-$langcode", 1);
     $this->assertNoOptionSelected("edit-card-1-$langcode", 2);
 
     // Submit form: Unselect the option.
     $edit = array("card_1[$langcode]" => '_none');
-    $this->drupalPost('test-entity/' . $entity->ftid .'/edit', $edit, t('Save'));
+    $this->drupalPost('test-entity/manage/' . $entity->ftid .'/edit', $edit, t('Save'));
     $this->assertFieldValues($entity_init, 'card_1', $langcode, array());
   }
 
@@ -308,7 +308,7 @@ class OptionsWidgetsTestCase extends Fie
     field_test_entity_save($entity);
 
     // Display form: with no field data, nothing is selected.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid .'/edit');
     $this->assertNoOptionSelected("edit-card-2-$langcode", 0);
     $this->assertNoOptionSelected("edit-card-2-$langcode", 1);
     $this->assertNoOptionSelected("edit-card-2-$langcode", 2);
@@ -320,7 +320,7 @@ class OptionsWidgetsTestCase extends Fie
     $this->assertFieldValues($entity_init, 'card_2', $langcode, array(0, 2));
 
     // Display form: check that the right options are selected.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid .'/edit');
     $this->assertOptionSelected("edit-card-2-$langcode", 0);
     $this->assertNoOptionSelected("edit-card-2-$langcode", 1);
     $this->assertOptionSelected("edit-card-2-$langcode", 2);
@@ -331,7 +331,7 @@ class OptionsWidgetsTestCase extends Fie
     $this->assertFieldValues($entity_init, 'card_2', $langcode, array(0));
 
     // Display form: check that the right options are selected.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid .'/edit');
     $this->assertOptionSelected("edit-card-2-$langcode", 0);
     $this->assertNoOptionSelected("edit-card-2-$langcode", 1);
     $this->assertNoOptionSelected("edit-card-2-$langcode", 2);
@@ -351,18 +351,18 @@ class OptionsWidgetsTestCase extends Fie
     // Check that the 'none' option has no efect if actual options are selected
     // as well.
     $edit = array("card_2[$langcode][]" => array('_none' => '_none', 0 => 0));
-    $this->drupalPost('test-entity/' . $entity->ftid .'/edit', $edit, t('Save'));
+    $this->drupalPost('test-entity/manage/' . $entity->ftid .'/edit', $edit, t('Save'));
     $this->assertFieldValues($entity_init, 'card_2', $langcode, array(0));
 
     // Check that selecting the 'none' option empties the field.
     $edit = array("card_2[$langcode][]" => array('_none' => '_none'));
-    $this->drupalPost('test-entity/' . $entity->ftid .'/edit', $edit, t('Save'));
+    $this->drupalPost('test-entity/manage/' . $entity->ftid .'/edit', $edit, t('Save'));
     $this->assertFieldValues($entity_init, 'card_2', $langcode, array());
 
     // A required select list does not have an empty key.
     $instance['required'] = TRUE;
     field_update_instance($instance);
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid .'/edit');
     $this->assertFalse($this->xpath('//select[@id=:id]//option[@value=""]', array(':id' => 'edit-card-2-' . $langcode)), t('A required select list does not have an empty key.'));
 
     // We do not have to test that a required select list with one option is
@@ -378,7 +378,7 @@ class OptionsWidgetsTestCase extends Fie
     field_update_instance($instance);
 
     // Display form: with no field data, nothing is selected.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid .'/edit');
     $this->assertNoOptionSelected("edit-card-2-$langcode", 0);
     $this->assertNoOptionSelected("edit-card-2-$langcode", 1);
     $this->assertNoOptionSelected("edit-card-2-$langcode", 2);
@@ -391,14 +391,14 @@ class OptionsWidgetsTestCase extends Fie
     $this->assertFieldValues($entity_init, 'card_2', $langcode, array(0));
 
     // Display form: check that the right options are selected.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid .'/edit');
     $this->assertOptionSelected("edit-card-2-$langcode", 0);
     $this->assertNoOptionSelected("edit-card-2-$langcode", 1);
     $this->assertNoOptionSelected("edit-card-2-$langcode", 2);
 
     // Submit form: Unselect the option.
     $edit = array("card_2[$langcode][]" => array('_none' => '_none'));
-    $this->drupalPost('test-entity/' . $entity->ftid .'/edit', $edit, t('Save'));
+    $this->drupalPost('test-entity/manage/' . $entity->ftid .'/edit', $edit, t('Save'));
     $this->assertFieldValues($entity_init, 'card_2', $langcode, array());
   }
 
@@ -425,7 +425,7 @@ class OptionsWidgetsTestCase extends Fie
     field_test_entity_save($entity);
 
     // Display form: with no field data, option is unchecked.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid .'/edit');
     $this->assertNoFieldChecked("edit-bool-$langcode");
     $this->assertRaw('Some dangerous &amp; unescaped <strong>markup</strong>', t('Option text was properly filtered.'));
 
@@ -435,7 +435,7 @@ class OptionsWidgetsTestCase extends Fie
     $this->assertFieldValues($entity_init, 'bool', $langcode, array(0));
 
     // Display form: check that the right options are selected.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid .'/edit');
     $this->assertFieldChecked("edit-bool-$langcode");
 
     // Submit form: uncheck the option.
@@ -444,7 +444,7 @@ class OptionsWidgetsTestCase extends Fie
     $this->assertFieldValues($entity_init, 'bool', $langcode, array(1));
 
     // Display form: with 'off' value, option is unchecked.
-    $this->drupalGet('test-entity/' . $entity->ftid .'/edit');
+    $this->drupalGet('test-entity/manage/' . $entity->ftid .'/edit');
     $this->assertNoFieldChecked("edit-bool-$langcode");
   }
 }
Index: modules/field/modules/text/text.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/modules/text/text.test,v
retrieving revision 1.26
diff -u -p -r1.26 text.test
--- modules/field/modules/text/text.test	5 Aug 2010 23:53:37 -0000	1.26
+++ modules/field/modules/text/text.test	16 Aug 2010 15:27:22 -0000
@@ -115,7 +115,7 @@ class TextFieldTestCase extends DrupalWe
       "{$this->field_name}[$langcode][0][value]" => $value,
     );
     $this->drupalPost(NULL, $edit, t('Save'));
-    preg_match('|test-entity/(\d+)/edit|', $this->url, $match);
+    preg_match('|test-entity/manage/(\d+)/edit|', $this->url, $match);
     $id = $match[1];
     $this->assertRaw(t('test_entity @id has been created.', array('@id' => $id)), t('Entity was created'));
 
@@ -184,7 +184,7 @@ class TextFieldTestCase extends DrupalWe
       "{$this->field_name}[$langcode][0][value]" => $value,
     );
     $this->drupalPost(NULL, $edit, t('Save'));
-    preg_match('|test-entity/(\d+)/edit|', $this->url, $match);
+    preg_match('|test-entity/manage/(\d+)/edit|', $this->url, $match);
     $id = $match[1];
     $this->assertRaw(t('test_entity @id has been created.', array('@id' => $id)), t('Entity was created'));
 
@@ -210,7 +210,7 @@ class TextFieldTestCase extends DrupalWe
 
     // Display edition form.
     // We should now have a 'text format' selector.
-    $this->drupalGet('test-entity/' . $id . '/edit');
+    $this->drupalGet('test-entity/manage/' . $id . '/edit');
     $this->assertFieldByName("{$this->field_name}[$langcode][0][value]", '', t('Widget is displayed'));
     $this->assertFieldByName("{$this->field_name}[$langcode][0][format]", '', t('Format selector is displayed'));
 
Index: modules/field/tests/field.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/tests/field.test,v
retrieving revision 1.37
diff -u -p -r1.37 field.test
--- modules/field/tests/field.test	8 Aug 2010 02:18:53 -0000	1.37
+++ modules/field/tests/field.test	16 Aug 2010 15:27:22 -0000
@@ -1259,14 +1259,14 @@ class FieldFormTestCase extends FieldTes
     $value = mt_rand(1, 127);
     $edit = array("{$this->field_name}[$langcode][0][value]" => $value);
     $this->drupalPost(NULL, $edit, t('Save'));
-    preg_match('|test-entity/(\d+)/edit|', $this->url, $match);
+    preg_match('|test-entity/manage/(\d+)/edit|', $this->url, $match);
     $id = $match[1];
     $this->assertRaw(t('test_entity @id has been created.', array('@id' => $id)), 'Entity was created');
     $entity = field_test_entity_test_load($id);
     $this->assertEqual($entity->{$this->field_name}[$langcode][0]['value'], $value, 'Field value was saved');
 
     // Display edit form.
-    $this->drupalGet('test-entity/' . $id . '/edit');
+    $this->drupalGet('test-entity/manage/' . $id . '/edit');
     $this->assertFieldByName("{$this->field_name}[$langcode][0][value]", $value, 'Widget is displayed with the correct default value');
     $this->assertNoField("{$this->field_name}[$langcode][1][value]", 'No extraneous widget is displayed');
 
@@ -1281,7 +1281,7 @@ class FieldFormTestCase extends FieldTes
     // Empty the field.
     $value = '';
     $edit = array("{$this->field_name}[$langcode][0][value]" => $value);
-    $this->drupalPost('test-entity/' . $id . '/edit', $edit, t('Save'));
+    $this->drupalPost('test-entity/manage/' . $id . '/edit', $edit, t('Save'));
     $this->assertRaw(t('test_entity @id has been updated.', array('@id' => $id)), 'Entity was updated');
     $entity = field_test_entity_test_load($id);
     $this->assertIdentical($entity->{$this->field_name}, array(), 'Field was emptied');
@@ -1306,7 +1306,7 @@ class FieldFormTestCase extends FieldTes
     $value = mt_rand(1, 127);
     $edit = array("{$this->field_name}[$langcode][0][value]" => $value);
     $this->drupalPost(NULL, $edit, t('Save'));
-    preg_match('|test-entity/(\d+)/edit|', $this->url, $match);
+    preg_match('|test-entity/manage/(\d+)/edit|', $this->url, $match);
     $id = $match[1];
     $this->assertRaw(t('test_entity @id has been created.', array('@id' => $id)), 'Entity was created');
     $entity = field_test_entity_test_load($id);
@@ -1315,7 +1315,7 @@ class FieldFormTestCase extends FieldTes
     // Edit with missing required value.
     $value = '';
     $edit = array("{$this->field_name}[$langcode][0][value]" => $value);
-    $this->drupalPost('test-entity/' . $id . '/edit', $edit, t('Save'));
+    $this->drupalPost('test-entity/manage/' . $id . '/edit', $edit, t('Save'));
     $this->assertRaw(t('!name field is required.', array('!name' => $this->instance['label'])), 'Required field with no value fails validation');
   }
 
@@ -1384,7 +1384,7 @@ class FieldFormTestCase extends FieldTes
 
     // Submit the form and create the entity.
     $this->drupalPost(NULL, $edit, t('Save'));
-    preg_match('|test-entity/(\d+)/edit|', $this->url, $match);
+    preg_match('|test-entity/manage/(\d+)/edit|', $this->url, $match);
     $id = $match[1];
     $this->assertRaw(t('test_entity @id has been created.', array('@id' => $id)), 'Entity was created');
     $entity = field_test_entity_test_load($id);
@@ -1474,7 +1474,7 @@ class FieldFormTestCase extends FieldTes
     // Create entity with three values.
     $edit = array("{$this->field_name}[$langcode]" => '1, 2, 3');
     $this->drupalPost(NULL, $edit, t('Save'));
-    preg_match('|test-entity/(\d+)/edit|', $this->url, $match);
+    preg_match('|test-entity/manage/(\d+)/edit|', $this->url, $match);
     $id = $match[1];
 
     // Check that the values were saved.
@@ -1482,7 +1482,7 @@ class FieldFormTestCase extends FieldTes
     $this->assertFieldValues($entity_init, $this->field_name, $langcode, array(1, 2, 3));
 
     // Display the form, check that the values are correctly filled in.
-    $this->drupalGet('test-entity/' . $id . '/edit');
+    $this->drupalGet('test-entity/manage/' . $id . '/edit');
     $this->assertFieldByName("{$this->field_name}[$langcode]", '1, 2, 3', t('Widget is displayed.'));
 
     // Submit the form with more values than the field accepts.
@@ -1529,7 +1529,7 @@ class FieldFormTestCase extends FieldTes
     // Create entity.
     $edit = array("{$field_name}[$langcode][0][value]" => 1);
     $this->drupalPost(NULL, $edit, t('Save'));
-    preg_match('|test-entity/(\d+)/edit|', $this->url, $match);
+    preg_match('|test-entity/manage/(\d+)/edit|', $this->url, $match);
     $id = $match[1];
 
     // Check that the default value was saved.
@@ -1539,7 +1539,7 @@ class FieldFormTestCase extends FieldTes
 
     // Create a new revision.
     $edit = array("{$field_name}[$langcode][0][value]" => 2, 'revision' => TRUE);
-    $this->drupalPost('test-entity/' . $id . '/edit', $edit, t('Save'));
+    $this->drupalPost('test-entity/manage/' . $id . '/edit', $edit, t('Save'));
 
     // Check that the new revision has the expected values.
     $entity = field_test_entity_test_load($id);
@@ -2721,7 +2721,7 @@ class FieldTranslationsTestCase extends 
     // Create a new revision.
     $langcode = field_valid_language(NULL);
     $edit = array("{$field_name}[$langcode][0][value]" => $entity->{$field_name}[$langcode][0]['value'], 'revision' => TRUE);
-    $this->drupalPost('test-entity/' . $eid . '/edit', $edit, t('Save'));
+    $this->drupalPost('test-entity/manage/' . $eid . '/edit', $edit, t('Save'));
 
     // Check translation revisions.
     $this->checkTranslationRevisions($eid, $eid, $available_languages);
Index: modules/field/tests/field_test.entity.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/tests/field_test.entity.inc,v
retrieving revision 1.12
diff -u -p -r1.12 field_test.entity.inc
--- modules/field/tests/field_test.entity.inc	17 Jun 2010 13:44:45 -0000	1.12
+++ modules/field/tests/field_test.entity.inc	16 Aug 2010 15:27:22 -0000
@@ -347,7 +347,7 @@ function field_test_entity_form_submit($
   drupal_set_message($message);
 
   if ($entity->ftid) {
-    $form_state['redirect'] = 'test-entity/' . $entity->ftid . '/edit';
+    $form_state['redirect'] = 'test-entity/manage/' . $entity->ftid . '/edit';
   }
   else {
     // Error on save.
Index: modules/field/tests/field_test.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/tests/field_test.module,v
retrieving revision 1.9
diff -u -p -r1.9 field_test.module
--- modules/field/tests/field_test.module	8 Aug 2010 02:18:53 -0000	1.9
+++ modules/field/tests/field_test.module	16 Aug 2010 15:27:22 -0000
@@ -52,10 +52,10 @@ function field_test_menu() {
       'type' => MENU_NORMAL_ITEM,
     );
   }
-  $items['test-entity/%field_test_entity_test/edit'] = array(
+  $items['test-entity/manage/%field_test_entity_test/edit'] = array(
     'title' => 'Edit test entity',
     'page callback' => 'field_test_entity_edit',
-    'page arguments' => array(1),
+    'page arguments' => array(2),
     'access arguments' => array('administer field_test content'),
     'type' => MENU_NORMAL_ITEM,
   );
Index: modules/menu/menu.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/menu/menu.module,v
retrieving revision 1.231
diff -u -p -r1.231 menu.module
--- modules/menu/menu.module	1 Aug 2010 23:33:18 -0000	1.231
+++ modules/menu/menu.module	16 Aug 2010 12:47:34 -0000
@@ -702,7 +702,7 @@ function menu_form_node_type_form_alter(
   $form['menu']['menu_options'] = array(
     '#type' => 'checkboxes',
     '#title' => t('Available menus'),
-    '#default_value' => variable_get('menu_options_' . $type->type, array('main-menu' => 'main-menu')),
+    '#default_value' => variable_get('menu_options_' . $type->type, array('main-menu')),
     '#options' => $menu_options,
     '#description' => t('The menus available to place links in for this content type.'),
   );
Index: modules/menu/menu.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/menu/menu.test,v
retrieving revision 1.38
diff -u -p -r1.38 menu.test
--- modules/menu/menu.test	5 Aug 2010 23:53:38 -0000	1.38
+++ modules/menu/menu.test	16 Aug 2010 15:27:22 -0000
@@ -112,14 +112,14 @@ class MenuTestCase extends DrupalWebTest
 
     // Assert the new menu.
     $this->drupalGet('admin/structure/menu/manage/' . $menu_name . '/edit');
-    $this->assertText($title, t('Custom menu was added.'));
+    $this->assertRaw($title, t('Custom menu was added.'));
 
     // Edit the menu.
     $new_title = $this->randomName(16);
     $menu['title'] = $new_title;
     menu_save($menu);
     $this->drupalGet('admin/structure/menu/manage/' . $menu_name . '/edit');
-    $this->assertText($new_title, t('Custom menu was edited.'));
+    $this->assertRaw($new_title, t('Custom menu was edited.'));
   }
 
   /**
@@ -626,3 +626,247 @@ class MenuNodeTestCase extends DrupalWeb
     $this->assertNoLink($node_title);
   }
 }
+
+/**
+ * Menu breadcrumbs related tests.
+ */
+class MenuBreadcrumbTestCase extends DrupalWebTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Breadcrumbs',
+      'description' => 'Tests breadcrumbs functionality.',
+      'group' => 'Menu',
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+    $perms = array_keys(module_invoke_all('permission'));
+    $this->admin_user = $this->drupalCreateUser($perms);
+    $this->drupalLogin($this->admin_user);
+  }
+
+  /**
+   * Tests breadcrumbs on node and administrative paths.
+   */
+  function testBreadCrumbs() {
+    // Prepare common base breadcrumb elements.
+    $home = array('<front>' => 'Home');
+    $admin = $home + array('admin' => t('Administer'));
+    $dashboard = $home + array('admin' => t('Dashboard'));
+    $config = $dashboard + array('admin/config' => t('Configuration'));
+    $type = 'article';
+
+    // Verify Taxonomy administration breadcrumbs.
+    $expected = $dashboard + array(
+      'admin/structure' => t('Structure'),
+    );
+    $this->assertBreadcrumb('admin/structure/taxonomy', $expected);
+
+    $expected += array(
+      'admin/structure' => t('Structure'),
+      'admin/structure/taxonomy' => t('Taxonomy'),
+    );
+    $this->assertBreadcrumb('admin/structure/taxonomy/tags', $expected);
+    $expected += array(
+      'admin/structure/taxonomy/tags' => t('Tags'),
+    );
+    $this->assertBreadcrumb('admin/structure/taxonomy/tags/edit', $expected);
+    $this->assertBreadcrumb('admin/structure/taxonomy/tags/fields', $expected);
+    $this->assertBreadcrumb('admin/structure/taxonomy/tags/add', $expected);
+
+    // Verify Node administration breadcrumbs.
+    $expected = $dashboard + array(
+      'admin/structure' => t('Structure'),
+      'admin/structure/types' => t('Content types'),
+    );
+    $this->assertBreadcrumb('admin/structure/types/add', $expected);
+    $this->assertBreadcrumb("admin/structure/types/manage/$type", $expected);
+    $expected += array(
+      'admin/structure/types/manage/$type' => t('Article'),
+    );
+    $this->assertBreadcrumb("admin/structure/types/manage/$type/fields", $expected);
+    $this->assertBreadcrumb("admin/structure/types/manage/$type/display", $expected);
+    $this->assertBreadcrumb("admin/structure/types/manage/$type/display/teaser", $expected);
+    $this->assertBreadcrumb("admin/structure/types/manage/$type/comment/fields", $expected);
+    $this->assertBreadcrumb("admin/structure/types/manage/$type/comment/display", $expected);
+    $this->assertBreadcrumb("admin/structure/types/manage/$type/delete", $expected);
+    $expected += array(
+      'admin/structure/types/manage/$type/fields' => t('Manage fields'),
+    );
+    $this->assertBreadcrumb("admin/structure/types/manage/$type/fields/body", $expected);
+    $expected += array(
+      'admin/structure/types/manage/$type/fields/body' => t('Body'),
+    );
+    $this->assertBreadcrumb("admin/structure/types/manage/$type/fields/body/widget-type", $expected);
+
+    // Verify Filter text format administration breadcrumbs.
+    $format = db_query_range("SELECT format, name FROM {filter_format}", 1, 1)->fetch();
+    $format_id = $format->format;
+    $expected = $config + array(
+      'admin/config/content' => t('Content authoring'),
+    );
+    $this->assertBreadcrumb('admin/config/content/formats', $expected);
+
+    $expected += array(
+      'admin/config/content/formats' => t('Text formats'),
+    );
+    $this->assertBreadcrumb('admin/config/content/formats/add', $expected);
+    $this->assertBreadcrumb("admin/config/content/formats/$format_id", $expected);
+    $expected += array(
+      "admin/config/content/formats/$format_id" => check_plain($format->name),
+    );
+    $this->assertBreadcrumb("admin/config/content/formats/$format_id/delete", $expected);
+
+    // Verify node breadcrumbs (without menu link).
+    $node1 = $this->drupalCreateNode();
+    $nid1 = $node1->nid;
+    $expected = $home;
+    $this->assertBreadcrumb("node/$nid1", $expected);
+    $expected += array(
+      "node/$nid1" => check_plain($node1->title),
+    );
+    $this->assertBreadcrumb("node/$nid1/edit", $expected);
+
+    // Verify that node listing page still contains "Home" only.
+    $expected = array();
+    $this->assertBreadcrumb('node', $expected);
+
+    // Verify node breadcrumbs (in menu).
+    // Do this separately for Main menu and Navigation menu, since only the
+    // latter is a preferred menu by default.
+    // @todo Also test all themes? Manually testing led to the suspicion that
+    //   breadcrumbs may differ, possibly due to template.php overrides.
+    $menus = array('main-menu', 'navigation');
+    // Alter node type menu settings.
+    variable_set("menu_options_$type", $menus);
+    variable_set("menu_parent_$type", 'navigation:0');
+
+    foreach ($menus as $menu) {
+      // Create a parent node in the current menu.
+      $title = $this->randomString();
+      $node2 = $this->drupalCreateNode(array(
+        'type' => $type,
+        'title' => $title,
+        'menu' => array(
+          'enabled' => 1,
+          'link_title' => 'Parent ' . $title,
+          'description' => '',
+          'menu_name' => $menu,
+          'plid' => 0,
+        ),
+      ));
+      $nid2 = $node2->nid;
+
+      $expected = $home;
+      $this->assertBreadcrumb("node/$nid2", $expected);
+      $expected += array(
+        "node/$nid2" => check_plain($node2->menu['link_title']),
+      );
+      $this->assertBreadcrumb("node/$nid2/edit", $expected);
+
+      // Create a child node in the current menu.
+      $title = $this->randomString();
+      $node3 = $this->drupalCreateNode(array(
+        'type' => $type,
+        'title' => $title,
+        'menu' => array(
+          'enabled' => 1,
+          'link_title' => 'Child ' . $title,
+          'description' => '',
+          'menu_name' => $menu,
+          'plid' => $node2->menu['mlid'],
+        ),
+      ));
+      $nid3 = $node3->nid;
+
+      $this->assertBreadcrumb("node/$nid3", $expected);
+      $expected += array(
+        "node/$nid3" => check_plain($node3->menu['link_title']),
+      );
+      $this->assertBreadcrumb("node/$nid3/edit", $expected);
+
+      // Verify that node listing page still contains "Home" only.
+      $expected = array();
+      $this->assertBreadcrumb('node', $expected);
+
+      if ($menu == 'navigation') {
+        $parent = $node2;
+        $child = $node3;
+      }
+    }
+
+    // Create a Navigation menu link for 'node', move the last parent node menu
+    // link below it, and verify a full breadcrumb for the last child node.
+    $menu = 'navigation';
+    $edit = array(
+      'link_title' => 'Root',
+      'link_path' => 'node',
+    );
+    $this->drupalPost("admin/structure/menu/manage/$menu/add", $edit, t('Save'));
+    $link = db_query('SELECT * FROM {menu_links} WHERE link_title = :title', array(':title' => 'Root'))->fetchAssoc();
+    $edit = array(
+      'menu[parent]' => $link['menu_name'] . ':' . $link['mlid'],
+    );
+    $this->drupalPost("node/{$parent->nid}/edit", $edit, t('Save'));
+    $expected = $home + array(
+      "node" => check_plain($link['link_title']),
+    );
+    $this->assertBreadcrumb(NULL, $expected);
+    $expected += array(
+      "node/{$parent->nid}" => check_plain($parent->menu['link_title']),
+    );
+    $this->assertBreadcrumb("node/{$child->nid}", $expected);
+
+    // @todo Add a taxonomy term + Navigation menu link, verify expected BC.
+    // @todo Add a Navigation menu link for $this->admin_user, verify expected BC.
+  }
+
+  /**
+   * Assert that a given path shows certain breadcrumb links.
+   *
+   * @param string $goto
+   *   A system path to pass to DrupalWebTestCase::drupalGet().
+   * @param array $links
+   *   An associative array whose keys are expected breadcrumb link paths and
+   *   whose values are expected breadcrumb link texts (sanitized).
+   */
+  protected function assertBreadcrumb($goto, $links) {
+    if (isset($goto)) {
+      $this->drupalGet($goto);
+    }
+    // Compare paths with actual breadcrumb.
+    $parts = $this->getParts();
+    $pass = TRUE;
+    foreach ($links as $path => $title) {
+      $url = url($path);
+      $part = array_shift($parts);
+      $pass = ($pass && $part['href'] === $url && $part['text'] === $title);
+    }
+    // No parts must be left, or an expected "Home" will always pass.
+    $pass = ($pass && empty($parts));
+
+    $this->assertTrue($pass, t('Breadcrumb !parts found on @path.', array(
+      '!parts' => implode(' » ', $links),
+      '@path' => $goto,
+    )));
+  }
+
+  /**
+   * Returns the breadcrumb contents of the current page in the internal browser.
+   */
+  protected function getParts() {
+    $parts = array();
+    $elements = $this->xpath('//div[@class="breadcrumb"]/a');
+    if (!empty($elements)) {
+      foreach ($elements as $element) {
+        $parts[] = array(
+          'text' => (string) $element,
+          'href' => (string) $element['href'],
+          'title' => (string) $element['title'],
+        );
+      }
+    }
+    return $parts;
+  }
+}
Index: modules/node/content_types.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/content_types.inc,v
retrieving revision 1.116
diff -u -p -r1.116 content_types.inc
--- modules/node/content_types.inc	8 Aug 2010 13:02:37 -0000	1.116
+++ modules/node/content_types.inc	15 Aug 2010 23:21:04 -0000
@@ -323,6 +323,7 @@ function node_type_form_submit($form, &$
     return;
   }
 
+  form_state_values_clean($form_state);
   $variables = $form_state['values'];
 
   // Remove everything that's been saved already - whatever's left is assumed
@@ -333,8 +334,6 @@ function node_type_form_submit($form, &$
     }
   }
 
-  unset($variables['form_token'], $variables['op'], $variables['submit'], $variables['delete'], $variables['reset'], $variables['form_id'], $variables['form_build_id']);
-
   // Save or reset persistent variable values.
   foreach ($variables as $key => $value) {
     $variable_new = $key . '_' . $type->type;
Index: modules/taxonomy/taxonomy.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.test,v
retrieving revision 1.88
diff -u -p -r1.88 taxonomy.test
--- modules/taxonomy/taxonomy.test	8 Aug 2010 02:06:56 -0000	1.88
+++ modules/taxonomy/taxonomy.test	16 Aug 2010 15:27:22 -0000
@@ -545,7 +545,7 @@ class TaxonomyTermTestCase extends Taxon
     // the first edit link found on the listing page is to our term.
     $this->clickLink(t('edit'));
 
-    $this->assertText($edit['name'], t('The randomly generated term name is present.'));
+    $this->assertRaw($edit['name'], t('The randomly generated term name is present.'));
     $this->assertText($edit['description[value]'], t('The randomly generated term description is present.'));
 
     $edit = array(
@@ -919,7 +919,7 @@ class TaxonomyTermFieldTestCase extends 
       "{$this->field_name}[$langcode]" => array($term->tid),
     );
     $this->drupalPost(NULL, $edit, t('Save'));
-    preg_match('|test-entity/(\d+)/edit|', $this->url, $match);
+    preg_match('|test-entity/manage/(\d+)/edit|', $this->url, $match);
     $id = $match[1];
     $this->assertRaw(t('test_entity @id has been created.', array('@id' => $id)), t('Entity was created'));
 
