Index: modules/blogapi/blogapi.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/blogapi/blogapi.module,v
retrieving revision 1.155
diff -u -p -r1.155 blogapi.module
--- modules/blogapi/blogapi.module	12 Jun 2009 08:39:35 -0000	1.155
+++ modules/blogapi/blogapi.module	15 Jun 2009 13:36:48 -0000
@@ -582,12 +582,10 @@ function blogapi_mt_validate_terms($node
     $found_terms = array();
     if (!empty($node->taxonomy)) {
       $term_list = array_unique($node->taxonomy);
-      $params = $term_list;
-      $params[] = $node->type;
-      $result = db_query(db_rewrite_sql("SELECT t.tid, t.vid FROM {taxonomy_term_data} t INNER JOIN {taxonomy_vocabulary_node_type} n ON t.vid = n.vid WHERE t.tid IN (" . db_placeholders($term_list) . ") AND n.type = '%s'", 't', 'tid'), $params);
+      $terms = taxonomy_term_load_multiple($term_list, array('type' => $node->type));
       $found_terms = array();
       $found_count = 0;
-      while ($term = db_fetch_object($result)) {
+      foreach ($terms as $term) {
         $found_terms[$term->vid][$term->tid] = $term->tid;
         $found_count++;
       }
@@ -597,9 +595,9 @@ function blogapi_mt_validate_terms($node
       }
     }
     // Look up all the vocabularies for this node type.
-    $result2 = db_query(db_rewrite_sql("SELECT v.vid, v.name, v.required, v.multiple FROM {taxonomy_vocabulary} v INNER JOIN {taxonomy_vocabulary_node_type} n ON v.vid = n.vid WHERE n.type = '%s'", 'v', 'vid'), $node->type);
+    $vocabularies = taxonomy_vocabulary_load_multiple(array(), array('type' => $node->type));
     // Check each vocabulary associated with this node type.
-    while ($vocabulary = db_fetch_object($result2)) {
+    foreach ($vocabularies as $vocabulary) {
       // Required vocabularies must have at least one term.
       if ($vocabulary->required && empty($found_terms[$vocabulary->vid])) {
         return blogapi_error(t('A category from the @vocabulary_name vocabulary is required.', array('@vocabulary_name' => $vocabulary->name)));
Index: modules/blogapi/blogapi.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/blogapi/blogapi.test,v
retrieving revision 1.12
diff -u -p -r1.12 blogapi.test
--- modules/blogapi/blogapi.test	12 Jun 2009 13:59:56 -0000	1.12
+++ modules/blogapi/blogapi.test	15 Jun 2009 13:36:48 -0000
@@ -22,16 +22,14 @@ class BlogAPITestCase extends DrupalWebT
    */
   function testBlogAPI() {
     global $base_url;
+    // Create user.
+    $web_user = $this->drupalCreateUser(array('create blog content', 'delete own blog content', 'edit own blog content', 'administer content with blog api'));
     // Create admin user and taxonomy for later use.
     $admin_user = $this->drupalCreateUser(array('administer taxonomy'));
     $this->drupalLogin($admin_user);
     $vid = $this->addVocabulary('simpletest_vocab');
-    $term = $this->addTerm($vid, 'simpletest_term1');
-    $this->drupalLogout();
-
-    // Create user.
-    $web_user = $this->drupalCreateUser(array('create blog content', 'delete own blog content', 'edit own blog content', 'administer content with blog api'));
-    $this->drupalLogin($web_user);
+    $term_1 = $this->addTerm($vid, 'simpletest_term1');
+    $term_2 = $this->addTerm($vid, 'simpletest_term2');
 
     // Init common variables.
     $local = url($base_url . '/xmlrpc.php', array('external' => TRUE));
@@ -61,8 +59,9 @@ class BlogAPITestCase extends DrupalWebT
     if ($result !== FALSE && array_key_exists('title', $result[0])) {
       $this->assertEqual($content, $result[0]['title'], t('Post found.'));
     }
-    else
-      $this->assertTrue(false, 'Post found.');
+    else {
+      $this->fail(t('Post found.'));
+    }
 
     // Edit post.
     $content_new = $this->randomName(10);
@@ -86,7 +85,7 @@ class BlogAPITestCase extends DrupalWebT
     $this->assertEqual($this->drupalGetContent(), $file_contents, t('Uploaded contents verified.'));
 
     // Set post categories.
-    $categories = array(array('categoryId' => $term));
+    $categories = array(array('categoryId' => $term_1));
     $result = xmlrpc($local, 'mt.setPostCategories', $nid, $web_user->name, $web_user->pass_raw, $categories);
     $this->assertTrue($result, t('Post categories set.'));
 
@@ -94,10 +93,35 @@ class BlogAPITestCase extends DrupalWebT
     $result = xmlrpc($local, 'mt.getPostCategories', $nid, $web_user->name, $web_user->pass_raw);
     $this->assertTrue($result, t('Category list successfully retrieved.'));
 
-    if ($result !== FALSE && array_key_exists('categoryId', $result[0])) {
-      $this->assertEqual($term, $result[0]['categoryId'], t('Category list verified.'));
+    if ($result !== FALSE && isset($result[0]['categoryId'])) {
+      $this->assertEqual($term_1, $result[0]['categoryId'], t('Category list verified.'));
     }
-
+    // Test validation of category assignment.
+    // Set post categories.
+    $categories[] = array('categoryId' => $term_2);
+    $result = xmlrpc($local, 'mt.setPostCategories', $nid, $web_user->name, $web_user->pass_raw, $categories);
+    $this->assertFalse($result, t('Post categories fail validation (attempt to post two when one is allowed).'));
+    // Change to required.
+    $this->updateVocabulary($vid, 'simpletest_vocab1', FALSE, TRUE);
+    $result = xmlrpc($local, 'mt.setPostCategories', $nid, $web_user->name, $web_user->pass_raw, array());
+    $this->assertFalse($result, t("Post categories fail validation (none posted when it's required)."));
+    // Change to allowing multiple, not required.
+    $this->updateVocabulary($vid, 'simpletest_vocab1', TRUE, FALSE);
+    $result = xmlrpc($local, 'mt.setPostCategories', $nid, $web_user->name, $web_user->pass_raw, $categories);
+    $this->assertTrue($result, t('Post categories pass validation (multiple allowed).'));
+    $result = xmlrpc($local, 'mt.setPostCategories', $nid, $web_user->name, $web_user->pass_raw, array());
+    $this->assertTrue($result, t('Post categories pass validation (multiple allowed, none posted).'));
+    // Change to multiple, but required.
+    $this->updateVocabulary($vid, 'simpletest_vocab1', TRUE, TRUE);
+    $result = xmlrpc($local, 'mt.setPostCategories', $nid, $web_user->name, $web_user->pass_raw, $categories);
+    $this->assertTrue($result, t('Post categories pass validation (multiple allowed).'));
+    $result = xmlrpc($local, 'mt.setPostCategories', $nid, $web_user->name, $web_user->pass_raw, array());
+    $this->assertFalse($result, t("Post categories fail validation (none posted when it's required)."));
+    // Try to add a non-existent term.
+    $categories[] = array('categoryId' => $term_2 + 1);
+    $result = xmlrpc($local, 'mt.setPostCategories', $nid, $web_user->name, $web_user->pass_raw, $categories);
+    $this->assertFalse($result, t('Post categories fail validation (unknown term).'));
+ 
     // Delete post.
     $result = xmlrpc($local, 'blogger.deletePost', $appid, $nid, $web_user->name, $web_user->pass_raw, TRUE);
     $this->assertTrue($result, t('Post successfully deleted.'));
@@ -124,6 +148,22 @@ class BlogAPITestCase extends DrupalWebT
 
     return $vocabulary->vid;
   }
+  /**
+   * Update a taxonomy vocabulary.
+   *
+   * @param  $vocab
+   *   Vocabulary name.
+   * @return integer
+   *   The vocab ID.
+   */
+  function updateVocabulary($vid, $vocab, $multiple = FALSE, $required = FALSE) {
+    $vocabulary = taxonomy_vocabulary_load($vid);
+    $vocabulary->name = $vocab;
+    $vocabulary->nodes = array('blog' => 'blog');
+    $vocabulary->multiple = $multiple;
+    $vocabulary->required = $required;
+    taxonomy_vocabulary_save($vocabulary);
+  }
 
   /**
    * Add a taxonomy term to vocabulary.
Index: modules/taxonomy/taxonomy.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.module,v
retrieving revision 1.478
diff -u -p -r1.478 taxonomy.module
--- modules/taxonomy/taxonomy.module	12 Jun 2009 13:59:56 -0000	1.478
+++ modules/taxonomy/taxonomy.module	15 Jun 2009 13:36:49 -0000
@@ -1250,10 +1250,11 @@ function taxonomy_vocabulary_load_multip
     $query
       ->fields('v')
       ->orderBy('v.weight')
-      ->orderBy('v.name');
+      ->orderBy('v.name')
+      ->addTag('vocabulary_access');
 
     if (!empty($type)) {
-      $query->leftJoin('taxonomy_vocabulary_node_type', 'n', 'v.vid = n.vid AND n.type  = :type', array(':type' => $type));
+      $query->join('taxonomy_vocabulary_node_type', 'n', 'v.vid = n.vid AND n.type = :type', array(':type' => $type));
     }
     else {
       $query->leftJoin('taxonomy_vocabulary_node_type', 'n', 'v.vid = n.vid');
@@ -1357,6 +1358,13 @@ function taxonomy_terms_load($str_tids) 
 function taxonomy_term_load_multiple($tids = array(), $conditions = array()) {
   $term_cache = &drupal_static(__FUNCTION__, array());
 
+  // Node type associations are not stored in the taxonomy_term_data table, so
+  // remove this from conditions into it's own variable.
+  if (isset($conditions['type'])) {
+    $type = $conditions['type'];
+    unset($conditions['type']);
+  }
+
   $terms = array();
 
   // Create a new variable which is either a prepared version of the $tids
@@ -1401,14 +1409,20 @@ function taxonomy_term_load_multiple($ti
     $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');
+    $query
+      ->fields('t', $taxonomy_term_data)
+      ->addTag('term_access');
 
     // If the $tids array is populated, add those to the query.
     if ($tids) {
       $query->condition('t.tid', $tids, 'IN');
     }
 
+    if (!empty($type)) {
+      $query->join('taxonomy_vocabulary_node_type', 'n', 't.vid = n.vid AND n.type = :type', array(':type' => $type));
+    }
+
     // If the conditions array is populated, add those to the query.
     if ($conditions) {
       // When name is passed as a condition use LIKE.
