Skip to content
Snippets Groups Projects
Commit 1de9a47e authored by Erik Stielstra's avatar Erik Stielstra Committed by Erik Stielstra
Browse files

Issue #2904528 by Sutharsan: Do not wrap a #cache only render array in field wrappers

parent c0e9870c
No related branches found
Tags 8.x-1.0 8.x-1.0-beta1
No related merge requests found
......@@ -2,6 +2,7 @@
namespace Drupal\extra_field_example\Plugin\ExtraField\Display;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\extra_field\Plugin\ExtraFieldDisplayFormattedBase;
......@@ -24,16 +25,27 @@ class ExampleMultilingualField extends ExtraFieldDisplayFormattedBase {
public function viewElements(ContentEntityInterface $entity) {
$elements = [];
if ($tagsField = $this->getTagsField()) {
$cache = new CacheableMetadata();
$tagsField = $this->getTagsField();
if ($tagsField && !$tagsField->isEmpty()) {
// Build the field output as a concatenation of tags.
// Build the field output as a concatenated string of tags.
$tags = [];
foreach ($tagsField as $item) {
$tags[] = $item->entity->label();
/** @var \Drupal\Core\Entity\ContentEntityInterface $tag */
$tag = $item->entity;
$tags[] = $tag->label();
$cache->addCacheableDependency($tag);
}
$elements = ['#markup' => implode(', ', $tags)];
}
else {
// Mark the result as empty to make sure no field wrapper is applied.
$this->isEmpty = TRUE;
}
$cache->applyTo($elements);
return $elements;
}
......
......@@ -11,6 +11,20 @@ use Drupal\Core\Render\Element;
*/
abstract class ExtraFieldDisplayFormattedBase extends ExtraFieldDisplayBase implements ExtraFieldDisplayFormattedInterface {
/**
* Flag to indicate that the extra field has no content.
*
* Set this flag when the render elements returned by ::viewElements only
* contains non-visible render data such as #cache or #attached but does not
* contain actual renderable data such as #markup, #theme or #item.
*
* When this flag is set, the render elements will not be wrapped in a field
* wrapper.
*
* @var bool
*/
protected $isEmpty = FALSE;
/**
* The langcode of the field values.
*
......@@ -29,10 +43,9 @@ abstract class ExtraFieldDisplayFormattedBase extends ExtraFieldDisplayBase impl
* {@inheritdoc}
*/
public function view(ContentEntityInterface $entity) {
$build = [];
$elements = $this->viewElements($entity);
if (!empty($elements)) {
if (!empty($elements) && !$this->isEmpty()) {
// Construct a render array for the extra field elements.
// @see \Drupal\Core\Field\FormatterBase::view
$build = [
......@@ -74,6 +87,9 @@ abstract class ExtraFieldDisplayFormattedBase extends ExtraFieldDisplayBase impl
$build[] = $elements;
}
}
else {
$build = $elements;
}
return $build;
}
......@@ -106,6 +122,13 @@ abstract class ExtraFieldDisplayFormattedBase extends ExtraFieldDisplayBase impl
return 'extra_field_' . $this->pluginId;
}
/**
* {@inheritdoc}
*/
public function isEmpty() {
return $this->isEmpty;
}
/**
* {@inheritdoc}
*/
......
......@@ -60,6 +60,15 @@ interface ExtraFieldDisplayFormattedInterface extends ExtraFieldDisplayInterface
*/
public function getFieldName();
/**
* Check if the extra field has data.
*
* @return bool
* True if the field has no actual data to render. False if it only contains
* non-visible render elements such as #cache and #attached.
*/
public function isEmpty();
/**
* Gets the langcode of the field values.
*
......
<?php
namespace Drupal\extra_field_test\Plugin\ExtraField\Display;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\extra_field\Plugin\ExtraFieldDisplayFormattedBase;
/**
* Extra field Display for a field without content.
*
* @ExtraFieldDisplay(
* id = "empty_formatted_test",
* label = @Translation("Formatted extra field without content"),
* bundles = {
* "node.first_node_type",
* },
* visible = true
* )
*/
class EmptyFormattedFieldTest extends ExtraFieldDisplayFormattedBase {
/**
* {@inheritdoc}
*/
public function viewElements(ContentEntityInterface $entity) {
$elements = ['#cache' => ['max-age' => 0]];
// This field has no content.
$this->isEmpty = TRUE;
return $elements;
}
}
......@@ -22,7 +22,7 @@ class ExtraFieldDisplayFieldTest extends ExtraFieldBrowserTestBase {
*
* @var \Drupal\node\Entity\Node
*/
protected $content;
protected $firstNode;
/**
* {@inheritdoc}
......@@ -30,36 +30,32 @@ class ExtraFieldDisplayFieldTest extends ExtraFieldBrowserTestBase {
protected function setUp() {
parent::setUp();
$this->content = $this->createContent('first_node_type');
$this->firstNode = $this->createContent('first_node_type');
$this->setupEnableExtraFieldTestModule();
}
/**
* Test the output of field with single value item.
*/
public function testSingleField() {
public function testFirstNodeTypeFields() {
$url = $this->content->toUrl();
$url = $this->firstNode->toUrl();
$this->drupalGet($url);
// Test the output of field with single value item.
$this->assertSession()->responseContains('<div class="field__item">Output from SingleTextFieldTest</div>');
$this->assertSession()->responseContains('<div class="field__label">Single text</div>');
$this->assertSession()->responseContains('field--name-field-single-text');
$this->assertSession()->responseContains('field--type-single-text');
$this->assertSession()->responseContains('field--label-inline');
}
/**
* Test the output of field with multiple value items.
*/
public function testMultipleField() {
$url = $this->content->toUrl();
$this->drupalGet($url);
// Test the output of field with multiple value items.
$this->assertSession()->responseContains('<div class="field__item">Aap</div>');
$this->assertSession()->responseContains('<div class="field__item">Noot</div>');
$this->assertSession()->responseContains('field--name-extra-field-multiple-text-test');
// Test the output of field without content.
$this->assertSession()->responseNotContains('field--name-extra-field-empty-formatted-test');
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment