diff --git a/core/modules/field_layout/src/Entity/FieldLayoutEntityDisplayTrait.php b/core/modules/field_layout/src/Entity/FieldLayoutEntityDisplayTrait.php index 91cf936..49da6a9 100644 --- a/core/modules/field_layout/src/Entity/FieldLayoutEntityDisplayTrait.php +++ b/core/modules/field_layout/src/Entity/FieldLayoutEntityDisplayTrait.php @@ -48,7 +48,9 @@ public function setLayoutId($layout_id, array $layout_settings = []) { if ($this->getLayoutId() !== $layout_id) { // @todo Devise a mechanism for mapping old regions to new ones in // https://www.drupal.org/node/2796877. - $new_region = $this->getLayoutDefinition($layout_id)->getDefaultRegion(); + $layout_definition = $this->getLayoutDefinition($layout_id); + $new_region = $layout_definition->getDefaultRegion(); + $layout_regions = $layout_definition->getRegions(); foreach ($this->getComponents() as $name => $component) { if (isset($component['region']) && !isset($layout_regions[$component['region']])) { $component['region'] = $new_region; @@ -57,6 +59,12 @@ public function setLayoutId($layout_id, array $layout_settings = []) { } } $this->setThirdPartySetting('field_layout', 'id', $layout_id); + // Instantiate the plugin and consult it for the updated plugin + // configuration. Once layouts are no longer stored as third party settings, + // this will be handled by the code in + // \Drupal\Core\Config\Entity\ConfigEntityBase::set() that handles + // \Drupal\Core\Entity\EntityWithPluginCollectionInterface. + $layout_settings = $this->doGetLayout($layout_id, $layout_settings)->getConfiguration(); $this->setThirdPartySetting('field_layout', 'settings', $layout_settings); return $this; } @@ -73,7 +81,22 @@ public function setLayout(LayoutInterface $layout) { * Implements \Drupal\field_layout\Display\EntityDisplayWithLayoutInterface::getLayout(). */ public function getLayout() { - return \Drupal::service('plugin.manager.core.layout')->createInstance($this->getLayoutId(), $this->getLayoutSettings()); + return $this->doGetLayout($this->getLayoutId(), $this->getLayoutSettings()); + } + + /** + * Gets the layout plugin. + * + * @param string $layout_id + * A layout plugin ID. + * @param array $layout_settings + * An array of settings. + * + * @return \Drupal\Core\Layout\LayoutInterface + * The layout plugin. + */ + protected function doGetLayout($layout_id, array $layout_settings) { + return \Drupal::service('plugin.manager.core.layout')->createInstance($layout_id, $layout_settings); } /** diff --git a/core/modules/field_layout/tests/modules/field_layout_test/config/schema/field_layout_test.schema.yml b/core/modules/field_layout/tests/modules/field_layout_test/config/schema/field_layout_test.schema.yml index c397e73..dc95ab3 100644 --- a/core/modules/field_layout/tests/modules/field_layout_test/config/schema/field_layout_test.schema.yml +++ b/core/modules/field_layout/tests/modules/field_layout_test/config/schema/field_layout_test.schema.yml @@ -1,4 +1,4 @@ -layout_plugin.settings.field_layout_test_plugin: +layout_plugin.settings.test_layout_main_and_footer: type: layout_plugin.settings label: 'Layout test plugin settings' mapping: diff --git a/core/modules/field_layout/tests/modules/field_layout_test/src/Plugin/Layout/TestLayoutContentFooter.php b/core/modules/field_layout/tests/modules/field_layout_test/src/Plugin/Layout/TestLayoutContentFooter.php new file mode 100644 index 0000000..c283c82 --- /dev/null +++ b/core/modules/field_layout/tests/modules/field_layout_test/src/Plugin/Layout/TestLayoutContentFooter.php @@ -0,0 +1,27 @@ +assertEntityValues($expected, $entity_display->toArray()); - // Assign a new layout that has default settings and complex dependencies. - $entity_display->setLayoutId('field_layout_test_plugin'); - $entity_display->save(); + // Assign a new layout that has default settings and complex dependencies, + // but do not save yet. + $entity_display->setLayoutId('test_layout_main_and_footer'); // The default settings were added. $expected['third_party_settings']['field_layout'] = [ - 'id' => 'field_layout_test_plugin', + 'id' => 'test_layout_main_and_footer', 'settings' => [ 'setting_1' => 'Default', ], @@ -99,6 +99,10 @@ public function testPreSave() { 'settings' => [], 'third_party_settings' => [], ]; + $this->assertEntityValues($expected, $entity_display->toArray()); + + // After saving, the dependencies have been updated. + $entity_display->save(); $expected['dependencies']['module'] = [ 'dependency_from_annotation', 'dependency_from_calculateDependencies', @@ -109,13 +113,41 @@ public function testPreSave() { $this->assertEntityValues($expected, $entity_display->toArray()); // Assign a layout with provided settings. - $entity_display->setLayoutId('field_layout_test_plugin', ['setting_1' => 'foobar']); + $entity_display->setLayoutId('test_layout_main_and_footer', ['setting_1' => 'foobar']); $entity_display->save(); // The setting overrides the default value. $expected['third_party_settings']['field_layout']['settings']['setting_1'] = 'foobar'; $this->assertEntityValues($expected, $entity_display->toArray()); + // Move a field to the non-default region. + $component = $entity_display->getComponent('foo'); + $component['region'] = 'footer'; + $entity_display->setComponent('foo', $component); + $entity_display->save(); + + // The field region is saved. + $expected['content']['foo']['region'] = 'footer'; + $this->assertEntityValues($expected, $entity_display->toArray()); + + // Assign a different layout that shares the same non-default region. + $entity_display->setLayoutId('test_layout_content_and_footer'); + $entity_display->save(); + + // The dependencies have been updated. + $expected['dependencies']['module'] = [ + 'entity_test', + 'field_layout', + 'field_layout_test', + ]; + // The layout has been updated. + $expected['third_party_settings']['field_layout'] = [ + 'id' => 'test_layout_content_and_footer', + 'settings' => [], + ]; + // The field remains in its current region instead of moving to the default. + $this->assertEntityValues($expected, $entity_display->toArray()); + $this->container->get('module_installer')->uninstall(['field_layout']); $entity_storage = $this->container->get('entity_type.manager')->getStorage('entity_view_display');