|
1 <?php |
|
2 |
|
3 /** |
|
4 * Test taxonomy upgrades. |
|
5 */ |
|
6 class UpgradePathTaxonomyTestCase extends UpgradePathTestCase { |
|
7 public static function getInfo() { |
|
8 return array( |
|
9 'name' => 'Taxonomy upgrade path', |
|
10 'description' => 'Taxonomy upgrade path tests.', |
|
11 'group' => 'Upgrade path', |
|
12 ); |
|
13 } |
|
14 |
|
15 public function setUp() { |
|
16 // Path to the database dump. |
|
17 $this->databaseDumpFiles = array( |
|
18 drupal_get_path('module', 'simpletest') . '/tests/upgrade/drupal-6.filled.database.php', |
|
19 ); |
|
20 parent::setUp(); |
|
21 } |
|
22 |
|
23 /** |
|
24 * Retrieve an array mapping allowed vocabulary id to field name for |
|
25 * all taxonomy_term_reference fields for which an instance exists |
|
26 * for the specified entity type and bundle. |
|
27 */ |
|
28 function instanceVocabularies($entity_type, $bundle) { |
|
29 $instances = array(); |
|
30 foreach (field_info_instances($entity_type, $bundle) as $instance) { |
|
31 $field = field_info_field($instance['field_name']); |
|
32 if ($field['type'] == 'taxonomy_term_reference') { |
|
33 foreach ($field['settings']['allowed_values'] as $tree) { |
|
34 // Prefer valid taxonomy term reference fields for a given vocabulary |
|
35 // when they exist. |
|
36 if (empty($instances[$tree['vocabulary']]) || $instances[$tree['vocabulary']] == 'taxonomyextra') { |
|
37 $instances[$tree['vocabulary']] = $field['field_name']; |
|
38 } |
|
39 } |
|
40 } |
|
41 } |
|
42 return $instances; |
|
43 } |
|
44 |
|
45 /** |
|
46 * Basic tests for the taxonomy upgrade. |
|
47 */ |
|
48 public function testTaxonomyUpgrade() { |
|
49 $this->assertTrue($this->performUpgrade(), 'The upgrade was completed successfully.'); |
|
50 |
|
51 // Visit the front page to assert for PHP warning and errors. |
|
52 $this->drupalGet(''); |
|
53 |
|
54 // Check that taxonomy_vocabulary_node_type and taxonomy_term_node have been |
|
55 // removed. |
|
56 $this->assertFalse(db_table_exists('taxonomy_vocabulary_node_type'), 'taxonomy_vocabulary_node_type has been removed.'); |
|
57 $this->assertFalse(db_table_exists('taxonomy_term_node'), 'taxonomy_term_node has been removed.'); |
|
58 |
|
59 // Check that taxonomy_index has not stored nids of unpublished nodes. |
|
60 $nids = db_query('SELECT nid from {node} WHERE status = :status', array(':status' => NODE_NOT_PUBLISHED))->fetchCol(); |
|
61 $indexed_nids = db_query('SELECT DISTINCT nid from {taxonomy_index}')->fetchCol(); |
|
62 $this->assertFalse(array_intersect($nids, $indexed_nids), 'No unpublished nid present in taxonomy_index'); |
|
63 |
|
64 // Check that the node type 'page' has been associated to a taxonomy |
|
65 // reference field for each vocabulary. |
|
66 $voc_keys = array(); |
|
67 foreach (taxonomy_get_vocabularies() as $vocab) { |
|
68 $voc_keys[] = $vocab->machine_name; |
|
69 } |
|
70 $instances = $this->instanceVocabularies('node', 'page'); |
|
71 $inst_keys = array_keys($instances); |
|
72 sort($voc_keys); |
|
73 sort($inst_keys); |
|
74 $this->assertEqual($voc_keys, $inst_keys, 'Node type page has instances for every vocabulary.'); |
|
75 |
|
76 // Ensure instance variables are getting through. |
|
77 foreach (array_unique($instances) as $instance) { |
|
78 $field_instance = field_info_instance('node', $instance, 'page'); |
|
79 $this->assertTrue(isset($field_instance['required']), 'The required setting was preserved during the upgrade path.'); |
|
80 $this->assertTrue($field_instance['description'], 'The description was preserved during the upgrade path'); |
|
81 } |
|
82 |
|
83 // Node type 'story' was not explicitly in $vocabulary->nodes but |
|
84 // each node of type 'story' was associated to one or more terms. |
|
85 // Check that the node type 'story' has been associated only to |
|
86 // the taxonomyextra field. |
|
87 $instances = $this->instanceVocabularies('node', 'story'); |
|
88 $field_names = array_flip($instances); |
|
89 $this->assertEqual(count($field_names), 1, 'Only one taxonomy term field instance exists for story nodes'); |
|
90 $this->assertEqual(key($field_names), 'taxonomyextra', 'Only the excess taxonomy term field is used on story nodes'); |
|
91 |
|
92 // Check that the node type 'poll' has been associated to no taxonomy |
|
93 // reference field. |
|
94 $instances = $this->instanceVocabularies('node', 'poll'); |
|
95 $this->assertTrue(empty($instances), 'Node type poll has no taxonomy term reference field instances.'); |
|
96 |
|
97 // Check that each node of type 'page' and 'story' is associated to all the |
|
98 // terms except terms whose ID is equal to the node ID or is equal to the |
|
99 // node ID subtracted from 49. |
|
100 $nodes = node_load_multiple(array(), array('type' => 'page')); |
|
101 $nodes += node_load_multiple(array(), array('type' => 'story')); |
|
102 $terms = db_select('taxonomy_term_data', 'td') |
|
103 ->fields('td') |
|
104 ->orderBy('vid') |
|
105 ->orderBy('tid') |
|
106 ->execute() |
|
107 ->fetchAllAssoc('tid'); |
|
108 field_attach_prepare_view('node', $nodes, 'full'); |
|
109 foreach ($nodes as $nid => $node) { |
|
110 $node->content = field_attach_view('node', $node, 'full'); |
|
111 $render = drupal_render($node->content); |
|
112 $this->drupalSetContent($render); |
|
113 $this->verbose($render); |
|
114 |
|
115 $vocabulary_seen = array(); |
|
116 foreach ($terms as $tid => $term) { |
|
117 // In our test database, each node is arbitrary associated with all |
|
118 // terms except two: one whose tid is ($nid) and one whose tid is |
|
119 // (49 - $nid). |
|
120 $should_be_displayed = ($tid != $nid) && ($tid + $nid != 49); |
|
121 |
|
122 // Only vocabularies 13 to 24 are properly associated with the node |
|
123 // type 'page'. All other node types are not associated with any |
|
124 // vocabulary, but still are associated with terms. Those terms |
|
125 // will be moved to the taxonomy extra field. |
|
126 if ($node->type == 'page' && $term->vid >= 13 && $term->vid <= 24) { |
|
127 $vocabulary = taxonomy_vocabulary_load($term->vid); |
|
128 $field_class = 'field-name-' . strtr('taxonomy_' . $vocabulary->machine_name, '_', '-');; |
|
129 } |
|
130 else { |
|
131 $field_class = 'field-name-taxonomyextra'; |
|
132 } |
|
133 |
|
134 // Odd vocabularies are single, so any additional term will be moved |
|
135 // to the taxonomy extra field. |
|
136 if ($should_be_displayed) { |
|
137 if ($term->vid % 2 == 1 && !empty($vocabulary_seen[$term->vid])) { |
|
138 $field_class = 'field-name-taxonomyextra'; |
|
139 } |
|
140 $vocabulary_seen[$term->vid] = TRUE; |
|
141 } |
|
142 |
|
143 $args = array( |
|
144 '%name' => $term->name, |
|
145 '@field' => $field_class, |
|
146 '%nid' => $nid, |
|
147 ); |
|
148 |
|
149 // Use link rather than term name because migrated term names can be |
|
150 // substrings of other term names. e.g. "term 1 of vocabulary 2" is |
|
151 // found when "term 1 of vocabulary 20" is output. |
|
152 $term_path = url('taxonomy/term/' . $term->tid); |
|
153 if (!$should_be_displayed) { |
|
154 // Look for any link with the term path. |
|
155 $links = $this->xpath('//a[@href=:term_path]', array(':term_path' => $term_path)); |
|
156 $this->assertFalse($links, format_string('Term %name (@field) is not displayed on node %nid', $args)); |
|
157 } |
|
158 else { |
|
159 // Look for a link with the term path inside the correct field. |
|
160 // We search for "SPACE + class + SPACE" to avoid matching a substring |
|
161 // of the class. |
|
162 $links = $this->xpath('//div[contains(concat(" ", normalize-space(@class), " "), :field_class)]//a[@href=:term_path]', array(':field_class' => ' ' . $field_class . ' ', ':term_path' => $term_path)); |
|
163 $this->assertTrue($links, format_string('Term %name (@field) is displayed on node %nid', $args)); |
|
164 } |
|
165 } |
|
166 |
|
167 // nid 1, revision 1 had a bogus record in {term_node} pointing to term |
|
168 // ID 0. Make sure we ignored this instead of generating a bogus term. |
|
169 if ($node->nid == 1) { |
|
170 $link = l($term->name, 'taxonomy/term/0'); |
|
171 $this->assertNoRaw($link, format_string('Bogus term (tid 0) is not displayed on node 1 vid %old_vid.', $args)); |
|
172 } |
|
173 |
|
174 // The first 12 nodes have two revisions. For nodes with |
|
175 // revisions, check that the oldest revision is associated only |
|
176 // to terms whose ID is equal to the node ID or 49 less the node ID. |
|
177 $revisions = node_revision_list($node); |
|
178 if ($node->nid < 13) { |
|
179 $this->assertEqual(count($revisions), 2, format_string('Node %nid has two revisions.', $args)); |
|
180 $last_rev = end($revisions); |
|
181 $args['%old_vid'] = $last_rev->vid; |
|
182 |
|
183 $node_old = node_load($node->nid, $last_rev->vid); |
|
184 field_attach_prepare_view('node', array($node_old->nid => $node_old), 'full'); |
|
185 $node_old->content = field_attach_view('node', $node_old, 'full'); |
|
186 $render = drupal_render($node_old->content); |
|
187 $this->drupalSetContent($render); |
|
188 $this->verbose($render); |
|
189 |
|
190 $term = $terms[$node->nid]; |
|
191 $link = l($term->name, 'taxonomy/term/' . $term->tid); |
|
192 $this->assertRaw($link, format_string('Term %name (@field) is displayed on node %nid vid %old_vid.', $args)); |
|
193 $term = $terms[49-$node->nid]; |
|
194 $link = l($term->name, 'taxonomy/term/' . $term->tid); |
|
195 $this->assertRaw($link, format_string('Term %name (@field) is displayed on node %nid %old_vid.', $args)); |
|
196 } |
|
197 else { |
|
198 $this->assertEqual(count($revisions), 1, format_string('Node %nid has one revision.', $args)); |
|
199 } |
|
200 } |
|
201 } |
|
202 } |