Chris@14
|
1 <?php
|
Chris@14
|
2
|
Chris@14
|
3 namespace Drupal\layout_builder\Controller;
|
Chris@14
|
4
|
Chris@17
|
5 use Drupal\Core\Ajax\AjaxHelperTrait;
|
Chris@14
|
6 use Drupal\Core\Block\BlockManagerInterface;
|
Chris@14
|
7 use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
|
Chris@17
|
8 use Drupal\Core\Entity\EntityTypeManagerInterface;
|
Chris@17
|
9 use Drupal\Core\StringTranslation\StringTranslationTrait;
|
Chris@14
|
10 use Drupal\Core\Url;
|
Chris@14
|
11 use Drupal\layout_builder\Context\LayoutBuilderContextTrait;
|
Chris@14
|
12 use Drupal\layout_builder\SectionStorageInterface;
|
Chris@14
|
13 use Symfony\Component\DependencyInjection\ContainerInterface;
|
Chris@14
|
14
|
Chris@14
|
15 /**
|
Chris@14
|
16 * Defines a controller to choose a new block.
|
Chris@14
|
17 *
|
Chris@14
|
18 * @internal
|
Chris@14
|
19 */
|
Chris@14
|
20 class ChooseBlockController implements ContainerInjectionInterface {
|
Chris@14
|
21
|
Chris@14
|
22 use AjaxHelperTrait;
|
Chris@14
|
23 use LayoutBuilderContextTrait;
|
Chris@17
|
24 use StringTranslationTrait;
|
Chris@14
|
25
|
Chris@14
|
26 /**
|
Chris@14
|
27 * The block manager.
|
Chris@14
|
28 *
|
Chris@14
|
29 * @var \Drupal\Core\Block\BlockManagerInterface
|
Chris@14
|
30 */
|
Chris@14
|
31 protected $blockManager;
|
Chris@14
|
32
|
Chris@14
|
33 /**
|
Chris@17
|
34 * The entity type manager.
|
Chris@17
|
35 *
|
Chris@17
|
36 * @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
Chris@17
|
37 */
|
Chris@17
|
38 protected $entityTypeManager;
|
Chris@17
|
39
|
Chris@17
|
40 /**
|
Chris@14
|
41 * ChooseBlockController constructor.
|
Chris@14
|
42 *
|
Chris@14
|
43 * @param \Drupal\Core\Block\BlockManagerInterface $block_manager
|
Chris@14
|
44 * The block manager.
|
Chris@17
|
45 * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
|
Chris@17
|
46 * The entity type manager.
|
Chris@14
|
47 */
|
Chris@17
|
48 public function __construct(BlockManagerInterface $block_manager, EntityTypeManagerInterface $entity_type_manager) {
|
Chris@14
|
49 $this->blockManager = $block_manager;
|
Chris@17
|
50 $this->entityTypeManager = $entity_type_manager;
|
Chris@14
|
51 }
|
Chris@14
|
52
|
Chris@14
|
53 /**
|
Chris@14
|
54 * {@inheritdoc}
|
Chris@14
|
55 */
|
Chris@14
|
56 public static function create(ContainerInterface $container) {
|
Chris@14
|
57 return new static(
|
Chris@17
|
58 $container->get('plugin.manager.block'),
|
Chris@17
|
59 $container->get('entity_type.manager')
|
Chris@14
|
60 );
|
Chris@14
|
61 }
|
Chris@14
|
62
|
Chris@14
|
63 /**
|
Chris@14
|
64 * Provides the UI for choosing a new block.
|
Chris@14
|
65 *
|
Chris@14
|
66 * @param \Drupal\layout_builder\SectionStorageInterface $section_storage
|
Chris@14
|
67 * The section storage.
|
Chris@14
|
68 * @param int $delta
|
Chris@14
|
69 * The delta of the section to splice.
|
Chris@14
|
70 * @param string $region
|
Chris@14
|
71 * The region the block is going in.
|
Chris@14
|
72 *
|
Chris@14
|
73 * @return array
|
Chris@14
|
74 * A render array.
|
Chris@14
|
75 */
|
Chris@14
|
76 public function build(SectionStorageInterface $section_storage, $delta, $region) {
|
Chris@17
|
77 $build['#title'] = $this->t('Choose a block');
|
Chris@17
|
78 if ($this->entityTypeManager->hasDefinition('block_content_type') && $types = $this->entityTypeManager->getStorage('block_content_type')->loadMultiple()) {
|
Chris@17
|
79 if (count($types) === 1) {
|
Chris@17
|
80 $type = reset($types);
|
Chris@17
|
81 $plugin_id = 'inline_block:' . $type->id();
|
Chris@17
|
82 if ($this->blockManager->hasDefinition($plugin_id)) {
|
Chris@17
|
83 $url = Url::fromRoute('layout_builder.add_block', [
|
Chris@17
|
84 'section_storage_type' => $section_storage->getStorageType(),
|
Chris@17
|
85 'section_storage' => $section_storage->getStorageId(),
|
Chris@17
|
86 'delta' => $delta,
|
Chris@17
|
87 'region' => $region,
|
Chris@17
|
88 'plugin_id' => $plugin_id,
|
Chris@17
|
89 ]);
|
Chris@17
|
90 }
|
Chris@17
|
91 }
|
Chris@17
|
92 else {
|
Chris@17
|
93 $url = Url::fromRoute('layout_builder.choose_inline_block', [
|
Chris@17
|
94 'section_storage_type' => $section_storage->getStorageType(),
|
Chris@17
|
95 'section_storage' => $section_storage->getStorageId(),
|
Chris@17
|
96 'delta' => $delta,
|
Chris@17
|
97 'region' => $region,
|
Chris@17
|
98 ]);
|
Chris@17
|
99 }
|
Chris@17
|
100 if (isset($url)) {
|
Chris@17
|
101 $build['add_block'] = [
|
Chris@17
|
102 '#type' => 'link',
|
Chris@17
|
103 '#url' => $url,
|
Chris@17
|
104 '#title' => $this->t('Create @entity_type', [
|
Chris@17
|
105 '@entity_type' => $this->entityTypeManager->getDefinition('block_content')->getSingularLabel(),
|
Chris@17
|
106 ]),
|
Chris@17
|
107 '#attributes' => $this->getAjaxAttributes(),
|
Chris@17
|
108 ];
|
Chris@17
|
109 $build['add_block']['#attributes']['class'][] = 'inline-block-create-button';
|
Chris@17
|
110 }
|
Chris@17
|
111 }
|
Chris@14
|
112
|
Chris@17
|
113 $block_categories['#type'] = 'container';
|
Chris@17
|
114 $block_categories['#attributes']['class'][] = 'block-categories';
|
Chris@17
|
115
|
Chris@17
|
116 // @todo Explicitly cast delta to an integer, remove this in
|
Chris@17
|
117 // https://www.drupal.org/project/drupal/issues/2984509.
|
Chris@17
|
118 $delta = (int) $delta;
|
Chris@17
|
119
|
Chris@17
|
120 $definitions = $this->blockManager->getFilteredDefinitions('layout_builder', $this->getAvailableContexts($section_storage), [
|
Chris@17
|
121 'section_storage' => $section_storage,
|
Chris@17
|
122 'delta' => $delta,
|
Chris@17
|
123 'region' => $region,
|
Chris@17
|
124 ]);
|
Chris@17
|
125 $grouped_definitions = $this->blockManager->getGroupedDefinitions($definitions);
|
Chris@17
|
126 foreach ($grouped_definitions as $category => $blocks) {
|
Chris@17
|
127 $block_categories[$category]['#type'] = 'details';
|
Chris@17
|
128 $block_categories[$category]['#open'] = TRUE;
|
Chris@17
|
129 $block_categories[$category]['#title'] = $category;
|
Chris@17
|
130 $block_categories[$category]['links'] = $this->getBlockLinks($section_storage, $delta, $region, $blocks);
|
Chris@17
|
131 }
|
Chris@17
|
132 $build['block_categories'] = $block_categories;
|
Chris@17
|
133 return $build;
|
Chris@17
|
134 }
|
Chris@17
|
135
|
Chris@17
|
136 /**
|
Chris@17
|
137 * Provides the UI for choosing a new inline block.
|
Chris@17
|
138 *
|
Chris@17
|
139 * @param \Drupal\layout_builder\SectionStorageInterface $section_storage
|
Chris@17
|
140 * The section storage.
|
Chris@17
|
141 * @param int $delta
|
Chris@17
|
142 * The delta of the section to splice.
|
Chris@17
|
143 * @param string $region
|
Chris@17
|
144 * The region the block is going in.
|
Chris@17
|
145 *
|
Chris@17
|
146 * @return array
|
Chris@17
|
147 * A render array.
|
Chris@17
|
148 */
|
Chris@17
|
149 public function inlineBlockList(SectionStorageInterface $section_storage, $delta, $region) {
|
Chris@17
|
150 $definitions = $this->blockManager->getFilteredDefinitions('layout_builder', $this->getAvailableContexts($section_storage), [
|
Chris@17
|
151 'section_storage' => $section_storage,
|
Chris@17
|
152 'region' => $region,
|
Chris@17
|
153 'list' => 'inline_blocks',
|
Chris@17
|
154 ]);
|
Chris@17
|
155 $blocks = $this->blockManager->getGroupedDefinitions($definitions);
|
Chris@17
|
156 $build = [];
|
Chris@17
|
157 if (isset($blocks['Inline blocks'])) {
|
Chris@17
|
158 $build['links'] = $this->getBlockLinks($section_storage, $delta, $region, $blocks['Inline blocks']);
|
Chris@17
|
159 $build['links']['#attributes']['class'][] = 'inline-block-list';
|
Chris@17
|
160 foreach ($build['links']['#links'] as &$link) {
|
Chris@17
|
161 $link['attributes']['class'][] = 'inline-block-list__item';
|
Chris@17
|
162 }
|
Chris@17
|
163 $build['back_button'] = [
|
Chris@17
|
164 '#type' => 'link',
|
Chris@17
|
165 '#url' => Url::fromRoute('layout_builder.choose_block',
|
Chris@17
|
166 [
|
Chris@17
|
167 'section_storage_type' => $section_storage->getStorageType(),
|
Chris@17
|
168 'section_storage' => $section_storage->getStorageId(),
|
Chris@17
|
169 'delta' => $delta,
|
Chris@17
|
170 'region' => $region,
|
Chris@17
|
171 ]
|
Chris@17
|
172 ),
|
Chris@17
|
173 '#title' => $this->t('Back'),
|
Chris@17
|
174 '#attributes' => $this->getAjaxAttributes(),
|
Chris@14
|
175 ];
|
Chris@14
|
176 }
|
Chris@14
|
177 return $build;
|
Chris@14
|
178 }
|
Chris@14
|
179
|
Chris@17
|
180 /**
|
Chris@17
|
181 * Gets a render array of block links.
|
Chris@17
|
182 *
|
Chris@17
|
183 * @param \Drupal\layout_builder\SectionStorageInterface $section_storage
|
Chris@17
|
184 * The section storage.
|
Chris@17
|
185 * @param int $delta
|
Chris@17
|
186 * The delta of the section to splice.
|
Chris@17
|
187 * @param string $region
|
Chris@17
|
188 * The region the block is going in.
|
Chris@17
|
189 * @param array $blocks
|
Chris@17
|
190 * The information for each block.
|
Chris@17
|
191 *
|
Chris@17
|
192 * @return array
|
Chris@17
|
193 * The block links render array.
|
Chris@17
|
194 */
|
Chris@17
|
195 protected function getBlockLinks(SectionStorageInterface $section_storage, $delta, $region, array $blocks) {
|
Chris@17
|
196 $links = [];
|
Chris@17
|
197 foreach ($blocks as $block_id => $block) {
|
Chris@17
|
198 $link = [
|
Chris@17
|
199 'title' => $block['admin_label'],
|
Chris@17
|
200 'url' => Url::fromRoute('layout_builder.add_block',
|
Chris@17
|
201 [
|
Chris@17
|
202 'section_storage_type' => $section_storage->getStorageType(),
|
Chris@17
|
203 'section_storage' => $section_storage->getStorageId(),
|
Chris@17
|
204 'delta' => $delta,
|
Chris@17
|
205 'region' => $region,
|
Chris@17
|
206 'plugin_id' => $block_id,
|
Chris@17
|
207 ]
|
Chris@17
|
208 ),
|
Chris@17
|
209 'attributes' => $this->getAjaxAttributes(),
|
Chris@17
|
210 ];
|
Chris@17
|
211
|
Chris@17
|
212 $links[] = $link;
|
Chris@17
|
213 }
|
Chris@17
|
214 return [
|
Chris@17
|
215 '#theme' => 'links',
|
Chris@17
|
216 '#links' => $links,
|
Chris@17
|
217 ];
|
Chris@17
|
218 }
|
Chris@17
|
219
|
Chris@17
|
220 /**
|
Chris@17
|
221 * Get dialog attributes if an ajax request.
|
Chris@17
|
222 *
|
Chris@17
|
223 * @return array
|
Chris@17
|
224 * The attributes array.
|
Chris@17
|
225 */
|
Chris@17
|
226 protected function getAjaxAttributes() {
|
Chris@17
|
227 if ($this->isAjax()) {
|
Chris@17
|
228 return [
|
Chris@17
|
229 'class' => ['use-ajax'],
|
Chris@17
|
230 'data-dialog-type' => 'dialog',
|
Chris@17
|
231 'data-dialog-renderer' => 'off_canvas',
|
Chris@17
|
232 ];
|
Chris@17
|
233 }
|
Chris@17
|
234 return [];
|
Chris@17
|
235 }
|
Chris@17
|
236
|
Chris@14
|
237 }
|