diff --git a/core/modules/field_layout/css/twocol.layout.css b/core/modules/field_layout/css/twocol.layout.css new file mode 100644 index 0000000..e969f51 --- /dev/null +++ b/core/modules/field_layout/css/twocol.layout.css @@ -0,0 +1,8 @@ +.field-layout-layout--twocol { + display: flex; + flex-wrap: wrap; + justify-content: space-between; +} +.field-layout-layout--twocol > .field-layout-region { + flex: 0 1 50%; +} diff --git a/core/modules/field_layout/field_layout.libraries.yml b/core/modules/field_layout/field_layout.libraries.yml index 59ed060..fdfa277 100644 --- a/core/modules/field_layout/field_layout.libraries.yml +++ b/core/modules/field_layout/field_layout.libraries.yml @@ -4,3 +4,9 @@ drupal.field_layout: js/field_layout.js: {} dependencies: - field_ui/drupal.field_ui + +drupal.field_layout.twocol: + version: VERSION + css: + layout: + css/twocol.layout.css: {} diff --git a/core/modules/field_layout/field_layout.module b/core/modules/field_layout/field_layout.module index b62c89a..29383ec 100644 --- a/core/modules/field_layout/field_layout.module +++ b/core/modules/field_layout/field_layout.module @@ -84,16 +84,23 @@ function _field_layout_apply_layout(array &$build, EntityDisplayInterface $displ return; } + // Wrap the regions in a layout element. + $build['field_layout']['#theme_wrappers'][] = 'field_layout_layout'; + $build['field_layout']['#layout'] = $layout_definition['layout']; + if (isset($layout_definition['library'])) { + $build['#attached']['library'][] = $layout_definition['library']; + } + // Add the regions to the $build in the correct order. foreach ($layout_definition['regions'] as $region => $region_info) { - $build['field_layout__' . $region]['#theme_wrappers'][] = 'field_layout_region'; - $build['field_layout__' . $region]['#region'] = $region; + $build['field_layout'][$region]['#theme_wrappers'][] = 'field_layout_region'; + $build['field_layout'][$region]['#region'] = $region; } // Move the field from the top-level of $build into a region-specific section. foreach ($display->getThirdPartySetting('field_layout', 'fields', []) as $name => $field) { if (isset($build[$name]) && $field['region'] !== 'hidden') { - $build['field_layout__' . $field['region']][$name] = $build[$name]; + $build['field_layout'][$field['region']][$name] = $build[$name]; } unset($build[$name]); } @@ -107,10 +114,28 @@ function field_layout_theme($existing, $type, $theme, $path) { 'field_layout_region' => [ 'render element' => 'elements', ], + 'field_layout_layout' => [ + 'render element' => 'elements', + ], ]; } /** + * Prepares variables for field layout layout templates. + * + * Default template: field-layout-layout.html.twig. + * + * @param array $variables + * An associative array containing: + * - elements: An associative array containing properties of the layout. + */ +function template_preprocess_field_layout_layout(&$variables) { + // Create the $content variable that templates expect. + $variables['content'] = $variables['elements']['#children']; + $variables['layout'] = $variables['elements']['#layout']; +} + +/** * Prepares variables for field layout region templates. * * Default template: field-layout-region.html.twig. diff --git a/core/modules/field_layout/src/LayoutRepository.php b/core/modules/field_layout/src/LayoutRepository.php index 83b3108..5fe4540 100644 --- a/core/modules/field_layout/src/LayoutRepository.php +++ b/core/modules/field_layout/src/LayoutRepository.php @@ -37,19 +37,9 @@ public function getLayoutDefinitions() { ], ], ], - '1col_stacked' => [ - 'label' => $this->t('One column stacked'), - 'regions' => [ - 'top' => [ - 'label' => $this->t('Top'), - ], - 'bottom' => [ - 'label' => $this->t('Bottom'), - ], - ], - ], - '2col' => [ + 'twocol' => [ 'label' => $this->t('Two column'), + 'library' => 'field_layout/drupal.field_layout.twocol', 'regions' => [ 'left' => [ 'label' => $this->t('Left'), @@ -60,6 +50,9 @@ public function getLayoutDefinitions() { ], ], ]; + foreach ($layouts as $layout_name => $layout) { + $layouts[$layout_name]['layout'] = $layout_name; + } return $layouts; } diff --git a/core/modules/field_layout/templates/field-layout-layout.html.twig b/core/modules/field_layout/templates/field-layout-layout.html.twig new file mode 100644 index 0000000..f08168c --- /dev/null +++ b/core/modules/field_layout/templates/field-layout-layout.html.twig @@ -0,0 +1,23 @@ +{# +/** + * @file + * Default theme implementation to display a layout. + * + * Available variables: + * - content: The content for this layout, typically blocks. + * - attributes: HTML attributes for the layout
. + * - layout: The name of the layout variable. + * + * @ingroup themeable + */ +#} +{% +set classes = [ +'field-layout--' ~ layout|clean_class, +] +%} +{% if content %} + + {{ content }} +
+{% endif %} diff --git a/core/modules/field_layout/templates/field-layout-region.html.twig b/core/modules/field_layout/templates/field-layout-region.html.twig index 6969b5f..11e3604 100644 --- a/core/modules/field_layout/templates/field-layout-region.html.twig +++ b/core/modules/field_layout/templates/field-layout-region.html.twig @@ -6,10 +6,7 @@ * Available variables: * - content: The content for this region, typically blocks. * - attributes: HTML attributes for the region
. - * - region: The name of the region variable as defined in the theme's - * .info.yml file. - * - * @see template_preprocess_region() + * - region: The name of the region variable. * * @ingroup themeable */ diff --git a/core/modules/field_layout/tests/src/FunctionalJavascript/FieldLayoutTest.php b/core/modules/field_layout/tests/src/FunctionalJavascript/FieldLayoutTest.php index ea007e0..6378b76 100644 --- a/core/modules/field_layout/tests/src/FunctionalJavascript/FieldLayoutTest.php +++ b/core/modules/field_layout/tests/src/FunctionalJavascript/FieldLayoutTest.php @@ -99,7 +99,7 @@ public function testEntityForm() { // Switch the layout to two columns. $this->click('#edit-field-layouts'); - $this->getSession()->getPage()->selectFieldOption('field_layout', '2col'); + $this->getSession()->getPage()->selectFieldOption('field_layout', 'twocol'); $this->submitForm([], 'Save'); $this->assertSession()->pageTextContains('Your settings have been saved.'); @@ -156,7 +156,7 @@ public function testEntityView() { // Switch the layout to two columns. $this->click('#edit-field-layouts'); - $this->getSession()->getPage()->selectFieldOption('field_layout', '2col'); + $this->getSession()->getPage()->selectFieldOption('field_layout', 'twocol'); $this->submitForm([], 'Save'); $this->assertSession()->pageTextContains('Your settings have been saved.'); @@ -164,6 +164,7 @@ public function testEntityView() { $this->drupalGet('entity_test/1'); // No fields are visible, and the regions don't display when empty. + $this->assertSession()->elementNotExists('css', '.field-layout--default'); $this->assertSession()->elementNotExists('css', '.field-layout-region'); $this->assertSession()->elementNotExists('css', '.field--name-field-test-text'); @@ -184,6 +185,7 @@ public function testEntityView() { // The new layout is used. $this->drupalGet('entity_test/1'); + $this->assertSession()->elementExists('css', '.field-layout--twocol'); $this->assertSession()->elementExists('css', '.field-layout-region--left .field--name-field-test-text'); // Move the field to the right region without tabledrag. @@ -201,6 +203,7 @@ public function testEntityView() { // The layout is still in use without Field UI. $this->container->get('module_installer')->uninstall(['field_ui']); $this->drupalGet('entity_test/1'); + $this->assertSession()->elementExists('css', '.field-layout--twocol'); $this->assertSession()->elementExists('css', '.field-layout-region--right .field--name-field-test-text'); } @@ -210,6 +213,7 @@ public function testEntityView() { public function testNodeView() { // By default, the default layout is used. $this->drupalGet('node/1'); + $this->assertSession()->elementExists('css', '.field-layout--default'); $this->assertSession()->elementExists('css', '.field-layout-region--content .field--name-body'); $this->drupalGet('admin/structure/types/manage/article/display'); diff --git a/core/modules/field_layout/tests/src/Unit/LayoutRepositoryTest.php b/core/modules/field_layout/tests/src/Unit/LayoutRepositoryTest.php index 303ce6c..8bbde70 100644 --- a/core/modules/field_layout/tests/src/Unit/LayoutRepositoryTest.php +++ b/core/modules/field_layout/tests/src/Unit/LayoutRepositoryTest.php @@ -20,7 +20,7 @@ class LayoutRepositoryTest extends UnitTestCase { public function testGetLayoutDefinitions() { $layout_repository = new LayoutRepository($this->getStringTranslationStub()); - $expected = ['default', '1col_stacked', '2col']; + $expected = ['default', 'twocol']; $layout_definitions = $layout_repository->getLayoutDefinitions(); $this->assertEquals($expected, array_keys($layout_definitions)); @@ -33,11 +33,12 @@ public function testGetLayoutForDisplay() { $layout_repository = new LayoutRepository($this->getStringTranslationStub()); $display = $this->prophesize(EntityDisplayInterface::class); - $display->getThirdPartySetting('field_layout', 'layout', 'default')->willReturn('2col'); + $display->getThirdPartySetting('field_layout', 'layout', 'default')->willReturn('twocol'); $expected = ['left', 'right']; $layout_definition = $layout_repository->getLayoutForDisplay($display->reveal()); + $this->assertSame('twocol', $layout_definition['layout']); $this->assertEquals($expected, array_keys($layout_definition['regions'])); } @@ -53,6 +54,7 @@ public function testGetLayoutForDisplayEmpty() { $expected = ['content']; $layout_definition = $layout_repository->getLayoutForDisplay($display->reveal()); + $this->assertSame('default', $layout_definition['layout']); $this->assertEquals($expected, array_keys($layout_definition['regions'])); } diff --git a/core/tests/Drupal/Tests/BrowserTestBase.php b/core/tests/Drupal/Tests/BrowserTestBase.php index ccbc142..ea88906 100644 --- a/core/tests/Drupal/Tests/BrowserTestBase.php +++ b/core/tests/Drupal/Tests/BrowserTestBase.php @@ -1547,8 +1547,8 @@ protected function htmlOutput($message) { if (!$this->htmlOutputEnabled) { return; } - $message = '
ID #' . $this->htmlOutputCounter . ' (Previous | Next)
' . $message; - $html_output_filename = $this->htmlOutputClassName . '-' . $this->htmlOutputCounter . '.html'; + $message = '
ID #' . $this->htmlOutputCounter . ' (Previous | Next)
' . $message; + $html_output_filename = $this->htmlOutputClassName . '-' . $this->htmlOutputCounter . '-' . $this->htmlOutputTestId . '.html'; file_put_contents($this->htmlOutputDirectory . '/' . $html_output_filename, $message); file_put_contents($this->htmlOutputCounterStorage, $this->htmlOutputCounter++); file_put_contents($this->htmlOutputFile, file_create_url('sites/simpletest/browser_output/' . $html_output_filename) . "\n", FILE_APPEND);