diff --git a/core/modules/layout_builder/src/Controller/LayoutBuilderController.php b/core/modules/layout_builder/src/Controller/LayoutBuilderController.php index 8dd70f73c7..62164f65f0 100644 --- a/core/modules/layout_builder/src/Controller/LayoutBuilderController.php +++ b/core/modules/layout_builder/src/Controller/LayoutBuilderController.php @@ -302,4 +302,27 @@ public function cancelLayout(SectionStorageInterface $section_storage) { return new RedirectResponse($section_storage->getCanonicalUrl()->setAbsolute()->toString()); } + /** + * Reverts the overridden layout to the defaults. + * + * @param \Drupal\layout_builder\SectionStorageInterface $section_storage + * The section storage. + * + * @return \Symfony\Component\HttpFoundation\RedirectResponse + * A redirect response. + */ + public function revertLayout(SectionStorageInterface $section_storage) { + if (!$section_storage instanceof OverridesSectionStorageInterface) { + throw new \InvalidArgumentException(sprintf('The section storage with type "%s" and ID "%s" does not provide overrides', $section_storage->getStorageType(), $section_storage->getStorageId())); + } + + // Remove all sections. + while ($section_storage->count()) { + $section_storage->removeSection(0); + } + $section_storage->save(); + $this->layoutTempstoreRepository->delete($section_storage); + return new RedirectResponse($section_storage->getLayoutBuilderUrl()->setAbsolute()->toString()); + } + } diff --git a/core/modules/layout_builder/src/Plugin/Derivative/LayoutBuilderLocalTaskDeriver.php b/core/modules/layout_builder/src/Plugin/Derivative/LayoutBuilderLocalTaskDeriver.php index 403c506c4b..ff78bced6c 100644 --- a/core/modules/layout_builder/src/Plugin/Derivative/LayoutBuilderLocalTaskDeriver.php +++ b/core/modules/layout_builder/src/Plugin/Derivative/LayoutBuilderLocalTaskDeriver.php @@ -49,6 +49,7 @@ public static function create(ContainerInterface $container, $base_plugin_id) { */ public function getDerivativeDefinitions($base_plugin_definition) { foreach ($this->getEntityTypes() as $entity_type_id => $entity_type) { + // Overrides. $this->derivatives["entity.$entity_type_id.layout_builder"] = $base_plugin_definition + [ 'route_name' => "entity.$entity_type_id.layout_builder", 'weight' => 15, @@ -72,27 +73,35 @@ public function getDerivativeDefinitions($base_plugin_definition) { 'weight' => 5, 'cache_contexts' => ['layout_builder_is_active:' . $entity_type_id], ]; - if ($entity_type->get('field_ui_base_route')) { - $this->derivatives["entity.entity_view_display.$entity_type_id.layout_builder"] = $base_plugin_definition + [ - 'route_name' => "entity.entity_view_display.$entity_type_id.layout_builder", - 'title' => $this->t('Manage layout'), - 'base_route' => "entity.entity_view_display.$entity_type_id.layout_builder", - 'entity_type_id' => $entity_type_id, - ]; - $this->derivatives["entity.entity_view_display.$entity_type_id.layout_builder_save"] = $base_plugin_definition + [ - 'route_name' => "entity.entity_view_display.$entity_type_id.layout_builder_save", - 'title' => $this->t('Save Layout'), - 'parent_id' => "layout_builder_ui:entity.entity_view_display.$entity_type_id.layout_builder", - 'entity_type_id' => $entity_type_id, - ]; - $this->derivatives["entity.entity_view_display.$entity_type_id.layout_builder_cancel"] = $base_plugin_definition + [ - 'route_name' => "entity.entity_view_display.$entity_type_id.layout_builder_cancel", - 'title' => $this->t('Cancel Layout'), - 'weight' => 5, - 'parent_id' => "layout_builder_ui:entity.entity_view_display.$entity_type_id.layout_builder", - 'entity_type_id' => $entity_type_id, - ]; - } + $this->derivatives["entity.$entity_type_id.layout_builder_revert"] = $base_plugin_definition + [ + 'route_name' => "entity.$entity_type_id.layout_builder_revert", + 'title' => $this->t('Revert to defaults'), + 'parent_id' => "layout_builder_ui:entity.$entity_type_id.layout_builder", + 'entity_type_id' => $entity_type_id, + 'weight' => 10, + 'cache_contexts' => ['layout_builder_is_active:' . $entity_type_id], + ]; + + // Defaults. + $this->derivatives["entity.entity_view_display.$entity_type_id.layout_builder"] = $base_plugin_definition + [ + 'route_name' => "entity.entity_view_display.$entity_type_id.layout_builder", + 'title' => $this->t('Manage layout'), + 'base_route' => "entity.entity_view_display.$entity_type_id.layout_builder", + 'entity_type_id' => $entity_type_id, + ]; + $this->derivatives["entity.entity_view_display.$entity_type_id.layout_builder_save"] = $base_plugin_definition + [ + 'route_name' => "entity.entity_view_display.$entity_type_id.layout_builder_save", + 'title' => $this->t('Save Layout'), + 'parent_id' => "layout_builder_ui:entity.entity_view_display.$entity_type_id.layout_builder", + 'entity_type_id' => $entity_type_id, + ]; + $this->derivatives["entity.entity_view_display.$entity_type_id.layout_builder_cancel"] = $base_plugin_definition + [ + 'route_name' => "entity.entity_view_display.$entity_type_id.layout_builder_cancel", + 'title' => $this->t('Cancel Layout'), + 'weight' => 5, + 'parent_id' => "layout_builder_ui:entity.entity_view_display.$entity_type_id.layout_builder", + 'entity_type_id' => $entity_type_id, + ]; } return $this->derivatives; diff --git a/core/modules/layout_builder/src/Routing/LayoutBuilderRoutes.php b/core/modules/layout_builder/src/Routing/LayoutBuilderRoutes.php index c393b24fd1..28e080c48b 100644 --- a/core/modules/layout_builder/src/Routing/LayoutBuilderRoutes.php +++ b/core/modules/layout_builder/src/Routing/LayoutBuilderRoutes.php @@ -172,6 +172,16 @@ protected function buildRoute($type, $route_name_prefix, $path, array $defaults, ->setOptions($options); $routes["{$route_name_prefix}.layout_builder_cancel"] = $route; + if ($type === 'overrides') { + $revert_defaults = $defaults; + $revert_defaults['_controller'] = '\Drupal\layout_builder\Controller\LayoutBuilderController::revertLayout'; + $route = (new Route("$path/revert")) + ->setDefaults($revert_defaults) + ->setRequirements($requirements) + ->setOptions($options); + $routes["{$route_name_prefix}.layout_builder_revert"] = $route; + } + return $routes; } diff --git a/core/modules/layout_builder/tests/src/Unit/LayoutBuilderRoutesTest.php b/core/modules/layout_builder/tests/src/Unit/LayoutBuilderRoutesTest.php index e47448c177..7eb293bd7a 100644 --- a/core/modules/layout_builder/tests/src/Unit/LayoutBuilderRoutesTest.php +++ b/core/modules/layout_builder/tests/src/Unit/LayoutBuilderRoutesTest.php @@ -148,6 +148,25 @@ public function testGetRoutes() { '_layout_builder' => TRUE, ] ), + 'entity.with_link_template.layout_builder_revert' => new Route( + '/entity/{entity}/layout/revert', + [ + 'entity_type_id' => 'with_link_template', + 'section_storage_type' => 'overrides', + 'section_storage' => '', + '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::revertLayout', + ], + [ + '_has_layout_section' => 'true', + ], + [ + 'parameters' => [ + 'section_storage' => ['layout_builder_tempstore' => TRUE], + 'with_link_template' => ['type' => 'entity:with_link_template'], + ], + '_layout_builder' => TRUE, + ] + ), 'entity.with_integer_id.layout_builder' => new Route( '/entity/{entity}/layout', [ @@ -210,6 +229,26 @@ public function testGetRoutes() { '_layout_builder' => TRUE, ] ), + 'entity.with_integer_id.layout_builder_revert' => new Route( + '/entity/{entity}/layout/revert', + [ + 'entity_type_id' => 'with_integer_id', + 'section_storage_type' => 'overrides', + 'section_storage' => '', + '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::revertLayout', + ], + [ + '_has_layout_section' => 'true', + 'with_integer_id' => '\d+', + ], + [ + 'parameters' => [ + 'section_storage' => ['layout_builder_tempstore' => TRUE], + 'with_integer_id' => ['type' => 'entity:with_integer_id'], + ], + '_layout_builder' => TRUE, + ] + ), 'entity.with_field_ui_route.layout_builder' => new Route( '/entity/{entity}/layout', [ @@ -272,6 +311,26 @@ public function testGetRoutes() { '_layout_builder' => TRUE, ] ), + 'entity.with_field_ui_route.layout_builder_revert' => new Route( + '/entity/{entity}/layout/revert', + [ + 'entity_type_id' => 'with_field_ui_route', + 'section_storage_type' => 'overrides', + 'section_storage' => '', + '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::revertLayout', + ], + [ + '_has_layout_section' => 'true', + 'with_field_ui_route' => '\d+', + ], + [ + 'parameters' => [ + 'section_storage' => ['layout_builder_tempstore' => TRUE], + 'with_field_ui_route' => ['type' => 'entity:with_field_ui_route'], + ], + '_layout_builder' => TRUE, + ] + ), 'entity.with_bundle_key.layout_builder' => new Route( '/entity/{entity}/layout', [ @@ -334,6 +393,26 @@ public function testGetRoutes() { '_layout_builder' => TRUE, ] ), + 'entity.with_bundle_key.layout_builder_revert' => new Route( + '/entity/{entity}/layout/revert', + [ + 'entity_type_id' => 'with_bundle_key', + 'section_storage_type' => 'overrides', + 'section_storage' => '', + '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::revertLayout', + ], + [ + '_has_layout_section' => 'true', + 'with_bundle_key' => '\d+', + ], + [ + 'parameters' => [ + 'section_storage' => ['layout_builder_tempstore' => TRUE], + 'with_bundle_key' => ['type' => 'entity:with_bundle_key'], + ], + '_layout_builder' => TRUE, + ] + ), 'entity.with_bundle_parameter.layout_builder' => new Route( '/entity/{entity}/layout', [ @@ -396,6 +475,26 @@ public function testGetRoutes() { '_layout_builder' => TRUE, ] ), + 'entity.with_bundle_parameter.layout_builder_revert' => new Route( + '/entity/{entity}/layout/revert', + [ + 'entity_type_id' => 'with_bundle_parameter', + 'section_storage_type' => 'overrides', + 'section_storage' => '', + '_controller' => '\Drupal\layout_builder\Controller\LayoutBuilderController::revertLayout', + ], + [ + '_has_layout_section' => 'true', + 'with_bundle_parameter' => '\d+', + ], + [ + 'parameters' => [ + 'section_storage' => ['layout_builder_tempstore' => TRUE], + 'with_bundle_parameter' => ['type' => 'entity:with_bundle_parameter'], + ], + '_layout_builder' => TRUE, + ] + ), ]; $this->assertEquals($expected, $this->routeBuilder->getRoutes());