Loading core/modules/layout_builder/src/Plugin/ConfigAction/AddComponent.php +31 −8 Original line number Diff line number Diff line Loading @@ -58,7 +58,7 @@ */ #[ConfigAction( id: 'add_layout_component', admin_label: new TranslatableMarkup('Add component to layout'), admin_label: new TranslatableMarkup('Add component(s) to layout'), deriver: AddComponentDeriver::class, )] final class AddComponent implements ConfigActionPluginInterface, ContainerFactoryPluginInterface { Loading @@ -67,6 +67,7 @@ public function __construct( private readonly ConfigManagerInterface $configManager, private readonly UuidInterface $uuidGenerator, private readonly string $pluginId, private readonly bool $multiple, ) {} /** Loading @@ -78,24 +79,47 @@ public static function create(ContainerInterface $container, array $configuratio $container->get(ConfigManagerInterface::class), $container->get(UuidInterface::class), $plugin_id, $plugin_definition['multiple'], ); } /** * {@inheritdoc} */ public function apply(string $configName, mixed $value): void { assert(is_array($value)); $section_delta = $value['section']; $position = $value['position']; public function apply(string $configName, mixed $values): void { assert(is_array($values)); assert(is_int($section_delta)); assert(is_int($position)); if ($this->multiple) { assert(array_is_list($values)); } else { $values = [$values]; } $entity = $this->configManager->loadConfigEntityByName($configName); if (!$entity instanceof SectionListInterface) { throw new ConfigActionException("No entity found for applying the addComponentToLayout action."); } foreach ($values as $value) { $this->applySingle($entity, $value); } $entity->save(); } /** * Adds a single component to the layout. * * @param \Drupal\layout_builder\SectionListInterface $entity * The entity with a layout. * @param array $value * The data for the config action. */ private function applySingle(SectionListInterface $entity, array $value): void { $section_delta = $value['section']; $position = $value['position']; assert(is_int($section_delta)); assert(is_int($position)); $section = $entity->getSection($section_delta); $component = $value['component']; Loading Loading @@ -127,7 +151,6 @@ public function apply(string $configName, mixed $value): void { $position = min($position, count($section->getComponentsByRegion($region))); $section->insertComponent($position, $component); $entity->setSection($section_delta, $section); $entity->save(); } } core/modules/layout_builder/src/Plugin/ConfigAction/Deriver/AddComponentDeriver.php +6 −1 Original line number Diff line number Diff line Loading @@ -41,7 +41,12 @@ public function getDerivativeDefinitions($base_plugin_definition): array { } } $base_plugin_definition['entity_types'] = $entity_types; $this->derivatives['addComponentToLayout'] = $base_plugin_definition; $this->derivatives['addComponentToLayout'] = $base_plugin_definition + [ 'multiple' => FALSE, ]; $this->derivatives['addComponentsToLayout'] = $base_plugin_definition + [ 'multiple' => TRUE, ]; return $this->derivatives; } Loading core/modules/layout_builder/tests/src/Kernel/Plugin/ConfigAction/AddComponentTest.php +76 −3 Original line number Diff line number Diff line Loading @@ -6,19 +6,25 @@ use Drupal\Core\Config\Action\ConfigActionException; use Drupal\Core\Config\Action\ConfigActionManager; use Drupal\Core\Entity\Entity\EntityViewDisplay; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\entity_test\EntityTestHelper; use Drupal\KernelTests\KernelTestBase; use Drupal\layout_builder\Plugin\ConfigAction\AddComponent; use Drupal\layout_builder\Plugin\ConfigAction\Deriver\AddComponentDeriver; use Drupal\layout_builder\Plugin\SectionStorage\DefaultsSectionStorage; use Drupal\layout_builder\Section; use Drupal\layout_builder\SectionListInterface; use Drupal\layout_builder\SectionStorage\SectionStorageManagerInterface; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; /** * @coversDefaultClass \Drupal\layout_builder\Plugin\ConfigAction\AddComponent * * @group layout_builder * Tests that `addComponentToLayout` config action. */ #[Group('layout_builder')] #[CoversClass(AddComponent::class)] #[CoversClass(AddComponentDeriver::class)] class AddComponentTest extends KernelTestBase { /** Loading Loading @@ -398,4 +404,71 @@ public function testActionFailsIfEntityNotFound(): void { ]); } /** * Tests that the deriver produces the expected derivatives. */ public function testDerivativeDefinitions(): void { $singular = $this->configActionManager->getDefinition('add_layout_component:addComponentToLayout'); $plural = $this->configActionManager->getDefinition('add_layout_component:addComponentsToLayout'); // These actions should be limited to entity types that carry section lists. $this->assertSame(['entity_view_display'], $singular['entity_types']); // The `multiple` flag should differ. $this->assertFalse($singular['multiple']); $this->assertTrue($plural['multiple']); // There should only be two derivatives (the singular and the plural). $definitions = array_filter( array_keys($this->configActionManager->getDefinitions()), fn (string $id): bool => str_starts_with($id, 'add_layout_component:'), ); $this->assertCount(2, $definitions); } /** * Tests adding multiple components at once. */ public function testAddMultipleComponents(): void { $uuid1 = '955493d5-f4c0-4fd1-a8aa-6bcf92d455e6'; $uuid2 = 'b6e2f3d1-a496-426c-b0e5-eff1d14fc461'; $this->configActionManager->applyAction( 'addComponentsToLayout', 'core.entity_view_display.entity_test.bundle_with_extra_fields.default', [ [ 'section' => 0, 'position' => 0, 'component' => [ 'region' => [ 'layout_twocol_section' => 'first', ], 'default_region' => 'content', 'configuration' => [ 'id' => 'my_plugin_id', ], 'uuid' => $uuid1, ], ], [ 'section' => 0, 'position' => 1, 'component' => [ 'region' => [ 'layout_twocol_section' => 'first', ], 'default_region' => 'content', 'configuration' => [ 'id' => 'my_plugin_id', ], 'uuid' => $uuid2, ], ], ], ); $display = EntityViewDisplay::load('entity_test.bundle_with_extra_fields.default'); $components = $display?->getSection(0)->getComponents(); $this->assertArrayHasKey($uuid1, $components); $this->assertArrayHasKey($uuid2, $components); } } Loading
core/modules/layout_builder/src/Plugin/ConfigAction/AddComponent.php +31 −8 Original line number Diff line number Diff line Loading @@ -58,7 +58,7 @@ */ #[ConfigAction( id: 'add_layout_component', admin_label: new TranslatableMarkup('Add component to layout'), admin_label: new TranslatableMarkup('Add component(s) to layout'), deriver: AddComponentDeriver::class, )] final class AddComponent implements ConfigActionPluginInterface, ContainerFactoryPluginInterface { Loading @@ -67,6 +67,7 @@ public function __construct( private readonly ConfigManagerInterface $configManager, private readonly UuidInterface $uuidGenerator, private readonly string $pluginId, private readonly bool $multiple, ) {} /** Loading @@ -78,24 +79,47 @@ public static function create(ContainerInterface $container, array $configuratio $container->get(ConfigManagerInterface::class), $container->get(UuidInterface::class), $plugin_id, $plugin_definition['multiple'], ); } /** * {@inheritdoc} */ public function apply(string $configName, mixed $value): void { assert(is_array($value)); $section_delta = $value['section']; $position = $value['position']; public function apply(string $configName, mixed $values): void { assert(is_array($values)); assert(is_int($section_delta)); assert(is_int($position)); if ($this->multiple) { assert(array_is_list($values)); } else { $values = [$values]; } $entity = $this->configManager->loadConfigEntityByName($configName); if (!$entity instanceof SectionListInterface) { throw new ConfigActionException("No entity found for applying the addComponentToLayout action."); } foreach ($values as $value) { $this->applySingle($entity, $value); } $entity->save(); } /** * Adds a single component to the layout. * * @param \Drupal\layout_builder\SectionListInterface $entity * The entity with a layout. * @param array $value * The data for the config action. */ private function applySingle(SectionListInterface $entity, array $value): void { $section_delta = $value['section']; $position = $value['position']; assert(is_int($section_delta)); assert(is_int($position)); $section = $entity->getSection($section_delta); $component = $value['component']; Loading Loading @@ -127,7 +151,6 @@ public function apply(string $configName, mixed $value): void { $position = min($position, count($section->getComponentsByRegion($region))); $section->insertComponent($position, $component); $entity->setSection($section_delta, $section); $entity->save(); } }
core/modules/layout_builder/src/Plugin/ConfigAction/Deriver/AddComponentDeriver.php +6 −1 Original line number Diff line number Diff line Loading @@ -41,7 +41,12 @@ public function getDerivativeDefinitions($base_plugin_definition): array { } } $base_plugin_definition['entity_types'] = $entity_types; $this->derivatives['addComponentToLayout'] = $base_plugin_definition; $this->derivatives['addComponentToLayout'] = $base_plugin_definition + [ 'multiple' => FALSE, ]; $this->derivatives['addComponentsToLayout'] = $base_plugin_definition + [ 'multiple' => TRUE, ]; return $this->derivatives; } Loading
core/modules/layout_builder/tests/src/Kernel/Plugin/ConfigAction/AddComponentTest.php +76 −3 Original line number Diff line number Diff line Loading @@ -6,19 +6,25 @@ use Drupal\Core\Config\Action\ConfigActionException; use Drupal\Core\Config\Action\ConfigActionManager; use Drupal\Core\Entity\Entity\EntityViewDisplay; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\entity_test\EntityTestHelper; use Drupal\KernelTests\KernelTestBase; use Drupal\layout_builder\Plugin\ConfigAction\AddComponent; use Drupal\layout_builder\Plugin\ConfigAction\Deriver\AddComponentDeriver; use Drupal\layout_builder\Plugin\SectionStorage\DefaultsSectionStorage; use Drupal\layout_builder\Section; use Drupal\layout_builder\SectionListInterface; use Drupal\layout_builder\SectionStorage\SectionStorageManagerInterface; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; /** * @coversDefaultClass \Drupal\layout_builder\Plugin\ConfigAction\AddComponent * * @group layout_builder * Tests that `addComponentToLayout` config action. */ #[Group('layout_builder')] #[CoversClass(AddComponent::class)] #[CoversClass(AddComponentDeriver::class)] class AddComponentTest extends KernelTestBase { /** Loading Loading @@ -398,4 +404,71 @@ public function testActionFailsIfEntityNotFound(): void { ]); } /** * Tests that the deriver produces the expected derivatives. */ public function testDerivativeDefinitions(): void { $singular = $this->configActionManager->getDefinition('add_layout_component:addComponentToLayout'); $plural = $this->configActionManager->getDefinition('add_layout_component:addComponentsToLayout'); // These actions should be limited to entity types that carry section lists. $this->assertSame(['entity_view_display'], $singular['entity_types']); // The `multiple` flag should differ. $this->assertFalse($singular['multiple']); $this->assertTrue($plural['multiple']); // There should only be two derivatives (the singular and the plural). $definitions = array_filter( array_keys($this->configActionManager->getDefinitions()), fn (string $id): bool => str_starts_with($id, 'add_layout_component:'), ); $this->assertCount(2, $definitions); } /** * Tests adding multiple components at once. */ public function testAddMultipleComponents(): void { $uuid1 = '955493d5-f4c0-4fd1-a8aa-6bcf92d455e6'; $uuid2 = 'b6e2f3d1-a496-426c-b0e5-eff1d14fc461'; $this->configActionManager->applyAction( 'addComponentsToLayout', 'core.entity_view_display.entity_test.bundle_with_extra_fields.default', [ [ 'section' => 0, 'position' => 0, 'component' => [ 'region' => [ 'layout_twocol_section' => 'first', ], 'default_region' => 'content', 'configuration' => [ 'id' => 'my_plugin_id', ], 'uuid' => $uuid1, ], ], [ 'section' => 0, 'position' => 1, 'component' => [ 'region' => [ 'layout_twocol_section' => 'first', ], 'default_region' => 'content', 'configuration' => [ 'id' => 'my_plugin_id', ], 'uuid' => $uuid2, ], ], ], ); $display = EntityViewDisplay::load('entity_test.bundle_with_extra_fields.default'); $components = $display?->getSection(0)->getComponents(); $this->assertArrayHasKey($uuid1, $components); $this->assertArrayHasKey($uuid2, $components); } }