Issue #2936358 by tim.plunkett, johndevman, tedbow, eiriksm, AaronMcHale, phenaproxima, pookmish, alexpott: Layout Builder should be opt-in per display (entity type/bundle/view mode)

8.7.x
Alex Pott 2018-07-24 20:51:45 +01:00
parent df94b0c1ef
commit c6cdc43923
No known key found for this signature in database
GPG Key ID: 31905460D4A69276
32 changed files with 900 additions and 47 deletions

View File

@ -2,6 +2,9 @@ core.entity_view_display.*.*.*.third_party.layout_builder:
type: mapping
label: 'Per-view-mode Layout Builder settings'
mapping:
enabled:
type: boolean
label: 'Whether the Layout Builder is enabled for this display'
allow_custom:
type: boolean
label: 'Allow a customized layout'

View File

@ -13,6 +13,8 @@ use Drupal\layout_builder\Section;
* Implements hook_install().
*/
function layout_builder_install() {
$display_changed = FALSE;
$displays = LayoutBuilderEntityViewDisplay::loadMultiple();
/** @var \Drupal\layout_builder\Entity\LayoutEntityDisplayInterface[] $displays */
foreach ($displays as $display) {
@ -20,21 +22,43 @@ function layout_builder_install() {
$field_layout = $display->getThirdPartySettings('field_layout');
if (isset($field_layout['id'])) {
$field_layout += ['settings' => []];
$display->appendSection(new Section($field_layout['id'], $field_layout['settings']));
$display
->enableLayoutBuilder()
->appendSection(new Section($field_layout['id'], $field_layout['settings']))
->save();
$display_changed = TRUE;
}
// Sort the components by weight.
$components = $display->get('content');
uasort($components, 'Drupal\Component\Utility\SortArray::sortByWeightElement');
foreach ($components as $name => $component) {
$display->setComponent($name, $component);
}
$display->save();
}
// Clear the rendered cache to ensure the new layout builder flow is used.
// While in many cases the above change will not affect the rendered output,
// the cacheability metadata will have changed and should be processed to
// prepare for future changes.
Cache::invalidateTags(['rendered']);
if ($display_changed) {
Cache::invalidateTags(['rendered']);
}
}
/**
* Enable Layout Builder for existing entity displays.
*/
function layout_builder_update_8601(&$sandbox) {
$config_factory = \Drupal::configFactory();
if (!isset($sandbox['count'])) {
$sandbox['ids'] = $config_factory->listAll('core.entity_view_display.');
$sandbox['count'] = count($sandbox['ids']);
}
$ids = array_splice($sandbox['ids'], 0, 50);
foreach ($ids as $id) {
$display = $config_factory->getEditable($id);
if ($display->get('third_party_settings.layout_builder')) {
$display
->set('third_party_settings.layout_builder.enabled', TRUE)
->save();
}
}
$sandbox['#finished'] = empty($sandbox['ids']) ? 1 : ($sandbox['count'] - count($sandbox['ids'])) / $sandbox['count'];
}

View File

@ -6,7 +6,7 @@
*/
use Drupal\Core\Config\Entity\ConfigEntityUpdater;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\layout_builder\Entity\LayoutEntityDisplayInterface;
/**
* Rebuild plugin dependencies for all entity view displays.
@ -39,7 +39,11 @@ function layout_builder_post_update_rebuild_plugin_dependencies(&$sandbox = NULL
*/
function layout_builder_post_update_add_extra_fields(&$sandbox = NULL) {
$entity_field_manager = \Drupal::service('entity_field.manager');
\Drupal::classResolver(ConfigEntityUpdater::class)->update($sandbox, 'entity_view_display', function (EntityViewDisplayInterface $display) use ($entity_field_manager) {
\Drupal::classResolver(ConfigEntityUpdater::class)->update($sandbox, 'entity_view_display', function (LayoutEntityDisplayInterface $display) use ($entity_field_manager) {
if (!$display->isLayoutBuilderEnabled()) {
return FALSE;
}
$extra_fields = $entity_field_manager->getExtraFields($display->getTargetEntityTypeId(), $display->getTargetBundle());
$components = $display->getComponents();
// Sort the components to avoid them being reordered by setComponent().

View File

@ -4,6 +4,7 @@ layout_builder.choose_section:
_controller: '\Drupal\layout_builder\Controller\ChooseSectionController::build'
requirements:
_permission: 'configure any layout'
_layout_builder_access: 'view'
options:
_admin_route: TRUE
parameters:
@ -16,6 +17,7 @@ layout_builder.add_section:
_controller: '\Drupal\layout_builder\Controller\AddSectionController::build'
requirements:
_permission: 'configure any layout'
_layout_builder_access: 'view'
options:
_admin_route: TRUE
parameters:
@ -32,6 +34,7 @@ layout_builder.configure_section:
plugin_id: null
requirements:
_permission: 'configure any layout'
_layout_builder_access: 'view'
options:
_admin_route: TRUE
parameters:
@ -44,6 +47,7 @@ layout_builder.remove_section:
_form: '\Drupal\layout_builder\Form\RemoveSectionForm'
requirements:
_permission: 'configure any layout'
_layout_builder_access: 'view'
options:
_admin_route: TRUE
parameters:
@ -56,6 +60,7 @@ layout_builder.choose_block:
_controller: '\Drupal\layout_builder\Controller\ChooseBlockController::build'
requirements:
_permission: 'configure any layout'
_layout_builder_access: 'view'
options:
_admin_route: TRUE
parameters:
@ -68,6 +73,7 @@ layout_builder.add_block:
_form: '\Drupal\layout_builder\Form\AddBlockForm'
requirements:
_permission: 'configure any layout'
_layout_builder_access: 'view'
options:
_admin_route: TRUE
parameters:
@ -80,6 +86,7 @@ layout_builder.update_block:
_form: '\Drupal\layout_builder\Form\UpdateBlockForm'
requirements:
_permission: 'configure any layout'
_layout_builder_access: 'view'
options:
_admin_route: TRUE
parameters:
@ -92,6 +99,7 @@ layout_builder.remove_block:
_form: '\Drupal\layout_builder\Form\RemoveBlockForm'
requirements:
_permission: 'configure any layout'
_layout_builder_access: 'view'
options:
_admin_route: TRUE
parameters:
@ -110,6 +118,7 @@ layout_builder.move_block:
preceding_block_uuid: null
requirements:
_permission: 'configure any layout'
_layout_builder_access: 'view'
options:
_admin_route: TRUE
parameters:

View File

@ -2,6 +2,10 @@ services:
layout_builder.tempstore_repository:
class: Drupal\layout_builder\LayoutTempstoreRepository
arguments: ['@tempstore.shared']
access_check.entity.layout_builder_access:
class: Drupal\layout_builder\Access\LayoutBuilderAccessCheck
tags:
- { name: access_check, applies_to: _layout_builder_access }
access_check.entity.layout:
class: Drupal\layout_builder\Access\LayoutSectionAccessCheck
tags:

View File

@ -0,0 +1,40 @@
<?php
namespace Drupal\layout_builder\Access;
use Drupal\Core\Cache\RefinableCacheableDependencyInterface;
use Drupal\Core\Routing\Access\AccessInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\layout_builder\SectionStorageInterface;
use Symfony\Component\Routing\Route;
/**
* Provides an access check for the Layout Builder defaults.
*
* @internal
*/
class LayoutBuilderAccessCheck implements AccessInterface {
/**
* Checks routing access to the layout.
*
* @param \Drupal\layout_builder\SectionStorageInterface $section_storage
* The section storage.
* @param \Drupal\Core\Session\AccountInterface $account
* The current user.
* @param \Symfony\Component\Routing\Route $route
* The route to check against.
*
* @return \Drupal\Core\Access\AccessResultInterface
* The access result.
*/
public function access(SectionStorageInterface $section_storage, AccountInterface $account, Route $route) {
$operation = $route->getRequirement('_layout_builder_access');
$access = $section_storage->access($operation, $account, TRUE);
if ($access instanceof RefinableCacheableDependencyInterface) {
$access->addCacheableDependency($section_storage);
}
return $access;
}
}

View File

@ -11,8 +11,10 @@ use Drupal\Core\Config\Entity\ThirdPartySettingsInterface;
* Layout Builder is currently experimental and should only be leveraged by
* experimental modules and development releases of contributed modules.
* See https://www.drupal.org/core/experimental for more information.
*
* @todo Refactor this interface in https://www.drupal.org/node/2985362.
*/
interface DefaultsSectionStorageInterface extends SectionStorageInterface, ThirdPartySettingsInterface {
interface DefaultsSectionStorageInterface extends SectionStorageInterface, ThirdPartySettingsInterface, LayoutBuilderEnabledInterface {
/**
* Determines if the defaults allow custom overrides.

View File

@ -58,6 +58,30 @@ class LayoutBuilderEntityViewDisplay extends BaseEntityViewDisplay implements La
return $this;
}
/**
* {@inheritdoc}
*/
public function isLayoutBuilderEnabled() {
return (bool) $this->getThirdPartySetting('layout_builder', 'enabled');
}
/**
* {@inheritdoc}
*/
public function enableLayoutBuilder() {
$this->setThirdPartySetting('layout_builder', 'enabled', TRUE);
return $this;
}
/**
* {@inheritdoc}
*/
public function disableLayoutBuilder() {
$this->setOverridable(FALSE);
$this->setThirdPartySetting('layout_builder', 'enabled', FALSE);
return $this;
}
/**
* {@inheritdoc}
*/
@ -92,6 +116,27 @@ class LayoutBuilderEntityViewDisplay extends BaseEntityViewDisplay implements La
$field->delete();
}
}
$already_enabled = isset($this->original) ? $this->original->isLayoutBuilderEnabled() : FALSE;
$set_enabled = $this->isLayoutBuilderEnabled();
if ($already_enabled !== $set_enabled) {
if ($set_enabled) {
// Loop through all existing field-based components and add them as
// section-based components.
$components = $this->getComponents();
// Sort the components by weight.
uasort($components, 'Drupal\Component\Utility\SortArray::sortByWeightElement');
foreach ($components as $name => $component) {
$this->setComponent($name, $component);
}
}
else {
// When being disabled, remove all existing section data.
while (count($this) > 0) {
$this->removeSection(0);
}
}
}
}
/**
@ -153,6 +198,9 @@ class LayoutBuilderEntityViewDisplay extends BaseEntityViewDisplay implements La
*/
public function buildMultiple(array $entities) {
$build_list = parent::buildMultiple($entities);
if (!$this->isLayoutBuilderEnabled()) {
return $build_list;
}
/** @var \Drupal\Core\Entity\EntityInterface $entity */
foreach ($entities as $id => $entity) {
@ -272,6 +320,11 @@ class LayoutBuilderEntityViewDisplay extends BaseEntityViewDisplay implements La
return $this;
}
// Only continue if Layout Builder is enabled.
if (!$this->isLayoutBuilderEnabled()) {
return $this;
}
// Retrieve the updated options after the parent:: call.
$options = $this->content[$name];
// Provide backwards compatibility by converting to a section component.

View File

@ -3,6 +3,7 @@
namespace Drupal\layout_builder\Entity;
use Drupal\Core\Entity\Display\EntityDisplayInterface;
use Drupal\layout_builder\LayoutBuilderEnabledInterface;
use Drupal\layout_builder\SectionListInterface;
/**
@ -12,8 +13,10 @@ use Drupal\layout_builder\SectionListInterface;
* Layout Builder is currently experimental and should only be leveraged by
* experimental modules and development releases of contributed modules.
* See https://www.drupal.org/core/experimental for more information.
*
* @todo Refactor this interface in https://www.drupal.org/node/2985362.
*/
interface LayoutEntityDisplayInterface extends EntityDisplayInterface, SectionListInterface {
interface LayoutEntityDisplayInterface extends EntityDisplayInterface, SectionListInterface, LayoutBuilderEnabledInterface {
/**
* Determines if the display allows custom overrides.

View File

@ -0,0 +1,106 @@
<?php
namespace Drupal\layout_builder\Form;
use Drupal\Core\Form\ConfirmFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\layout_builder\DefaultsSectionStorageInterface;
use Drupal\layout_builder\LayoutTempstoreRepositoryInterface;
use Drupal\layout_builder\SectionStorageInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Disables Layout Builder for a given default.
*/
class LayoutBuilderDisableForm extends ConfirmFormBase {
/**
* The layout tempstore repository.
*
* @var \Drupal\layout_builder\LayoutTempstoreRepositoryInterface
*/
protected $layoutTempstoreRepository;
/**
* The section storage.
*
* @var \Drupal\layout_builder\DefaultsSectionStorageInterface
*/
protected $sectionStorage;
/**
* Constructs a new RevertOverridesForm.
*
* @param \Drupal\layout_builder\LayoutTempstoreRepositoryInterface $layout_tempstore_repository
* The layout tempstore repository.
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
* The messenger service.
*/
public function __construct(LayoutTempstoreRepositoryInterface $layout_tempstore_repository, MessengerInterface $messenger) {
$this->layoutTempstoreRepository = $layout_tempstore_repository;
$this->setMessenger($messenger);
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('layout_builder.tempstore_repository'),
$container->get('messenger')
);
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'layout_builder_disable_form';
}
/**
* {@inheritdoc}
*/
public function getQuestion() {
return $this->t('Are you sure you want to disable Layout Builder?');
}
/**
* {@inheritdoc}
*/
public function getDescription() {
return $this->t('All customizations will be removed. This action cannot be undone.');
}
/**
* {@inheritdoc}
*/
public function getCancelUrl() {
return $this->sectionStorage->getRedirectUrl();
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state, SectionStorageInterface $section_storage = NULL) {
if (!$section_storage instanceof DefaultsSectionStorageInterface) {
throw new \InvalidArgumentException(sprintf('The section storage with type "%s" and ID "%s" does not provide defaults', $section_storage->getStorageType(), $section_storage->getStorageId()));
}
$this->sectionStorage = $section_storage;
return parent::buildForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$this->sectionStorage->disableLayoutBuilder()->save();
$this->layoutTempstoreRepository->delete($this->sectionStorage);
$this->messenger()->addMessage($this->t('Layout Builder has been disabled.'));
$form_state->setRedirectUrl($this->getCancelUrl());
}
}

View File

@ -2,6 +2,7 @@
namespace Drupal\layout_builder\Form;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\field_ui\Form\EntityViewDisplayEditForm;
@ -28,7 +29,7 @@ class LayoutBuilderEntityViewDisplayForm extends EntityViewDisplayEditForm {
/**
* The storage section.
*
* @var \Drupal\layout_builder\SectionStorageInterface
* @var \Drupal\layout_builder\DefaultsSectionStorageInterface
*/
protected $sectionStorage;
@ -46,10 +47,17 @@ class LayoutBuilderEntityViewDisplayForm extends EntityViewDisplayEditForm {
public function form(array $form, FormStateInterface $form_state) {
$form = parent::form($form, $form_state);
// Hide the table of fields.
$form['fields']['#access'] = FALSE;
$form['#fields'] = [];
$form['#extra'] = [];
$is_enabled = $this->entity->isLayoutBuilderEnabled();
if ($is_enabled) {
// Hide the table of fields.
$form['fields']['#access'] = FALSE;
$form['#fields'] = [];
$form['#extra'] = [];
}
else {
// Remove the Layout Builder field from the list.
$form['#fields'] = array_diff($form['#fields'], ['layout_builder__layout']);
}
$form['manage_layout'] = [
'#type' => 'link',
@ -57,18 +65,26 @@ class LayoutBuilderEntityViewDisplayForm extends EntityViewDisplayEditForm {
'#weight' => -10,
'#attributes' => ['class' => ['button']],
'#url' => $this->sectionStorage->getLayoutBuilderUrl(),
'#access' => $is_enabled,
];
$form['layout'] = [
'#type' => 'details',
'#open' => TRUE,
'#title' => $this->t('Layout options'),
'#tree' => TRUE,
];
$form['layout']['enabled'] = [
'#type' => 'checkbox',
'#title' => $this->t('Use Layout Builder'),
'#default_value' => $is_enabled,
];
$form['#entity_builders']['layout_builder'] = '::entityFormEntityBuild';
// @todo Expand to work for all view modes in
// https://www.drupal.org/node/2907413.
if ($this->entity->getMode() === 'default') {
$form['layout'] = [
'#type' => 'details',
'#open' => TRUE,
'#title' => $this->t('Layout options'),
'#tree' => TRUE,
];
$entity_type = $this->entityTypeManager->getDefinition($this->entity->getTargetEntityTypeId());
$form['layout']['allow_custom'] = [
'#type' => 'checkbox',
@ -76,14 +92,26 @@ class LayoutBuilderEntityViewDisplayForm extends EntityViewDisplayEditForm {
'@entity' => $entity_type->getSingularLabel(),
]),
'#default_value' => $this->entity->isOverridable(),
'#states' => [
'disabled' => [
':input[name="layout[enabled]"]' => ['checked' => FALSE],
],
'invisible' => [
':input[name="layout[enabled]"]' => ['checked' => FALSE],
],
],
];
if (!$is_enabled) {
$form['layout']['allow_custom']['#attributes']['disabled'] = 'disabled';
}
// Prevent turning off overrides while any exist.
if ($this->hasOverrides($this->entity)) {
$form['layout']['enabled']['#disabled'] = TRUE;
$form['layout']['enabled']['#description'] = $this->t('You must revert all customized layouts of this display before you can disable this option.');
$form['layout']['allow_custom']['#disabled'] = TRUE;
$form['layout']['allow_custom']['#description'] = $this->t('You must revert all customized layouts of this display before you can disable this option.');
}
else {
$form['#entity_builders'][] = '::entityFormEntityBuild';
unset($form['layout']['allow_custom']['#states']);
unset($form['#entity_builders']['layout_builder']);
}
}
return $form;
@ -112,26 +140,62 @@ class LayoutBuilderEntityViewDisplayForm extends EntityViewDisplayEditForm {
return (bool) $query->count()->execute();
}
/**
* {@inheritdoc}
*/
protected function copyFormValuesToEntity(EntityInterface $entity, array $form, FormStateInterface $form_state) {
// Do not process field values if Layout Builder is or will be enabled.
$set_enabled = (bool) $form_state->getValue(['layout', 'enabled'], FALSE);
/** @var \Drupal\layout_builder\Entity\LayoutEntityDisplayInterface $entity */
$already_enabled = $entity->isLayoutBuilderEnabled();
if ($already_enabled || $set_enabled) {
$form['#fields'] = [];
$form['#extra'] = [];
}
parent::copyFormValuesToEntity($entity, $form, $form_state);
}
/**
* Entity builder for layout options on the entity view display form.
*/
public function entityFormEntityBuild($entity_type_id, LayoutEntityDisplayInterface $display, &$form, FormStateInterface &$form_state) {
$new_value = (bool) $form_state->getValue(['layout', 'allow_custom'], FALSE);
$display->setOverridable($new_value);
$set_enabled = (bool) $form_state->getValue(['layout', 'enabled'], FALSE);
$already_enabled = $display->isLayoutBuilderEnabled();
if ($set_enabled) {
$overridable = (bool) $form_state->getValue(['layout', 'allow_custom'], FALSE);
$display->setOverridable($overridable);
if (!$already_enabled) {
$display->enableLayoutBuilder();
}
}
elseif ($already_enabled) {
$form_state->setRedirectUrl($this->sectionStorage->getLayoutBuilderUrl('disable'));
}
}
/**
* {@inheritdoc}
*/
protected function buildFieldRow(FieldDefinitionInterface $field_definition, array $form, FormStateInterface $form_state) {
// Intentionally empty.
if ($this->entity->isLayoutBuilderEnabled() || $field_definition->getType() === 'layout_section') {
return [];
}
return parent::buildFieldRow($field_definition, $form, $form_state);
}
/**
* {@inheritdoc}
*/
protected function buildExtraFieldRow($field_id, $extra_field) {
// Intentionally empty.
if ($this->entity->isLayoutBuilderEnabled()) {
return [];
}
return parent::buildExtraFieldRow($field_id, $extra_field);
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace Drupal\layout_builder;
/**
* Provides methods for enabling and disabling Layout Builder.
*/
interface LayoutBuilderEnabledInterface {
/**
* Determines if Layout Builder is enabled.
*
* @return bool
* TRUE if Layout Builder is enabled, FALSE otherwise.
*/
public function isLayoutBuilderEnabled();
/**
* Enables the Layout Builder.
*
* @return $this
*/
public function enableLayoutBuilder();
/**
* Disables the Layout Builder.
*
* @return $this
*/
public function disableLayoutBuilder();
}

View File

@ -3,12 +3,14 @@
namespace Drupal\layout_builder\Plugin\SectionStorage;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Plugin\Context\EntityContext;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use Drupal\field_ui\FieldUI;
use Drupal\layout_builder\DefaultsSectionStorageInterface;
@ -123,8 +125,8 @@ class DefaultsSectionStorage extends SectionStorageBase implements ContainerFact
/**
* {@inheritdoc}
*/
public function getLayoutBuilderUrl() {
return Url::fromRoute("layout_builder.{$this->getStorageType()}.{$this->getDisplay()->getTargetEntityTypeId()}.view", $this->getRouteParameters());
public function getLayoutBuilderUrl($rel = 'view') {
return Url::fromRoute("layout_builder.{$this->getStorageType()}.{$this->getDisplay()->getTargetEntityTypeId()}.$rel", $this->getRouteParameters());
}
/**
@ -296,6 +298,29 @@ class DefaultsSectionStorage extends SectionStorageBase implements ContainerFact
return $this;
}
/**
* {@inheritdoc}
*/
public function isLayoutBuilderEnabled() {
return $this->getDisplay()->isLayoutBuilderEnabled();
}
/**
* {@inheritdoc}
*/
public function enableLayoutBuilder() {
$this->getDisplay()->enableLayoutBuilder();
return $this;
}
/**
* {@inheritdoc}
*/
public function disableLayoutBuilder() {
$this->getDisplay()->disableLayoutBuilder();
return $this;
}
/**
* {@inheritdoc}
*/
@ -325,4 +350,12 @@ class DefaultsSectionStorage extends SectionStorageBase implements ContainerFact
return $this->getDisplay()->getThirdPartyProviders();
}
/**
* {@inheritdoc}
*/
public function access($operation, AccountInterface $account = NULL, $return_as_object = FALSE) {
$result = AccessResult::allowedIf($this->isLayoutBuilderEnabled());
return $return_as_object ? $result : $result->isAllowed();
}
}

View File

@ -2,6 +2,7 @@
namespace Drupal\layout_builder\Plugin\SectionStorage;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
@ -9,6 +10,7 @@ use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Plugin\Context\EntityContext;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay;
use Drupal\layout_builder\OverridesSectionStorageInterface;
@ -200,10 +202,10 @@ class OverridesSectionStorage extends SectionStorageBase implements ContainerFac
/**
* {@inheritdoc}
*/
public function getLayoutBuilderUrl() {
public function getLayoutBuilderUrl($rel = 'view') {
$entity = $this->getEntity();
$route_parameters[$entity->getEntityTypeId()] = $entity->id();
return Url::fromRoute("layout_builder.{$this->getStorageType()}.{$this->getEntity()->getEntityTypeId()}.view", $route_parameters);
return Url::fromRoute("layout_builder.{$this->getStorageType()}.{$this->getEntity()->getEntityTypeId()}.$rel", $route_parameters);
}
/**
@ -229,4 +231,13 @@ class OverridesSectionStorage extends SectionStorageBase implements ContainerFac
return $this->getEntity()->save();
}
/**
* {@inheritdoc}
*/
public function access($operation, AccountInterface $account = NULL, $return_as_object = FALSE) {
$default_section_storage = $this->getDefaultSectionStorage();
$result = AccessResult::allowedIf($default_section_storage->isLayoutBuilderEnabled())->addCacheableDependency($default_section_storage);
return $return_as_object ? $result : $result->isAllowed();
}
}

View File

@ -3,6 +3,7 @@
namespace Drupal\layout_builder\Routing;
use Drupal\Component\Utility\NestedArray;
use Drupal\layout_builder\DefaultsSectionStorageInterface;
use Drupal\layout_builder\OverridesSectionStorageInterface;
use Drupal\layout_builder\SectionStorage\SectionStorageDefinition;
use Symfony\Component\Routing\Route;
@ -43,6 +44,7 @@ trait LayoutBuilderRoutesTrait {
$defaults['section_storage'] = '';
// Trigger the layout builder access check.
$requirements['_has_layout_section'] = 'true';
$requirements['_layout_builder_access'] = 'view';
// Trigger the layout builder RouteEnhancer.
$options['_layout_builder'] = TRUE;
// Trigger the layout builder param converter.
@ -92,6 +94,17 @@ trait LayoutBuilderRoutesTrait {
->setOptions($options);
$collection->add("$route_name_prefix.revert", $route);
}
elseif (is_subclass_of($definition->getClass(), DefaultsSectionStorageInterface::class)) {
$disable_defaults = $defaults;
$disable_defaults['_form'] = '\Drupal\layout_builder\Form\LayoutBuilderDisableForm';
$disable_options = $options;
unset($disable_options['_admin_route'], $disable_options['_layout_builder']);
$route = (new Route("$path/disable"))
->setDefaults($disable_defaults)
->setRequirements($requirements)
->setOptions($disable_options);
$collection->add("$route_name_prefix.disable", $route);
}
}
}

View File

@ -3,6 +3,7 @@
namespace Drupal\layout_builder;
use Drupal\Component\Plugin\PluginInspectionInterface;
use Drupal\Core\Access\AccessibleInterface;
use Symfony\Component\Routing\RouteCollection;
/**
@ -13,7 +14,7 @@ use Symfony\Component\Routing\RouteCollection;
* experimental modules and development releases of contributed modules.
* See https://www.drupal.org/core/experimental for more information.
*/
interface SectionStorageInterface extends SectionListInterface, PluginInspectionInterface {
interface SectionStorageInterface extends SectionListInterface, PluginInspectionInterface, AccessibleInterface {
/**
* Returns an identifier for this storage.
@ -88,10 +89,14 @@ interface SectionStorageInterface extends SectionListInterface, PluginInspection
/**
* Gets the URL used to display the Layout Builder UI.
*
* @param string $rel
* (optional) The link relationship type, for example: 'view' or 'disable'.
* Defaults to 'view'.
*
* @return \Drupal\Core\Url
* The URL object.
*/
public function getLayoutBuilderUrl();
public function getLayoutBuilderUrl($rel = 'view');
/**
* Configures the plugin based on route values.

View File

@ -0,0 +1,44 @@
<?php
/**
* @file
* Test fixture.
*/
use Drupal\Core\Database\Database;
$connection = Database::getConnection();
// Add a layout plugin to an existing entity view display without explicitly
// enabling Layout Builder for this display.
$display = $connection->select('config')
->fields('config', ['data'])
->condition('collection', '')
->condition('name', 'core.entity_view_display.block_content.basic.default')
->execute()
->fetchField();
$display = unserialize($display);
$display['third_party_settings']['layout_builder']['sections'][] = [
'layout_id' => 'layout_onecol',
'layout_settings' => [],
'components' => [
'some-uuid' => [
'uuid' => 'some-uuid',
'region' => 'content',
'configuration' => [
'id' => 'system_powered_by_block',
],
'additional' => [],
'weight' => 0,
],
],
];
$connection->update('config')
->fields([
'data' => serialize($display),
'collection' => '',
'name' => 'core.entity_view_display.block_content.basic.default',
])
->condition('collection', '')
->condition('name', 'core.entity_view_display.block_content.basic.default')
->execute();

View File

@ -0,0 +1,29 @@
<?php
/**
* @file
* Test fixture.
*/
use Drupal\Core\Database\Database;
$connection = Database::getConnection();
// Enable Layout Builder on an existing entity view display.
$display = $connection->select('config')
->fields('config', ['data'])
->condition('collection', '')
->condition('name', 'core.entity_view_display.node.article.default')
->execute()
->fetchField();
$display = unserialize($display);
$display['third_party_settings']['layout_builder']['enabled'] = TRUE;
$connection->update('config')
->fields([
'data' => serialize($display),
'collection' => '',
'name' => 'core.entity_view_display.node.article.default',
])
->condition('collection', '')
->condition('name', 'core.entity_view_display.node.article.default')
->execute();

View File

@ -9,6 +9,17 @@ use Drupal\Core\Database\Database;
$connection = Database::getConnection();
// Set the schema version.
$connection->merge('key_value')
->fields([
'value' => 'i:8000;',
'name' => 'layout_builder',
'collection' => 'system.schema',
])
->condition('collection', 'system.schema')
->condition('name', 'layout_builder')
->execute();
// Update core.extension.
$extensions = $connection->select('config')
->fields('config', ['data'])

View File

@ -80,6 +80,10 @@ class LayoutBuilderTest extends BrowserTestBase {
// From the manage display page, go to manage the layout.
$this->drupalGet("$field_ui_prefix/display/default");
$assert_session->linkNotExists('Manage layout');
$assert_session->fieldDisabled('layout[allow_custom]');
$this->drupalPostForm(NULL, ['layout[enabled]' => TRUE], 'Save');
$assert_session->linkExists('Manage layout');
$this->clickLink('Manage layout');
$assert_session->addressEquals("$field_ui_prefix/display-layout/default");
@ -153,6 +157,7 @@ class LayoutBuilderTest extends BrowserTestBase {
// Assert that overrides cannot be turned off while overrides exist.
$this->drupalGet("$field_ui_prefix/display/default");
$assert_session->checkboxChecked('layout[allow_custom]');
$assert_session->fieldDisabled('layout[allow_custom]');
// Alter the defaults.
@ -243,7 +248,9 @@ class LayoutBuilderTest extends BrowserTestBase {
$page->fillField('id', 'myothermenu');
$page->pressButton('Save');
$this->drupalGet('admin/structure/types/manage/bundle_with_section_field/display-layout/default');
$this->drupalPostForm('admin/structure/types/manage/bundle_with_section_field/display', ['layout[enabled]' => TRUE], 'Save');
$assert_session->linkExists('Manage layout');
$this->clickLink('Manage layout');
$assert_session->linkExists('Add Section');
$this->clickLink('Add Section');
$assert_session->linkExists('Layout plugin (with dependencies)');
@ -305,6 +312,7 @@ class LayoutBuilderTest extends BrowserTestBase {
$field_ui_prefix = 'admin/structure/types/manage/bundle_with_section_field';
// Allow overrides for the layout.
$this->drupalPostForm("$field_ui_prefix/display/default", ['layout[enabled]' => TRUE], 'Save');
$this->drupalPostForm("$field_ui_prefix/display/default", ['layout[allow_custom]' => TRUE], 'Save');
// Customize the default view mode.
@ -365,7 +373,8 @@ class LayoutBuilderTest extends BrowserTestBase {
]));
// From the manage display page, go to manage the layout.
$this->drupalGet('admin/structure/types/manage/bundle_with_section_field/display/default');
$this->drupalPostForm('admin/structure/types/manage/bundle_with_section_field/display/default', ['layout[enabled]' => TRUE], 'Save');
$assert_session->linkExists('Manage layout');
$this->clickLink('Manage layout');
// Add a new block.
@ -412,6 +421,7 @@ class LayoutBuilderTest extends BrowserTestBase {
$field_ui_prefix = 'admin/structure/types/manage/bundle_with_section_field';
// Enable overrides.
$this->drupalPostForm("$field_ui_prefix/display/default", ['layout[enabled]' => TRUE], 'Save');
$this->drupalPostForm("$field_ui_prefix/display/default", ['layout[allow_custom]' => TRUE], 'Save');
$this->drupalGet('node/1');

View File

@ -41,6 +41,7 @@ class LayoutSectionTest extends BrowserTestBase {
]);
LayoutBuilderEntityViewDisplay::load('node.bundle_with_section_field.default')
->enableLayoutBuilder()
->setOverridable()
->save();

View File

@ -20,6 +20,7 @@ class ExtraFieldUpdatePathTest extends UpdatePathTestBase {
$this->databaseDumpFiles = [
__DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.4.0.bare.standard.php.gz',
__DIR__ . '/../../../fixtures/update/layout-builder.php',
__DIR__ . '/../../../fixtures/update/layout-builder-extra.php',
];
}
@ -27,15 +28,26 @@ class ExtraFieldUpdatePathTest extends UpdatePathTestBase {
* Tests the upgrade path for Layout Builder extra fields.
*/
public function testRunUpdates() {
// The default view mode has Layout Builder enabled.
$data = EntityViewDisplay::load('node.article.default')->toArray();
$this->assertArrayHasKey('third_party_settings', $data);
$this->assertArrayNotHasKey('sections', $data['third_party_settings']['layout_builder']);
// The teaser view mode does not have Layout Builder enabled.
$data = EntityViewDisplay::load('node.article.teaser')->toArray();
$this->assertArrayNotHasKey('third_party_settings', $data);
$this->runUpdates();
$data = EntityViewDisplay::load('node.article.teaser')->toArray();
// The extra links have been added.
$data = EntityViewDisplay::load('node.article.default')->toArray();
$components = $data['third_party_settings']['layout_builder']['sections'][0]->getComponents();
$component = reset($components);
$this->assertSame('extra_field_block:node:article:links', $component->getPluginId());
// No extra links have been added.
$data = EntityViewDisplay::load('node.article.teaser')->toArray();
$this->assertArrayNotHasKey('third_party_settings', $data);
}
}

View File

@ -0,0 +1,86 @@
<?php
namespace Drupal\Tests\layout_builder\Functional\Update;
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
/**
* Tests the upgrade path for enabling Layout Builder.
*
* @see layout_builder_update_8601()
*
* @group layout_builder
* @group legacy
*/
class LayoutBuilderEnableUpdatePathTest extends UpdatePathTestBase {
/**
* {@inheritdoc}
*/
protected function setDatabaseDumpFiles() {
$this->databaseDumpFiles = [
__DIR__ . '/../../../../../system/tests/fixtures/update/drupal-8.4.0.bare.standard.php.gz',
__DIR__ . '/../../../fixtures/update/layout-builder.php',
__DIR__ . '/../../../fixtures/update/layout-builder-enable.php',
];
}
/**
* Tests the upgrade path for enabling Layout Builder.
*/
public function testRunUpdates() {
$assert_session = $this->assertSession();
$expected = [
'sections' => [
[
'layout_id' => 'layout_onecol',
'layout_settings' => [],
'components' => [
'some-uuid' => [
'uuid' => 'some-uuid',
'region' => 'content',
'configuration' => [
'id' => 'system_powered_by_block',
],
'additional' => [],
'weight' => 0,
],
],
],
],
];
$this->assertLayoutBuilderSettings($expected, 'block_content', 'basic', 'default');
$this->assertLayoutBuilderSettings(NULL, 'node', 'page', 'default');
$this->runUpdates();
// The display with existing sections is enabled while the other is not.
$expected['enabled'] = TRUE;
$this->assertLayoutBuilderSettings($expected, 'block_content', 'basic', 'default');
$this->assertLayoutBuilderSettings(NULL, 'node', 'page', 'default');
$this->drupalLogin($this->rootUser);
$this->drupalGet('admin/structure/block/block-content/manage/basic/display');
$assert_session->checkboxChecked('layout[enabled]');
$this->drupalGet('admin/structure/types/manage/page/display');
$assert_session->checkboxNotChecked('layout[enabled]');
}
/**
* Asserts the Layout Builder settings for a given display.
*
* @param mixed $expected
* The expected value.
* @param string $entity_type_id
* The entity type ID.
* @param string $bundle
* The bundle.
* @param string $view_mode
* The view mode.
*/
protected function assertLayoutBuilderSettings($expected, $entity_type_id, $bundle, $view_mode) {
$this->assertEquals($expected, \Drupal::config("core.entity_view_display.$entity_type_id.$bundle.$view_mode")->get('third_party_settings.layout_builder'));
}
}

View File

@ -60,7 +60,7 @@ class AjaxBlockTest extends WebDriverTestBase {
$field_ui_prefix = 'admin/structure/types/manage/bundle_with_section_field';
// From the manage display page, go to manage the layout.
$this->drupalGet("$field_ui_prefix/display/default");
$this->drupalPostForm("$field_ui_prefix/display/default", ['layout[enabled]' => TRUE], 'Save');
$assert_session->linkExists('Manage layout');
$this->clickLink('Manage layout');
$assert_session->addressEquals("$field_ui_prefix/display-layout/default");

View File

@ -44,7 +44,10 @@ class ItemLayoutFieldBlockTest extends WebDriverTestBase {
$page = $this->getSession()->getPage();
// Allow overrides for the layout.
$this->drupalPostForm('admin/structure/types/manage/bundle_with_layout_overrides/display/default', ['layout[allow_custom]' => TRUE], 'Save');
$this->drupalGet('admin/structure/types/manage/bundle_with_layout_overrides/display/default');
$page->checkField('layout[enabled]');
$page->checkField('layout[allow_custom]');
$page->pressButton('Save');
// Start by creating a node of type with layout overrides.
$node = $this->createNode([

View File

@ -0,0 +1,184 @@
<?php
namespace Drupal\Tests\layout_builder\FunctionalJavascript;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
/**
* Tests the ability for opting in and out of Layout Builder.
*
* @group layout_builder
*/
class LayoutBuilderOptInTest extends WebDriverTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = [
'node',
'field_ui',
'block',
];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// @todo The Layout Builder UI relies on local tasks; fix in
// https://www.drupal.org/project/drupal/issues/2917777.
$this->drupalPlaceBlock('local_tasks_block');
// Create one content type before installing Layout Builder and one after.
$this->createContentType(['type' => 'before']);
$this->container->get('module_installer')->install(['layout_builder']);
$this->rebuildAll();
$this->createContentType(['type' => 'after']);
$this->drupalLogin($this->drupalCreateUser([
'configure any layout',
'administer node display',
]));
}
/**
* Tests the interaction between the two layout checkboxes.
*/
public function testCheckboxLogic() {
$assert_session = $this->assertSession();
$page = $this->getSession()->getPage();
$this->drupalGet('admin/structure/types/manage/before/display/default');
// Both fields are unchecked and allow_custom is disabled and hidden.
$assert_session->checkboxNotChecked('layout[enabled]');
$assert_session->checkboxNotChecked('layout[allow_custom]');
$assert_session->fieldDisabled('layout[allow_custom]');
$this->assertFalse($page->findField('layout[allow_custom]')->isVisible());
// Checking is_enable will show allow_custom.
$page->checkField('layout[enabled]');
$assert_session->checkboxNotChecked('layout[allow_custom]');
$this->assertTrue($page->findField('layout[allow_custom]')->isVisible());
$page->pressButton('Save');
$assert_session->checkboxChecked('layout[enabled]');
$assert_session->checkboxNotChecked('layout[allow_custom]');
// Check and submit allow_custom.
$page->checkField('layout[allow_custom]');
$page->pressButton('Save');
$assert_session->checkboxChecked('layout[enabled]');
$assert_session->checkboxChecked('layout[allow_custom]');
// Reset the checkboxes.
$page->uncheckField('layout[enabled]');
$page->pressButton('Save');
$page->pressButton('Confirm');
$assert_session->checkboxNotChecked('layout[enabled]');
$assert_session->checkboxNotChecked('layout[allow_custom]');
// Check both at the same time.
$page->checkField('layout[enabled]');
$page->checkField('layout[allow_custom]');
$page->pressButton('Save');
$assert_session->checkboxChecked('layout[enabled]');
$assert_session->checkboxChecked('layout[allow_custom]');
}
/**
* Tests the expected default values for enabling Layout Builder.
*/
public function testDefaultValues() {
$assert_session = $this->assertSession();
$page = $this->getSession()->getPage();
// Both the content type created before and after Layout Builder was
// installed is still using the Field UI.
$this->drupalGet('admin/structure/types/manage/before/display/default');
$assert_session->checkboxNotChecked('layout[enabled]');
$field_ui_prefix = 'admin/structure/types/manage/after/display/default';
$this->drupalGet($field_ui_prefix);
$assert_session->checkboxNotChecked('layout[enabled]');
$page->checkField('layout[enabled]');
$page->pressButton('Save');
$layout_builder_ui = $this->getPathForFieldBlock('node', 'after', 'default', 'body');
$assert_session->linkExists('Manage layout');
$this->clickLink('Manage layout');
// Ensure the body appears once and only once.
$assert_session->elementsCount('css', '.field--name-body', 1);
// Change the body formatter to Trimmed.
$this->drupalGet($layout_builder_ui);
$assert_session->fieldValueEquals('settings[formatter][type]', 'text_default');
$page->selectFieldOption('settings[formatter][type]', 'text_trimmed');
$assert_session->assertWaitOnAjaxRequest();
$page->pressButton('Update');
$assert_session->linkExists('Save Layout');
$this->clickLink('Save Layout');
$this->drupalGet($layout_builder_ui);
$assert_session->fieldValueEquals('settings[formatter][type]', 'text_trimmed');
// Disable Layout Builder.
$this->drupalPostForm($field_ui_prefix, ['layout[enabled]' => FALSE], 'Save');
$page->pressButton('Confirm');
// The Layout Builder UI is no longer accessible.
$this->drupalGet($layout_builder_ui);
$assert_session->pageTextContains('You are not authorized to access this page.');
// The original body formatter is reflected in Field UI.
$this->drupalGet($field_ui_prefix);
$assert_session->fieldValueEquals('fields[body][type]', 'text_default');
// Change the body formatter to Summary.
$page->selectFieldOption('fields[body][type]', 'text_summary_or_trimmed');
$assert_session->assertWaitOnAjaxRequest();
$page->pressButton('Save');
$assert_session->fieldValueEquals('fields[body][type]', 'text_summary_or_trimmed');
// Reactivate Layout Builder.
$this->drupalPostForm($field_ui_prefix, ['layout[enabled]' => TRUE], 'Save');
$assert_session->linkExists('Manage layout');
$this->clickLink('Manage layout');
// Ensure the body appears once and only once.
$assert_session->elementsCount('css', '.field--name-body', 1);
// The changed body formatter is reflected in Layout Builder UI.
$this->drupalGet($this->getPathForFieldBlock('node', 'after', 'default', 'body'));
$assert_session->fieldValueEquals('settings[formatter][type]', 'text_summary_or_trimmed');
}
/**
* Returns the path to update a field block in the UI.
*
* @param string $entity_type_id
* The entity type ID.
* @param string $bundle
* The bundle.
* @param string $view_mode
* The view mode.
* @param string $field_name
* The field name.
*
* @return string
* The path.
*/
protected function getPathForFieldBlock($entity_type_id, $bundle, $view_mode, $field_name) {
$delta = 0;
/** @var \Drupal\layout_builder\Entity\LayoutEntityDisplayInterface $display */
$display = $this->container->get('entity_type.manager')->getStorage('entity_view_display')->load("$entity_type_id.$bundle.$view_mode");
$body_component = NULL;
foreach ($display->getSection($delta)->getComponents() as $component) {
if ($component->getPluginId() === "field_block:$entity_type_id:$bundle:$field_name") {
$body_component = $component;
}
}
$this->assertNotNull($body_component);
return 'layout_builder/update/block/defaults/node.after.default/0/content/' . $body_component->getUuid();
}
}

View File

@ -23,7 +23,7 @@ abstract class LayoutBuilderCompatibilityTestBase extends EntityKernelTestBase {
/**
* The entity view display.
*
* @var \Drupal\field_layout\Display\EntityDisplayWithLayoutInterface
* @var \Drupal\layout_builder\Entity\LayoutEntityDisplayInterface
*/
protected $display;
@ -86,13 +86,21 @@ abstract class LayoutBuilderCompatibilityTestBase extends EntityKernelTestBase {
/**
* Installs the Layout Builder.
*
* Also configures and reloads the entity display, and reloads the entity.
* Also configures and reloads the entity display.
*/
protected function installLayoutBuilder() {
$this->container->get('module_installer')->install(['layout_builder']);
$this->refreshServices();
$this->display = $this->reloadEntity($this->display);
$this->display->enableLayoutBuilder()->save();
$this->entity = $this->reloadEntity($this->entity);
}
/**
* Enables overrides for the display and reloads the entity.
*/
protected function enableOverrides() {
$this->display->setOverridable()->save();
$this->entity = $this->reloadEntity($this->entity);
}

View File

@ -54,6 +54,7 @@ class LayoutBuilderFieldLayoutCompatibilityTest extends LayoutBuilderCompatibili
$this->assertFieldAttributes($this->entity, $expected_fields);
// Add a layout override.
$this->enableOverrides();
/** @var \Drupal\layout_builder\SectionStorageInterface $field_list */
$field_list = $this->entity->get('layout_builder__layout');
$field_list->appendSection(new Section('layout_onecol'));

View File

@ -33,6 +33,8 @@ class LayoutBuilderInstallTest extends LayoutBuilderCompatibilityTestBase {
$this->assertFieldAttributes($this->entity, $expected_fields);
// Add a layout override.
$this->enableOverrides();
$this->entity = $this->reloadEntity($this->entity);
$this->entity->get('layout_builder__layout')->appendSection(new Section('layout_onecol'));
$this->entity->save();

View File

@ -32,7 +32,10 @@ class LayoutSectionItemListTest extends SectionStorageTestBase {
'bundle' => 'entity_test_base_field_display',
'mode' => 'default',
'status' => TRUE,
])->setOverridable()->save();
])
->enableLayoutBuilder()
->setOverridable()
->save();
array_map(function ($row) {
return ['section' => $row];

View File

@ -254,6 +254,7 @@ class DefaultsSectionStorageTest extends UnitTestCase {
[
'_field_ui_view_mode_access' => 'administer with_bundle_key display',
'_has_layout_section' => 'true',
'_layout_builder_access' => 'view',
],
[
'parameters' => [
@ -275,6 +276,7 @@ class DefaultsSectionStorageTest extends UnitTestCase {
[
'_field_ui_view_mode_access' => 'administer with_bundle_key display',
'_has_layout_section' => 'true',
'_layout_builder_access' => 'view',
],
[
'parameters' => [
@ -296,6 +298,7 @@ class DefaultsSectionStorageTest extends UnitTestCase {
[
'_field_ui_view_mode_access' => 'administer with_bundle_key display',
'_has_layout_section' => 'true',
'_layout_builder_access' => 'view',
],
[
'parameters' => [
@ -305,6 +308,26 @@ class DefaultsSectionStorageTest extends UnitTestCase {
'_admin_route' => FALSE,
]
),
'layout_builder.defaults.with_bundle_key.disable' => new Route(
'/admin/entity/whatever/display-layout/{view_mode_name}/disable',
[
'entity_type_id' => 'with_bundle_key',
'bundle_key' => 'my_bundle_type',
'section_storage_type' => 'defaults',
'section_storage' => '',
'_form' => '\Drupal\layout_builder\Form\LayoutBuilderDisableForm',
],
[
'_field_ui_view_mode_access' => 'administer with_bundle_key display',
'_has_layout_section' => 'true',
'_layout_builder_access' => 'view',
],
[
'parameters' => [
'section_storage' => ['layout_builder_tempstore' => TRUE],
],
]
),
'layout_builder.defaults.with_bundle_parameter.view' => new Route(
'/admin/entity/{bundle}/display-layout/{view_mode_name}',
[
@ -318,6 +341,7 @@ class DefaultsSectionStorageTest extends UnitTestCase {
[
'_field_ui_view_mode_access' => 'administer with_bundle_parameter display',
'_has_layout_section' => 'true',
'_layout_builder_access' => 'view',
],
[
'parameters' => [
@ -338,6 +362,7 @@ class DefaultsSectionStorageTest extends UnitTestCase {
[
'_field_ui_view_mode_access' => 'administer with_bundle_parameter display',
'_has_layout_section' => 'true',
'_layout_builder_access' => 'view',
],
[
'parameters' => [
@ -358,6 +383,7 @@ class DefaultsSectionStorageTest extends UnitTestCase {
[
'_field_ui_view_mode_access' => 'administer with_bundle_parameter display',
'_has_layout_section' => 'true',
'_layout_builder_access' => 'view',
],
[
'parameters' => [
@ -367,6 +393,25 @@ class DefaultsSectionStorageTest extends UnitTestCase {
'_admin_route' => FALSE,
]
),
'layout_builder.defaults.with_bundle_parameter.disable' => new Route(
'/admin/entity/{bundle}/display-layout/{view_mode_name}/disable',
[
'entity_type_id' => 'with_bundle_parameter',
'section_storage_type' => 'defaults',
'section_storage' => '',
'_form' => '\Drupal\layout_builder\Form\LayoutBuilderDisableForm',
],
[
'_field_ui_view_mode_access' => 'administer with_bundle_parameter display',
'_has_layout_section' => 'true',
'_layout_builder_access' => 'view',
],
[
'parameters' => [
'section_storage' => ['layout_builder_tempstore' => TRUE],
],
]
),
];
$collection = new RouteCollection();

View File

@ -223,6 +223,7 @@ class OverridesSectionStorageTest extends UnitTestCase {
],
[
'_has_layout_section' => 'true',
'_layout_builder_access' => 'view',
],
[
'parameters' => [
@ -242,6 +243,7 @@ class OverridesSectionStorageTest extends UnitTestCase {
],
[
'_has_layout_section' => 'true',
'_layout_builder_access' => 'view',
],
[
'parameters' => [
@ -261,6 +263,7 @@ class OverridesSectionStorageTest extends UnitTestCase {
],
[
'_has_layout_section' => 'true',
'_layout_builder_access' => 'view',
],
[
'parameters' => [
@ -280,6 +283,7 @@ class OverridesSectionStorageTest extends UnitTestCase {
],
[
'_has_layout_section' => 'true',
'_layout_builder_access' => 'view',
],
[
'parameters' => [
@ -301,6 +305,7 @@ class OverridesSectionStorageTest extends UnitTestCase {
],
[
'_has_layout_section' => 'true',
'_layout_builder_access' => 'view',
'with_integer_id' => '\d+',
],
[
@ -321,6 +326,7 @@ class OverridesSectionStorageTest extends UnitTestCase {
],
[
'_has_layout_section' => 'true',
'_layout_builder_access' => 'view',
'with_integer_id' => '\d+',
],
[
@ -341,6 +347,7 @@ class OverridesSectionStorageTest extends UnitTestCase {
],
[
'_has_layout_section' => 'true',
'_layout_builder_access' => 'view',
'with_integer_id' => '\d+',
],
[
@ -361,6 +368,7 @@ class OverridesSectionStorageTest extends UnitTestCase {
],
[
'_has_layout_section' => 'true',
'_layout_builder_access' => 'view',
'with_integer_id' => '\d+',
],
[