PageRenderTime 27ms CodeModel.GetById 32ms RepoModel.GetById 1ms app.codeStats 0ms

/core/modules/field/src/Tests/EntityReference/EntityReferenceFormatterTest.php

https://gitlab.com/geeta7/drupal
PHP | 301 lines | 167 code | 45 blank | 89 comment | 0 complexity | 1e8c490715a79916c845e76d704986b3 MD5 | raw file
  1. <?php
  2. /**
  3. * @file
  4. * Contains \Drupal\field\Tests\EntityReference\EntityReferenceFormatterTest.
  5. */
  6. namespace Drupal\field\Tests\EntityReference;
  7. use Drupal\Core\Cache\Cache;
  8. use Drupal\Core\Cache\CacheableMetadata;
  9. use Drupal\Core\Field\FieldStorageDefinitionInterface;
  10. use Drupal\field\Entity\FieldStorageConfig;
  11. use Drupal\filter\Entity\FilterFormat;
  12. use Drupal\system\Tests\Entity\EntityUnitTestBase;
  13. use Drupal\user\Entity\Role;
  14. use Drupal\user\RoleInterface;
  15. /**
  16. * Tests the formatters functionality.
  17. *
  18. * @group entity_reference
  19. */
  20. class EntityReferenceFormatterTest extends EntityUnitTestBase {
  21. use EntityReferenceTestTrait;
  22. /**
  23. * The entity type used in this test.
  24. *
  25. * @var string
  26. */
  27. protected $entityType = 'entity_test';
  28. /**
  29. * The bundle used in this test.
  30. *
  31. * @var string
  32. */
  33. protected $bundle = 'entity_test';
  34. /**
  35. * The name of the field used in this test.
  36. *
  37. * @var string
  38. */
  39. protected $fieldName = 'field_test';
  40. /**
  41. * The entity to be referenced in this test.
  42. *
  43. * @var \Drupal\Core\Entity\EntityInterface
  44. */
  45. protected $referencedEntity;
  46. /**
  47. * The entity that is not yet saved to its persistent storage to be referenced
  48. * in this test.
  49. *
  50. * @var \Drupal\Core\Entity\EntityInterface
  51. */
  52. protected $unsavedReferencedEntity;
  53. protected function setUp() {
  54. parent::setUp();
  55. // Use Classy theme for testing markup output.
  56. \Drupal::service('theme_handler')->install(['classy']);
  57. $this->config('system.theme')->set('default', 'classy')->save();
  58. // Grant the 'view test entity' permission.
  59. $this->installConfig(array('user'));
  60. Role::load(RoleInterface::ANONYMOUS_ID)
  61. ->grantPermission('view test entity')
  62. ->save();
  63. // The label formatter rendering generates links, so build the router.
  64. $this->installSchema('system', 'router');
  65. $this->container->get('router.builder')->rebuild();
  66. $this->createEntityReferenceField($this->entityType, $this->bundle, $this->fieldName, 'Field test', $this->entityType, 'default', array(), FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
  67. // Set up a field, so that the entity that'll be referenced bubbles up a
  68. // cache tag when rendering it entirely.
  69. entity_create('field_storage_config', array(
  70. 'field_name' => 'body',
  71. 'entity_type' => $this->entityType,
  72. 'type' => 'text',
  73. 'settings' => array(),
  74. ))->save();
  75. entity_create('field_config', array(
  76. 'entity_type' => $this->entityType,
  77. 'bundle' => $this->bundle,
  78. 'field_name' => 'body',
  79. 'label' => 'Body',
  80. ))->save();
  81. entity_get_display($this->entityType, $this->bundle, 'default')
  82. ->setComponent('body', array(
  83. 'type' => 'text_default',
  84. 'settings' => array(),
  85. ))
  86. ->save();
  87. entity_create('filter_format', array(
  88. 'format' => 'full_html',
  89. 'name' => 'Full HTML',
  90. ))->save();
  91. // Create the entity to be referenced.
  92. $this->referencedEntity = entity_create($this->entityType, array('name' => $this->randomMachineName()));
  93. $this->referencedEntity->body = array(
  94. 'value' => '<p>Hello, world!</p>',
  95. 'format' => 'full_html',
  96. );
  97. $this->referencedEntity->save();
  98. // Create another entity to be referenced but do not save it.
  99. $this->unsavedReferencedEntity = entity_create($this->entityType, array('name' => $this->randomMachineName()));
  100. $this->unsavedReferencedEntity->body = array(
  101. 'value' => '<p>Hello, unsaved world!</p>',
  102. 'format' => 'full_html',
  103. );
  104. }
  105. /**
  106. * Assert inaccessible items don't change the data of the fields.
  107. */
  108. public function testAccess() {
  109. // Revoke the 'view test entity' permission for this test.
  110. Role::load(RoleInterface::ANONYMOUS_ID)
  111. ->revokePermission('view test entity')
  112. ->save();
  113. $field_name = $this->fieldName;
  114. $referencing_entity = entity_create($this->entityType, array('name' => $this->randomMachineName()));
  115. $referencing_entity->save();
  116. $referencing_entity->{$field_name}->entity = $this->referencedEntity;
  117. // Assert user doesn't have access to the entity.
  118. $this->assertFalse($this->referencedEntity->access('view'), 'Current user does not have access to view the referenced entity.');
  119. $formatter_manager = $this->container->get('plugin.manager.field.formatter');
  120. // Get all the existing formatters.
  121. foreach ($formatter_manager->getOptions('entity_reference') as $formatter => $name) {
  122. // Set formatter type for the 'full' view mode.
  123. entity_get_display($this->entityType, $this->bundle, 'default')
  124. ->setComponent($field_name, array(
  125. 'type' => $formatter,
  126. ))
  127. ->save();
  128. // Invoke entity view.
  129. entity_view($referencing_entity, 'default');
  130. // Verify the un-accessible item still exists.
  131. $this->assertEqual($referencing_entity->{$field_name}->target_id, $this->referencedEntity->id(), format_string('The un-accessible item still exists after @name formatter was executed.', array('@name' => $name)));
  132. }
  133. }
  134. /**
  135. * Tests the ID formatter.
  136. */
  137. public function testIdFormatter() {
  138. $formatter = 'entity_reference_entity_id';
  139. $build = $this->buildRenderArray([$this->referencedEntity, $this->unsavedReferencedEntity], $formatter);
  140. $this->assertEqual($build[0]['#plain_text'], $this->referencedEntity->id(), sprintf('The markup returned by the %s formatter is correct for an item with a saved entity.', $formatter));
  141. $this->assertEqual($build[0]['#cache']['tags'], $this->referencedEntity->getCacheTags(), sprintf('The %s formatter has the expected cache tags.', $formatter));
  142. $this->assertTrue(!isset($build[1]), sprintf('The markup returned by the %s formatter is correct for an item with a unsaved entity.', $formatter));
  143. }
  144. /**
  145. * Tests the entity formatter.
  146. */
  147. public function testEntityFormatter() {
  148. /** @var \Drupal\Core\Render\RendererInterface $renderer */
  149. $renderer = $this->container->get('renderer');
  150. $formatter = 'entity_reference_entity_view';
  151. $build = $this->buildRenderArray([$this->referencedEntity, $this->unsavedReferencedEntity], $formatter);
  152. // Test the first field item.
  153. $expected_rendered_name_field_1 = '
  154. <div class="field field--name-name field--type-string field--label-hidden field__item">' . $this->referencedEntity->label() . '</div>
  155. ';
  156. $expected_rendered_body_field_1 = '
  157. <div class="clearfix text-formatted field field--name-body field--type-text field--label-above">
  158. <div class="field__label">Body</div>
  159. <div class="field__item"><p>Hello, world!</p></div>
  160. </div>
  161. ';
  162. $renderer->renderRoot($build[0]);
  163. $this->assertEqual($build[0]['#markup'], 'default | ' . $this->referencedEntity->label() . $expected_rendered_name_field_1 . $expected_rendered_body_field_1, sprintf('The markup returned by the %s formatter is correct for an item with a saved entity.', $formatter));
  164. $expected_cache_tags = Cache::mergeTags(\Drupal::entityManager()->getViewBuilder($this->entityType)->getCacheTags(), $this->referencedEntity->getCacheTags());
  165. $expected_cache_tags = Cache::mergeTags($expected_cache_tags, FilterFormat::load('full_html')->getCacheTags());
  166. $this->assertEqual($build[0]['#cache']['tags'], $expected_cache_tags, format_string('The @formatter formatter has the expected cache tags.', array('@formatter' => $formatter)));
  167. // Test the second field item.
  168. $renderer->renderRoot($build[1]);
  169. $this->assertEqual($build[1]['#markup'], $this->unsavedReferencedEntity->label(), sprintf('The markup returned by the %s formatter is correct for an item with a unsaved entity.', $formatter));
  170. }
  171. /**
  172. * Tests the label formatter.
  173. */
  174. public function testLabelFormatter() {
  175. /** @var \Drupal\Core\Render\RendererInterface $renderer */
  176. $renderer = $this->container->get('renderer');
  177. $formatter = 'entity_reference_label';
  178. // The 'link' settings is TRUE by default.
  179. $build = $this->buildRenderArray([$this->referencedEntity, $this->unsavedReferencedEntity], $formatter);
  180. $expected_field_cacheability = [
  181. 'contexts' => [],
  182. 'tags' => [],
  183. 'max-age' => Cache::PERMANENT,
  184. ];
  185. $this->assertEqual($build['#cache'], $expected_field_cacheability, 'The field render array contains the entity access cacheability metadata');
  186. $expected_item_1 = array(
  187. '#type' => 'link',
  188. '#title' => $this->referencedEntity->label(),
  189. '#url' => $this->referencedEntity->urlInfo(),
  190. '#options' => $this->referencedEntity->urlInfo()->getOptions(),
  191. '#cache' => array(
  192. 'contexts' => [
  193. 'user.permissions',
  194. ],
  195. 'tags' => $this->referencedEntity->getCacheTags(),
  196. ),
  197. );
  198. $this->assertEqual($renderer->renderRoot($build[0]), $renderer->renderRoot($expected_item_1), sprintf('The markup returned by the %s formatter is correct for an item with a saved entity.', $formatter));
  199. $this->assertEqual(CacheableMetadata::createFromRenderArray($build[0]), CacheableMetadata::createFromRenderArray($expected_item_1));
  200. // The second referenced entity is "autocreated", therefore not saved and
  201. // lacking any URL info.
  202. $expected_item_2 = array(
  203. '#plain_text' => $this->unsavedReferencedEntity->label(),
  204. '#cache' => array(
  205. 'contexts' => [
  206. 'user.permissions',
  207. ],
  208. 'tags' => $this->unsavedReferencedEntity->getCacheTags(),
  209. 'max-age' => Cache::PERMANENT,
  210. ),
  211. );
  212. $this->assertEqual($build[1], $expected_item_2, sprintf('The render array returned by the %s formatter is correct for an item with a unsaved entity.', $formatter));
  213. // Test with the 'link' setting set to FALSE.
  214. $build = $this->buildRenderArray([$this->referencedEntity, $this->unsavedReferencedEntity], $formatter, array('link' => FALSE));
  215. $this->assertEqual($build[0]['#plain_text'], $this->referencedEntity->label(), sprintf('The markup returned by the %s formatter is correct for an item with a saved entity.', $formatter));
  216. $this->assertEqual($build[1]['#plain_text'], $this->unsavedReferencedEntity->label(), sprintf('The markup returned by the %s formatter is correct for an item with a unsaved entity.', $formatter));
  217. // Test an entity type that doesn't have any link templates, which means
  218. // \Drupal\Core\Entity\EntityInterface::urlInfo() will throw an exception
  219. // and the label formatter will output only the label instead of a link.
  220. $field_storage_config = FieldStorageConfig::loadByName($this->entityType, $this->fieldName);
  221. $field_storage_config->setSetting('target_type', 'entity_test_label');
  222. $field_storage_config->save();
  223. $referenced_entity_with_no_link_template = entity_create('entity_test_label', array(
  224. 'name' => $this->randomMachineName(),
  225. ));
  226. $referenced_entity_with_no_link_template->save();
  227. $build = $this->buildRenderArray([$referenced_entity_with_no_link_template], $formatter, array('link' => TRUE));
  228. $this->assertEqual($build[0]['#plain_text'], $referenced_entity_with_no_link_template->label(), sprintf('The markup returned by the %s formatter is correct for an entity type with no valid link template.', $formatter));
  229. }
  230. /**
  231. * Sets field values and returns a render array as built by
  232. * \Drupal\Core\Field\FieldItemListInterface::view().
  233. *
  234. * @param \Drupal\Core\Entity\EntityInterface[] $referenced_entities
  235. * An array of entity objects that will be referenced.
  236. * @param string $formatter
  237. * The formatted plugin that will be used for building the render array.
  238. * @param array $formatter_options
  239. * Settings specific to the formatter. Defaults to the formatter's default
  240. * settings.
  241. *
  242. * @return array
  243. * A render array.
  244. */
  245. protected function buildRenderArray(array $referenced_entities, $formatter, $formatter_options = array()) {
  246. // Create the entity that will have the entity reference field.
  247. $referencing_entity = entity_create($this->entityType, array('name' => $this->randomMachineName()));
  248. $items = $referencing_entity->get($this->fieldName);
  249. // Assign the referenced entities.
  250. foreach ($referenced_entities as $referenced_entity) {
  251. $items[] = ['entity' => $referenced_entity];
  252. }
  253. // Build the renderable array for the field.
  254. return $items->view(array('type' => $formatter, 'settings' => $formatter_options));
  255. }
  256. }