Skip to content

Commit 86d8b9a

Browse files
committed
1 parent c96ab5a commit 86d8b9a

File tree

4 files changed

+87
-16
lines changed

4 files changed

+87
-16
lines changed

core/modules/layout_builder/src/Controller/ChooseBlockController.php

Lines changed: 78 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Drupal\layout_builder\Context\LayoutBuilderContextTrait;
1212
use Drupal\layout_builder\SectionStorageInterface;
1313
use Symfony\Component\DependencyInjection\ContainerInterface;
14+
use Drupal\Core\Entity\EntityTypeRepositoryInterface;
1415

1516
/**
1617
* Defines a controller to choose a new block.
@@ -37,17 +38,27 @@ class ChooseBlockController implements ContainerInjectionInterface {
3738
*/
3839
protected $entityTypeManager;
3940

41+
/**
42+
* The entity type repository.
43+
*
44+
* @var \Drupal\Core\Entity\EntityTypeRepositoryInterface
45+
*/
46+
protected $entityTypeRepository;
47+
4048
/**
4149
* ChooseBlockController constructor.
4250
*
4351
* @param \Drupal\Core\Block\BlockManagerInterface $block_manager
4452
* The block manager.
4553
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
4654
* The entity type manager.
55+
* @param \Drupal\Core\Entity\EntityTypeRepositoryInterface $entity_type_repository
56+
* The entity type repository.
4757
*/
48-
public function __construct(BlockManagerInterface $block_manager, EntityTypeManagerInterface $entity_type_manager) {
58+
public function __construct(BlockManagerInterface $block_manager, EntityTypeManagerInterface $entity_type_manager, EntityTypeRepositoryInterface $entity_type_repository) {
4959
$this->blockManager = $block_manager;
5060
$this->entityTypeManager = $entity_type_manager;
61+
$this->entityTypeRepository = $entity_type_repository;
5162
}
5263

5364
/**
@@ -56,7 +67,8 @@ public function __construct(BlockManagerInterface $block_manager, EntityTypeMana
5667
public static function create(ContainerInterface $container) {
5768
return new static(
5869
$container->get('plugin.manager.block'),
59-
$container->get('entity_type.manager')
70+
$container->get('entity_type.manager'),
71+
$container->get('entity_type.repository')
6072
);
6173
}
6274

@@ -74,6 +86,7 @@ public static function create(ContainerInterface $container) {
7486
* A render array.
7587
*/
7688
public function build(SectionStorageInterface $section_storage, $delta, $region) {
89+
$entity_type_label = $this->getEntityFieldCategoryLabels();
7790
if ($this->entityTypeManager->hasDefinition('block_content_type') && $types = $this->entityTypeManager->getStorage('block_content_type')->loadMultiple()) {
7891
if (count($types) === 1) {
7992
$type = reset($types);
@@ -132,13 +145,16 @@ public function build(SectionStorageInterface $section_storage, $delta, $region)
132145
'delta' => $delta,
133146
'region' => $region,
134147
]);
148+
$field_block_category_weight = -200;
149+
$non_view_configurable_field_links = [];
150+
$links = [];
135151
$grouped_definitions = $this->blockManager->getGroupedDefinitions($definitions);
136152
foreach ($grouped_definitions as $category => $blocks) {
137153
$block_categories[$category]['#type'] = 'details';
138154
$block_categories[$category]['#attributes']['class'][] = 'js-layout-builder-category';
139-
$block_categories[$category]['#open'] = TRUE;
155+
$block_categories[$category]['#open'] = FALSE;
140156
$block_categories[$category]['#title'] = $category;
141-
$block_categories[$category]['links'] = $this->getBlockLinks($section_storage, $delta, $region, $blocks);
157+
$this->addBlockLinks($block_categories[$category], $section_storage, $delta, $region, $blocks);
142158
}
143159
$build['block_categories'] = $block_categories;
144160
return $build;
@@ -166,7 +182,7 @@ public function inlineBlockList(SectionStorageInterface $section_storage, $delta
166182
$blocks = $this->blockManager->getGroupedDefinitions($definitions);
167183
$build = [];
168184
if (isset($blocks['Inline blocks'])) {
169-
$build['links'] = $this->getBlockLinks($section_storage, $delta, $region, $blocks['Inline blocks']);
185+
$this->addBlockLinks($build, $section_storage, $delta, $region, $blocks['Inline blocks']);
170186
$build['links']['#attributes']['class'][] = 'inline-block-list';
171187
$build['back_button'] = [
172188
'#type' => 'link',
@@ -186,8 +202,10 @@ public function inlineBlockList(SectionStorageInterface $section_storage, $delta
186202
}
187203

188204
/**
189-
* Gets a render array of block links.
205+
* Adds a render array of block links.
190206
*
207+
* @param array $render_array
208+
* Render array to add links to.
191209
* @param \Drupal\layout_builder\SectionStorageInterface $section_storage
192210
* The section storage.
193211
* @param int $delta
@@ -200,9 +218,14 @@ public function inlineBlockList(SectionStorageInterface $section_storage, $delta
200218
* @return array
201219
* The block links render array.
202220
*/
203-
protected function getBlockLinks(SectionStorageInterface $section_storage, $delta, $region, array $blocks) {
221+
protected function addBlockLinks(&$render_array, SectionStorageInterface $section_storage, $delta, $region, array $blocks) {
222+
static $field_block_category_weight = -200;
204223
$links = [];
224+
$category = NULL;
205225
foreach ($blocks as $block_id => $block) {
226+
if (!$category) {
227+
$category = $block['category'];
228+
}
206229
$attributes = $this->getAjaxAttributes();
207230
$attributes['class'][] = 'js-layout-builder-block-link';
208231
$link = [
@@ -218,10 +241,40 @@ protected function getBlockLinks(SectionStorageInterface $section_storage, $delt
218241
),
219242
'attributes' => $attributes,
220243
];
221-
222-
$links[] = $link;
244+
if ($block['id'] === 'field_block' && empty($block['_is_view_configurable'])) {
245+
$non_view_configurable_field_links[] = $link;
246+
}
247+
else {
248+
$links[] = $link;
249+
}
250+
}
251+
if ($non_view_configurable_field_links) {
252+
if (empty($links)) {
253+
// If no other links exist add these links as top level links for the
254+
// category.
255+
$links = $non_view_configurable_field_links;
256+
}
257+
else {
258+
$render_array['more_fields'] = [
259+
'#type' => 'details',
260+
'#title' => $this->t('More+'),
261+
'#open' => FALSE,
262+
'links' => [
263+
'#theme' => 'links',
264+
'#links' => $non_view_configurable_field_links,
265+
],
266+
'#weight' => 100,
267+
];
268+
}
269+
}
270+
// If this a entity category and there are links besides non 'view'
271+
// configurable field blocks move the category to the top and open it.
272+
if (in_array($category, $this->getEntityFieldCategoryLabels()) && $links) {
273+
$render_array['#open'] = TRUE;
274+
$render_array['#weight'] = $field_block_category_weight;
275+
$field_block_category_weight += 10;
223276
}
224-
return [
277+
$render_array['links'] = [
225278
'#theme' => 'links',
226279
'#links' => $links,
227280
];
@@ -244,4 +297,19 @@ protected function getAjaxAttributes() {
244297
return [];
245298
}
246299

300+
/**
301+
* Gets the category labels used for entity fields.
302+
*
303+
* @return string[]
304+
* The category labels.
305+
*/
306+
protected function getEntityFieldCategoryLabels() {
307+
$entity_type_labels = $this->entityTypeRepository->getEntityTypeLabels();
308+
foreach ($entity_type_labels as &$entity_type_label) {
309+
$entity_type_label = $this->t('@entity fields', ['@entity' => $entity_type_label])
310+
->render();
311+
}
312+
return $entity_type_labels;
313+
}
314+
247315
}

core/modules/layout_builder/src/Plugin/Derivative/FieldBlockDeriver.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,11 @@ public function getDerivativeDefinitions($base_plugin_definition) {
118118
// unavailable to place in the block UI.
119119
$derivative['_block_ui_hidden'] = !$field_definition->isDisplayConfigurable('view');
120120

121+
// Mark as view configurable or not to enable highlighting of view
122+
// configurable fields in the 'Add Block' listing of the layout
123+
// builder.
124+
$derivative['_is_view_configurable'] = $field_definition->isDisplayConfigurable('view');
125+
121126
$context_definition = EntityContextDefinition::fromEntityTypeId($entity_type_id)->setLabel($entity_type_labels[$entity_type_id]);
122127
$context_definition->addConstraint('Bundle', [$bundle]);
123128
$derivative['context'] = [

core/modules/layout_builder/tests/src/FunctionalJavascript/AjaxBlockTest.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,12 @@
22

33
namespace Drupal\Tests\layout_builder\FunctionalJavascript;
44

5-
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
6-
75
/**
86
* Ajax blocks tests.
97
*
108
* @group layout_builder
119
*/
12-
class AjaxBlockTest extends WebDriverTestBase {
10+
class AjaxBlockTest extends LayoutBuilderTestBase {
1311

1412
/**
1513
* {@inheritdoc}
@@ -71,7 +69,8 @@ public function testAddAjaxBlock() {
7169
$assert_session->linkExists('Add Block');
7270
$this->clickLink('Add Block');
7371
$assert_session->assertWaitOnAjaxRequest();
74-
$assert_session->linkExists('TestAjax');
72+
$this->clickBlockCategory('Test');
73+
$this->assertBlockLinkVisible('TestAjax');
7574
$this->clickLink('TestAjax');
7675
$assert_session->assertWaitOnAjaxRequest();
7776
// Find the radio buttons.

core/modules/layout_builder/tests/src/FunctionalJavascript/InlineBlockTestBase.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@
33
namespace Drupal\Tests\layout_builder\FunctionalJavascript;
44

55
use Drupal\block_content\Entity\BlockContentType;
6-
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
76
use Drupal\Tests\contextual\FunctionalJavascript\ContextualLinkClickTrait;
87

98
/**
109
* Base class for testing inline blocks.
1110
*/
12-
abstract class InlineBlockTestBase extends WebDriverTestBase {
11+
abstract class InlineBlockTestBase extends LayoutBuilderTestBase {
1312

1413
use ContextualLinkClickTrait;
1514

0 commit comments

Comments
 (0)