comparison core/modules/views/tests/src/Kernel/FieldApiDataTest.php @ 5:12f9dff5fda9 tip

Update to Drupal core 8.7.1
author Chris Cannam
date Thu, 09 May 2019 15:34:47 +0100
parents
children
comparison
equal deleted inserted replaced
4:a9cd425dd02b 5:12f9dff5fda9
1 <?php
2
3 namespace Drupal\Tests\views\Kernel;
4
5 use Drupal\Component\Render\MarkupInterface;
6 use Drupal\field\Entity\FieldConfig;
7 use Drupal\field\Entity\FieldStorageConfig;
8 use Drupal\language\Entity\ConfigurableLanguage;
9 use Drupal\language\Entity\ContentLanguageSettings;
10 use Drupal\node\Entity\Node;
11 use Drupal\node\Entity\NodeType;
12 use Drupal\views\Views;
13
14 /**
15 * Tests the Field Views data.
16 *
17 * @group views
18 */
19 class FieldApiDataTest extends ViewsKernelTestBase {
20
21 /**
22 * {@inheritdoc}
23 */
24 public static $modules = [
25 'field',
26 'filter',
27 'language',
28 'node',
29 'user',
30 ];
31
32 /**
33 * {@inheritdoc}
34 */
35 public static $testViews = ['test_field_config_translation_filter'];
36
37 /**
38 * {@inheritdoc}
39 */
40 protected function setUp($import_test_views = TRUE) {
41 parent::setUp($import_test_views);
42 $this->installEntitySchema('user');
43 $this->installEntitySchema('node');
44 $this->installSchema('node', ['node_access']);
45 }
46
47 /**
48 * Unit testing the views data structure.
49 *
50 * We check data structure for both node and node revision tables.
51 */
52 public function testViewsData() {
53 $field_storage_string = FieldStorageConfig::create([
54 'field_name' => 'field_string',
55 'entity_type' => 'node',
56 'type' => 'string',
57 ]);
58 $field_storage_string->save();
59
60 $field_storage_string_long = FieldStorageConfig::create([
61 'field_name' => 'field_string_long',
62 'entity_type' => 'node',
63 'type' => 'string_long',
64 ]);
65 $field_storage_string_long->save();
66
67 NodeType::create(['type' => 'page'])->save();
68 NodeType::create(['type' => 'article'])->save();
69
70 // Attach the field to nodes.
71 FieldConfig::create([
72 'field_name' => 'field_string',
73 'entity_type' => 'node',
74 'bundle' => 'page',
75 'label' => 'GiraffeA" label',
76 ])->save();
77
78 // Attach the string_long field to the page node type.
79 FieldConfig::create([
80 'field_name' => 'field_string_long',
81 'entity_type' => 'node',
82 'bundle' => 'page',
83 'label' => 'string_long label',
84 ])->save();
85
86 // Attach the same field to a different bundle with a different label.
87 FieldConfig::create([
88 'field_name' => 'field_string',
89 'entity_type' => 'node',
90 'bundle' => 'article',
91 'label' => 'GiraffeB" label',
92 ])->save();
93
94 // Now create some example nodes/users for the view result.
95 for ($i = 0; $i < 5; $i++) {
96 $edit = [
97 'field_string' => [(['value' => $this->randomMachineName()])],
98 ];
99 $nodes[] = Node::create(['type' => 'page'] + $edit);
100 }
101
102 /** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */
103 $table_mapping = $this->container->get('entity_type.manager')
104 ->getStorage('node')
105 ->getTableMapping();
106
107 $current_table = $table_mapping->getDedicatedDataTableName($field_storage_string);
108 $revision_table = $table_mapping->getDedicatedRevisionTableName($field_storage_string);
109 $data = $this->getViewsData();
110
111 $this->assertArrayHasKey($current_table, $data);
112 $this->assertArrayHasKey($revision_table, $data);
113
114 // The node field should join against node_field_data.
115 $this->assertArrayHasKey('node_field_data', $data[$current_table]['table']['join']);
116 $this->assertArrayHasKey('node_field_revision', $data[$revision_table]['table']['join']);
117
118 $expected_join = [
119 'table' => $current_table,
120 'left_field' => 'nid',
121 'field' => 'entity_id',
122 'extra' => [
123 ['field' => 'deleted', 'value' => 0, 'numeric' => TRUE],
124 ['left_field' => 'langcode', 'field' => 'langcode'],
125 ],
126 ];
127 $this->assertSame($expected_join, $data[$current_table]['table']['join']['node_field_data']);
128 $expected_join = [
129 'table' => $revision_table,
130 'left_field' => 'vid',
131 'field' => 'revision_id',
132 'extra' => [
133 ['field' => 'deleted', 'value' => 0, 'numeric' => TRUE],
134 ['left_field' => 'langcode', 'field' => 'langcode'],
135 ],
136 ];
137 $this->assertSame($expected_join, $data[$revision_table]['table']['join']['node_field_revision']);
138
139 // Test click sortable for string field.
140 $this->assertTrue($data[$current_table][$field_storage_string->getName()]['field']['click sortable']);
141 // Click sort should only be on the primary field.
142 $this->assertTrue(empty($data[$revision_table][$field_storage_string->getName()]['field']['click sortable']));
143 // Test click sortable for long text field.
144 $data_long = $this->getViewsData('field_string_long');
145 $current_table_long = $table_mapping->getDedicatedDataTableName($field_storage_string_long);
146 $this->assertTrue($data_long[$current_table_long][$field_storage_string_long->getName()]['field']['click sortable']);
147
148 $this->assertInstanceOf(MarkupInterface::class, $data[$current_table][$field_storage_string->getName()]['help']);
149 $this->assertEquals('Appears in: page, article. Also known as: Content: GiraffeB&quot; label', $data[$current_table][$field_storage_string->getName()]['help']);
150
151 $this->assertInstanceOf(MarkupInterface::class, $data[$current_table][$field_storage_string->getName() . '_value']['help']);
152 $this->assertEquals('Appears in: page, article. Also known as: Content: GiraffeA&quot; label (field_string)', $data[$current_table][$field_storage_string->getName() . '_value']['help']);
153
154 // Since each label is only used once, views_entity_field_label() will
155 // return a label using alphabetical sorting.
156 $this->assertEquals('GiraffeA&quot; label (field_string)', $data[$current_table][$field_storage_string->getName() . '_value']['title']);
157
158 // Attach the same field to a different bundle with a different label.
159 NodeType::create(['type' => 'news'])->save();
160 FieldConfig::create([
161 'field_name' => $field_storage_string->getName(),
162 'entity_type' => 'node',
163 'bundle' => 'news',
164 'label' => 'GiraffeB" label',
165 ])->save();
166 $this->container->get('views.views_data')->clear();
167 $data = $this->getViewsData();
168
169 // Now the 'GiraffeB&quot; label' is used twice and therefore will be
170 // selected by views_entity_field_label().
171 $this->assertEquals('GiraffeB&quot; label (field_string)', $data[$current_table][$field_storage_string->getName() . '_value']['title']);
172 $this->assertInstanceOf(MarkupInterface::class, $data[$current_table][$field_storage_string->getName()]['help']);
173 $this->assertEquals('Appears in: page, article, news. Also known as: Content: GiraffeA&quot; label', $data[$current_table][$field_storage_string->getName()]['help']);
174 }
175
176 /**
177 * Gets the views data for the field created in setUp().
178 *
179 * @param string $field_storage_key
180 * (optional) The optional field name.
181 *
182 * @return array
183 * Views data.
184 */
185 protected function getViewsData($field_storage_key = 'field_string') {
186 $views_data = $this->container->get('views.views_data');
187 $data = [];
188
189 // Check the table and the joins of the first field. Attached to node only.
190 /** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */
191 $table_mapping = $this->container->get('entity_type.manager')->getStorage('node')->getTableMapping();
192 $field_storage = FieldStorageConfig::loadByName('node', $field_storage_key);
193 $current_table = $table_mapping->getDedicatedDataTableName($field_storage);
194 $revision_table = $table_mapping->getDedicatedRevisionTableName($field_storage);
195 $data[$current_table] = $views_data->get($current_table);
196 $data[$revision_table] = $views_data->get($revision_table);
197 return $data;
198 }
199
200 /**
201 * Tests filtering entries with different translatability.
202 */
203 public function testEntityFieldFilter() {
204 NodeType::create(['type' => 'bundle1'])->save();
205 NodeType::create(['type' => 'bundle2'])->save();
206
207 // Create some example content.
208 ConfigurableLanguage::create(['id' => 'es'])->save();
209 ConfigurableLanguage::create(['id' => 'fr'])->save();
210
211 ContentLanguageSettings::loadByEntityTypeBundle('node', 'bundle1')
212 ->setDefaultLangcode('es')
213 ->setLanguageAlterable(TRUE)
214 ->save();
215 ContentLanguageSettings::loadByEntityTypeBundle('node', 'bundle2')
216 ->setDefaultLangcode('es')
217 ->setLanguageAlterable(TRUE)
218 ->save();
219
220 $field_translation_map = [
221 1 => ['bundle1' => TRUE, 'bundle2' => TRUE],
222 2 => ['bundle1' => FALSE, 'bundle2' => FALSE],
223 3 => ['bundle1' => TRUE, 'bundle2' => FALSE],
224 ];
225
226 for ($i = 1; $i < 4; $i++) {
227 $field_name = "field_name_$i";
228 FieldStorageConfig::create([
229 'field_name' => $field_name,
230 'entity_type' => 'node',
231 'type' => 'string',
232 ])->save();
233
234 foreach (['bundle1', 'bundle2'] as $bundle) {
235 FieldConfig::create([
236 'field_name' => $field_name,
237 'entity_type' => 'node',
238 'bundle' => $bundle,
239 'translatable' => $field_translation_map[$i][$bundle],
240 ])->save();
241 }
242 }
243
244 $node1 = Node::create([
245 'title' => 'Test title bundle1',
246 'type' => 'bundle1',
247 'langcode' => 'es',
248 'field_name_1' => 'field name 1: es',
249 'field_name_2' => 'field name 2: es',
250 'field_name_3' => 'field name 3: es',
251 ]);
252 $node1->save();
253 /** @var \Drupal\node\NodeInterface $translation */
254 $node1->addTranslation('fr', [
255 'title' => $node1->title->value,
256 'field_name_1' => 'field name 1: fr',
257 'field_name_3' => 'field name 3: fr',
258 ])->save();
259
260 $node2 = Node::create([
261 'title' => 'Test title bundle2',
262 'type' => 'bundle2',
263 'langcode' => 'es',
264 'field_name_1' => 'field name 1: es',
265 'field_name_2' => 'field name 2: es',
266 'field_name_3' => 'field name 3: es',
267 ]);
268 $node2->save();
269
270 $node2->addTranslation('fr', [
271 'title' => $node2->title->value,
272 'field_name_1' => 'field name 1: fr',
273 ])->save();
274
275 $map = [
276 'nid' => 'nid',
277 'langcode' => 'langcode',
278 ];
279
280 $view = Views::getView('test_field_config_translation_filter');
281
282 // Filter by 'field name 1: es'.
283 $view->setDisplay('embed_1');
284 $this->executeView($view);
285 $expected = [
286 [
287 'nid' => $node1->id(),
288 'langcode' => 'es',
289 ],
290 [
291 'nid' => $node2->id(),
292 'langcode' => 'es',
293 ],
294 ];
295
296 $this->assertIdenticalResultset($view, $expected, $map);
297 $view->destroy();
298
299 // Filter by 'field name 1: fr'.
300 $view->setDisplay('embed_2');
301 $this->executeView($view);
302 $expected = [
303 [
304 'nid' => $node1->id(),
305 'langcode' => 'fr',
306 ],
307 [
308 'nid' => $node2->id(),
309 'langcode' => 'fr',
310 ],
311 ];
312
313 $this->assertIdenticalResultset($view, $expected, $map);
314 $view->destroy();
315
316 // Filter by 'field name 2: es'.
317 $view->setDisplay('embed_3');
318 $this->executeView($view);
319 $expected = [
320 [
321 'nid' => $node1->id(),
322 'langcode' => 'es',
323 ],
324 [
325 'nid' => $node1->id(),
326 'langcode' => 'fr',
327 ],
328 [
329 'nid' => $node2->id(),
330 'langcode' => 'es',
331 ],
332 [
333 'nid' => $node2->id(),
334 'langcode' => 'fr',
335 ],
336 ];
337
338 $this->assertIdenticalResultset($view, $expected, $map);
339 $view->destroy();
340
341 // Filter by 'field name 2: fr', which doesn't exist.
342 $view->setDisplay('embed_4');
343 $this->executeView($view);
344 $expected = [];
345
346 $this->assertIdenticalResultset($view, $expected, $map);
347 $view->destroy();
348
349 // Filter by 'field name 3: es'.
350 $view->setDisplay('embed_5');
351 $this->executeView($view);
352 $expected = [
353 [
354 'nid' => $node1->id(),
355 'langcode' => 'es',
356 ],
357 [
358 'nid' => $node2->id(),
359 'langcode' => 'es',
360 ],
361 // Why is this one returned?
362 [
363 'nid' => $node2->id(),
364 'langcode' => 'fr',
365 ],
366 ];
367
368 $this->assertIdenticalResultset($view, $expected, $map);
369 $view->destroy();
370
371 // Filter by 'field name 3: fr'.
372 $view->setDisplay('embed_6');
373 $this->executeView($view);
374 $expected = [
375 [
376 'nid' => $node1->id(),
377 'langcode' => 'fr',
378 ],
379 ];
380
381 $this->assertIdenticalResultset($view, $expected, $map);
382 $view->destroy();
383 }
384
385 }