Index: CHANGELOG.txt
===================================================================
RCS file: /cvs/drupal/drupal/CHANGELOG.txt,v
retrieving revision 1.313
diff -u -p -r1.313 CHANGELOG.txt
--- CHANGELOG.txt	8 Jun 2009 05:00:11 -0000	1.313
+++ CHANGELOG.txt	11 Jun 2009 11:36:46 -0000
@@ -109,7 +109,7 @@ Drupal 7.0, xxxx-xx-xx (development vers
     * Modules can declare RDF namespaces which are serialized in the <html> tag
       for RDFa support.
 - Field API:
-    * Custom data fields may be attached to nodes and users in Drupal.
+    * Custom data fields may be attached to nodes, users and taxonomy terms in Drupal.
     * In addition, any other object type may register with Field API
       and allow custom data fields to be attached to itself.
     * Provides a subset of the features of the Content Construction
Index: modules/blogapi/blogapi.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/blogapi/blogapi.test,v
retrieving revision 1.11
diff -u -p -r1.11 blogapi.test
--- modules/blogapi/blogapi.test	4 May 2009 10:38:47 -0000	1.11
+++ modules/blogapi/blogapi.test	11 Jun 2009 11:36:47 -0000
@@ -112,24 +112,17 @@ class BlogAPITestCase extends DrupalWebT
    *   The vocab ID.
    */
   function addVocabulary($vocab) {
-    $edit = array();
-    $edit['name'] = $vocab;
-    $edit['nodes[blog]'] = TRUE;
-    $this->drupalPost('admin/content/taxonomy/add', $edit, t('Save'));
-    $this->assertRaw(t('Created new vocabulary %vocab.', array('%vocab' => $edit['name'])), t('Taxonomy vocabulary added.'));
+    // Create a vocabulary.
+    $vocabulary = new stdClass();
+    $vocabulary->name = $vocab;
+    $vocabulary->description = $this->randomName();
+    $vocabulary->machine_name = $this->randomName();
+    $vocabulary->help = '';
+    $vocabulary->nodes = array('blog' => 'blog');
+    $vocabulary->weight = mt_rand(0, 10);
+    taxonomy_vocabulary_save($vocabulary);
 
-    $vocab_arr = taxonomy_get_vocabularies();
-    $vid = NULL;
-    foreach ($vocab_arr as $vocab_item) {
-      if ($vocab_item->name == $vocab) {
-        $vid = $vocab_item->vid;
-        break;
-      }
-    }
-
-    $this->assertNotNull($vid, t('Vocabulary found in database.'));
-
-    return $vid;
+    return $vocabulary->vid;
   }
 
   /**
@@ -142,23 +135,11 @@ class BlogAPITestCase extends DrupalWebT
    * @return integer
    *   The Term ID.
    */
-  function addTerm($vid, $term) {
-    $edit = array();
-    $edit['name'] = $term;
-    $this->drupalPost('admin/content/taxonomy/' . $vid . '/add', $edit, t('Save'));
-    $this->assertRaw(t('Created new term %term.', array('%term' => $edit['name'])), t('Taxonomy term added.'));
-
-    $tree = taxonomy_get_tree($vid);
-    $tid = NULL;
-    foreach ($tree as $tree_term) {
-      if ($tree_term->name == $term) {
-        $tid = $tree_term->tid;
-        break;
-      }
-    }
-
-    $this->assertNotNull($tid, t('Term found in database.'));
-
-    return $tid;
+  function addTerm($vid, $term_name) {
+    $term = new stdClass();
+    $term->name = $term_name;
+    $term->vid = $vid;
+    taxonomy_term_save($term);
+    return $term->tid;
   }
 }
Index: modules/forum/forum.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/forum/forum.test,v
retrieving revision 1.19
diff -u -p -r1.19 forum.test
--- modules/forum/forum.test	24 May 2009 17:39:32 -0000	1.19
+++ modules/forum/forum.test	11 Jun 2009 11:36:52 -0000
@@ -126,6 +126,7 @@ class ForumTestCase extends DrupalWebTes
     $edit = array(
       'name' => $title,
       'description' => $description,
+      'machine_name' => drupal_strtolower($this->randomName()),
       'help' => '',
     );
 
Index: modules/taxonomy/taxonomy.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.admin.inc,v
retrieving revision 1.53
diff -u -p -r1.53 taxonomy.admin.inc
--- modules/taxonomy/taxonomy.admin.inc	4 Jun 2009 03:33:29 -0000	1.53
+++ modules/taxonomy/taxonomy.admin.inc	11 Jun 2009 11:37:02 -0000
@@ -102,11 +102,13 @@ function theme_taxonomy_overview_vocabul
  * @see taxonomy_form_vocabulary_submit()
  */
 function taxonomy_form_vocabulary(&$form_state, $edit = array()) {
+  drupal_add_js(drupal_get_path('module', 'taxonomy') . '/vocabulary.js');
   if (!is_array($edit)) {
     $edit = (array)$edit;
   }
   $edit += array(
     'name' => '',
+    'machine_name' => '',
     'description' => '',
     'help' => '',
     'nodes' => array(),
@@ -117,6 +119,7 @@ function taxonomy_form_vocabulary(&$form
     'required' => 0,
     'weight' => 0,
   );
+  $form['#vocabulary'] = (object) $edit;
   // Check whether we need a deletion confirmation form.
   if (isset($form_state['confirm_delete']) && isset($form_state['values']['vid'])) {
     return taxonomy_vocabulary_confirm_delete($form_state, $form_state['values']['vid']);
@@ -128,6 +131,15 @@ function taxonomy_form_vocabulary(&$form
     '#maxlength' => 255,
     '#description' => t('The name for this vocabulary, e.g., <em>"Tags"</em>.'),
     '#required' => TRUE,
+    '#field_suffix' => ' <small id="vocabulary-name-suffix">&nbsp;</small>',
+  );
+  $form['machine_name'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Machine readable name'),
+    '#default_value' => $edit['machine_name'],
+    '#maxlength' => 255,
+    '#description' => t('The unique machine readable name for this vocabulary, used for theme templates, can only contain lowercase letters, numbers and underscores.'),
+    '#required' => TRUE,
   );
   $form['help'] = array(
     '#type' => 'textfield',
@@ -194,9 +206,33 @@ function taxonomy_form_vocabulary(&$form
 }
 
 /**
+ * Validation handler for the vocabulary form.
+ *
+ * @see taxonomy_form_vocabulary()
+ */
+function taxonomy_form_vocabulary_validate($form, &$form_state) {
+  if ($form_state['clicked_button']['#value'] != t('Delete') && isset($form_state['values']['machine_name'])) {
+
+    // Restrict machine names to appropriate characters.
+    $machine_name = $form_state['values']['machine_name'];
+    if (!preg_match('!^[a-z0-9_]+$!', $form_state['values']['machine_name'])) {
+      form_set_error('machine_name', t('The machine-readable name must contain only lowercase letters, numbers, and underscores.'));
+    }
+
+    // Do not allow duplicate machine names.
+    $vocabularies = taxonomy_get_vocabularies();
+    foreach ($vocabularies as $vocabulary) {
+      if ($machine_name == $vocabulary->machine_name && (!(isset($form_state['values']['vid']) && $vocabulary->vid != $form_state['values']['vid']))) {
+        form_set_error('machine_name', t('This machine-readable name is already in use by another vocabulary and must be unique.'));
+      }
+    }
+  }
+}
+/**
  * Accept the form submission for a vocabulary and save the results.
  */
 function taxonomy_form_vocabulary_submit($form, &$form_state) {
+  $old_vocabulary = $form['#vocabulary'];
   if ($form_state['clicked_button']['#value'] == t('Delete')) {
     // Rebuild the form to confirm vocabulary deletion.
     $form_state['rebuild'] = TRUE;
@@ -206,6 +242,9 @@ function taxonomy_form_vocabulary_submit
   // Fix up the nodes array to remove unchecked nodes.
   $form_state['values']['nodes'] = array_filter($form_state['values']['nodes']);
   $vocabulary = (object) $form_state['values'];
+  if ($vocabulary->machine_name != $old_vocabulary->machine_name) {
+    field_attach_rename_bundle($old_vocabulary->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)));
@@ -636,15 +675,22 @@ function taxonomy_form_term(&$form_state
   $edit += array(
     'name' => '',
     'description' => '',
+    'vocabulary_machine_name' => $vocabulary->machine_name,
     'tid' => NULL,
     'weight' => 0,
   );
 
+  // Take into account multi-step rebuilding.
+  if (isset($form_state['term'])) {
+    $edit = $form_state['term'] + $edit;
+  }
+
   $parent = array_keys(taxonomy_get_parents($edit['tid']));
   $form['#term'] = $edit;
   $form['#term']['parent'] = $parent;
   $form['#vocabulary'] = $vocabulary;
   $form['#vocabulary']->nodes = drupal_map_assoc($vocabulary->nodes);
+  $form['#builder_function'] = 'taxonomy_form_term_submit_builder';
 
   // Check for confirmation forms.
   if (isset($form_state['confirm_delete'])) {
@@ -672,6 +718,14 @@ function taxonomy_form_term(&$form_state
     '#default_value' => $edit['description'],
     '#description' => t('A description of the term. To be displayed on taxonomy/term pages and RSS feeds.'));
 
+  $form['vocabulary_machine_name'] = array(
+    '#type' => 'textfield',
+    '#access' => FALSE,
+    '#value' => isset($edit['vocabulary_machine_name']) ? $edit['vocabulary_machine_name'] : $vocabulary->name,
+  );
+
+  field_attach_form('taxonomy_term', (object) $edit, $form, $form_state);
+
   $form['advanced'] = array(
     '#type' => 'fieldset',
     '#title' => t('Advanced options'),
@@ -731,11 +785,14 @@ function taxonomy_form_term(&$form_state
 }
 
 /**
- * Validation handler for the term edit form. Ensure numeric weight values.
+ * Validation handler for the term form.
  *
  * @see taxonomy_form_term()
  */
 function taxonomy_form_term_validate($form, &$form_state) {
+  field_attach_form_validate('taxonomy_term', (object) $form_state['values'], $form, $form_state);
+
+  // Ensure numeric values.
   if (isset($form_state['values']['weight']) && !is_numeric($form_state['values']['weight'])) {
     form_set_error('weight', t('Weight value must be numeric.'));
   }
@@ -764,7 +821,8 @@ function taxonomy_form_term_submit($form
     return;
   }
 
-  $term = (object) $form_state['values'];
+  $term = taxonomy_form_term_submit_builder($form, $form_state);
+
   $status = taxonomy_term_save($term);
   switch ($status) {
     case SAVED_NEW:
@@ -805,6 +863,19 @@ function taxonomy_form_term_submit($form
 }
 
 /**
+ * Build a term by processing form values and prepare for a form rebuild.
+ */
+function taxonomy_form_term_submit_builder($form, &$form_state) {
+  $term = (object) $form_state['values'];
+  field_attach_submit('taxonomy_term', $term, $form, $form_state);
+
+  $form_state['term'] = (array)$term;
+  $form_state['rebuild'] = TRUE;
+
+  return $term;
+}
+
+/**
  * Form builder for the confirmation of multiple term parents.
  *
  * @ingroup forms
@@ -836,6 +907,7 @@ function taxonomy_term_confirm_delete(&$
   $form['type'] = array('#type' => 'value', '#value' => 'term');
   $form['name'] = array('#type' => 'value', '#value' => $term->name);
   $form['tid'] = array('#type' => 'value', '#value' => $tid);
+  $form['vocabulary_machine_name'] = array('#type' => 'value', '#value' => $term->vocabulary_machine_name);
   $form['delete'] = array('#type' => 'value', '#value' => TRUE);
   return confirm_form($form,
                   t('Are you sure you want to delete the term %title?',
Index: modules/taxonomy/taxonomy.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.install,v
retrieving revision 1.18
diff -u -p -r1.18 taxonomy.install
--- modules/taxonomy/taxonomy.install	1 Jun 2009 22:07:10 -0000	1.18
+++ modules/taxonomy/taxonomy.install	11 Jun 2009 11:37:02 -0000
@@ -226,6 +226,13 @@ function taxonomy_schema() {
         'default' => '',
         'description' => 'Name of the vocabulary.',
       ),
+      'machine_name' => array(
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+        'description' => 'The vocabulary machine name.',
+      ),
       'description' => array(
         'type' => 'text',
         'not null' => FALSE,
@@ -345,3 +352,29 @@ function taxonomy_update_7001() {
 
   return $ret;
 }
+
+/**
+ * Add vocabulary machine_name column.
+ */
+function taxonomy_update_7002() {
+  $ret = array();
+  $field = array(
+    'type' => 'varchar',
+    'length' => 255,
+    'not null' => TRUE,
+    'default' => '',
+    'description' => 'The vocabulary machine name.',
+  );
+
+  db_add_field($ret, 'taxonomy_vocabulary', 'machine_name', $field);
+
+  foreach (taxonomy_get_vocabularies() as $vid => $vocabulary) {
+    $machine_name = 'vocabulary_' . $vid;
+    db_update('taxonomy_vocabulary')
+      ->fields(array('machine_name' => 'vocabulary_' . $vid))
+      ->condition('vid', $vid)
+      ->execute();
+    field_attach_create_bundle($machine_name);
+  }
+  return $ret;
+}
Index: modules/taxonomy/taxonomy.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.module,v
retrieving revision 1.477
diff -u -p -r1.477 taxonomy.module
--- modules/taxonomy/taxonomy.module	5 Jun 2009 05:23:57 -0000	1.477
+++ modules/taxonomy/taxonomy.module	11 Jun 2009 11:37:03 -0000
@@ -19,6 +19,36 @@ function taxonomy_perm() {
 }
 
 /**
+ * Implement hook_fieldable_info().
+ */
+function taxonomy_fieldable_info() {
+  $return = array(
+    'taxonomy_term' => array(
+      'name' => t('Taxonomy term'),
+      'id key' => 'tid',
+      'bundle key' => 'vocabulary_machine_name',
+      'bundles' => taxonomy_vocabulary_machine_names(),
+    ),
+  );
+  return $return;
+}
+
+/**
+ * Implement hook_field_build_modes();
+ *
+ * @TODO: build mode for display as a field (when attached to nodes etc.).
+ */
+function taxonomy_field_build_modes($obj_type) {
+  $modes = array();
+  if ($obj_type == 'term') {
+    $modes = array(
+      'full' => t('Taxonomy term page'),
+    );
+  }
+  return $modes;
+}
+
+/**
  * Implement hook_theme().
  */
 function taxonomy_theme() {
@@ -259,6 +289,7 @@ function taxonomy_vocabulary_save($vocab
       }
       $query->execute();
     }
+    field_attach_create_bundle($vocabulary->machine_name);
     module_invoke_all('taxonomy_vocabulary_insert', $vocabulary);
   }
 
@@ -290,6 +321,7 @@ function taxonomy_vocabulary_delete($vid
     taxonomy_term_delete($tid);
   }
 
+  field_attach_delete_bundle($vocabulary['machine_name']);
   module_invoke_all('taxonomy', 'delete', 'vocabulary', $vocabulary);
 
   cache_clear_all();
@@ -352,13 +384,21 @@ function taxonomy_term_save($term) {
     // Prevent leading and trailing spaces in term names.
     $term->name = trim($term->name);
   }
+  if (!isset($term->vocabulary_machine_name)) {
+    $vocabulary = taxonomy_vocabulary_load($term->vid);
+    $term->vocabulary_machine_name = $vocabulary->machine_name;
+  }
+
+  field_attach_presave('taxonomy_term', $term);
 
   if (!empty($term->tid) && $term->name) {
     $status = drupal_write_record('taxonomy_term_data', $term, 'tid');
+    field_attach_update('taxonomy_term', $term);
     module_invoke_all('taxonomy_term_insert', $term);
   }
   else {
     $status = drupal_write_record('taxonomy_term_data', $term);
+    field_attach_insert('taxonomy_term', $term);
     module_invoke_all('taxonomy_term_update', $term);
   }
 
@@ -484,6 +524,7 @@ function taxonomy_term_delete($tid) {
         ->condition('tid', $tid)
         ->execute();
 
+      field_attach_delete('taxonomy_term', $term);
       module_invoke_all('taxonomy_term_delete', $term);
     }
 
@@ -571,6 +612,21 @@ function taxonomy_get_vocabularies($type
 }
 
 /**
+ * Get machine names for all taxonomy vocabularies.
+ *
+ * @return
+ *   An array of machine names.
+ */
+function taxonomy_vocabulary_machine_names() {
+  $machine_names = array();
+  $vocabularies = taxonomy_get_vocabularies();
+  foreach ($vocabularies as $vocabulary) {
+    $machine_names[] = $vocabulary->machine_name;
+  }
+  return $machine_names;
+}
+
+/**
  * Implement hook_form_alter().
  * Generate a form for selecting terms to associate with a node.
  * We check for taxonomy_override_selector before loading the full
@@ -786,6 +842,7 @@ function taxonomy_node_save($node, $term
     unset($terms['tags']);
 
     foreach ($typed_input as $vid => $vid_value) {
+      $vocabulary = taxonomy_vocabulary_load($vid);
       $typed_terms = drupal_explode_tags($vid_value);
 
       $inserted = array();
@@ -801,7 +858,11 @@ function taxonomy_node_save($node, $term
         }
 
         if (!$typed_term_tid) {
-          $edit = array('vid' => $vid, 'name' => $typed_term);
+          $edit = array(
+            'vid' => $vid,
+            'name' => $typed_term,
+            'vocabulary_machine_name' => $vocabulary->machine_name,
+          );
           $term = (object)$edit;
           $status = taxonomy_term_save($term);
           $typed_term_tid = $term->tid;
@@ -1321,7 +1382,7 @@ function taxonomy_term_load_multiple($ti
 
   // Remove any loaded terms from the array if they don't match $conditions.
   if ($conditions) {
-    // Name matching is case insensitive, note that with some collations 
+    // Name matching is case insensitive, note that with some collations
     // LOWER() and drupal_strtolower() may return different results.
     foreach ($terms as $term) {
       $term_values = (array) $term;
@@ -1338,8 +1399,10 @@ function taxonomy_term_load_multiple($ti
   // $tids still to load, or if $conditions was passed without $tids.
   if ($tids || ($conditions && !$passed_tids)) {
     $query = db_select('taxonomy_term_data', 't');
+    $query->join('taxonomy_vocabulary', 'v', 't.vid = v.vid');
     $taxonomy_term_data = drupal_schema_fields_sql('taxonomy_term_data');
     $query->fields('t', $taxonomy_term_data);
+    $query->addField('v', 'machine_name', 'vocabulary_machine_name');
 
     // If the $tids array is populated, add those to the query.
     if ($tids) {
@@ -1358,9 +1421,14 @@ function taxonomy_term_load_multiple($ti
       }
     }
     $queried_terms = $query->execute()->fetchAllAssoc('tid');
-    // Invoke hook_taxonomy_term_load() on the terms loaded from the database
-    // and add them to the static cache.
+
     if (!empty($queried_terms)) {
+
+      // Attach fields.
+      field_attach_load('taxonomy_term', $queried_terms);
+
+      // Invoke hook_taxonomy_term_load() and add the term objects to the
+      // static cache.
       foreach (module_implements('taxonomy_term_load') as $module) {
         $function = $module . '_taxonomy_term_load';
         $function($queried_terms);
Index: modules/taxonomy/taxonomy.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.pages.inc,v
retrieving revision 1.28
diff -u -p -r1.28 taxonomy.pages.inc
--- modules/taxonomy/taxonomy.pages.inc	24 May 2009 17:39:35 -0000	1.28
+++ modules/taxonomy/taxonomy.pages.inc	11 Jun 2009 11:37:03 -0000
@@ -50,9 +50,11 @@ function taxonomy_term_page($terms, $dep
           drupal_add_css(drupal_get_path('module', 'taxonomy') . '/taxonomy.css');
 
           $build = array();
-          // Only display the description if we have a single term, to avoid clutter and confusion.
+          // Only display fields if we have a single term, to avoid clutter and
+          // confusion.
           if (count($tids) == 1) {
             $term = taxonomy_term_load($tids[0]);
+            $build += field_attach_view('taxonomy_term', $term);
             if (!empty($term->description)) {
               $build['term_description'] = array(
                 '#markup' => filter_xss_admin($term->description),
Index: modules/taxonomy/taxonomy.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.test,v
retrieving revision 1.33
diff -u -p -r1.33 taxonomy.test
--- modules/taxonomy/taxonomy.test	5 Jun 2009 05:23:58 -0000	1.33
+++ modules/taxonomy/taxonomy.test	11 Jun 2009 11:37:04 -0000
@@ -19,6 +19,7 @@ class TaxonomyWebTestCase extends Drupal
     $vocabulary = new stdClass();
     $vocabulary->name = $this->randomName();
     $vocabulary->description = $this->randomName();
+    $vocabulary->machine_name = drupal_strtolower($this->randomName());
     $vocabulary->help = '';
     $vocabulary->nodes = array('article' => 'article');
     $vocabulary->weight = mt_rand(0, 10);
@@ -29,10 +30,10 @@ class TaxonomyWebTestCase extends Drupal
   /**
    * Returns a new term with random properties in vocabulary $vid.
    */
-  function createTerm($vid) {
+  function createTerm($vocabulary) {
     $term = new stdClass();
     $term->name = $this->randomName();
-    $term->vid = $vid;
+    $term->vid = $vocabulary->vid;
     taxonomy_term_save($term);
     return $term;
   }
@@ -70,6 +71,7 @@ class TaxonomyVocabularyFunctionalTest e
     $edit = array();
     $edit['name'] = $this->randomName();
     $edit['description'] = $this->randomName();
+    $edit['machine_name'] = drupal_strtolower($this->randomName());
     $edit['help'] = $this->randomName();
     $edit['nodes[article]'] = 'article';
     $edit['tags'] = 1;
@@ -84,10 +86,19 @@ class TaxonomyVocabularyFunctionalTest e
     $this->clickLink(t('edit vocabulary'));
     $edit = array();
     $edit['name'] = $this->randomName();
+    $edit['machine_name'] = drupal_strtolower($this->randomName());
     $this->drupalPost(NULL, $edit, t('Save'));
-    $this->assertRaw(t('Updated vocabulary %name.', array('%name' => $edit['name'])));
     $this->drupalGet('admin/content/taxonomy');
     $this->assertText($edit['name'], t('Vocabulary found in the vocabulary overview listing.'));
+
+    // Try to submit a vocabulary with a duplicate machine name.
+    $this->drupalPost('admin/content/taxonomy/add', $edit, t('Save'));
+    $this->assertText(t('This machine-readable name is already in use by another vocabulary and must be unique.'), t('Duplicate machine name validation was successful'));
+
+    // Try to submit an invalid machine name.
+    $edit['machine_name'] = '!&^%';
+    $this->drupalPost('admin/content/taxonomy/add', $edit, t('Save'));
+    $this->assertText(t('The machine-readable name must contain only lowercase letters, numbers, and underscores.'));
   }
 
   /**
@@ -125,13 +136,11 @@ class TaxonomyVocabularyFunctionalTest e
     // Delete all vocabularies.
     $vocabularies = taxonomy_get_vocabularies();
     foreach ($vocabularies as $key => $vocabulary) {
-      $edit = array();
-      $this->drupalPost('admin/content/taxonomy/' . $vocabulary->vid, $edit, t('Delete'));
-      // Submit the confirm form for deletion.
-      $this->drupalPost(NULL, NULL, t('Delete'));
+      taxonomy_vocabulary_delete($key);
     }
     // Confirm that no vocabularies are found in the database.
     $this->assertFalse(taxonomy_get_vocabularies(), t('No vocabularies found in the database'));
+    $this->drupalGet('admin/content/taxonomy');
     // Check the default message for no vocabularies.
     $this->assertText(t('No vocabularies available.'), t('No vocabularies were found.'));
   }
@@ -143,6 +152,7 @@ class TaxonomyVocabularyFunctionalTest e
     // Create a vocabulary.
     $edit = array(
       'name' => $this->randomName(),
+      'machine_name' => drupal_strtolower($this->randomName()),
       'nodes[article]' => 'article',
     );
     $this->drupalPost('admin/content/taxonomy/add', $edit, t('Save'));
@@ -257,6 +267,12 @@ class TaxonomyVocabularyUnitTest extends
     $vocabulary3->weight = 2;
     taxonomy_vocabulary_save($vocabulary3);
 
+    // Fetch the machine names for all vocabularies.
+    $machine_names = taxonomy_vocabulary_machine_names();
+    $this->assertTrue(in_array($vocabulary1->machine_name, $machine_names));
+    $this->assertTrue(in_array($vocabulary2->machine_name, $machine_names));
+    $this->assertTrue(in_array($vocabulary3->machine_name, $machine_names));
+
     // Fetch all of the vocabularies using taxonomy_get_vocabularies().
     // Confirm that the vocabularies are ordered by weight.
     $vocabularies = taxonomy_get_vocabularies();
@@ -306,9 +322,9 @@ class TaxonomyTermUnitTest extends Taxon
   function testTaxonomyTermCountNodes() {
     // Create a vocabulary with three terms.
     $vocabulary = $this->createVocabulary();
-    $term1 = $this->createTerm($vocabulary->vid);
-    $term2 = $this->createTerm($vocabulary->vid);
-    $term3 = $this->createTerm($vocabulary->vid);
+    $term1 = $this->createTerm($vocabulary);
+    $term2 = $this->createTerm($vocabulary);
+    $term3 = $this->createTerm($vocabulary);
 
     // Attach term1 to a node.
     $node1 = $this->drupalCreateNode(array('type' => 'page'));
@@ -396,8 +412,8 @@ class TaxonomyTermTestCase extends Taxon
    */
   function testTaxonomyTermRelations() {
     // Create two taxonomy terms.
-    $term1 = $this->createTerm($this->vocabulary->vid);
-    $term2 = $this->createTerm($this->vocabulary->vid);
+    $term1 = $this->createTerm($this->vocabulary);
+    $term2 = $this->createTerm($this->vocabulary);
 
     // Edit $term1 and add $term2 as a relationship.
     $edit = array();
@@ -406,7 +422,7 @@ class TaxonomyTermTestCase extends Taxon
     $related = taxonomy_get_related($term1->tid);
     $this->assertTrue(isset($related[$term2->tid]), t('Related term was found'));
     // Create a third term.
-    $term3 = $this->createTerm($this->vocabulary->vid);
+    $term3 = $this->createTerm($this->vocabulary);
     $edit['relations[]'] = $term3->tid;
     $this->drupalPost('taxonomy/term/' . $term1->tid . '/edit', $edit, t('Save'));
 
@@ -420,7 +436,7 @@ class TaxonomyTermTestCase extends Taxon
    */
   function testTaxonomySynonyms() {
     // Create a taxonomy term with one synonym.
-    $term = $this->createTerm($this->vocabulary->vid);
+    $term = $this->createTerm($this->vocabulary);
     $term->synonyms = $this->randomName();
     taxonomy_term_save($term);
 
@@ -439,8 +455,8 @@ class TaxonomyTermTestCase extends Taxon
    */
   function testTaxonomyTermHierarchy() {
     // Create two taxonomy terms.
-    $term1 = $this->createTerm($this->vocabulary->vid);
-    $term2 = $this->createTerm($this->vocabulary->vid);
+    $term1 = $this->createTerm($this->vocabulary);
+    $term2 = $this->createTerm($this->vocabulary);
 
     // Edit $term2, setting $term1 as parent.
     $edit = array();
@@ -454,7 +470,7 @@ class TaxonomyTermTestCase extends Taxon
     $this->assertTrue(isset($parents[$term1->tid]), t('Parent found correctly.'));
 
     // Create a third term and save this as a parent of term2.
-    $term3 = $this->createTerm($this->vocabulary->vid);
+    $term3 = $this->createTerm($this->vocabulary);
     $term2->parent = array($term1->tid, $term3->tid);
     taxonomy_term_save($term2);
     $parents = taxonomy_get_parents($term2->tid);
@@ -468,8 +484,8 @@ class TaxonomyTermTestCase extends Taxon
    */
   function testTaxonomyNode() {
     // Create two taxonomy terms.
-    $term1 = $this->createTerm($this->vocabulary->vid);
-    $term2 = $this->createTerm($this->vocabulary->vid);
+    $term1 = $this->createTerm($this->vocabulary);
+    $term2 = $this->createTerm($this->vocabulary);
 
     // Post an article.
     $edit = array();
@@ -580,7 +596,7 @@ class TaxonomyTermTestCase extends Taxon
    * Test taxonomy_get_term_by_name().
    */
   function testTaxonomyGetTermByName() {
-    $term = $this->createTerm($this->vocabulary->vid);
+    $term = $this->createTerm($this->vocabulary);
 
     // Load the term with the exact name.
     $terms = taxonomy_get_term_by_name($term->name);
@@ -639,7 +655,7 @@ class TaxonomyLoadMultipleUnitTest exten
     $i = 0;
     while ($i < 5) {
       $i++;
-      $this->createTerm($vocabulary->vid);
+      $this->createTerm($vocabulary);
     }
     // Load the terms from the vocabulary.
     $terms = taxonomy_term_load_multiple(NULL, array('vid' => $vocabulary->vid));
@@ -667,7 +683,7 @@ class TaxonomyLoadMultipleUnitTest exten
     $this->assertFalse(isset($terms4[$deleted->tid]));
 
     // Create a single term and load it by name.
-    $term = $this->createTerm($vocabulary->vid);
+    $term = $this->createTerm($vocabulary);
     $loaded_terms = taxonomy_term_load_multiple(array(), array('name' => $term->name));
     $this->assertEqual(count($loaded_terms), 1, t('One term was loaded'));
     $loaded_term = reset($loaded_terms);
@@ -678,7 +694,7 @@ class TaxonomyLoadMultipleUnitTest exten
 /**
  * Tests for taxonomy hook invocation.
  */
-class TaxonomyHooksTestCase extends DrupalWebTestCase {
+class TaxonomyHooksTestCase extends TaxonomyWebTestCase {
   public static function getInfo() {
     return array(
       'name' => t('Taxonomy term hooks'),
@@ -697,18 +713,14 @@ class TaxonomyHooksTestCase extends Drup
    * Test that hooks are run correctly on creating, editing and deleting a term.
    */
   function testTaxonomyTermHooks() {
-    // Create a taxonomy vocabulary.
-    $edit = array(
-      'name' => $this->randomName(),
-    );
-    $this->drupalPost('admin/content/taxonomy/add', $edit, t('Save'));
+    $vocabulary = $this->createVocabulary();
 
     // Create a term with one antonym.
     $edit = array(
       'name' => $this->randomName(),
       'antonyms' => 'Long',
     );
-    $this->drupalPost('admin/content/taxonomy/1/add', $edit, t('Save'));
+    $this->drupalPost('admin/content/taxonomy/' . $vocabulary->vid . '/add', $edit, t('Save'));
     $term = reset(taxonomy_get_term_by_name($edit['name']));
     $this->assertEqual($term->antonyms[0], $edit['antonyms'], t('Antonyms were loaded into the term object'));
 
Index: profiles/default/default.profile
===================================================================
RCS file: /cvs/drupal/drupal/profiles/default/default.profile,v
retrieving revision 1.46
diff -u -p -r1.46 default.profile
--- profiles/default/default.profile	4 Jun 2009 20:09:29 -0000	1.46
+++ profiles/default/default.profile	11 Jun 2009 11:37:04 -0000
@@ -203,6 +203,7 @@ function default_profile_tasks(&$task, $
   $vid = db_insert('taxonomy_vocabulary')->fields(array(
     'name' => 'Tags',
     'description' => $description,
+    'machine_name' => 'tags',
     'help' => $help,
     'relations' => 0,
     'hierarchy' => 0,
