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