? .git
? .gitignore
? 876762-36_taxonomy_update_machine.patch
? 876762-42_taxonomy_update_machine.patch
? taxonomy_update_machine_name-876762-31.patch
? sites/all/modules/devel
? sites/default/files
? sites/default/settings.php
Index: modules/field/tests/field_test.storage.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/tests/field_test.storage.inc,v
retrieving revision 1.7
diff -u -p -r1.7 field_test.storage.inc
--- modules/field/tests/field_test.storage.inc	26 Sep 2010 23:31:35 -0000	1.7
+++ modules/field/tests/field_test.storage.inc	10 Oct 2010 20:17:22 -0000
@@ -453,10 +453,9 @@ function field_test_field_attach_rename_
 /**
  * Implements hook_field_attach_delete_bundle().
  */
-function field_test_field_attach_delete_bundle($bundle, $instances) {
+function field_test_field_attach_delete_bundle($entity_type, $bundle, $instances) {
   $data = _field_test_storage_data();
 
-  $instances = field_info_instances($bundle);
   foreach ($instances as $field_name => $instance) {
     $field = field_info_field($field_name);
     if ($field['storage']['type'] == 'field_test_storage') {
Index: modules/taxonomy/taxonomy.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.admin.inc,v
retrieving revision 1.111
diff -u -p -r1.111 taxonomy.admin.inc
--- modules/taxonomy/taxonomy.admin.inc	6 Oct 2010 13:38:40 -0000	1.111
+++ modules/taxonomy/taxonomy.admin.inc	10 Oct 2010 20:17:22 -0000
@@ -163,6 +163,10 @@ function taxonomy_form_vocabulary($form,
       'js' => array(drupal_get_path('module', 'system') . '/system.js', $js_settings),
     ),
   );
+  $form['old_machine_name'] = array(
+    '#type' => 'value',
+    '#value' => $vocabulary->machine_name,
+  );
   $form['description'] = array(
     '#type' => 'textfield',
     '#title' => t('Description'),
@@ -223,12 +227,10 @@ function taxonomy_form_vocabulary_submit
     $form_state['confirm_delete'] = TRUE;
     return;
   }
-  $old_machine_name = $form_state['vocabulary']->machine_name;
+
   $vocabulary = $form_state['vocabulary'];
   entity_form_submit_build_entity('taxonomy_vocabulary', $vocabulary, $form, $form_state);
-  if ($vocabulary->machine_name != $old_machine_name) {
-    field_attach_rename_bundle('taxonomy_term', $old_machine_name, $vocabulary->machine_name);
-  }
+
   switch (taxonomy_vocabulary_save($vocabulary)) {
     case SAVED_NEW:
       drupal_set_message(t('Created new vocabulary %name.', array('%name' => $vocabulary->name)));
Index: modules/taxonomy/taxonomy.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.module,v
retrieving revision 1.609
diff -u -p -r1.609 taxonomy.module
--- modules/taxonomy/taxonomy.module	3 Oct 2010 01:15:33 -0000	1.609
+++ modules/taxonomy/taxonomy.module	10 Oct 2010 20:17:22 -0000
@@ -374,11 +374,14 @@ function taxonomy_admin_vocabulary_title
  * Save a vocabulary given a vocabulary object.
  */
 function taxonomy_vocabulary_save($vocabulary) {
-
+  // Prevent leading and trailing spaces in vocabulary names.
   if (!empty($vocabulary->name)) {
-    // Prevent leading and trailing spaces in vocabulary names.
     $vocabulary->name = trim($vocabulary->name);
   }
+  // For existing vocabularies, make sure we can detect machine name changes.
+  if (!empty($vocabulary->vid) && !isset($vocabulary->old_machine_name)) {
+    $vocabulary->old_machine_name = db_query("SELECT machine_name FROM {taxonomy_vocabulary} WHERE vid = :vid", array(':vid' => $vocabulary->vid))->fetchField();
+  }
 
   if (!isset($vocabulary->module)) {
     $vocabulary->module = 'taxonomy';
@@ -388,6 +391,9 @@ function taxonomy_vocabulary_save($vocab
 
   if (!empty($vocabulary->vid) && !empty($vocabulary->name)) {
     $status = drupal_write_record('taxonomy_vocabulary', $vocabulary, 'vid');
+    if ($vocabulary->old_machine_name != $vocabulary->machine_name) {
+      field_attach_rename_bundle('taxonomy_term', $vocabulary->old_machine_name, $vocabulary->machine_name);
+    }
     module_invoke_all('taxonomy_vocabulary_update', $vocabulary);
     module_invoke_all('entity_update', $vocabulary, 'taxonomy_vocabulary');
   }
@@ -434,6 +440,31 @@ function taxonomy_vocabulary_delete($vid
 }
 
 /**
+ * Implements hook_field_attach_rename_bundle().
+ */
+function taxonomy_field_attach_rename_bundle($entity_type, $bundle_old, $bundle_new) {
+  if ($entity_type == 'taxonomy_term') {
+    // Reflect machine name changes in the definitions of existing 'taxonomy'
+    // fields.
+    $fields = field_read_fields();
+    foreach ($fields as $field_name => $field) {
+      $update = FALSE;
+      if ($field['type'] == 'taxonomy_term_reference') {
+        foreach ($field['settings']['allowed_values'] as $key => &$value) {
+          if ($value['vocabulary'] == $bundle_old) {
+            $value['vocabulary'] = $bundle_new;
+            $update = TRUE;
+          }
+        }
+        if ($update) {
+          field_update_field($field);
+        }
+      }
+    }
+  }
+}
+
+/**
  * Dynamically check and update the hierarchy flag of a vocabulary.
  *
  * Checks the current parents of all terms in a vocabulary and updates the
Index: modules/taxonomy/taxonomy.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.test,v
retrieving revision 1.93
diff -u -p -r1.93 taxonomy.test
--- modules/taxonomy/taxonomy.test	1 Oct 2010 01:37:13 -0000	1.93
+++ modules/taxonomy/taxonomy.test	10 Oct 2010 20:17:22 -0000
@@ -192,7 +192,7 @@ class TaxonomyVocabularyUnitTest extends
   }
 
   function setUp() {
-    parent::setUp('taxonomy');
+    parent::setUp('taxonomy', 'field_test');
     $admin_user = $this->drupalCreateUser(array('create article content', 'administer taxonomy'));
     $this->drupalLogin($admin_user);
     $this->vocabulary = $this->createVocabulary();
@@ -325,6 +325,32 @@ class TaxonomyVocabularyUnitTest extends
     // Fetch vocabulary 1 by name and ID.
     $this->assertTrue(current(taxonomy_vocabulary_load_multiple(array($vocabulary1->vid), array('name' => $vocabulary1->name)))->vid == $vocabulary1->vid, t('Vocabulary loaded successfully by name and ID.'));
   }
+
+  /**
+   * Tests that machine name changes are properly reflected.
+   */
+  function testTaxonomyVocabularyChangeMachineName() {
+    // Add a field instance to the vocabulary.
+    $field = array(
+      'field_name' => 'field_test',
+      'type' => 'test_field',
+    );
+    field_create_field($field);
+    $instance = array(
+      'field_name' => 'field_test',
+      'entity_type' => 'taxonomy_term',
+      'bundle' => $this->vocabulary->machine_name,
+    );
+    field_create_instance($instance);
+
+    // Change the machine name.
+    $new_name = drupal_strtolower($this->randomName());
+    $this->vocabulary->machine_name = $new_name;
+    taxonomy_vocabulary_save($this->vocabulary);
+
+    // Check that the field instance is still attached to the vocabulary.
+    $this->assertTrue(field_info_instance('taxonomy_term', 'field_test', $new_name), t('The bundle name was updated correctly.'));
+  }
 }
 
 /**
@@ -586,7 +612,7 @@ class TaxonomyTermTestCase extends Taxon
     $term->description = '';
     taxonomy_term_save($term);
     $this->drupalGet('taxonomy/term/' . $term->tid);
-    $this->assertNoPattern('|class="term-listing-heading"|', 'Term page did not display the term description when description was blank.');    
+    $this->assertNoPattern('|class="term-listing-heading"|', 'Term page did not display the term description when description was blank.');
 
     // Check that the term feed page is working.
     $this->drupalGet('taxonomy/term/' . $term->tid . '/feed');
@@ -830,15 +856,9 @@ class TaxonomyTermFieldTestCase extends 
     $web_user = $this->drupalCreateUser(array('access field_test content', 'administer field_test content', 'administer taxonomy'));
     $this->drupalLogin($web_user);
     $this->vocabulary = $this->createVocabulary();
-  }
 
-  /**
-   * Test term field validation.
-   */
-  function testTaxonomyTermFieldValidation() {
+    // Setup a field and instance.
     $this->field_name = drupal_strtolower($this->randomName());
-
-    // Create a field with settings to validate.
     $this->field = array(
       'field_name' => $this->field_name,
       'type' => 'taxonomy_term_reference',
@@ -866,7 +886,12 @@ class TaxonomyTermFieldTestCase extends 
       ),
     );
     field_create_instance($this->instance);
+  }
 
+  /**
+   * Test term field validation.
+   */
+  function testTaxonomyTermFieldValidation() {
     // Test valid and invalid values with field_attach_validate().
     $langcode = LANGUAGE_NONE;
     $entity = field_test_create_stub_entity();
@@ -896,38 +921,6 @@ class TaxonomyTermFieldTestCase extends 
    * Test widgets.
    */
   function testTaxonomyTermFieldWidgets() {
-    // Setup a field and instance.
-    $entity_type = 'test_entity';
-    $this->field_name = drupal_strtolower($this->randomName());
-    $this->field = array(
-      'field_name' => $this->field_name,
-      'type' => 'taxonomy_term_reference',
-      'settings' => array(
-        'allowed_values' => array(
-          array(
-            'vocabulary' => $this->vocabulary->machine_name,
-            'parent' => '0',
-          ),
-        ),
-      )
-    );
-    field_create_field($this->field);
-    $this->instance = array(
-      'field_name' => $this->field_name,
-      'entity_type' => 'test_entity',
-      'bundle' => 'test_bundle',
-      'label' => $this->randomName() . '_label',
-      'widget' => array(
-        'type' => 'options_select',
-      ),
-      'display' => array(
-        'full' => array(
-          'type' => 'taxonomy_term_reference_link',
-        ),
-      ),
-    );
-    field_create_instance($this->instance);
-
     // Create a term in the vocabulary.
     $term = $this->createTerm($this->vocabulary);
 
@@ -948,11 +941,45 @@ class TaxonomyTermFieldTestCase extends 
     // Display the object.
     $entity = field_test_entity_test_load($id);
     $entities = array($id => $entity);
-    field_attach_prepare_view($entity_type, $entities, 'full');
-    $entity->content = field_attach_view($entity_type, $entity, 'full');
+    field_attach_prepare_view('test_entity', $entities, 'full');
+    $entity->content = field_attach_view('test_entity', $entity, 'full');
     $this->content = drupal_render($entity->content);
     $this->assertText($term->name, t('Term name is displayed'));
   }
+
+  /**
+   * Tests that vocabulary machine name changes are mirrored in field definitions.
+   */
+  function testTaxonomyTermFieldChangeMachineName() {
+    // Add several entries in the 'allowed_values' setting, to make sure that
+    // they all get updated.
+    $this->field['settings']['allowed_values'] = array(
+      array(
+        'vocabulary' => $this->vocabulary->machine_name,
+        'parent' => '0',
+      ),
+      array(
+        'vocabulary' => $this->vocabulary->machine_name,
+        'parent' => '0',
+      ),
+      array(
+        'vocabulary' => 'foo',
+        'parent' => '0',
+      ),
+    );
+    field_update_field($this->field);
+    // Change the machine name.
+    $new_name = drupal_strtolower($this->randomName());
+    $this->vocabulary->machine_name = $new_name;
+    taxonomy_vocabulary_save($this->vocabulary);
+
+    // Check that the field instance is still attached to the vocabulary.
+    $field = field_info_field($this->field_name);
+    $allowed_values = $field['settings']['allowed_values'];
+    $this->assertEqual($allowed_values[0]['vocabulary'], $new_name, t('Index 0: Machine name was updated correctly.'));
+    $this->assertEqual($allowed_values[1]['vocabulary'], $new_name, t('Index 1: Machine name was updated correctly.'));
+    $this->assertEqual($allowed_values[2]['vocabulary'], 'foo', t('Index 2: Machine name was left untouched.'));
+  }
 }
 
 /**
@@ -1036,7 +1063,7 @@ class TaxonomyTokenReplaceTestCase exten
     $tests['[term:node-count]'] = 0;
     $tests['[term:parent:name]'] = '[term:parent:name]';
     $tests['[term:vocabulary:name]'] = check_plain($this->vocabulary->name);
-    
+
     foreach ($tests as $input => $expected) {
       $output = token_replace($input, array('term' => $term1), array('language' => $language));
       $this->assertFalse(strcmp($output, $expected), t('Sanitized taxonomy term token %token replaced.', array('%token' => $input)));
