Mercurial > hg > isophonics-drupal-site
comparison core/modules/layout_builder/src/Controller/LayoutBuilderController.php @ 14:1fec387a4317
Update Drupal core to 8.5.2 via Composer
author | Chris Cannam |
---|---|
date | Mon, 23 Apr 2018 09:46:53 +0100 |
parents | |
children | c2387f117808 |
comparison
equal
deleted
inserted
replaced
13:5fb285c0d0e3 | 14:1fec387a4317 |
---|---|
1 <?php | |
2 | |
3 namespace Drupal\layout_builder\Controller; | |
4 | |
5 use Drupal\Core\DependencyInjection\ContainerInjectionInterface; | |
6 use Drupal\Core\Messenger\MessengerInterface; | |
7 use Drupal\Core\Plugin\PluginFormInterface; | |
8 use Drupal\Core\StringTranslation\StringTranslationTrait; | |
9 use Drupal\Core\Url; | |
10 use Drupal\layout_builder\Context\LayoutBuilderContextTrait; | |
11 use Drupal\layout_builder\LayoutTempstoreRepositoryInterface; | |
12 use Drupal\layout_builder\OverridesSectionStorageInterface; | |
13 use Drupal\layout_builder\Section; | |
14 use Drupal\layout_builder\SectionStorageInterface; | |
15 use Symfony\Component\DependencyInjection\ContainerInterface; | |
16 use Symfony\Component\HttpFoundation\RedirectResponse; | |
17 | |
18 /** | |
19 * Defines a controller to provide the Layout Builder admin UI. | |
20 * | |
21 * @internal | |
22 */ | |
23 class LayoutBuilderController implements ContainerInjectionInterface { | |
24 | |
25 use LayoutBuilderContextTrait; | |
26 use StringTranslationTrait; | |
27 | |
28 /** | |
29 * The layout tempstore repository. | |
30 * | |
31 * @var \Drupal\layout_builder\LayoutTempstoreRepositoryInterface | |
32 */ | |
33 protected $layoutTempstoreRepository; | |
34 | |
35 /** | |
36 * The messenger service. | |
37 * | |
38 * @var \Drupal\Core\Messenger\MessengerInterface | |
39 */ | |
40 protected $messenger; | |
41 | |
42 /** | |
43 * LayoutBuilderController constructor. | |
44 * | |
45 * @param \Drupal\layout_builder\LayoutTempstoreRepositoryInterface $layout_tempstore_repository | |
46 * The layout tempstore repository. | |
47 * @param \Drupal\Core\Messenger\MessengerInterface $messenger | |
48 * The messenger service. | |
49 */ | |
50 public function __construct(LayoutTempstoreRepositoryInterface $layout_tempstore_repository, MessengerInterface $messenger) { | |
51 $this->layoutTempstoreRepository = $layout_tempstore_repository; | |
52 $this->messenger = $messenger; | |
53 } | |
54 | |
55 /** | |
56 * {@inheritdoc} | |
57 */ | |
58 public static function create(ContainerInterface $container) { | |
59 return new static( | |
60 $container->get('layout_builder.tempstore_repository'), | |
61 $container->get('messenger') | |
62 ); | |
63 } | |
64 | |
65 /** | |
66 * Provides a title callback. | |
67 * | |
68 * @param \Drupal\layout_builder\SectionStorageInterface $section_storage | |
69 * The section storage. | |
70 * | |
71 * @return string | |
72 * The title for the layout page. | |
73 */ | |
74 public function title(SectionStorageInterface $section_storage) { | |
75 return $this->t('Edit layout for %label', ['%label' => $section_storage->label()]); | |
76 } | |
77 | |
78 /** | |
79 * Renders the Layout UI. | |
80 * | |
81 * @param \Drupal\layout_builder\SectionStorageInterface $section_storage | |
82 * The section storage. | |
83 * @param bool $is_rebuilding | |
84 * (optional) Indicates if the layout is rebuilding, defaults to FALSE. | |
85 * | |
86 * @return array | |
87 * A render array. | |
88 */ | |
89 public function layout(SectionStorageInterface $section_storage, $is_rebuilding = FALSE) { | |
90 $this->prepareLayout($section_storage, $is_rebuilding); | |
91 | |
92 $output = []; | |
93 $count = 0; | |
94 for ($i = 0; $i < $section_storage->count(); $i++) { | |
95 $output[] = $this->buildAddSectionLink($section_storage, $count); | |
96 $output[] = $this->buildAdministrativeSection($section_storage, $count); | |
97 $count++; | |
98 } | |
99 $output[] = $this->buildAddSectionLink($section_storage, $count); | |
100 $output['#attached']['library'][] = 'layout_builder/drupal.layout_builder'; | |
101 $output['#type'] = 'container'; | |
102 $output['#attributes']['id'] = 'layout-builder'; | |
103 // Mark this UI as uncacheable. | |
104 $output['#cache']['max-age'] = 0; | |
105 return $output; | |
106 } | |
107 | |
108 /** | |
109 * Prepares a layout for use in the UI. | |
110 * | |
111 * @param \Drupal\layout_builder\SectionStorageInterface $section_storage | |
112 * The section storage. | |
113 * @param bool $is_rebuilding | |
114 * Indicates if the layout is rebuilding. | |
115 */ | |
116 protected function prepareLayout(SectionStorageInterface $section_storage, $is_rebuilding) { | |
117 // Only add sections if the layout is new and empty. | |
118 if (!$is_rebuilding && $section_storage->count() === 0) { | |
119 $sections = []; | |
120 // If this is an empty override, copy the sections from the corresponding | |
121 // default. | |
122 if ($section_storage instanceof OverridesSectionStorageInterface) { | |
123 $sections = $section_storage->getDefaultSectionStorage()->getSections(); | |
124 } | |
125 | |
126 // For an empty layout, begin with a single section of one column. | |
127 if (!$sections) { | |
128 $sections[] = new Section('layout_onecol'); | |
129 } | |
130 | |
131 foreach ($sections as $section) { | |
132 $section_storage->appendSection($section); | |
133 } | |
134 $this->layoutTempstoreRepository->set($section_storage); | |
135 } | |
136 } | |
137 | |
138 /** | |
139 * Builds a link to add a new section at a given delta. | |
140 * | |
141 * @param \Drupal\layout_builder\SectionStorageInterface $section_storage | |
142 * The section storage. | |
143 * @param int $delta | |
144 * The delta of the section to splice. | |
145 * | |
146 * @return array | |
147 * A render array for a link. | |
148 */ | |
149 protected function buildAddSectionLink(SectionStorageInterface $section_storage, $delta) { | |
150 $storage_type = $section_storage->getStorageType(); | |
151 $storage_id = $section_storage->getStorageId(); | |
152 return [ | |
153 'link' => [ | |
154 '#type' => 'link', | |
155 '#title' => $this->t('Add Section'), | |
156 '#url' => Url::fromRoute('layout_builder.choose_section', | |
157 [ | |
158 'section_storage_type' => $storage_type, | |
159 'section_storage' => $storage_id, | |
160 'delta' => $delta, | |
161 ], | |
162 [ | |
163 'attributes' => [ | |
164 'class' => ['use-ajax'], | |
165 'data-dialog-type' => 'dialog', | |
166 'data-dialog-renderer' => 'off_canvas', | |
167 ], | |
168 ] | |
169 ), | |
170 ], | |
171 '#type' => 'container', | |
172 '#attributes' => [ | |
173 'class' => ['add-section'], | |
174 ], | |
175 ]; | |
176 } | |
177 | |
178 /** | |
179 * Builds the render array for the layout section while editing. | |
180 * | |
181 * @param \Drupal\layout_builder\SectionStorageInterface $section_storage | |
182 * The section storage. | |
183 * @param int $delta | |
184 * The delta of the section. | |
185 * | |
186 * @return array | |
187 * The render array for a given section. | |
188 */ | |
189 protected function buildAdministrativeSection(SectionStorageInterface $section_storage, $delta) { | |
190 $storage_type = $section_storage->getStorageType(); | |
191 $storage_id = $section_storage->getStorageId(); | |
192 $section = $section_storage->getSection($delta); | |
193 | |
194 $layout = $section->getLayout(); | |
195 $build = $section->toRenderArray($this->getAvailableContexts($section_storage), TRUE); | |
196 $layout_definition = $layout->getPluginDefinition(); | |
197 | |
198 foreach ($layout_definition->getRegions() as $region => $info) { | |
199 if (!empty($build[$region])) { | |
200 foreach ($build[$region] as $uuid => $block) { | |
201 $build[$region][$uuid]['#attributes']['class'][] = 'draggable'; | |
202 $build[$region][$uuid]['#attributes']['data-layout-block-uuid'] = $uuid; | |
203 $build[$region][$uuid]['#contextual_links'] = [ | |
204 'layout_builder_block' => [ | |
205 'route_parameters' => [ | |
206 'section_storage_type' => $storage_type, | |
207 'section_storage' => $storage_id, | |
208 'delta' => $delta, | |
209 'region' => $region, | |
210 'uuid' => $uuid, | |
211 ], | |
212 ], | |
213 ]; | |
214 } | |
215 } | |
216 | |
217 $build[$region]['layout_builder_add_block']['link'] = [ | |
218 '#type' => 'link', | |
219 '#title' => $this->t('Add Block'), | |
220 '#url' => Url::fromRoute('layout_builder.choose_block', | |
221 [ | |
222 'section_storage_type' => $storage_type, | |
223 'section_storage' => $storage_id, | |
224 'delta' => $delta, | |
225 'region' => $region, | |
226 ], | |
227 [ | |
228 'attributes' => [ | |
229 'class' => ['use-ajax'], | |
230 'data-dialog-type' => 'dialog', | |
231 'data-dialog-renderer' => 'off_canvas', | |
232 ], | |
233 ] | |
234 ), | |
235 ]; | |
236 $build[$region]['layout_builder_add_block']['#type'] = 'container'; | |
237 $build[$region]['layout_builder_add_block']['#attributes'] = ['class' => ['add-block']]; | |
238 $build[$region]['layout_builder_add_block']['#weight'] = 1000; | |
239 $build[$region]['#attributes']['data-region'] = $region; | |
240 $build[$region]['#attributes']['class'][] = 'layout-builder--layout__region'; | |
241 } | |
242 | |
243 $build['#attributes']['data-layout-update-url'] = Url::fromRoute('layout_builder.move_block', [ | |
244 'section_storage_type' => $storage_type, | |
245 'section_storage' => $storage_id, | |
246 ])->toString(); | |
247 $build['#attributes']['data-layout-delta'] = $delta; | |
248 $build['#attributes']['class'][] = 'layout-builder--layout'; | |
249 | |
250 return [ | |
251 '#type' => 'container', | |
252 '#attributes' => [ | |
253 'class' => ['layout-section'], | |
254 ], | |
255 'configure' => [ | |
256 '#type' => 'link', | |
257 '#title' => $this->t('Configure section'), | |
258 '#access' => $layout instanceof PluginFormInterface, | |
259 '#url' => Url::fromRoute('layout_builder.configure_section', [ | |
260 'section_storage_type' => $storage_type, | |
261 'section_storage' => $storage_id, | |
262 'delta' => $delta, | |
263 ]), | |
264 '#attributes' => [ | |
265 'class' => ['use-ajax', 'configure-section'], | |
266 'data-dialog-type' => 'dialog', | |
267 'data-dialog-renderer' => 'off_canvas', | |
268 ], | |
269 ], | |
270 'remove' => [ | |
271 '#type' => 'link', | |
272 '#title' => $this->t('Remove section'), | |
273 '#url' => Url::fromRoute('layout_builder.remove_section', [ | |
274 'section_storage_type' => $storage_type, | |
275 'section_storage' => $storage_id, | |
276 'delta' => $delta, | |
277 ]), | |
278 '#attributes' => [ | |
279 'class' => ['use-ajax', 'remove-section'], | |
280 'data-dialog-type' => 'dialog', | |
281 'data-dialog-renderer' => 'off_canvas', | |
282 ], | |
283 ], | |
284 'layout-section' => $build, | |
285 ]; | |
286 } | |
287 | |
288 /** | |
289 * Saves the layout. | |
290 * | |
291 * @param \Drupal\layout_builder\SectionStorageInterface $section_storage | |
292 * The section storage. | |
293 * | |
294 * @return \Symfony\Component\HttpFoundation\RedirectResponse | |
295 * A redirect response. | |
296 */ | |
297 public function saveLayout(SectionStorageInterface $section_storage) { | |
298 $section_storage->save(); | |
299 $this->layoutTempstoreRepository->delete($section_storage); | |
300 | |
301 if ($section_storage instanceof OverridesSectionStorageInterface) { | |
302 $this->messenger->addMessage($this->t('The layout override has been saved.')); | |
303 } | |
304 else { | |
305 $this->messenger->addMessage($this->t('The layout has been saved.')); | |
306 } | |
307 | |
308 return new RedirectResponse($section_storage->getRedirectUrl()->setAbsolute()->toString()); | |
309 } | |
310 | |
311 /** | |
312 * Cancels the layout. | |
313 * | |
314 * @param \Drupal\layout_builder\SectionStorageInterface $section_storage | |
315 * The section storage. | |
316 * | |
317 * @return \Symfony\Component\HttpFoundation\RedirectResponse | |
318 * A redirect response. | |
319 */ | |
320 public function cancelLayout(SectionStorageInterface $section_storage) { | |
321 $this->layoutTempstoreRepository->delete($section_storage); | |
322 | |
323 $this->messenger->addMessage($this->t('The changes to the layout have been discarded.')); | |
324 | |
325 return new RedirectResponse($section_storage->getRedirectUrl()->setAbsolute()->toString()); | |
326 } | |
327 | |
328 } |