Index: taxonomy.php
===================================================================
--- taxonomy.php	(revision 16713)
+++ taxonomy.php	(working copy)
@@ -1498,8 +1498,8 @@
 /**
  * Will unlink the object from the taxonomy or taxonomies.
  *
- * Will remove all relationships between the object and any terms in 
- * a particular taxonomy or taxonomies. Does not remove the term or 
+ * Will remove all relationships between the object and any terms in
+ * a particular taxonomy or taxonomies. Does not remove the term or
  * taxonomy itself.
  *
  * @package WordPress
@@ -1613,8 +1613,8 @@
 	// Clean the relationship caches for all object types using this term
 	$tax_object = get_taxonomy( $taxonomy );
 	foreach ( $tax_object->object_type as $object_type )
-		clean_object_term_cache( $objects, $object_type ); 
-	
+		clean_object_term_cache( $objects, $object_type );
+
 	do_action( 'delete_term_taxonomy', $tt_id );
 	$wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->term_taxonomy WHERE term_taxonomy_id = %d", $tt_id ) );
 	do_action( 'deleted_term_taxonomy', $tt_id );
@@ -1649,24 +1649,29 @@
  * Retrieves the terms associated with the given object(s), in the supplied taxonomies.
  *
  * The following information has to do the $args parameter and for what can be
- * contained in the string or array of that parameter, if it exists.
+ * contained in the string or array of that parameter, if it exists. The arguments
+ * can be:
  *
- * The first argument is called, 'orderby' and has the default value of 'name'.
- * The other value that is supported is 'count'.
+ *  'orderby' The default value is 'name', and the other potential values are
+ *            'count', 'slug', 'term_group','term_order' or 'none'.
  *
- * The second argument is called, 'order' and has the default value of 'ASC'.
- * The only other value that will be acceptable is 'DESC'.
+ *  'order'   The default value of 'ASC', and the other acceptable value is 'DESC'.
  *
- * The final argument supported is called, 'fields' and has the default value of
- * 'all'. There are multiple other options that can be used instead. Supported
- * values are as follows: 'all', 'ids', 'names', and finally
- * 'all_with_object_id'.
+ *  'parent'  There is no default value but if specified it should contain an integer
+ *            value corresponding to the value of the parent field to filter by.
  *
- * The fields argument also decides what will be returned. If 'all' or
- * 'all_with_object_id' is choosen or the default kept intact, then all matching
- * terms objects will be returned. If either 'ids' or 'names' is used, then an
- * array of all matching term ids or term names will be returned respectively.
+ *  'fields'  The default value is 'all' with the other options supported being
+ *            'all', 'ids', 'names', 'id=>name', 'id=>term', 'tt_ids' and
+ *            'all_with_object_id'.
  *
+ * The fields argument also decides what will be returned. If the default is
+ * used or either 'all' or 'all_with_object_id' is specified then all matching
+ * terms objects will be returned. If either 'ids', 'tt_ids' or 'names' is used,
+ * then an array of all matching term ids, undocumented (tt_ids) or term names
+ * will be returned respectively.
+ *
+ * May return duplicate terms when when 'fields' equals 'all_with_object_id'.
+ *
  * @package WordPress
  * @subpackage Taxonomy
  * @since 2.3.0
@@ -1746,23 +1751,43 @@
 		$select_this = 't.term_id';
 	else if ( 'names' == $fields )
 		$select_this = 't.name';
+	else if ( 'id=>name' == $fields )
+		$select_this = 't.term_id,t.name';
+	else if ( 'id=>term' == $fields )
+		$select_this = 't.*';
 	else if ( 'all_with_object_id' == $fields )
 		$select_this = 't.*, tt.*, tr.object_id';
 
-	$query = "SELECT $select_this FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN $wpdb->term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ($taxonomies) AND tr.object_id IN ($object_ids) $orderby $order";
+	$where_parent = (empty($parent) ? '' : " tt.parent={$parent} AND");
+	$distinct = ('all_with_object_id' == $fields ? '' : ' DISTINCT');
 
-	if ( 'all' == $fields || 'all_with_object_id' == $fields ) {
-		$terms = array_merge($terms, $wpdb->get_results($query));
-		update_term_cache($terms);
-	} else if ( 'ids' == $fields || 'names' == $fields ) {
-		$terms = array_merge($terms, $wpdb->get_col($query));
-	} else if ( 'tt_ids' == $fields ) {
-		$terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM $wpdb->term_relationships AS tr INNER JOIN $wpdb->term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ($object_ids) AND tt.taxonomy IN ($taxonomies) $orderby $order");
+	if ( 'tt_ids' == $fields ) {
+		$terms = $wpdb->get_col("SELECT{$distinct} tr.term_taxonomy_id FROM $wpdb->term_relationships AS tr INNER JOIN $wpdb->term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE{$where_parent} tr.object_id IN ($object_ids) AND tt.taxonomy IN ($taxonomies) $orderby $order");
+	} else {
+		$query = "SELECT{$distinct} DISTINCT $select_this FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN $wpdb->term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE{$where_parent} tt.taxonomy IN ($taxonomies) AND tr.object_id IN ($object_ids) $orderby $order";
+		if ( 'all' == $fields || 'all_with_object_id' == $fields ) {
+			$terms = array_merge($terms, $wpdb->get_results($query));
+			update_term_cache($terms);
+		} else if ( 'ids' == $fields || 'names' == $fields ) {
+			$terms = array_merge($terms, $wpdb->get_col($query));
+		}
 	}
 
 	if ( ! $terms )
 		$terms = array();
 
+	if ( 'id=>name' == $fields ) {
+		$_terms = array();
+		foreach($terms as $term)
+			$_terms[$term->term_id] = $term->name;
+	  $terms = $_terms;
+	} else if ( 'id=>term' == $fields ) {
+		$_terms = array();
+		foreach($terms as $term)
+			$_terms[$term->term_id] = $term;
+	  $terms = $_terms;
+	}
+
 	return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args);
 }
 
