FieldAttachOtherTest.php 16.7 KB
Newer Older
1 2 3 4
<?php

/**
 * @file
5
 * Contains \Drupal\field\Tests\FieldAttachOtherTest.
6 7 8 9
 */

namespace Drupal\field\Tests;

10
use Drupal\Core\Form\FormState;
11
use Drupal\entity_test\Entity\EntityTest;
12 13

/**
14
 * Tests other Field API functions.
15
 *
16
 * @group field
17
 * @todo move this to the Entity module
18
 */
19
class FieldAttachOtherTest extends FieldUnitTestBase {
20

21
  protected function setUp() {
22
    parent::setUp();
23
    $this->container->get('router.builder')->rebuild();
24
    $this->installEntitySchema('entity_test_rev');
25
    $this->createFieldWithStorage();
26 27
  }

28
  /**
29
   * Test rendering fields with EntityDisplay build().
30
   */
31
  function testEntityDisplayBuild() {
32
    $this->createFieldWithStorage('_2');
33

34
    $entity_type = 'entity_test';
35 36 37
    $entity_init = $this->container->get('entity_type.manager')
      ->getStorage($entity_type)
      ->create();
38 39

    // Populate values to be displayed.
40 41 42 43
    $values = $this->_generateTestFieldValues($this->fieldTestData->field_storage->getCardinality());
    $entity_init->{$this->fieldTestData->field_name}->setValue($values);
    $values_2 = $this->_generateTestFieldValues($this->fieldTestData->field_storage_2->getCardinality());
    $entity_init->{$this->fieldTestData->field_name_2}->setValue($values_2);
44 45 46

    // Simple formatter, label displayed.
    $entity = clone($entity_init);
47 48
    $display = entity_get_display($entity_type, $entity->bundle(), 'full');

49
    $formatter_setting = $this->randomMachineName();
50 51 52 53 54
    $display_options = array(
      'label' => 'above',
      'type' => 'field_test_default',
      'settings' => array(
        'test_formatter_setting' => $formatter_setting,
55 56
      ),
    );
57
    $display->setComponent($this->fieldTestData->field_name, $display_options);
58

59
    $formatter_setting_2 = $this->randomMachineName();
60 61 62 63 64
    $display_options_2 = array(
      'label' => 'above',
      'type' => 'field_test_default',
      'settings' => array(
        'test_formatter_setting' => $formatter_setting_2,
65 66
      ),
    );
67
    $display->setComponent($this->fieldTestData->field_name_2, $display_options_2);
68

69
    // View all fields.
70
    $content = $display->build($entity);
71
    $this->render($content);
72
    $this->assertRaw($this->fieldTestData->field->getLabel(), "First field's label is displayed.");
73 74 75
    foreach ($values as $delta => $value) {
      $this->assertRaw("$formatter_setting|{$value['value']}", "Value $delta is displayed, formatter settings are applied.");
    }
76
    $this->assertRaw($this->fieldTestData->field_2->getLabel(), "Second field's label is displayed.");
77 78 79
    foreach ($values_2 as $delta => $value) {
      $this->assertRaw("$formatter_setting_2|{$value['value']}", "Value $delta is displayed, formatter settings are applied.");
    }
80 81 82

    // Label hidden.
    $entity = clone($entity_init);
83
    $display_options['label'] = 'hidden';
84
    $display->setComponent($this->fieldTestData->field_name, $display_options);
85
    $content = $display->build($entity);
86
    $this->render($content);
87
    $this->assertNoRaw($this->fieldTestData->field->getLabel(), "Hidden label: label is not displayed.");
88 89 90

    // Field hidden.
    $entity = clone($entity_init);
91
    $display->removeComponent($this->fieldTestData->field_name);
92
    $content = $display->build($entity);
93
    $this->render($content);
94
    $this->assertNoRaw($this->fieldTestData->field->getLabel(), "Hidden field: label is not displayed.");
95
    foreach ($values as $delta => $value) {
96
      $this->assertNoRaw("$formatter_setting|{$value['value']}", "Hidden field: value $delta is not displayed.");
97 98 99 100
    }

    // Multiple formatter.
    $entity = clone($entity_init);
101
    $formatter_setting = $this->randomMachineName();
102
    $display->setComponent($this->fieldTestData->field_name, array(
103 104 105 106
      'label' => 'above',
      'type' => 'field_test_multiple',
      'settings' => array(
        'test_formatter_setting_multiple' => $formatter_setting,
107
      ),
108
    ));
109
    $content = $display->build($entity);
110
    $this->render($content);
111
    $expected_output = $formatter_setting;
112
    foreach ($values as $delta => $value) {
113
      $expected_output .= "|$delta:{$value['value']}";
114
    }
115
    $this->assertRaw($expected_output, "Multiple formatter: all values are displayed, formatter settings are applied.");
116 117 118

    // Test a formatter that uses hook_field_formatter_prepare_view().
    $entity = clone($entity_init);
119
    $formatter_setting = $this->randomMachineName();
120
    $display->setComponent($this->fieldTestData->field_name, array(
121 122 123 124
      'label' => 'above',
      'type' => 'field_test_with_prepare_view',
      'settings' => array(
        'test_formatter_setting_additional' => $formatter_setting,
125
      ),
126
    ));
127
    $content = $display->build($entity);
128
    $this->render($content);
129 130 131 132 133 134 135 136 137 138
    foreach ($values as $delta => $value) {
      $expected = $formatter_setting . '|' . $value['value'] . '|' . ($value['value'] + 1);
      $this->assertRaw($expected, "Value $delta is displayed, formatter settings are applied.");
    }

    // TODO:
    // - check display order with several fields
  }

  /**
139
   * Tests rendering fields with EntityDisplay::buildMultiple().
140
   */
141 142
  function testEntityDisplayViewMultiple() {
    // Use a formatter that has a prepareView() step.
143
    $display = entity_get_display('entity_test', 'entity_test', 'full')
144
      ->setComponent($this->fieldTestData->field_name, array(
145 146 147
        'type' => 'field_test_with_prepare_view',
      ));

148
    // Create two entities.
149
    $entity1 = EntityTest::create(array('id' => 1, 'type' => 'entity_test'));
150
    $entity1->{$this->fieldTestData->field_name}->setValue($this->_generateTestFieldValues(1));
151
    $entity2 = EntityTest::create(array('id' => 2, 'type' => 'entity_test'));
152
    $entity2->{$this->fieldTestData->field_name}->setValue($this->_generateTestFieldValues(1));
153 154 155

    // Run buildMultiple(), and check that the entities come out as expected.
    $display->buildMultiple(array($entity1, $entity2));
156
    $item1 = $entity1->{$this->fieldTestData->field_name}[0];
157
    $this->assertEqual($item1->additional_formatter_value, $item1->value + 1, 'Entity 1 ran through the prepareView() formatter method.');
158
    $item2 = $entity2->{$this->fieldTestData->field_name}[0];
159
    $this->assertEqual($item2->additional_formatter_value, $item2->value + 1, 'Entity 2 ran through the prepareView() formatter method.');
160 161 162
  }

  /**
163 164 165
   * Test entity cache.
   *
   * Complements unit test coverage in
166
   * \Drupal\Tests\Core\Entity\Sql\SqlContentEntityStorageTest.
167
   */
168
  function testEntityCache() {
169
    // Initialize random values and a test entity.
170
    $entity_init = EntityTest::create(array('type' => $this->fieldTestData->field->getTargetBundle()));
171
    $values = $this->_generateTestFieldValues($this->fieldTestData->field_storage->getCardinality());
172 173

    // Non-cacheable entity type.
174
    $entity_type = 'entity_test';
175
    $cid = "values:$entity_type:" . $entity_init->id();
176 177

    // Check that no initial cache entry is present.
178
    $this->assertFalse(\Drupal::cache('entity')->get($cid), 'Non-cached: no initial cache entry');
179 180 181

    // Save, and check that no cache entry is present.
    $entity = clone($entity_init);
182
    $entity->{$this->fieldTestData->field_name}->setValue($values);
183
    $entity = $this->entitySaveReload($entity);
184
    $cid = "values:$entity_type:" . $entity->id();
185
    $this->assertFalse(\Drupal::cache('entity')->get($cid), 'Non-cached: no cache entry on insert and load');
186 187

    // Cacheable entity type.
188
    $entity_type = 'entity_test_rev';
189
    $this->createFieldWithStorage('_2', $entity_type);
190

191 192 193 194 195
    $entity_init = $this->container->get('entity_type.manager')
      ->getStorage($entity_type)
      ->create(array(
        'type' => $entity_type,
      ));
196

197
    // Check that no initial cache entry is present.
198
    $cid = "values:$entity_type:" . $entity->id();
199
    $this->assertFalse(\Drupal::cache('entity')->get($cid), 'Cached: no initial cache entry');
200 201 202

    // Save, and check that no cache entry is present.
    $entity = clone($entity_init);
203
    $entity->{$this->fieldTestData->field_name_2} = $values;
204
    $entity->save();
205
    $cid = "values:$entity_type:" . $entity->id();
206

207
    $this->assertFalse(\Drupal::cache('entity')->get($cid), 'Cached: no cache entry on insert');
208
    // Load, and check that a cache entry is present with the expected values.
209
    $controller = $this->container->get('entity.manager')->getStorage($entity->getEntityTypeId());
210
    $controller->resetCache();
211
    $cached_entity = $controller->load($entity->id());
212
    $cache = \Drupal::cache('entity')->get($cid);
213
    $this->assertEqual($cache->data, $cached_entity, 'Cached: correct cache entry on load');
214 215

    // Update with different values, and check that the cache entry is wiped.
216 217
    $values = $this->_generateTestFieldValues($this->fieldTestData->field_storage_2->getCardinality());
    $entity->{$this->fieldTestData->field_name_2} = $values;
218
    $entity->save();
219
    $this->assertFalse(\Drupal::cache('entity')->get($cid), 'Cached: no cache entry on update');
220 221

    // Load, and check that a cache entry is present with the expected values.
222
    $controller->resetCache();
223
    $cached_entity = $controller->load($entity->id());
224
    $cache = \Drupal::cache('entity')->get($cid);
225
    $this->assertEqual($cache->data, $cached_entity, 'Cached: correct cache entry on load');
226 227

    // Create a new revision, and check that the cache entry is wiped.
228 229
    $values = $this->_generateTestFieldValues($this->fieldTestData->field_storage_2->getCardinality());
    $entity->{$this->fieldTestData->field_name_2} = $values;
230 231
    $entity->setNewRevision();
    $entity->save();
232
    $this->assertFalse(\Drupal::cache('entity')->get($cid), 'Cached: no cache entry on new revision creation');
233 234

    // Load, and check that a cache entry is present with the expected values.
235
    $controller->resetCache();
236
    $cached_entity = $controller->load($entity->id());
237
    $cache = \Drupal::cache('entity')->get($cid);
238
    $this->assertEqual($cache->data, $cached_entity, 'Cached: correct cache entry on load');
239 240

    // Delete, and check that the cache entry is wiped.
241
    $entity->delete();
242
    $this->assertFalse(\Drupal::cache('entity')->get($cid), 'Cached: no cache entry after delete');
243 244 245
  }

  /**
246
   * Tests \Drupal\Core\Entity\Display\EntityFormDisplayInterface::buildForm().
247 248 249 250
   *
   * This could be much more thorough, but it does verify that the correct
   * widgets show up.
   */
251
  function testEntityFormDisplayBuildForm() {
252
    $this->createFieldWithStorage('_2');
253

254
    $entity_type = 'entity_test';
255
    $entity = entity_create($entity_type, array('id' => 1, 'revision_id' => 1, 'type' => $this->fieldTestData->field->getTargetBundle()));
256

257
    // Test generating widgets for all fields.
258
    $display = entity_get_form_display($entity_type, $this->fieldTestData->field->getTargetBundle(), 'default');
259
    $form = array();
260
    $form_state = new FormState();
261
    $display->buildForm($entity, $form, $form_state);
262

263 264
    $this->assertEqual($form[$this->fieldTestData->field_name]['widget']['#title'], $this->fieldTestData->field->getLabel(), "First field's form title is {$this->fieldTestData->field->getLabel()}");
    $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()}");
265
    for ($delta = 0; $delta < $this->fieldTestData->field_storage->getCardinality(); $delta++) {
266
      // field_test_widget uses 'textfield'
267
      $this->assertEqual($form[$this->fieldTestData->field_name]['widget'][$delta]['value']['#type'], 'textfield', "First field's form delta $delta widget is textfield");
268
    }
269
    for ($delta = 0; $delta < $this->fieldTestData->field_storage_2->getCardinality(); $delta++) {
270
      // field_test_widget uses 'textfield'
271
      $this->assertEqual($form[$this->fieldTestData->field_name_2]['widget'][$delta]['value']['#type'], 'textfield', "Second field's form delta $delta widget is textfield");
272 273
    }

274
    // Test generating widgets for all fields.
275
    $display = entity_get_form_display($entity_type, $this->fieldTestData->field->getTargetBundle(), 'default');
276
    foreach ($display->getComponents() as $name => $options) {
277
      if ($name != $this->fieldTestData->field_name_2) {
278 279 280
        $display->removeComponent($name);
      }
    }
281
    $form = array();
282
    $form_state = new FormState();
283
    $display->buildForm($entity, $form, $form_state);
284

285
    $this->assertFalse(isset($form[$this->fieldTestData->field_name]), 'The first field does not exist in the form');
286
    $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()}");
287
    for ($delta = 0; $delta < $this->fieldTestData->field_storage_2->getCardinality(); $delta++) {
288
      // field_test_widget uses 'textfield'
289
      $this->assertEqual($form[$this->fieldTestData->field_name_2]['widget'][$delta]['value']['#type'], 'textfield', "Second field's form delta $delta widget is textfield");
290 291 292 293
    }
  }

  /**
294
   * Tests \Drupal\Core\Entity\Display\EntityFormDisplayInterface::extractFormValues().
295
   */
296
  function testEntityFormDisplayExtractFormValues() {
297
    $this->createFieldWithStorage('_2');
298

299
    $entity_type = 'entity_test';
300 301 302
    $entity_init = $this->container->get('entity_type.manager')
      ->getStorage($entity_type)
      ->create(array('id' => 1, 'revision_id' => 1, 'type' => $this->fieldTestData->field->getTargetBundle()));
303

304
    // Build the form for all fields.
305
    $display = entity_get_form_display($entity_type, $this->fieldTestData->field->getTargetBundle(), 'default');
306
    $form = array();
307
    $form_state = new FormState();
308
    $display->buildForm($entity_init, $form, $form_state);
309 310

    // Simulate incoming values.
311
    // First field.
312 313
    $values = array();
    $weights = array();
314
    for ($delta = 0; $delta < $this->fieldTestData->field_storage->getCardinality(); $delta++) {
315 316 317
      $values[$delta]['value'] = mt_rand(1, 127);
      // Assign random weight.
      do {
318
        $weight = mt_rand(0, $this->fieldTestData->field_storage->getCardinality());
319 320 321 322 323 324
      } while (in_array($weight, $weights));
      $weights[$delta] = $weight;
      $values[$delta]['_weight'] = $weight;
    }
    // Leave an empty value. 'field_test' fields are empty if empty().
    $values[1]['value'] = 0;
325 326 327
    // Second field.
    $values_2 = array();
    $weights_2 = array();
328
    for ($delta = 0; $delta < $this->fieldTestData->field_storage_2->getCardinality(); $delta++) {
329 330 331
      $values_2[$delta]['value'] = mt_rand(1, 127);
      // Assign random weight.
      do {
332
        $weight = mt_rand(0, $this->fieldTestData->field_storage_2->getCardinality());
333 334 335 336 337 338
      } while (in_array($weight, $weights_2));
      $weights_2[$delta] = $weight;
      $values_2[$delta]['_weight'] = $weight;
    }
    // Leave an empty value. 'field_test' fields are empty if empty().
    $values_2[1]['value'] = 0;
339 340

    // Pretend the form has been built.
341
    $form_state->setFormObject(\Drupal::entityManager()->getFormObject($entity_type, 'default'));
342
    \Drupal::formBuilder()->prepareForm('field_test_entity_form', $form, $form_state);
343
    \Drupal::formBuilder()->processForm('field_test_entity_form', $form, $form_state);
344 345
    $form_state->setValue($this->fieldTestData->field_name, $values);
    $form_state->setValue($this->fieldTestData->field_name_2, $values_2);
346

347
    // Extract values for all fields.
348
    $entity = clone($entity_init);
349
    $display->extractFormValues($entity, $form, $form_state);
350 351

    asort($weights);
352
    asort($weights_2);
353
    $expected_values = array();
354
    $expected_values_2 = array();
355 356 357 358 359
    foreach ($weights as $key => $value) {
      if ($key != 1) {
        $expected_values[] = array('value' => $values[$key]['value']);
      }
    }
360
    $this->assertIdentical($entity->{$this->fieldTestData->field_name}->getValue(), $expected_values, 'Submit filters empty values');
361 362 363 364 365
    foreach ($weights_2 as $key => $value) {
      if ($key != 1) {
        $expected_values_2[] = array('value' => $values_2[$key]['value']);
      }
    }
366
    $this->assertIdentical($entity->{$this->fieldTestData->field_name_2}->getValue(), $expected_values_2, 'Submit filters empty values');
367

368
    // Call EntityFormDisplayInterface::extractFormValues() for a single field (the second field).
369
    foreach ($display->getComponents() as $name => $options) {
370
      if ($name != $this->fieldTestData->field_name_2) {
371 372 373
        $display->removeComponent($name);
      }
    }
374
    $entity = clone($entity_init);
375
    $display->extractFormValues($entity, $form, $form_state);
376 377 378 379 380 381
    $expected_values_2 = array();
    foreach ($weights_2 as $key => $value) {
      if ($key != 1) {
        $expected_values_2[] = array('value' => $values_2[$key]['value']);
      }
    }
382 383
    $this->assertTrue($entity->{$this->fieldTestData->field_name}->isEmpty(), 'The first field is empty in the entity object');
    $this->assertIdentical($entity->{$this->fieldTestData->field_name_2}->getValue(), $expected_values_2, 'Submit filters empty values');
384
  }
385

386
}