From d7f5dbc09cd02101aebb4bf8f967b6dd747a5d99 Mon Sep 17 00:00:00 2001 From: Alex Pott Date: Wed, 11 Dec 2024 17:08:38 +0000 Subject: [PATCH] Issue #3493287 by phenaproxima, alexpott, longwave, tim.plunkett: The default content importer should handle Layout Builder section data (cherry picked from commit a44cf1ef0088f1c16f90a685fb6093a238303eca) --- .../src/Plugin/DataType/SectionData.php | 3 + .../tests/src/Kernel/SectionDataTest.php | 40 +++++++++++++ .../DefaultContent/ContentImportTest.php | 19 ++++++ .../32650de8-9edd-48dc-80b8-8bda180ebbac.yml | 60 +++++++++++++++++++ 4 files changed, 122 insertions(+) create mode 100644 core/modules/layout_builder/tests/src/Kernel/SectionDataTest.php create mode 100644 core/tests/fixtures/default_content/node/32650de8-9edd-48dc-80b8-8bda180ebbac.yml diff --git a/core/modules/layout_builder/src/Plugin/DataType/SectionData.php b/core/modules/layout_builder/src/Plugin/DataType/SectionData.php index 9acf046b0a4..67c60801bc3 100644 --- a/core/modules/layout_builder/src/Plugin/DataType/SectionData.php +++ b/core/modules/layout_builder/src/Plugin/DataType/SectionData.php @@ -31,6 +31,9 @@ class SectionData extends TypedData { * {@inheritdoc} */ public function setValue($value, $notify = TRUE) { + if (is_array($value)) { + $value = Section::fromArray($value); + } if ($value && !$value instanceof Section) { throw new \InvalidArgumentException(sprintf('Value assigned to "%s" is not a valid section', $this->getName())); } diff --git a/core/modules/layout_builder/tests/src/Kernel/SectionDataTest.php b/core/modules/layout_builder/tests/src/Kernel/SectionDataTest.php new file mode 100644 index 00000000000..77972ea0d96 --- /dev/null +++ b/core/modules/layout_builder/tests/src/Kernel/SectionDataTest.php @@ -0,0 +1,40 @@ +container->get(TypedDataManagerInterface::class) + ->create($definition, name: 'test_section'); + + // If an array is passed, it's converted to a Section object. + $data->setValue([]); + $this->assertInstanceOf(Section::class, $data->getValue()); + // Anything else should raise an exception. + $this->expectExceptionMessage('Value assigned to "test_section" is not a valid section'); + $data->setValue('[]'); + } + +} diff --git a/core/tests/Drupal/FunctionalTests/DefaultContent/ContentImportTest.php b/core/tests/Drupal/FunctionalTests/DefaultContent/ContentImportTest.php index c177b503af0..17164828ed3 100644 --- a/core/tests/Drupal/FunctionalTests/DefaultContent/ContentImportTest.php +++ b/core/tests/Drupal/FunctionalTests/DefaultContent/ContentImportTest.php @@ -13,6 +13,7 @@ use Drupal\Core\DefaultContent\Finder; use Drupal\Core\DefaultContent\Importer; use Drupal\Core\DefaultContent\ImportException; use Drupal\Core\DefaultContent\InvalidEntityException; +use Drupal\Core\Entity\EntityDisplayRepositoryInterface; use Drupal\Core\Entity\EntityRepositoryInterface; use Drupal\Core\File\FileExists; use Drupal\Core\Url; @@ -22,6 +23,7 @@ use Drupal\file\FileInterface; use Drupal\FunctionalTests\Core\Recipe\RecipeTestTrait; use Drupal\language\Entity\ConfigurableLanguage; use Drupal\language\Entity\ContentLanguageSettings; +use Drupal\layout_builder\Section; use Drupal\media\MediaInterface; use Drupal\menu_link_content\MenuLinkContentInterface; use Drupal\node\NodeInterface; @@ -57,6 +59,7 @@ class ContentImportTest extends BrowserTestBase { 'block_content', 'content_translation', 'entity_test', + 'layout_builder', 'media', 'menu_link_content', 'node', @@ -108,6 +111,13 @@ class ContentImportTest extends BrowserTestBase { $this->contentDir = $this->getDrupalRoot() . '/core/tests/fixtures/default_content'; \Drupal::service('file_system')->copy($this->contentDir . '/file/druplicon_copy.png', $this->publicFilesDirectory . '/druplicon_copy.png', FileExists::Error); + + // Enable Layout Builder for the Page content type, with custom overrides. + \Drupal::service(EntityDisplayRepositoryInterface::class) + ->getViewDisplay('node', 'page') + ->enableLayoutBuilder() + ->setOverridable() + ->save(); } /** @@ -259,6 +269,15 @@ class ContentImportTest extends BrowserTestBase { $translation = $node->getTranslation('fr'); $this->assertSame('Perdu en traduction', $translation->label()); $this->assertSame("Içi c'est la version français.", $translation->body->value); + + // Layout data should be imported. + $node = $entity_repository->loadEntityByUuid('node', '32650de8-9edd-48dc-80b8-8bda180ebbac'); + $this->assertInstanceOf(NodeInterface::class, $node); + $section = $node->layout_builder__layout[0]->section; + $this->assertInstanceOf(Section::class, $section); + $this->assertCount(2, $section->getComponents()); + $this->assertSame('system_powered_by_block', $section->getComponent('03b45f14-cf74-469a-8398-edf3383ce7fa')->getPluginId()); + } } diff --git a/core/tests/fixtures/default_content/node/32650de8-9edd-48dc-80b8-8bda180ebbac.yml b/core/tests/fixtures/default_content/node/32650de8-9edd-48dc-80b8-8bda180ebbac.yml new file mode 100644 index 00000000000..e2cc0400c2c --- /dev/null +++ b/core/tests/fixtures/default_content/node/32650de8-9edd-48dc-80b8-8bda180ebbac.yml @@ -0,0 +1,60 @@ +_meta: + version: '1.0' + entity_type: node + uuid: 32650de8-9edd-48dc-80b8-8bda180ebbac + bundle: page + default_langcode: en +default: + revision_uid: + - + target_id: 1 + status: + - + value: true + uid: + - + target_id: 1 + title: + - + value: 'Layout override' + created: + - + value: 1733930395 + promote: + - + value: true + sticky: + - + value: false + revision_translation_affected: + - + value: true + layout_builder__layout: + - + section: + layout_id: layout_onecol + layout_settings: + label: '' + components: + 199f7eea-3e6e-4a91-bf5e-7b1d6f13fecd: + uuid: 199f7eea-3e6e-4a91-bf5e-7b1d6f13fecd + region: content + configuration: + id: 'extra_field_block:node:test:links' + label_display: '0' + context_mapping: + entity: layout_builder.entity + weight: 1 + additional: { } + 03b45f14-cf74-469a-8398-edf3383ce7fa: + uuid: 03b45f14-cf74-469a-8398-edf3383ce7fa + region: content + configuration: + id: system_powered_by_block + label: 'Powered by Drupal' + label_display: 0 + provider: system + context_mapping: { } + weight: 0 + additional: { } + third_party_settings: { }