Issue #2363025 by Wim Leers, dawehner, larowlan: Push usage of drupal_set_page_content() higher: out of blocks and page display variants.
parent
faff6ffabf
commit
ffe035e68f
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\Block\MainContentBlockPluginInterface.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\Block;
|
||||
|
||||
/**
|
||||
* The interface for "main page content" blocks.
|
||||
*
|
||||
* A main page content block represents the content returns by the controller.
|
||||
*
|
||||
* @ingroup block_api
|
||||
*/
|
||||
interface MainContentBlockPluginInterface extends BlockPluginInterface {
|
||||
|
||||
/**
|
||||
* Sets the main content render array.
|
||||
*
|
||||
* @param array $main_content
|
||||
* The render array representing the main content.
|
||||
*/
|
||||
public function setMainContent(array $main_content);
|
||||
|
||||
}
|
|
@ -13,9 +13,7 @@ use Drupal\Component\Annotation\Plugin;
|
|||
* Defines a display variant annotation object.
|
||||
*
|
||||
* Display variants are used to dictate the output of a given Display, which
|
||||
* can be used to control the output of many parts of Drupal. For example, the
|
||||
* FullPageVariant is used by the Block module to control regions and output
|
||||
* block content placed in those regions.
|
||||
* can be used to control the output of many parts of Drupal.
|
||||
*
|
||||
* Variants are usually chosen by some selection criteria, and are instantiated
|
||||
* directly. Each variant must define its own approach to rendering, and can
|
||||
|
@ -33,6 +31,7 @@ use Drupal\Component\Annotation\Plugin;
|
|||
* @see \Drupal\Core\Display\VariantInterface
|
||||
* @see \Drupal\Core\Display\VariantBase
|
||||
* @see \Drupal\Core\Display\VariantManager
|
||||
* @see \Drupal\Core\Display\PageVariantInterface
|
||||
* @see plugin_api
|
||||
*
|
||||
* @Annotation
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\Display\Annotation\PageDisplayVariant.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\Display\Annotation;
|
||||
|
||||
/**
|
||||
* Defines a page display variant annotation object.
|
||||
*
|
||||
* Page display variants are a specific type of display variant, intended to
|
||||
* render the main content of a page.
|
||||
*
|
||||
* @see \Drupal\Core\Display\VariantInterface
|
||||
* @see \Drupal\Core\Display\PageVariantInterface
|
||||
* @see \Drupal\Core\Display\VariantBase
|
||||
* @see \Drupal\Core\Display\VariantManager
|
||||
* @see plugin_api
|
||||
*
|
||||
* @Annotation
|
||||
*/
|
||||
class PageDisplayVariant extends DisplayVariant {
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\Display\PageVariantInterface.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\Display;
|
||||
|
||||
/**
|
||||
* Provides an interface for PageDisplayVariant plugins.
|
||||
*
|
||||
* Page display variants are a specific type of DisplayVariant, intended for
|
||||
* "pages", which always have some main content to be rendered. Hence page
|
||||
* display variants may choose to render that main content in a certain way:
|
||||
* decorated in a certain way, laid out in a certain way, et cetera.
|
||||
*
|
||||
* For example, the \Drupal\block\Plugin\DisplayVariant\FullPageVariant page
|
||||
* display variant is used by the Block module to control regions and output
|
||||
* blocks placed in those regions.
|
||||
*
|
||||
* @see \Drupal\Core\Display\Annotation\DisplayVariant
|
||||
* @see \Drupal\Core\Display\VariantBase
|
||||
* @see \Drupal\Core\Display\VariantManager
|
||||
* @see plugin_api
|
||||
*/
|
||||
interface PageVariantInterface extends VariantInterface {
|
||||
|
||||
/**
|
||||
* Sets the main content for the page being rendered.
|
||||
*
|
||||
* @param array $main_content
|
||||
* The render array representing the main content.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setMainContent(array $main_content);
|
||||
|
||||
}
|
|
@ -76,6 +76,7 @@ function _block_page_build(&$page) {
|
|||
// regions.
|
||||
$page += \Drupal::service('plugin.manager.display_variant')
|
||||
->createInstance('full_page')
|
||||
->setMainContent(drupal_set_page_content())
|
||||
->build();
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
namespace Drupal\block\Plugin\DisplayVariant;
|
||||
|
||||
use Drupal\Core\Block\MainContentBlockPluginInterface;
|
||||
use Drupal\Core\Display\PageVariantInterface;
|
||||
use Drupal\Core\Entity\EntityStorageInterface;
|
||||
use Drupal\Core\Entity\EntityViewBuilderInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
|
@ -18,12 +20,12 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
|||
/**
|
||||
* Provides a display variant that represents the full page.
|
||||
*
|
||||
* @DisplayVariant(
|
||||
* @PageDisplayVariant(
|
||||
* id = "full_page",
|
||||
* admin_label = @Translation("Full page")
|
||||
* )
|
||||
*/
|
||||
class FullPageVariant extends VariantBase implements ContainerFactoryPluginInterface {
|
||||
class FullPageVariant extends VariantBase implements PageVariantInterface, ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* The block storage.
|
||||
|
@ -60,6 +62,13 @@ class FullPageVariant extends VariantBase implements ContainerFactoryPluginInter
|
|||
*/
|
||||
protected $themeNegotiator;
|
||||
|
||||
/**
|
||||
* The render array representing the main page content.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $mainContent;
|
||||
|
||||
/**
|
||||
* Constructs a new FullPageVariant.
|
||||
*
|
||||
|
@ -101,6 +110,14 @@ class FullPageVariant extends VariantBase implements ContainerFactoryPluginInter
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setMainContent(array $main_content) {
|
||||
$this->mainContent = $main_content;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current theme for this page.
|
||||
*
|
||||
|
@ -115,12 +132,20 @@ class FullPageVariant extends VariantBase implements ContainerFactoryPluginInter
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function build() {
|
||||
// Track whether a block that shows the main content is displayed or not.
|
||||
$main_content_block_displayed = FALSE;
|
||||
|
||||
$build = array();
|
||||
// Load all region content assigned via blocks.
|
||||
foreach ($this->getRegionAssignments() as $region => $blocks) {
|
||||
/** @var $blocks \Drupal\block\BlockInterface[] */
|
||||
foreach ($blocks as $key => $block) {
|
||||
if ($block->access('view')) {
|
||||
$block_plugin = $block->getPlugin();
|
||||
if ($block_plugin instanceof MainContentBlockPluginInterface) {
|
||||
$block_plugin->setMainContent($this->mainContent);
|
||||
$main_content_block_displayed = TRUE;
|
||||
}
|
||||
$build[$region][$key] = $this->blockViewBuilder->view($block);
|
||||
}
|
||||
}
|
||||
|
@ -129,6 +154,14 @@ class FullPageVariant extends VariantBase implements ContainerFactoryPluginInter
|
|||
$build[$region]['#sorted'] = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// If no block that shows the main content is displayed, still show the main
|
||||
// content. Otherwise the end user will see all displayed blocks, but not
|
||||
// the main content they came for.
|
||||
if (!$main_content_block_displayed) {
|
||||
$build['content']['system_main'] = $this->mainContent;
|
||||
}
|
||||
|
||||
return $build;
|
||||
}
|
||||
|
||||
|
|
|
@ -65,13 +65,78 @@ class FullPageVariantTest extends UnitTestCase {
|
|||
->getMock();
|
||||
}
|
||||
|
||||
public function providerBuild() {
|
||||
$blocks_config = array(
|
||||
'block1' => array(
|
||||
TRUE, 'top', 0, FALSE,
|
||||
),
|
||||
// Test a block without access.
|
||||
'block2' => array(
|
||||
FALSE, 'bottom', 0, FALSE,
|
||||
),
|
||||
// Test two blocks in the same region with specific weight.
|
||||
'block3' => array(
|
||||
TRUE, 'bottom', 5, FALSE,
|
||||
),
|
||||
'block4' => array(
|
||||
TRUE, 'bottom', -5, FALSE,
|
||||
),
|
||||
// Test a block implementing MainContentBlockPluginInterface.
|
||||
'block5' => array(
|
||||
TRUE, 'center', 0, TRUE,
|
||||
),
|
||||
);
|
||||
|
||||
$test_cases = [];
|
||||
$test_cases[] = [$blocks_config, 4,
|
||||
[
|
||||
'top' => [
|
||||
'block1' => [],
|
||||
'#sorted' => TRUE,
|
||||
],
|
||||
// The main content was rendered via a block.
|
||||
'center' => [
|
||||
'block5' => [],
|
||||
'#sorted' => TRUE,
|
||||
],
|
||||
'bottom' => [
|
||||
'block4' => [],
|
||||
'block3' => [],
|
||||
'#sorted' => TRUE,
|
||||
],
|
||||
],
|
||||
];
|
||||
unset($blocks_config['block5']);
|
||||
$test_cases[] = [$blocks_config, 3,
|
||||
[
|
||||
'top' => [
|
||||
'block1' => [],
|
||||
'#sorted' => TRUE,
|
||||
],
|
||||
'bottom' => [
|
||||
'block4' => [],
|
||||
'block3' => [],
|
||||
'#sorted' => TRUE,
|
||||
],
|
||||
// The main content was rendered via the fallback in case there is no
|
||||
// block rendering the main content.
|
||||
'content' => [
|
||||
'system_main' => ['#markup' => 'Hello kittens!'],
|
||||
],
|
||||
],
|
||||
];
|
||||
return $test_cases;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the building of a full page variant.
|
||||
*
|
||||
* @covers ::build
|
||||
* @covers ::getRegionAssignments
|
||||
*
|
||||
* @dataProvider providerBuild
|
||||
*/
|
||||
public function testBuild() {
|
||||
public function testBuild(array $blocks_config, $visible_block_count, array $expected_render_array) {
|
||||
$theme = $this->randomMachineName();
|
||||
$display_variant = $this->setUpDisplayVariant();
|
||||
$this->themeNegotiator->expects($this->any())
|
||||
|
@ -82,26 +147,14 @@ class FullPageVariantTest extends UnitTestCase {
|
|||
->method('getRegionNames')
|
||||
->will($this->returnValue(array(
|
||||
'top' => 'Top',
|
||||
'center' => 'Center',
|
||||
'bottom' => 'Bottom',
|
||||
)));
|
||||
$display_variant->setMainContent(['#markup' => 'Hello kittens!']);
|
||||
|
||||
$blocks_config = array(
|
||||
'block1' => array(
|
||||
TRUE, 'top', 0,
|
||||
),
|
||||
// Test a block without access.
|
||||
'block2' => array(
|
||||
FALSE, 'bottom', 0,
|
||||
),
|
||||
// Test two blocks in the same region with specific weight.
|
||||
'block3' => array(
|
||||
TRUE, 'bottom', 5,
|
||||
),
|
||||
'block4' => array(
|
||||
TRUE, 'bottom', -5,
|
||||
),
|
||||
);
|
||||
$blocks = array();
|
||||
$block_plugin = $this->getMock('Drupal\Core\Block\BlockPluginInterface');
|
||||
$main_content_block_plugin = $this->getMock('Drupal\Core\Block\MainContentBlockPluginInterface');
|
||||
foreach ($blocks_config as $block_id => $block_config) {
|
||||
$block = $this->getMock('Drupal\block\BlockInterface');
|
||||
$block->expects($this->once())
|
||||
|
@ -114,10 +167,13 @@ class FullPageVariantTest extends UnitTestCase {
|
|||
array('weight', $block_config[2]),
|
||||
array('status', TRUE),
|
||||
)));
|
||||
$block->expects($this->any())
|
||||
->method('getPlugin')
|
||||
->willReturn($block_config[3] ? $main_content_block_plugin : $block_plugin);
|
||||
$blocks[$block_id] = $block;
|
||||
}
|
||||
|
||||
$this->blockViewBuilder->expects($this->exactly(3))
|
||||
$this->blockViewBuilder->expects($this->exactly($visible_block_count))
|
||||
->method('view')
|
||||
->will($this->returnValue(array()));
|
||||
$this->blockStorage->expects($this->once())
|
||||
|
@ -125,18 +181,7 @@ class FullPageVariantTest extends UnitTestCase {
|
|||
->with(array('theme' => $theme))
|
||||
->will($this->returnValue($blocks));
|
||||
|
||||
$expected = array(
|
||||
'top' => array(
|
||||
'block1' => array(),
|
||||
'#sorted' => TRUE,
|
||||
),
|
||||
'bottom' => array(
|
||||
'block4' => array(),
|
||||
'block3' => array(),
|
||||
'#sorted' => TRUE,
|
||||
),
|
||||
);
|
||||
$this->assertSame($expected, $display_variant->build());
|
||||
$this->assertSame($expected_render_array, $display_variant->build());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
namespace Drupal\system\Plugin\Block;
|
||||
|
||||
use Drupal\Core\Block\BlockBase;
|
||||
use Drupal\Core\Block\MainContentBlockPluginInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
|
@ -18,15 +19,27 @@ use Drupal\Core\Form\FormStateInterface;
|
|||
* admin_label = @Translation("Main page content")
|
||||
* )
|
||||
*/
|
||||
class SystemMainBlock extends BlockBase {
|
||||
class SystemMainBlock extends BlockBase implements MainContentBlockPluginInterface {
|
||||
|
||||
/**
|
||||
* The render array representing the main page content.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $mainContent;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setMainContent(array $main_content) {
|
||||
$this->mainContent = $main_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function build() {
|
||||
return array(
|
||||
drupal_set_page_content()
|
||||
);
|
||||
return $this->mainContent;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue