summaryrefslogtreecommitdiff
path: root/modules/taxonomy
diff options
context:
space:
mode:
Diffstat (limited to 'modules/taxonomy')
-rw-r--r--modules/taxonomy/taxonomy.js2
-rw-r--r--modules/taxonomy/taxonomy.module73
-rw-r--r--modules/taxonomy/taxonomy.pages.inc15
-rw-r--r--modules/taxonomy/taxonomy.test330
4 files changed, 400 insertions, 20 deletions
diff --git a/modules/taxonomy/taxonomy.js b/modules/taxonomy/taxonomy.js
index cc9cdf7a6..1a0c7908a 100644
--- a/modules/taxonomy/taxonomy.js
+++ b/modules/taxonomy/taxonomy.js
@@ -10,7 +10,7 @@ Drupal.behaviors.termDrag = {
attach: function (context, settings) {
var table = $('#taxonomy', context);
var tableDrag = Drupal.tableDrag.taxonomy; // Get the blocks tableDrag object.
- var rows = $('tr', table).size();
+ var rows = $('tr', table).length;
// When a row is swapped, keep previous and next page classes set.
tableDrag.row.prototype.onSwap = function (swappedRow) {
diff --git a/modules/taxonomy/taxonomy.module b/modules/taxonomy/taxonomy.module
index ccbd7c523..d7e9b2f1c 100644
--- a/modules/taxonomy/taxonomy.module
+++ b/modules/taxonomy/taxonomy.module
@@ -21,7 +21,7 @@ function taxonomy_help($path, $arg) {
case 'admin/help#taxonomy':
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
- $output .= '<p>' . t('The Taxonomy module allows you to classify the content of your website. To classify content, you define <em>vocabularies</em> that contain related <em>terms</em>, and then assign the vocabularies to content types. For more information, see the online handbook entry for the <a href="@taxonomy">Taxonomy module</a>.', array('@taxonomy' => 'http://drupal.org/handbook/modules/taxonomy/')) . '</p>';
+ $output .= '<p>' . t('The Taxonomy module allows you to classify the content of your website. To classify content, you define <em>vocabularies</em> that contain related <em>terms</em>, and then assign the vocabularies to content types. For more information, see the online handbook entry for the <a href="@taxonomy">Taxonomy module</a>.', array('@taxonomy' => 'http://drupal.org/documentation/modules/taxonomy/')) . '</p>';
$output .= '<h3>' . t('Uses') . '</h3>';
$output .= '<dl>';
$output .= '<dt>' . t('Creating vocabularies') . '</dt>';
@@ -195,7 +195,7 @@ function taxonomy_field_extra_fields() {
* @param $limit
* Integer. The maximum number of nodes to find.
* Set to FALSE for no limit.
- * @order
+ * @param $order
* An array of fields and directions.
*
* @return
@@ -475,6 +475,30 @@ function taxonomy_vocabulary_delete($vid) {
module_invoke_all('taxonomy_vocabulary_delete', $vocabulary);
module_invoke_all('entity_delete', $vocabulary, 'taxonomy_vocabulary');
+ // Load all Taxonomy module fields and delete those which use only this
+ // vocabulary.
+ $taxonomy_fields = field_read_fields(array('module' => 'taxonomy'));
+ foreach ($taxonomy_fields as $field_name => $taxonomy_field) {
+ $modified_field = FALSE;
+ // Term reference fields may reference terms from more than one
+ // vocabulary.
+ foreach ($taxonomy_field['settings']['allowed_values'] as $key => $allowed_value) {
+ if ($allowed_value['vocabulary'] == $vocabulary->machine_name) {
+ unset($taxonomy_field['settings']['allowed_values'][$key]);
+ $modified_field = TRUE;
+ }
+ }
+ if ($modified_field) {
+ if (empty($taxonomy_field['settings']['allowed_values'])) {
+ field_delete_field($field_name);
+ }
+ else {
+ // Update the field definition with the new allowed values.
+ field_update_field($taxonomy_field);
+ }
+ }
+ }
+
cache_clear_all();
taxonomy_vocabulary_static_reset();
@@ -544,7 +568,7 @@ function taxonomy_check_vocabulary_hierarchy($vocabulary, $changed_term) {
$hierarchy = 2;
break;
}
- elseif (count($term->parents) == 1 && 0 !== array_shift($term->parents)) {
+ elseif (count($term->parents) == 1 && !isset($term->parents[0])) {
$hierarchy = 1;
}
}
@@ -847,7 +871,11 @@ function taxonomy_get_vocabularies() {
* Get names for all taxonomy vocabularies.
*
* @return
- * An array of vocabulary ids, names, machine names, keyed by machine name.
+ * An associative array of objects keyed by vocabulary machine name with
+ * information about taxonomy vocabularies. Each object has properties:
+ * - name: The vocabulary name.
+ * - machine_name: The machine name.
+ * - vid: The vocabulary ID.
*/
function taxonomy_vocabulary_get_names() {
$names = &drupal_static(__FUNCTION__);
@@ -1071,12 +1099,25 @@ function taxonomy_get_tree($vid, $parent = 0, $max_depth = NULL, $load_entities
*
* @param $name
* Name of the term to search for.
+ * @param $vocabulary
+ * (optional) Vocabulary machine name to limit the search. Defaults to NULL.
*
* @return
* An array of matching term objects.
*/
-function taxonomy_get_term_by_name($name) {
- return taxonomy_term_load_multiple(array(), array('name' => trim($name)));
+function taxonomy_get_term_by_name($name, $vocabulary = NULL) {
+ $conditions = array('name' => trim($name));
+ if (isset($vocabulary)) {
+ $vocabularies = taxonomy_vocabulary_get_names();
+ if (isset($vocabularies[$vocabulary])) {
+ $conditions['vid'] = $vocabularies[$vocabulary]->vid;
+ }
+ else {
+ // Return an empty array when filtering by a non-existing vocabulary.
+ return array();
+ }
+ }
+ return taxonomy_term_load_multiple(array(), $conditions);
}
/**
@@ -1331,7 +1372,7 @@ function taxonomy_field_widget_info_alter(&$info) {
/**
* Implements hook_options_list().
*/
-function taxonomy_options_list($field) {
+function taxonomy_options_list($field, $instance, $entity_type, $entity) {
$function = !empty($field['settings']['options_list_callback']) ? $field['settings']['options_list_callback'] : 'taxonomy_allowed_values';
return $function($field);
}
@@ -1418,6 +1459,10 @@ function taxonomy_field_formatter_info() {
'label' => t('Plain text'),
'field types' => array('taxonomy_term_reference'),
),
+ 'taxonomy_term_reference_rss_category' => array(
+ 'label' => t('RSS category'),
+ 'field types' => array('taxonomy_term_reference'),
+ ),
);
}
@@ -1460,6 +1505,18 @@ function taxonomy_field_formatter_view($entity_type, $entity, $field, $instance,
);
}
break;
+
+ case 'taxonomy_term_reference_rss_category':
+ foreach ($items as $delta => $item) {
+ $entity->rss_elements[] = array(
+ 'key' => 'category',
+ 'value' => $item['tid'] != 'autocreate' ? $item['taxonomy_term']->name : $item['name'],
+ 'attributes' => array(
+ 'domain' => $item['tid'] != 'autocreate' ? url('taxonomy/term/' . $item['tid'], array('absolute' => TRUE)) : '',
+ ),
+ );
+ }
+ break;
}
return $element;
@@ -1519,7 +1576,7 @@ function taxonomy_field_formatter_prepare_view($entity_type, $entities, $field,
$items[$id][$delta]['taxonomy_term'] = $terms[$item['tid']];
}
// Terms to be created are not in $terms, but are still legitimate.
- else if ($item['tid'] == 'autocreate') {
+ elseif ($item['tid'] == 'autocreate') {
// Leave the item in place.
}
// Otherwise, unset the instance value, since the term does not exist.
diff --git a/modules/taxonomy/taxonomy.pages.inc b/modules/taxonomy/taxonomy.pages.inc
index 26304136d..501ebbe10 100644
--- a/modules/taxonomy/taxonomy.pages.inc
+++ b/modules/taxonomy/taxonomy.pages.inc
@@ -108,7 +108,20 @@ function taxonomy_term_feed($term) {
* @see taxonomy_field_widget_info()
*/
function taxonomy_autocomplete($field_name, $tags_typed = '') {
- $field = field_info_field($field_name);
+ // If the request has a '/' in the search text, then the menu system will have
+ // split it into multiple arguments, recover the intended $tags_typed.
+ $args = func_get_args();
+ // Shift off the $field_name argument.
+ array_shift($args);
+ $tags_typed = implode('/', $args);
+
+ // Make sure the field exists and is a taxonomy field.
+ if (!($field = field_info_field($field_name)) || $field['type'] !== 'taxonomy_term_reference') {
+ // Error string. The JavaScript handler will realize this is not JSON and
+ // will display it as debugging information.
+ print t('Taxonomy field @field_name not found.', array('@field_name' => $field_name));
+ exit;
+ }
// The user enters a comma-separated list of tags. We only autocomplete the last tag.
$tags_typed = drupal_explode_tags($tags_typed);
diff --git a/modules/taxonomy/taxonomy.test b/modules/taxonomy/taxonomy.test
index 25743bfea..42b4d4767 100644
--- a/modules/taxonomy/taxonomy.test
+++ b/modules/taxonomy/taxonomy.test
@@ -180,7 +180,7 @@ class TaxonomyVocabularyFunctionalTest extends TaxonomyWebTestCase {
/**
* Tests for taxonomy vocabulary functions.
*/
-class TaxonomyVocabularyUnitTest extends TaxonomyWebTestCase {
+class TaxonomyVocabularyTestCase extends TaxonomyWebTestCase {
public static function getInfo() {
return array(
@@ -215,7 +215,7 @@ class TaxonomyVocabularyUnitTest extends TaxonomyWebTestCase {
// This should return a vocabulary object since it now matches a real vid.
$vocabulary = taxonomy_vocabulary_load($vid);
$this->assertTrue(!empty($vocabulary) && is_object($vocabulary), t('Vocabulary is an object'));
- $this->assertTrue($vocabulary->vid == $vid, t('Valid vocabulary vid is the same as our previously invalid one.'));
+ $this->assertEqual($vocabulary->vid, $vid, 'Valid vocabulary vid is the same as our previously invalid one.');
}
/**
@@ -319,10 +319,10 @@ class TaxonomyVocabularyUnitTest extends TaxonomyWebTestCase {
// Fetch vocabulary 1 by name.
$vocabulary = current(taxonomy_vocabulary_load_multiple(array(), array('name' => $vocabulary1->name)));
- $this->assertTrue($vocabulary->vid == $vocabulary1->vid, t('Vocabulary loaded successfully by name.'));
+ $this->assertEqual($vocabulary->vid, $vocabulary1->vid, 'Vocabulary loaded successfully by name.');
// 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.'));
+ $this->assertEqual(current(taxonomy_vocabulary_load_multiple(array($vocabulary1->vid), array('name' => $vocabulary1->name)))->vid, $vocabulary1->vid, 'Vocabulary loaded successfully by name and ID.');
}
/**
@@ -369,7 +369,6 @@ class TaxonomyVocabularyUnitTest extends TaxonomyWebTestCase {
field_create_instance($this->instance);
module_disable(array('taxonomy'));
- drupal_flush_all_caches();
require_once DRUPAL_ROOT . '/includes/install.inc';
drupal_uninstall_modules(array('taxonomy'));
module_enable(array('taxonomy'));
@@ -389,7 +388,7 @@ class TaxonomyVocabularyUnitTest extends TaxonomyWebTestCase {
/**
* Unit tests for taxonomy term functions.
*/
-class TaxonomyTermUnitTest extends TaxonomyWebTestCase {
+class TaxonomyTermFunctionTestCase extends TaxonomyWebTestCase {
public static function getInfo() {
return array(
@@ -561,6 +560,10 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase {
$term1 = $this->createTerm($this->vocabulary);
$term2 = $this->createTerm($this->vocabulary);
+ // Check that hierarchy is flat.
+ $vocabulary = taxonomy_vocabulary_load($this->vocabulary->vid);
+ $this->assertEqual(0, $vocabulary->hierarchy, 'Vocabulary is flat.');
+
// Edit $term2, setting $term1 as parent.
$edit = array();
$edit['parent[]'] = array($term1->tid);
@@ -696,6 +699,66 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase {
$input = substr($term_objects['term3']->name, 0, 3);
$this->drupalGet('taxonomy/autocomplete/taxonomy_' . $this->vocabulary->machine_name . '/' . $input);
$this->assertRaw('{"' . $term_objects['term3']->name . '":"' . $term_objects['term3']->name . '"}', t('Autocomplete returns term %term_name after typing the first 3 letters.', array('%term_name' => $term_objects['term3']->name)));
+
+ // Test taxonomy autocomplete with a nonexistent field.
+ $field_name = $this->randomName();
+ $tag = $this->randomName();
+ $message = t("Taxonomy field @field_name not found.", array('@field_name' => $field_name));
+ $this->assertFalse(field_info_field($field_name), t('Field %field_name does not exist.', array('%field_name' => $field_name)));
+ $this->drupalGet('taxonomy/autocomplete/' . $field_name . '/' . $tag);
+ $this->assertRaw($message, t('Autocomplete returns correct error message when the taxonomy field does not exist.'));
+ }
+
+ /**
+ * Tests term autocompletion edge cases with slashes in the names.
+ */
+ function testTermAutocompletion() {
+ // Add a term with a slash in the name.
+ $first_term = $this->createTerm($this->vocabulary);
+ $first_term->name = '10/16/2011';
+ taxonomy_term_save($first_term);
+ // Add another term that differs after the slash character.
+ $second_term = $this->createTerm($this->vocabulary);
+ $second_term->name = '10/17/2011';
+ taxonomy_term_save($second_term);
+ // Add another term that has both a comma and a slash character.
+ $third_term = $this->createTerm($this->vocabulary);
+ $third_term->name = 'term with, a comma and / a slash';
+ taxonomy_term_save($third_term);
+
+ // Try to autocomplete a term name that matches both terms.
+ // We should get both term in a json encoded string.
+ $input = '10/';
+ $path = 'taxonomy/autocomplete/taxonomy_';
+ $path .= $this->vocabulary->machine_name . '/' . $input;
+ // The result order is not guaranteed, so check each term separately.
+ $url = url($path, array('absolute' => TRUE));
+ $result = drupal_http_request($url);
+ $data = drupal_json_decode($result->data);
+ $this->assertEqual($data[$first_term->name], check_plain($first_term->name), 'Autocomplete returned the first matching term');
+ $this->assertEqual($data[$second_term->name], check_plain($second_term->name), 'Autocomplete returned the second matching term');
+
+ // Try to autocomplete a term name that matches first term.
+ // We should only get the first term in a json encoded string.
+ $input = '10/16';
+ $url = 'taxonomy/autocomplete/taxonomy_';
+ $url .= $this->vocabulary->machine_name . '/' . $input;
+ $this->drupalGet($url);
+ $target = array($first_term->name => check_plain($first_term->name));
+ $this->assertRaw(drupal_json_encode($target), 'Autocomplete returns only the expected matching term.');
+
+ // Try to autocomplete a term name with both a comma and a slash.
+ $input = '"term with, comma and / a';
+ $url = 'taxonomy/autocomplete/taxonomy_';
+ $url .= $this->vocabulary->machine_name . '/' . $input;
+ $this->drupalGet($url);
+ $n = $third_term->name;
+ // Term names containing commas or quotes must be wrapped in quotes.
+ if (strpos($third_term->name, ',') !== FALSE || strpos($third_term->name, '"') !== FALSE) {
+ $n = '"' . str_replace('"', '""', $third_term->name) . '"';
+ }
+ $target = array($n => check_plain($third_term->name));
+ $this->assertRaw(drupal_json_encode($target), 'Autocomplete returns a term containing a comma and a slash.');
}
/**
@@ -887,6 +950,127 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase {
// Try to load the term using a substring of the name.
$terms = taxonomy_get_term_by_name(drupal_substr($term->name, 2));
$this->assertFalse($terms);
+
+ // Create a new term in a different vocabulary with the same name.
+ $new_vocabulary = $this->createVocabulary();
+ $new_term = new stdClass();
+ $new_term->name = $term->name;
+ $new_term->vid = $new_vocabulary->vid;
+ taxonomy_term_save($new_term);
+
+ // Load multiple terms with the same name.
+ $terms = taxonomy_get_term_by_name($term->name);
+ $this->assertEqual(count($terms), 2, t('Two terms loaded with the same name.'));
+
+ // Load single term when restricted to one vocabulary.
+ $terms = taxonomy_get_term_by_name($term->name, $this->vocabulary->machine_name);
+ $this->assertEqual(count($terms), 1, t('One term loaded when restricted by vocabulary.'));
+ $this->assertTrue(isset($terms[$term->tid]), t('Term loaded using exact name and vocabulary machine name.'));
+
+ // Create a new term with another name.
+ $term2 = $this->createTerm($this->vocabulary);
+
+ // Try to load a term by name that doesn't exist in this vocabulary but
+ // exists in another vocabulary.
+ $terms = taxonomy_get_term_by_name($term2->name, $new_vocabulary->machine_name);
+ $this->assertFalse($terms, t('Invalid term name restricted by vocabulary machine name not loaded.'));
+
+ // Try to load terms filtering by a non-existing vocabulary.
+ $terms = taxonomy_get_term_by_name($term2->name, 'non_existing_vocabulary');
+ $this->assertEqual(count($terms), 0, t('No terms loaded when restricted by a non-existing vocabulary.'));
+ }
+}
+
+/**
+ * Tests the rendering of term reference fields in RSS feeds.
+ */
+class TaxonomyRSSTestCase extends TaxonomyWebTestCase {
+
+ public static function getInfo() {
+ return array(
+ 'name' => 'Taxonomy RSS Content.',
+ 'description' => 'Ensure that data added as terms appears in RSS feeds if "RSS Category" format is selected.',
+ 'group' => 'Taxonomy',
+ );
+ }
+
+ function setUp() {
+ parent::setUp('taxonomy');
+ $this->admin_user = $this->drupalCreateUser(array('administer taxonomy', 'bypass node access', 'administer content types'));
+ $this->drupalLogin($this->admin_user);
+ $this->vocabulary = $this->createVocabulary();
+
+ $field = array(
+ 'field_name' => 'taxonomy_' . $this->vocabulary->machine_name,
+ 'type' => 'taxonomy_term_reference',
+ 'cardinality' => FIELD_CARDINALITY_UNLIMITED,
+ 'settings' => array(
+ 'allowed_values' => array(
+ array(
+ 'vocabulary' => $this->vocabulary->machine_name,
+ 'parent' => 0,
+ ),
+ ),
+ ),
+ );
+ field_create_field($field);
+
+ $this->instance = array(
+ 'field_name' => 'taxonomy_' . $this->vocabulary->machine_name,
+ 'bundle' => 'article',
+ 'entity_type' => 'node',
+ 'widget' => array(
+ 'type' => 'options_select',
+ ),
+ 'display' => array(
+ 'default' => array(
+ 'type' => 'taxonomy_term_reference_link',
+ ),
+ ),
+ );
+ field_create_instance($this->instance);
+ }
+
+ /**
+ * Tests that terms added to nodes are displayed in core RSS feed.
+ *
+ * Create a node and assert that taxonomy terms appear in rss.xml.
+ */
+ function testTaxonomyRSS() {
+ // Create two taxonomy terms.
+ $term1 = $this->createTerm($this->vocabulary);
+
+ // RSS display must be added manually.
+ $this->drupalGet("admin/structure/types/manage/article/display");
+ $edit = array(
+ "view_modes_custom[rss]" => '1',
+ );
+ $this->drupalPost(NULL, $edit, t('Save'));
+
+ // Change the format to 'RSS category'.
+ $this->drupalGet("admin/structure/types/manage/article/display/rss");
+ $edit = array(
+ "fields[taxonomy_" . $this->vocabulary->machine_name . "][type]" => 'taxonomy_term_reference_rss_category',
+ );
+ $this->drupalPost(NULL, $edit, t('Save'));
+
+ // Post an article.
+ $edit = array();
+ $langcode = LANGUAGE_NONE;
+ $edit["title"] = $this->randomName();
+ $edit[$this->instance['field_name'] . '[' . $langcode .'][]'] = $term1->tid;
+ $this->drupalPost('node/add/article', $edit, t('Save'));
+
+ // Check that the term is displayed when the RSS feed is viewed.
+ $this->drupalGet('rss.xml');
+ $test_element = array(
+ 'key' => 'category',
+ 'value' => $term1->name,
+ 'attributes' => array(
+ 'domain' => url('taxonomy/term/' . $term1->tid, array('absolute' => TRUE)),
+ ),
+ );
+ $this->assertRaw(format_xml_elements(array($test_element)), 'Term is displayed when viewing the rss feed.');
}
}
@@ -1110,7 +1294,7 @@ class TaxonomyTermIndexTestCase extends TaxonomyWebTestCase {
/**
* Test the taxonomy_term_load_multiple() function.
*/
-class TaxonomyLoadMultipleUnitTest extends TaxonomyWebTestCase {
+class TaxonomyLoadMultipleTestCase extends TaxonomyWebTestCase {
public static function getInfo() {
return array(
@@ -1143,11 +1327,11 @@ class TaxonomyLoadMultipleUnitTest extends TaxonomyWebTestCase {
// Load the terms from the vocabulary.
$terms = taxonomy_term_load_multiple(NULL, array('vid' => $vocabulary->vid));
$count = count($terms);
- $this->assertTrue($count == 5, t('Correct number of terms were loaded. !count terms.', array('!count' => $count)));
+ $this->assertEqual($count, 5, format_string('Correct number of terms were loaded. !count terms.', array('!count' => $count)));
// Load the same terms again by tid.
$terms2 = taxonomy_term_load_multiple(array_keys($terms));
- $this->assertTrue($count == count($terms2), t('Five terms were loaded by tid'));
+ $this->assertEqual($count, count($terms2), 'Five terms were loaded by tid');
$this->assertEqual($terms, $terms2, t('Both arrays contain the same terms'));
// Load the terms by tid, with a condition on vid.
@@ -1162,7 +1346,7 @@ class TaxonomyLoadMultipleUnitTest extends TaxonomyWebTestCase {
// Load terms from the vocabulary by vid.
$terms4 = taxonomy_term_load_multiple(NULL, array('vid' => $vocabulary->vid));
- $this->assertTrue(count($terms4 == 4), t('Correct number of terms were loaded.'));
+ $this->assertEqual(count($terms4), 4, 'Correct number of terms were loaded.');
$this->assertFalse(isset($terms4[$deleted->tid]));
// Create a single term and load it by name.
@@ -1335,6 +1519,11 @@ class TaxonomyTermFieldTestCase extends TaxonomyWebTestCase {
$entity->content = field_attach_view('test_entity', $entity, 'full');
$this->content = drupal_render($entity->content);
$this->assertText($term->name, t('Term name is displayed'));
+
+ // Delete the vocabulary and verify that the widget is gone.
+ taxonomy_vocabulary_delete($this->vocabulary->vid);
+ $this->drupalGet('test-entity/add/test-bundle');
+ $this->assertNoFieldByName("{$this->field_name}[$langcode]", '', 'Widget is not displayed');
}
/**
@@ -1379,6 +1568,127 @@ class TaxonomyTermFieldTestCase extends TaxonomyWebTestCase {
}
/**
+ * Tests a taxonomy term reference field that allows multiple vocabularies.
+ */
+class TaxonomyTermFieldMultipleVocabularyTestCase extends TaxonomyWebTestCase {
+ protected $instance;
+ protected $vocabulary1;
+ protected $vocabulary2;
+
+ public static function getInfo() {
+ return array(
+ 'name' => 'Multiple vocabulary term reference field',
+ 'description' => 'Tests term reference fields that allow multiple vocabularies.',
+ 'group' => 'Taxonomy',
+ );
+ }
+
+ function setUp() {
+ parent::setUp('field_test');
+
+ $web_user = $this->drupalCreateUser(array('access field_test content', 'administer field_test content', 'administer taxonomy'));
+ $this->drupalLogin($web_user);
+ $this->vocabulary1 = $this->createVocabulary();
+ $this->vocabulary2 = $this->createVocabulary();
+
+ // Set up a field and instance.
+ $this->field_name = drupal_strtolower($this->randomName());
+ $this->field = array(
+ 'field_name' => $this->field_name,
+ 'type' => 'taxonomy_term_reference',
+ 'cardinality' => FIELD_CARDINALITY_UNLIMITED,
+ 'settings' => array(
+ 'allowed_values' => array(
+ array(
+ 'vocabulary' => $this->vocabulary1->machine_name,
+ 'parent' => '0',
+ ),
+ array(
+ 'vocabulary' => $this->vocabulary2->machine_name,
+ 'parent' => '0',
+ ),
+ ),
+ )
+ );
+ field_create_field($this->field);
+ $this->instance = array(
+ 'field_name' => $this->field_name,
+ 'entity_type' => 'test_entity',
+ 'bundle' => 'test_bundle',
+ 'widget' => array(
+ 'type' => 'options_select',
+ ),
+ 'display' => array(
+ 'full' => array(
+ 'type' => 'taxonomy_term_reference_link',
+ ),
+ ),
+ );
+ field_create_instance($this->instance);
+ }
+
+ /**
+ * Tests term reference field and widget with multiple vocabularies.
+ */
+ function testTaxonomyTermFieldMultipleVocabularies() {
+ // Create a term in each vocabulary.
+ $term1 = $this->createTerm($this->vocabulary1);
+ $term2 = $this->createTerm($this->vocabulary2);
+
+ // Submit an entity with both terms.
+ $langcode = LANGUAGE_NONE;
+ $this->drupalGet('test-entity/add/test-bundle');
+ $this->assertFieldByName("{$this->field_name}[$langcode][]", '', 'Widget is displayed');
+ $edit = array(
+ "{$this->field_name}[$langcode][]" => array($term1->tid, $term2->tid),
+ );
+ $this->drupalPost(NULL, $edit, t('Save'));
+ 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.');
+
+ // Render the entity.
+ $entity = field_test_entity_test_load($id);
+ $entities = array($id => $entity);
+ 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($term1->name, 'Term 1 name is displayed.');
+ $this->assertText($term2->name, 'Term 2 name is displayed.');
+
+ // Delete vocabulary 2.
+ taxonomy_vocabulary_delete($this->vocabulary2->vid);
+
+ // Re-render the content.
+ $entity = field_test_entity_test_load($id);
+ $entities = array($id => $entity);
+ field_attach_prepare_view('test_entity', $entities, 'full');
+ $entity->content = field_attach_view('test_entity', $entity, 'full');
+ $this->plainTextContent = FALSE;
+ $this->content = drupal_render($entity->content);
+
+ // Term 1 should still be displayed; term 2 should not be.
+ $this->assertText($term1->name, 'Term 1 name is displayed.');
+ $this->assertNoText($term2->name, 'Term 2 name is not displayed.');
+
+ // Verify that field and instance settings are correct.
+ $field_info = field_info_field($this->field_name);
+ $this->assertEqual(sizeof($field_info['settings']['allowed_values']), 1, 'Only one vocabulary is allowed for the field.');
+
+ // The widget should still be displayed.
+ $this->drupalGet('test-entity/add/test-bundle');
+ $this->assertFieldByName("{$this->field_name}[$langcode][]", '', 'Widget is still displayed');
+
+ // Term 1 should still pass validation.
+ $edit = array(
+ "{$this->field_name}[$langcode][]" => array($term1->tid),
+ );
+ $this->drupalPost(NULL, $edit, t('Save'));
+ }
+}
+
+
+/**
* Test taxonomy token replacement in strings.
*/
class TaxonomyTokenReplaceTestCase extends TaxonomyWebTestCase {