core/lib/Drupal/Core/Menu/MenuLinkTree.php | 3 ++- core/lib/Drupal/Core/Render/Element.php | 16 ++++++++++++++++ core/modules/block/src/BlockViewBuilder.php | 2 +- core/tests/Drupal/Tests/Core/Render/ElementTest.php | 21 +++++++++++++++++++++ 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/core/lib/Drupal/Core/Menu/MenuLinkTree.php b/core/lib/Drupal/Core/Menu/MenuLinkTree.php index 9d95501..332a2c7 100644 --- a/core/lib/Drupal/Core/Menu/MenuLinkTree.php +++ b/core/lib/Drupal/Core/Menu/MenuLinkTree.php @@ -8,6 +8,7 @@ namespace Drupal\Core\Menu; use Drupal\Component\Utility\NestedArray; +use Drupal\Core\Access\AccessResultInterface; use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Controller\ControllerResolverInterface; @@ -179,7 +180,7 @@ public function build(array $tree, $level = 0) { $tree_link_cacheability = $tree_link_cacheability->merge(CacheableMetadata::createFromObject($data->link)); // Only render accessible links. - if (!$data->access->isAllowed()) { + if ($data->access instanceof AccessResultInterface && !$data->access->isAllowed()) { continue; } diff --git a/core/lib/Drupal/Core/Render/Element.php b/core/lib/Drupal/Core/Render/Element.php index 094a7d5..256b5e3 100644 --- a/core/lib/Drupal/Core/Render/Element.php +++ b/core/lib/Drupal/Core/Render/Element.php @@ -177,4 +177,20 @@ public static function setAttributes(array &$element, array $map) { } } + /** + * Indicates whether the given element is empty. + * + * An element that only has #cache set is considered empty, because it will + * render to the empty string. + * + * @param array $elements + * The element. + * + * @return bool + * Whether the given element is empty. + */ + public static function isEmpty(array $elements) { + return empty($elements) || count($elements) === 1 && array_keys($elements) === ['#cache']; + } + } diff --git a/core/modules/block/src/BlockViewBuilder.php b/core/modules/block/src/BlockViewBuilder.php index 5b94d5c..f674d68 100644 --- a/core/modules/block/src/BlockViewBuilder.php +++ b/core/modules/block/src/BlockViewBuilder.php @@ -105,7 +105,7 @@ public function buildBlock($build) { // Remove the block entity from the render array, to ensure that blocks // can be rendered without the block config entity. unset($build['#block']); - if (!empty($content) && !(count($content) === 1 && array_keys($content) === ['#cache'])) { + if (!Element::isEmpty($content)) { // Place the $content returned by the block plugin into a 'content' child // element, as a way to allow the plugin to have complete control of its // properties and rendering (e.g., its own #theme) without conflicting diff --git a/core/tests/Drupal/Tests/Core/Render/ElementTest.php b/core/tests/Drupal/Tests/Core/Render/ElementTest.php index 0d764cd..8220d99 100644 --- a/core/tests/Drupal/Tests/Core/Render/ElementTest.php +++ b/core/tests/Drupal/Tests/Core/Render/ElementTest.php @@ -179,4 +179,25 @@ public function providerTestSetAttributes() { ); } + /** + * @covers ::isEmpty + * + * @dataProvider providerTestIsEmpty + */ + public function testIsEmpty(array $element, $expected) { + $this->assertSame(Element::isEmpty($element), $expected); + } + + public function providerTestIsEmpty() { + return [ + [[], TRUE], + [['#cache' => []], TRUE], + [['#cache' => ['tags' => ['foo']]], TRUE], + [['#cache' => ['contexts' => ['bar']]], TRUE], + + [['#cache' => [], '#any_other_property' => TRUE], FALSE], + [['#any_other_property' => TRUE], FALSE], + ]; + } + }