3 namespace Drupal\layout_builder\Controller;
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;
11 use Drupal\layout_builder\Context\LayoutBuilderContextTrait;
12 use Drupal\layout_builder\SectionStorageInterface;
13 use Symfony\Component\DependencyInjection\ContainerInterface;
16 * Defines a controller to choose a new block.
20 class ChooseBlockController implements ContainerInjectionInterface {
23 use LayoutBuilderContextTrait;
24 use StringTranslationTrait;
29 * @var \Drupal\Core\Block\BlockManagerInterface
31 protected $blockManager;
34 * The entity type manager.
36 * @var \Drupal\Core\Entity\EntityTypeManagerInterface
38 protected $entityTypeManager;
41 * ChooseBlockController constructor.
43 * @param \Drupal\Core\Block\BlockManagerInterface $block_manager
45 * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
46 * The entity type manager.
48 public function __construct(BlockManagerInterface $block_manager, EntityTypeManagerInterface $entity_type_manager) {
49 $this->blockManager = $block_manager;
50 $this->entityTypeManager = $entity_type_manager;
56 public static function create(ContainerInterface $container) {
58 $container->get('plugin.manager.block'),
59 $container->get('entity_type.manager')
64 * Provides the UI for choosing a new block.
66 * @param \Drupal\layout_builder\SectionStorageInterface $section_storage
67 * The section storage.
69 * The delta of the section to splice.
70 * @param string $region
71 * The region the block is going in.
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(),
88 'plugin_id' => $plugin_id,
93 $url = Url::fromRoute('layout_builder.choose_inline_block', [
94 'section_storage_type' => $section_storage->getStorageType(),
95 'section_storage' => $section_storage->getStorageId(),
101 $build['add_block'] = [
104 '#title' => $this->t('Create @entity_type', [
105 '@entity_type' => $this->entityTypeManager->getDefinition('block_content')->getSingularLabel(),
107 '#attributes' => $this->getAjaxAttributes(),
109 $build['add_block']['#attributes']['class'][] = 'inline-block-create-button';
113 $block_categories['#type'] = 'container';
114 $block_categories['#attributes']['class'][] = 'block-categories';
116 // @todo Explicitly cast delta to an integer, remove this in
117 // https://www.drupal.org/project/drupal/issues/2984509.
118 $delta = (int) $delta;
120 $definitions = $this->blockManager->getFilteredDefinitions('layout_builder', $this->getAvailableContexts($section_storage), [
121 'section_storage' => $section_storage,
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);
132 $build['block_categories'] = $block_categories;
137 * Provides the UI for choosing a new inline block.
139 * @param \Drupal\layout_builder\SectionStorageInterface $section_storage
140 * The section storage.
142 * The delta of the section to splice.
143 * @param string $region
144 * The region the block is going in.
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,
153 'list' => 'inline_blocks',
155 $blocks = $this->blockManager->getGroupedDefinitions($definitions);
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';
163 $build['back_button'] = [
165 '#url' => Url::fromRoute('layout_builder.choose_block',
167 'section_storage_type' => $section_storage->getStorageType(),
168 'section_storage' => $section_storage->getStorageId(),
173 '#title' => $this->t('Back'),
174 '#attributes' => $this->getAjaxAttributes(),
181 * Gets a render array of block links.
183 * @param \Drupal\layout_builder\SectionStorageInterface $section_storage
184 * The section storage.
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.
193 * The block links render array.
195 protected function getBlockLinks(SectionStorageInterface $section_storage, $delta, $region, array $blocks) {
197 foreach ($blocks as $block_id => $block) {
199 'title' => $block['admin_label'],
200 'url' => Url::fromRoute('layout_builder.add_block',
202 'section_storage_type' => $section_storage->getStorageType(),
203 'section_storage' => $section_storage->getStorageId(),
206 'plugin_id' => $block_id,
209 'attributes' => $this->getAjaxAttributes(),
221 * Get dialog attributes if an ajax request.
224 * The attributes array.
226 protected function getAjaxAttributes() {
227 if ($this->isAjax()) {
229 'class' => ['use-ajax'],
230 'data-dialog-type' => 'dialog',
231 'data-dialog-renderer' => 'off_canvas',