Mercurial > hg > isophonics-drupal-site
comparison core/modules/block/src/Plugin/DisplayVariant/BlockPageVariant.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children | af1871eacc83 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 | |
3 namespace Drupal\block\Plugin\DisplayVariant; | |
4 | |
5 use Drupal\block\BlockRepositoryInterface; | |
6 use Drupal\Core\Block\MainContentBlockPluginInterface; | |
7 use Drupal\Core\Block\TitleBlockPluginInterface; | |
8 use Drupal\Core\Block\MessagesBlockPluginInterface; | |
9 use Drupal\Core\Cache\CacheableMetadata; | |
10 use Drupal\Core\Display\PageVariantInterface; | |
11 use Drupal\Core\Entity\EntityViewBuilderInterface; | |
12 use Drupal\Core\Plugin\ContainerFactoryPluginInterface; | |
13 use Drupal\Core\Display\VariantBase; | |
14 use Symfony\Component\DependencyInjection\ContainerInterface; | |
15 | |
16 /** | |
17 * Provides a page display variant that decorates the main content with blocks. | |
18 * | |
19 * To ensure essential information is displayed, each essential part of a page | |
20 * has a corresponding block plugin interface, so that BlockPageVariant can | |
21 * automatically provide a fallback in case no block for each of these | |
22 * interfaces is placed. | |
23 * | |
24 * @see \Drupal\Core\Block\MainContentBlockPluginInterface | |
25 * @see \Drupal\Core\Block\MessagesBlockPluginInterface | |
26 * | |
27 * @PageDisplayVariant( | |
28 * id = "block_page", | |
29 * admin_label = @Translation("Page with blocks") | |
30 * ) | |
31 */ | |
32 class BlockPageVariant extends VariantBase implements PageVariantInterface, ContainerFactoryPluginInterface { | |
33 | |
34 /** | |
35 * The block repository. | |
36 * | |
37 * @var \Drupal\block\BlockRepositoryInterface | |
38 */ | |
39 protected $blockRepository; | |
40 | |
41 /** | |
42 * The block view builder. | |
43 * | |
44 * @var \Drupal\Core\Entity\EntityViewBuilderInterface | |
45 */ | |
46 protected $blockViewBuilder; | |
47 | |
48 /** | |
49 * The Block entity type list cache tags. | |
50 * | |
51 * @var string[] | |
52 */ | |
53 protected $blockListCacheTags; | |
54 | |
55 /** | |
56 * The render array representing the main page content. | |
57 * | |
58 * @var array | |
59 */ | |
60 protected $mainContent = []; | |
61 | |
62 /** | |
63 * The page title: a string (plain title) or a render array (formatted title). | |
64 * | |
65 * @var string|array | |
66 */ | |
67 protected $title = ''; | |
68 | |
69 /** | |
70 * Constructs a new BlockPageVariant. | |
71 * | |
72 * @param array $configuration | |
73 * A configuration array containing information about the plugin instance. | |
74 * @param string $plugin_id | |
75 * The plugin ID for the plugin instance. | |
76 * @param mixed $plugin_definition | |
77 * The plugin implementation definition. | |
78 * @param \Drupal\block\BlockRepositoryInterface $block_repository | |
79 * The block repository. | |
80 * @param \Drupal\Core\Entity\EntityViewBuilderInterface $block_view_builder | |
81 * The block view builder. | |
82 * @param string[] $block_list_cache_tags | |
83 * The Block entity type list cache tags. | |
84 */ | |
85 public function __construct(array $configuration, $plugin_id, $plugin_definition, BlockRepositoryInterface $block_repository, EntityViewBuilderInterface $block_view_builder, array $block_list_cache_tags) { | |
86 parent::__construct($configuration, $plugin_id, $plugin_definition); | |
87 $this->blockRepository = $block_repository; | |
88 $this->blockViewBuilder = $block_view_builder; | |
89 $this->blockListCacheTags = $block_list_cache_tags; | |
90 } | |
91 | |
92 /** | |
93 * {@inheritdoc} | |
94 */ | |
95 public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { | |
96 return new static( | |
97 $configuration, | |
98 $plugin_id, | |
99 $plugin_definition, | |
100 $container->get('block.repository'), | |
101 $container->get('entity.manager')->getViewBuilder('block'), | |
102 $container->get('entity.manager')->getDefinition('block')->getListCacheTags() | |
103 ); | |
104 } | |
105 | |
106 /** | |
107 * {@inheritdoc} | |
108 */ | |
109 public function setMainContent(array $main_content) { | |
110 $this->mainContent = $main_content; | |
111 return $this; | |
112 } | |
113 | |
114 /** | |
115 * {@inheritdoc} | |
116 */ | |
117 public function setTitle($title) { | |
118 $this->title = $title; | |
119 return $this; | |
120 } | |
121 | |
122 /** | |
123 * {@inheritdoc} | |
124 */ | |
125 public function build() { | |
126 // Track whether blocks showing the main content and messages are displayed. | |
127 $main_content_block_displayed = FALSE; | |
128 $messages_block_displayed = FALSE; | |
129 | |
130 $build = [ | |
131 '#cache' => [ | |
132 'tags' => $this->blockListCacheTags, | |
133 ], | |
134 ]; | |
135 // Load all region content assigned via blocks. | |
136 $cacheable_metadata_list = []; | |
137 foreach ($this->blockRepository->getVisibleBlocksPerRegion($cacheable_metadata_list) as $region => $blocks) { | |
138 /** @var $blocks \Drupal\block\BlockInterface[] */ | |
139 foreach ($blocks as $key => $block) { | |
140 $block_plugin = $block->getPlugin(); | |
141 if ($block_plugin instanceof MainContentBlockPluginInterface) { | |
142 $block_plugin->setMainContent($this->mainContent); | |
143 $main_content_block_displayed = TRUE; | |
144 } | |
145 elseif ($block_plugin instanceof TitleBlockPluginInterface) { | |
146 $block_plugin->setTitle($this->title); | |
147 } | |
148 elseif ($block_plugin instanceof MessagesBlockPluginInterface) { | |
149 $messages_block_displayed = TRUE; | |
150 } | |
151 $build[$region][$key] = $this->blockViewBuilder->view($block); | |
152 | |
153 // The main content block cannot be cached: it is a placeholder for the | |
154 // render array returned by the controller. It should be rendered as-is, | |
155 // with other placed blocks "decorating" it. Analogous reasoning for the | |
156 // title block. | |
157 if ($block_plugin instanceof MainContentBlockPluginInterface || $block_plugin instanceof TitleBlockPluginInterface) { | |
158 unset($build[$region][$key]['#cache']['keys']); | |
159 } | |
160 } | |
161 if (!empty($build[$region])) { | |
162 // \Drupal\block\BlockRepositoryInterface::getVisibleBlocksPerRegion() | |
163 // returns the blocks in sorted order. | |
164 $build[$region]['#sorted'] = TRUE; | |
165 } | |
166 } | |
167 | |
168 // If no block that shows the main content is displayed, still show the main | |
169 // content. Otherwise the end user will see all displayed blocks, but not | |
170 // the main content they came for. | |
171 if (!$main_content_block_displayed) { | |
172 $build['content']['system_main'] = $this->mainContent; | |
173 } | |
174 | |
175 // If no block displays status messages, still render them. | |
176 if (!$messages_block_displayed) { | |
177 $build['content']['messages'] = [ | |
178 '#weight' => -1000, | |
179 '#type' => 'status_messages', | |
180 ]; | |
181 } | |
182 | |
183 // If any render arrays are manually placed, render arrays and blocks must | |
184 // be sorted. | |
185 if (!$main_content_block_displayed || !$messages_block_displayed) { | |
186 unset($build['content']['#sorted']); | |
187 } | |
188 | |
189 // The access results' cacheability is currently added to the top level of the | |
190 // render array. This is done to prevent issues with empty regions being | |
191 // displayed. | |
192 // This would need to be changed to allow caching of block regions, as each | |
193 // region must then have the relevant cacheable metadata. | |
194 $merged_cacheable_metadata = CacheableMetadata::createFromRenderArray($build); | |
195 foreach ($cacheable_metadata_list as $cacheable_metadata) { | |
196 $merged_cacheable_metadata = $merged_cacheable_metadata->merge($cacheable_metadata); | |
197 } | |
198 $merged_cacheable_metadata->applyTo($build); | |
199 | |
200 return $build; | |
201 } | |
202 | |
203 } |