Updated Drupal to 8.6. This goes with the following updates because it's possible...
[yaffs-website] / web / core / modules / field / tests / src / Kernel / FieldAttachOtherTest.php
1 <?php
2
3 namespace Drupal\Tests\field\Kernel;
4
5 use Drupal\Core\Form\FormState;
6 use Drupal\entity_test\Entity\EntityTest;
7
8 /**
9  * Tests other Field API functions.
10  *
11  * @group field
12  * @todo move this to the Entity module
13  */
14 class FieldAttachOtherTest extends FieldKernelTestBase {
15
16   protected function setUp() {
17     parent::setUp();
18     $this->container->get('router.builder')->rebuild();
19     $this->installEntitySchema('entity_test_rev');
20     $this->createFieldWithStorage();
21   }
22
23   /**
24    * Test rendering fields with EntityDisplay build().
25    */
26   public function testEntityDisplayBuild() {
27     $this->createFieldWithStorage('_2');
28
29     $entity_type = 'entity_test';
30     $entity_init = $this->container->get('entity_type.manager')
31       ->getStorage($entity_type)
32       ->create();
33
34     // Populate values to be displayed.
35     $values = $this->_generateTestFieldValues($this->fieldTestData->field_storage->getCardinality());
36     $entity_init->{$this->fieldTestData->field_name}->setValue($values);
37     $values_2 = $this->_generateTestFieldValues($this->fieldTestData->field_storage_2->getCardinality());
38     $entity_init->{$this->fieldTestData->field_name_2}->setValue($values_2);
39
40     // Simple formatter, label displayed.
41     $entity = clone($entity_init);
42     $display = entity_get_display($entity_type, $entity->bundle(), 'full');
43
44     $formatter_setting = $this->randomMachineName();
45     $display_options = [
46       'label' => 'above',
47       'type' => 'field_test_default',
48       'settings' => [
49         'test_formatter_setting' => $formatter_setting,
50       ],
51     ];
52     $display->setComponent($this->fieldTestData->field_name, $display_options);
53
54     $formatter_setting_2 = $this->randomMachineName();
55     $display_options_2 = [
56       'label' => 'above',
57       'type' => 'field_test_default',
58       'settings' => [
59         'test_formatter_setting' => $formatter_setting_2,
60       ],
61     ];
62     $display->setComponent($this->fieldTestData->field_name_2, $display_options_2);
63
64     // View all fields.
65     $content = $display->build($entity);
66     $this->render($content);
67     $this->assertRaw($this->fieldTestData->field->getLabel(), "First field's label is displayed.");
68     foreach ($values as $delta => $value) {
69       $this->assertRaw("$formatter_setting|{$value['value']}", "Value $delta is displayed, formatter settings are applied.");
70     }
71     $this->assertRaw($this->fieldTestData->field_2->getLabel(), "Second field's label is displayed.");
72     foreach ($values_2 as $delta => $value) {
73       $this->assertRaw("$formatter_setting_2|{$value['value']}", "Value $delta is displayed, formatter settings are applied.");
74     }
75
76     // Label hidden.
77     $entity = clone($entity_init);
78     $display_options['label'] = 'hidden';
79     $display->setComponent($this->fieldTestData->field_name, $display_options);
80     $content = $display->build($entity);
81     $this->render($content);
82     $this->assertNoRaw($this->fieldTestData->field->getLabel(), "Hidden label: label is not displayed.");
83
84     // Field hidden.
85     $entity = clone($entity_init);
86     $display->removeComponent($this->fieldTestData->field_name);
87     $content = $display->build($entity);
88     $this->render($content);
89     $this->assertNoRaw($this->fieldTestData->field->getLabel(), "Hidden field: label is not displayed.");
90     foreach ($values as $delta => $value) {
91       $this->assertNoRaw("$formatter_setting|{$value['value']}", "Hidden field: value $delta is not displayed.");
92     }
93
94     // Multiple formatter.
95     $entity = clone($entity_init);
96     $formatter_setting = $this->randomMachineName();
97     $display->setComponent($this->fieldTestData->field_name, [
98       'label' => 'above',
99       'type' => 'field_test_multiple',
100       'settings' => [
101         'test_formatter_setting_multiple' => $formatter_setting,
102       ],
103     ]);
104     $content = $display->build($entity);
105     $this->render($content);
106     $expected_output = $formatter_setting;
107     foreach ($values as $delta => $value) {
108       $expected_output .= "|$delta:{$value['value']}";
109     }
110     $this->assertRaw($expected_output, "Multiple formatter: all values are displayed, formatter settings are applied.");
111
112     // Test a formatter that uses hook_field_formatter_prepare_view().
113     $entity = clone($entity_init);
114     $formatter_setting = $this->randomMachineName();
115     $display->setComponent($this->fieldTestData->field_name, [
116       'label' => 'above',
117       'type' => 'field_test_with_prepare_view',
118       'settings' => [
119         'test_formatter_setting_additional' => $formatter_setting,
120       ],
121     ]);
122     $content = $display->build($entity);
123     $this->render($content);
124     foreach ($values as $delta => $value) {
125       $expected = $formatter_setting . '|' . $value['value'] . '|' . ($value['value'] + 1);
126       $this->assertRaw($expected, "Value $delta is displayed, formatter settings are applied.");
127     }
128
129     // TODO:
130     // - check display order with several fields
131   }
132
133   /**
134    * Tests rendering fields with EntityDisplay::buildMultiple().
135    */
136   public function testEntityDisplayViewMultiple() {
137     // Use a formatter that has a prepareView() step.
138     $display = entity_get_display('entity_test', 'entity_test', 'full')
139       ->setComponent($this->fieldTestData->field_name, [
140         'type' => 'field_test_with_prepare_view',
141       ]);
142
143     // Create two entities.
144     $entity1 = EntityTest::create(['id' => 1, 'type' => 'entity_test']);
145     $entity1->{$this->fieldTestData->field_name}->setValue($this->_generateTestFieldValues(1));
146     $entity2 = EntityTest::create(['id' => 2, 'type' => 'entity_test']);
147     $entity2->{$this->fieldTestData->field_name}->setValue($this->_generateTestFieldValues(1));
148
149     // Run buildMultiple(), and check that the entities come out as expected.
150     $display->buildMultiple([$entity1, $entity2]);
151     $item1 = $entity1->{$this->fieldTestData->field_name}[0];
152     $this->assertEqual($item1->additional_formatter_value, $item1->value + 1, 'Entity 1 ran through the prepareView() formatter method.');
153     $item2 = $entity2->{$this->fieldTestData->field_name}[0];
154     $this->assertEqual($item2->additional_formatter_value, $item2->value + 1, 'Entity 2 ran through the prepareView() formatter method.');
155   }
156
157   /**
158    * Test entity cache.
159    *
160    * Complements unit test coverage in
161    * \Drupal\Tests\Core\Entity\Sql\SqlContentEntityStorageTest.
162    */
163   public function testEntityCache() {
164     // Initialize random values and a test entity.
165     $entity_init = EntityTest::create(['type' => $this->fieldTestData->field->getTargetBundle()]);
166     $values = $this->_generateTestFieldValues($this->fieldTestData->field_storage->getCardinality());
167
168     // Non-cacheable entity type.
169     $entity_type = 'entity_test';
170     $cid = "values:$entity_type:" . $entity_init->id();
171
172     // Check that no initial cache entry is present.
173     $this->assertFalse(\Drupal::cache('entity')->get($cid), 'Non-cached: no initial cache entry');
174
175     // Save, and check that no cache entry is present.
176     $entity = clone($entity_init);
177     $entity->{$this->fieldTestData->field_name}->setValue($values);
178     $entity = $this->entitySaveReload($entity);
179     $cid = "values:$entity_type:" . $entity->id();
180     $this->assertFalse(\Drupal::cache('entity')->get($cid), 'Non-cached: no cache entry on insert and load');
181
182     // Cacheable entity type.
183     $entity_type = 'entity_test_rev';
184     $this->createFieldWithStorage('_2', $entity_type);
185
186     $entity_init = $this->container->get('entity_type.manager')
187       ->getStorage($entity_type)
188       ->create([
189         'type' => $entity_type,
190       ]);
191
192     // Check that no initial cache entry is present.
193     $cid = "values:$entity_type:" . $entity->id();
194     $this->assertFalse(\Drupal::cache('entity')->get($cid), 'Cached: no initial cache entry');
195
196     // Save, and check that no cache entry is present.
197     $entity = clone($entity_init);
198     $entity->{$this->fieldTestData->field_name_2} = $values;
199     $entity->save();
200     $cid = "values:$entity_type:" . $entity->id();
201
202     $this->assertFalse(\Drupal::cache('entity')->get($cid), 'Cached: no cache entry on insert');
203     // Load, and check that a cache entry is present with the expected values.
204     $controller = $this->container->get('entity.manager')->getStorage($entity->getEntityTypeId());
205     $controller->resetCache();
206     $cached_entity = $controller->load($entity->id());
207     $cache = \Drupal::cache('entity')->get($cid);
208     $this->assertEqual($cache->data, $cached_entity, 'Cached: correct cache entry on load');
209
210     // Update with different values, and check that the cache entry is wiped.
211     $values = $this->_generateTestFieldValues($this->fieldTestData->field_storage_2->getCardinality());
212     $entity->{$this->fieldTestData->field_name_2} = $values;
213     $entity->save();
214     $this->assertFalse(\Drupal::cache('entity')->get($cid), 'Cached: no cache entry on update');
215
216     // Load, and check that a cache entry is present with the expected values.
217     $controller->resetCache();
218     $cached_entity = $controller->load($entity->id());
219     $cache = \Drupal::cache('entity')->get($cid);
220     $this->assertEqual($cache->data, $cached_entity, 'Cached: correct cache entry on load');
221
222     // Create a new revision, and check that the cache entry is wiped.
223     $values = $this->_generateTestFieldValues($this->fieldTestData->field_storage_2->getCardinality());
224     $entity->{$this->fieldTestData->field_name_2} = $values;
225     $entity->setNewRevision();
226     $entity->save();
227     $this->assertFalse(\Drupal::cache('entity')->get($cid), 'Cached: no cache entry on new revision creation');
228
229     // Load, and check that a cache entry is present with the expected values.
230     $controller->resetCache();
231     $cached_entity = $controller->load($entity->id());
232     $cache = \Drupal::cache('entity')->get($cid);
233     $this->assertEqual($cache->data, $cached_entity, 'Cached: correct cache entry on load');
234
235     // Delete, and check that the cache entry is wiped.
236     $entity->delete();
237     $this->assertFalse(\Drupal::cache('entity')->get($cid), 'Cached: no cache entry after delete');
238   }
239
240   /**
241    * Tests \Drupal\Core\Entity\Display\EntityFormDisplayInterface::buildForm().
242    *
243    * This could be much more thorough, but it does verify that the correct
244    * widgets show up.
245    */
246   public function testEntityFormDisplayBuildForm() {
247     $this->createFieldWithStorage('_2');
248
249     $entity_type = 'entity_test';
250     $entity = entity_create($entity_type, ['id' => 1, 'revision_id' => 1, 'type' => $this->fieldTestData->field->getTargetBundle()]);
251
252     // Test generating widgets for all fields.
253     $display = entity_get_form_display($entity_type, $this->fieldTestData->field->getTargetBundle(), 'default');
254     $form = [];
255     $form_state = new FormState();
256     $display->buildForm($entity, $form, $form_state);
257
258     $this->assertEqual($form[$this->fieldTestData->field_name]['widget']['#title'], $this->fieldTestData->field->getLabel(), "First field's form title is {$this->fieldTestData->field->getLabel()}");
259     $this->assertEqual($form[$this->fieldTestData->field_name_2]['widget']['#title'], $this->fieldTestData->field_2->getLabel(), "Second field's form title is {$this->fieldTestData->field_2->getLabel()}");
260     for ($delta = 0; $delta < $this->fieldTestData->field_storage->getCardinality(); $delta++) {
261       // field_test_widget uses 'textfield'
262       $this->assertEqual($form[$this->fieldTestData->field_name]['widget'][$delta]['value']['#type'], 'textfield', "First field's form delta $delta widget is textfield");
263     }
264     for ($delta = 0; $delta < $this->fieldTestData->field_storage_2->getCardinality(); $delta++) {
265       // field_test_widget uses 'textfield'
266       $this->assertEqual($form[$this->fieldTestData->field_name_2]['widget'][$delta]['value']['#type'], 'textfield', "Second field's form delta $delta widget is textfield");
267     }
268
269     // Test generating widgets for all fields.
270     $display = entity_get_form_display($entity_type, $this->fieldTestData->field->getTargetBundle(), 'default');
271     foreach ($display->getComponents() as $name => $options) {
272       if ($name != $this->fieldTestData->field_name_2) {
273         $display->removeComponent($name);
274       }
275     }
276     $form = [];
277     $form_state = new FormState();
278     $display->buildForm($entity, $form, $form_state);
279
280     $this->assertFalse(isset($form[$this->fieldTestData->field_name]), 'The first field does not exist in the form');
281     $this->assertEqual($form[$this->fieldTestData->field_name_2]['widget']['#title'], $this->fieldTestData->field_2->getLabel(), "Second field's form title is {$this->fieldTestData->field_2->getLabel()}");
282     for ($delta = 0; $delta < $this->fieldTestData->field_storage_2->getCardinality(); $delta++) {
283       // field_test_widget uses 'textfield'
284       $this->assertEqual($form[$this->fieldTestData->field_name_2]['widget'][$delta]['value']['#type'], 'textfield', "Second field's form delta $delta widget is textfield");
285     }
286   }
287
288   /**
289    * Tests \Drupal\Core\Entity\Display\EntityFormDisplayInterface::extractFormValues().
290    */
291   public function testEntityFormDisplayExtractFormValues() {
292     $this->createFieldWithStorage('_2');
293
294     $entity_type = 'entity_test';
295     $entity_init = $this->container->get('entity_type.manager')
296       ->getStorage($entity_type)
297       ->create(['id' => 1, 'revision_id' => 1, 'type' => $this->fieldTestData->field->getTargetBundle()]);
298
299     // Build the form for all fields.
300     $display = entity_get_form_display($entity_type, $this->fieldTestData->field->getTargetBundle(), 'default');
301     $form = [];
302     $form_state = new FormState();
303     $display->buildForm($entity_init, $form, $form_state);
304
305     // Simulate incoming values.
306     // First field.
307     $values = [];
308     $weights = [];
309     for ($delta = 0; $delta < $this->fieldTestData->field_storage->getCardinality(); $delta++) {
310       $values[$delta]['value'] = mt_rand(1, 127);
311       // Assign random weight.
312       do {
313         $weight = mt_rand(0, $this->fieldTestData->field_storage->getCardinality());
314       } while (in_array($weight, $weights));
315       $weights[$delta] = $weight;
316       $values[$delta]['_weight'] = $weight;
317     }
318     // Leave an empty value. 'field_test' fields are empty if empty().
319     $values[1]['value'] = 0;
320     // Second field.
321     $values_2 = [];
322     $weights_2 = [];
323     for ($delta = 0; $delta < $this->fieldTestData->field_storage_2->getCardinality(); $delta++) {
324       $values_2[$delta]['value'] = mt_rand(1, 127);
325       // Assign random weight.
326       do {
327         $weight = mt_rand(0, $this->fieldTestData->field_storage_2->getCardinality());
328       } while (in_array($weight, $weights_2));
329       $weights_2[$delta] = $weight;
330       $values_2[$delta]['_weight'] = $weight;
331     }
332     // Leave an empty value. 'field_test' fields are empty if empty().
333     $values_2[1]['value'] = 0;
334
335     // Pretend the form has been built.
336     $form_state->setFormObject(\Drupal::entityManager()->getFormObject($entity_type, 'default'));
337     \Drupal::formBuilder()->prepareForm('field_test_entity_form', $form, $form_state);
338     \Drupal::formBuilder()->processForm('field_test_entity_form', $form, $form_state);
339     $form_state->setValue($this->fieldTestData->field_name, $values);
340     $form_state->setValue($this->fieldTestData->field_name_2, $values_2);
341
342     // Extract values for all fields.
343     $entity = clone($entity_init);
344     $display->extractFormValues($entity, $form, $form_state);
345
346     asort($weights);
347     asort($weights_2);
348     $expected_values = [];
349     $expected_values_2 = [];
350     foreach ($weights as $key => $value) {
351       if ($key != 1) {
352         $expected_values[] = ['value' => $values[$key]['value']];
353       }
354     }
355     $this->assertIdentical($entity->{$this->fieldTestData->field_name}->getValue(), $expected_values, 'Submit filters empty values');
356     foreach ($weights_2 as $key => $value) {
357       if ($key != 1) {
358         $expected_values_2[] = ['value' => $values_2[$key]['value']];
359       }
360     }
361     $this->assertIdentical($entity->{$this->fieldTestData->field_name_2}->getValue(), $expected_values_2, 'Submit filters empty values');
362
363     // Call EntityFormDisplayInterface::extractFormValues() for a single field (the second field).
364     foreach ($display->getComponents() as $name => $options) {
365       if ($name != $this->fieldTestData->field_name_2) {
366         $display->removeComponent($name);
367       }
368     }
369     $entity = clone($entity_init);
370     $display->extractFormValues($entity, $form, $form_state);
371     $expected_values_2 = [];
372     foreach ($weights_2 as $key => $value) {
373       if ($key != 1) {
374         $expected_values_2[] = ['value' => $values_2[$key]['value']];
375       }
376     }
377     $this->assertTrue($entity->{$this->fieldTestData->field_name}->isEmpty(), 'The first field is empty in the entity object');
378     $this->assertIdentical($entity->{$this->fieldTestData->field_name_2}->getValue(), $expected_values_2, 'Submit filters empty values');
379   }
380
381 }