Skip to content
Snippets Groups Projects
Verified Commit c8054435 authored by Lee Rowlands's avatar Lee Rowlands
Browse files

Issue #2927349 by tim.plunkett: Decouple the Layout Builder UI from entities

parent bcb5afd4
No related branches found
No related tags found
2 merge requests!7452Issue #1797438. HTML5 validation is preventing form submit and not fully...,!789Issue #3210310: Adjust Database API to remove deprecated Drupal 9 code in Drupal 10
Showing
with 284 additions and 341 deletions
layout_builder.choose_section:
path: '/layout_builder/choose/section/{entity_type_id}/{entity}/{delta}'
path: '/layout_builder/choose/section/{section_storage_type}/{section_storage}/{delta}'
defaults:
_controller: '\Drupal\layout_builder\Controller\ChooseSectionController::build'
requirements:
......@@ -7,12 +7,11 @@ layout_builder.choose_section:
options:
_admin_route: TRUE
parameters:
entity:
type: entity:{entity_type_id}
section_storage:
layout_builder_tempstore: TRUE
layout_builder.add_section:
path: '/layout_builder/add/section/{entity_type_id}/{entity}/{delta}/{plugin_id}'
path: '/layout_builder/add/section/{section_storage_type}/{section_storage}/{delta}/{plugin_id}'
defaults:
_controller: '\Drupal\layout_builder\Controller\AddSectionController::build'
requirements:
......@@ -20,12 +19,11 @@ layout_builder.add_section:
options:
_admin_route: TRUE
parameters:
entity:
type: entity:{entity_type_id}
section_storage:
layout_builder_tempstore: TRUE
layout_builder.configure_section:
path: '/layout_builder/configure/section/{entity_type_id}/{entity}/{delta}/{plugin_id}'
path: '/layout_builder/configure/section/{section_storage_type}/{section_storage}/{delta}/{plugin_id}'
defaults:
_title: 'Configure section'
_form: '\Drupal\layout_builder\Form\ConfigureSectionForm'
......@@ -37,12 +35,11 @@ layout_builder.configure_section:
options:
_admin_route: TRUE
parameters:
entity:
type: entity:{entity_type_id}
section_storage:
layout_builder_tempstore: TRUE
layout_builder.remove_section:
path: '/layout_builder/remove/section/{entity_type_id}/{entity}/{delta}'
path: '/layout_builder/remove/section/{section_storage_type}/{section_storage}/{delta}'
defaults:
_form: '\Drupal\layout_builder\Form\RemoveSectionForm'
requirements:
......@@ -50,12 +47,11 @@ layout_builder.remove_section:
options:
_admin_route: TRUE
parameters:
entity:
type: entity:{entity_type_id}
section_storage:
layout_builder_tempstore: TRUE
layout_builder.choose_block:
path: '/layout_builder/choose/block/{entity_type_id}/{entity}/{delta}/{region}'
path: '/layout_builder/choose/block/{section_storage_type}/{section_storage}/{delta}/{region}'
defaults:
_controller: '\Drupal\layout_builder\Controller\ChooseBlockController::build'
requirements:
......@@ -63,12 +59,11 @@ layout_builder.choose_block:
options:
_admin_route: TRUE
parameters:
entity:
type: entity:{entity_type_id}
section_storage:
layout_builder_tempstore: TRUE
layout_builder.add_block:
path: '/layout_builder/add/block/{entity_type_id}/{entity}/{delta}/{region}/{plugin_id}'
path: '/layout_builder/add/block/{section_storage_type}/{section_storage}/{delta}/{region}/{plugin_id}'
defaults:
_form: '\Drupal\layout_builder\Form\AddBlockForm'
requirements:
......@@ -76,12 +71,11 @@ layout_builder.add_block:
options:
_admin_route: TRUE
parameters:
entity:
type: entity:{entity_type_id}
section_storage:
layout_builder_tempstore: TRUE
layout_builder.update_block:
path: '/layout_builder/update/block/{entity_type_id}/{entity}/{delta}/{region}/{uuid}'
path: '/layout_builder/update/block/{section_storage_type}/{section_storage}/{delta}/{region}/{uuid}'
defaults:
_form: '\Drupal\layout_builder\Form\UpdateBlockForm'
requirements:
......@@ -89,12 +83,11 @@ layout_builder.update_block:
options:
_admin_route: TRUE
parameters:
entity:
type: entity:{entity_type_id}
section_storage:
layout_builder_tempstore: TRUE
layout_builder.remove_block:
path: '/layout_builder/remove/block/{entity_type_id}/{entity}/{delta}/{region}/{uuid}'
path: '/layout_builder/remove/block/{section_storage_type}/{section_storage}/{delta}/{region}/{uuid}'
defaults:
_form: '\Drupal\layout_builder\Form\RemoveBlockForm'
requirements:
......@@ -102,12 +95,11 @@ layout_builder.remove_block:
options:
_admin_route: TRUE
parameters:
entity:
type: entity:{entity_type_id}
section_storage:
layout_builder_tempstore: TRUE
layout_builder.move_block:
path: '/layout_builder/move/block/{entity_type_id}/{entity}/{delta_from}/{delta_to}/{region_from}/{region_to}/{block_uuid}/{preceding_block_uuid}'
path: '/layout_builder/move/block/{section_storage_type}/{section_storage}/{delta_from}/{delta_to}/{region_from}/{region_to}/{block_uuid}/{preceding_block_uuid}'
defaults:
_controller: '\Drupal\layout_builder\Controller\MoveBlockController::build'
delta_from: null
......@@ -121,8 +113,7 @@ layout_builder.move_block:
options:
_admin_route: TRUE
parameters:
entity:
type: entity:{entity_type_id}
section_storage:
layout_builder_tempstore: TRUE
route_callbacks:
......
services:
layout_builder.tempstore_repository:
class: Drupal\layout_builder\LayoutTempstoreRepository
arguments: ['@user.shared_tempstore', '@entity_type.manager']
arguments: ['@user.shared_tempstore']
access_check.entity.layout:
class: Drupal\layout_builder\Access\LayoutSectionAccessCheck
tags:
......@@ -15,9 +15,12 @@ services:
- { name: route_enhancer }
layout_builder.param_converter:
class: Drupal\layout_builder\Routing\LayoutTempstoreParamConverter
arguments: ['@entity.manager', '@layout_builder.tempstore_repository']
arguments: ['@layout_builder.tempstore_repository', '@class_resolver']
tags:
- { name: paramconverter, priority: 10 }
layout_builder.section_storage_param_converter.overrides:
class: Drupal\layout_builder\Routing\SectionStorageOverridesParamConverter
arguments: ['@entity.manager']
cache_context.layout_builder_is_active:
class: Drupal\layout_builder\Cache\LayoutBuilderIsActiveCacheContext
arguments: ['@current_route_match']
......
......@@ -3,10 +3,10 @@
namespace Drupal\layout_builder\Access;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Routing\Access\AccessInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\layout_builder\SectionStorageInterface;
/**
* Provides an access check for the Layout Builder UI.
......@@ -16,7 +16,7 @@
class LayoutSectionAccessCheck implements AccessInterface {
/**
* Checks routing access to layout for the entity.
* Checks routing access to the layout.
*
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The current route match.
......@@ -27,24 +27,20 @@ class LayoutSectionAccessCheck implements AccessInterface {
* The access result.
*/
public function access(RouteMatchInterface $route_match, AccountInterface $account) {
// Attempt to retrieve the generic 'entity' parameter, otherwise look up the
// specific entity via the entity type ID.
$entity = $route_match->getParameter('entity') ?: $route_match->getParameter($route_match->getParameter('entity_type_id'));
$section_storage = $route_match->getParameter('section_storage');
// If we don't have an entity, forbid access.
if (empty($entity)) {
if (empty($section_storage)) {
return AccessResult::forbidden()->addCacheContexts(['route']);
}
// If the entity isn't fieldable, forbid access.
if (!$entity instanceof FieldableEntityInterface || !$entity->hasField('layout_builder__layout')) {
if (!$section_storage instanceof SectionStorageInterface) {
$access = AccessResult::forbidden();
}
else {
$access = AccessResult::allowedIfHasPermission($account, 'configure any layout');
}
return $access->addCacheableDependency($entity);
return $access->addCacheableDependency($section_storage);
}
}
......@@ -4,9 +4,9 @@
use Drupal\Core\DependencyInjection\ClassResolverInterface;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\layout_builder\LayoutTempstoreRepositoryInterface;
use Drupal\layout_builder\Section;
use Drupal\layout_builder\SectionStorageInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
......@@ -51,10 +51,10 @@ public static function create(ContainerInterface $container) {
}
/**
* Add the layout to the entity field in a tempstore.
* Adds the new section.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity.
* @param \Drupal\layout_builder\SectionStorageInterface $section_storage
* The section storage.
* @param int $delta
* The delta of the section to splice.
* @param string $plugin_id
......@@ -63,18 +63,16 @@ public static function create(ContainerInterface $container) {
* @return \Symfony\Component\HttpFoundation\Response
* The controller response.
*/
public function build(EntityInterface $entity, $delta, $plugin_id) {
/** @var \Drupal\layout_builder\SectionStorageInterface $field_list */
$field_list = $entity->layout_builder__layout;
$field_list->insertSection($delta, new Section($plugin_id));
public function build(SectionStorageInterface $section_storage, $delta, $plugin_id) {
$section_storage->insertSection($delta, new Section($plugin_id));
$this->layoutTempstoreRepository->set($entity);
$this->layoutTempstoreRepository->set($section_storage);
if ($this->isAjax()) {
return $this->rebuildAndClose($entity);
return $this->rebuildAndClose($section_storage);
}
else {
$url = $entity->toUrl('layout-builder');
$url = $section_storage->getLayoutBuilderUrl();
return new RedirectResponse($url->setAbsolute()->toString());
}
}
......
......@@ -4,8 +4,8 @@
use Drupal\Core\Block\BlockManagerInterface;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Url;
use Drupal\layout_builder\SectionStorageInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
......@@ -46,8 +46,8 @@ public static function create(ContainerInterface $container) {
/**
* Provides the UI for choosing a new block.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity.
* @param \Drupal\layout_builder\SectionStorageInterface $section_storage
* The section storage.
* @param int $delta
* The delta of the section to splice.
* @param string $region
......@@ -56,7 +56,7 @@ public static function create(ContainerInterface $container) {
* @return array
* A render array.
*/
public function build(EntityInterface $entity, $delta, $region) {
public function build(SectionStorageInterface $section_storage, $delta, $region) {
$build['#type'] = 'container';
$build['#attributes']['class'][] = 'block-categories';
......@@ -72,8 +72,8 @@ public function build(EntityInterface $entity, $delta, $region) {
'title' => $block['admin_label'],
'url' => Url::fromRoute('layout_builder.add_block',
[
'entity_type_id' => $entity->getEntityTypeId(),
'entity' => $entity->id(),
'section_storage_type' => $section_storage->getStorageType(),
'section_storage' => $section_storage->getStorageId(),
'delta' => $delta,
'region' => $region,
'plugin_id' => $block_id,
......
......@@ -3,11 +3,11 @@
namespace Drupal\layout_builder\Controller;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Layout\LayoutPluginManagerInterface;
use Drupal\Core\Plugin\PluginFormInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url;
use Drupal\layout_builder\SectionStorageInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
......@@ -49,15 +49,15 @@ public static function create(ContainerInterface $container) {
/**
* Choose a layout plugin to add as a section.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity.
* @param \Drupal\layout_builder\SectionStorageInterface $section_storage
* The section storage.
* @param int $delta
* The delta of the section to splice.
*
* @return array
* The render array.
*/
public function build(EntityInterface $entity, $delta) {
public function build(SectionStorageInterface $section_storage, $delta) {
$output['#title'] = $this->t('Choose a layout');
$items = [];
......@@ -75,8 +75,8 @@ public function build(EntityInterface $entity, $delta) {
'#url' => Url::fromRoute(
$layout instanceof PluginFormInterface ? 'layout_builder.configure_section' : 'layout_builder.add_section',
[
'entity_type_id' => $entity->getEntityTypeId(),
'entity' => $entity->id(),
'section_storage_type' => $section_storage->getStorageType(),
'section_storage' => $section_storage->getStorageId(),
'delta' => $delta,
'plugin_id' => $plugin_id,
]
......
......@@ -3,12 +3,12 @@
namespace Drupal\layout_builder\Controller;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Plugin\PluginFormInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url;
use Drupal\layout_builder\LayoutTempstoreRepositoryInterface;
use Drupal\layout_builder\Section;
use Drupal\layout_builder\SectionStorageInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
......@@ -50,48 +50,38 @@ public static function create(ContainerInterface $container) {
/**
* Provides a title callback.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity.
* @param \Drupal\layout_builder\SectionStorageInterface $section_storage
* The section storage.
*
* @return string
* The title for the layout page.
*/
public function title(EntityInterface $entity) {
return $this->t('Edit layout for %label', ['%label' => $entity->label()]);
public function title(SectionStorageInterface $section_storage) {
return $this->t('Edit layout for %label', ['%label' => $section_storage->label()]);
}
/**
* Renders the Layout UI.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity.
* @param \Drupal\layout_builder\SectionStorageInterface $section_storage
* The section storage.
* @param bool $is_rebuilding
* (optional) Indicates if the layout is rebuilding, defaults to FALSE.
*
* @return array
* A render array.
*/
public function layout(EntityInterface $entity, $is_rebuilding = FALSE) {
$entity_id = $entity->id();
$entity_type_id = $entity->getEntityTypeId();
/** @var \Drupal\layout_builder\SectionStorageInterface $field_list */
$field_list = $entity->layout_builder__layout;
// For a new layout override, begin with a single section of one column.
if (!$is_rebuilding && $field_list->count() === 0) {
$field_list->appendSection(new Section('layout_onecol'));
$this->layoutTempstoreRepository->set($entity);
}
public function layout(SectionStorageInterface $section_storage, $is_rebuilding = FALSE) {
$this->prepareLayout($section_storage, $is_rebuilding);
$output = [];
$count = 0;
foreach ($field_list->getSections() as $section) {
$output[] = $this->buildAddSectionLink($entity_type_id, $entity_id, $count);
$output[] = $this->buildAdministrativeSection($section, $entity, $count);
for ($i = 0; $i < $section_storage->count(); $i++) {
$output[] = $this->buildAddSectionLink($section_storage, $count);
$output[] = $this->buildAdministrativeSection($section_storage, $count);
$count++;
}
$output[] = $this->buildAddSectionLink($entity_type_id, $entity_id, $count);
$output[] = $this->buildAddSectionLink($section_storage, $count);
$output['#attached']['library'][] = 'layout_builder/drupal.layout_builder';
$output['#type'] = 'container';
$output['#attributes']['id'] = 'layout-builder';
......@@ -100,28 +90,51 @@ public function layout(EntityInterface $entity, $is_rebuilding = FALSE) {
return $output;
}
/**
* Prepares a layout for use in the UI.
*
* @param \Drupal\layout_builder\SectionStorageInterface $section_storage
* The section storage.
* @param bool $is_rebuilding
* Indicates if the layout is rebuilding.
*/
protected function prepareLayout(SectionStorageInterface $section_storage, $is_rebuilding) {
// For a new layout, begin with a single section of one column.
if (!$is_rebuilding && $section_storage->count() === 0) {
$sections = [];
if (!$sections) {
$sections[] = new Section('layout_onecol');
}
foreach ($sections as $section) {
$section_storage->appendSection($section);
}
$this->layoutTempstoreRepository->set($section_storage);
}
}
/**
* Builds a link to add a new section at a given delta.
*
* @param string $entity_type_id
* The entity type.
* @param string $entity_id
* The entity ID.
* @param \Drupal\layout_builder\SectionStorageInterface $section_storage
* The section storage.
* @param int $delta
* The delta of the section to splice.
*
* @return array
* A render array for a link.
*/
protected function buildAddSectionLink($entity_type_id, $entity_id, $delta) {
protected function buildAddSectionLink(SectionStorageInterface $section_storage, $delta) {
$storage_type = $section_storage->getStorageType();
$storage_id = $section_storage->getStorageId();
return [
'link' => [
'#type' => 'link',
'#title' => $this->t('Add Section'),
'#url' => Url::fromRoute('layout_builder.choose_section',
[
'entity_type_id' => $entity_type_id,
'entity' => $entity_id,
'section_storage_type' => $storage_type,
'section_storage' => $storage_id,
'delta' => $delta,
],
[
......@@ -143,19 +156,18 @@ protected function buildAddSectionLink($entity_type_id, $entity_id, $delta) {
/**
* Builds the render array for the layout section while editing.
*
* @param \Drupal\layout_builder\Section $section
* The layout section.
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity.
* @param \Drupal\layout_builder\SectionStorageInterface $section_storage
* The section storage.
* @param int $delta
* The delta of the section.
*
* @return array
* The render array for a given section.
*/
protected function buildAdministrativeSection(Section $section, EntityInterface $entity, $delta) {
$entity_type_id = $entity->getEntityTypeId();
$entity_id = $entity->id();
protected function buildAdministrativeSection(SectionStorageInterface $section_storage, $delta) {
$storage_type = $section_storage->getStorageType();
$storage_id = $section_storage->getStorageId();
$section = $section_storage->getSection($delta);
$layout = $section->getLayout();
$build = $section->toRenderArray();
......@@ -169,8 +181,8 @@ protected function buildAdministrativeSection(Section $section, EntityInterface
$build[$region][$uuid]['#contextual_links'] = [
'layout_builder_block' => [
'route_parameters' => [
'entity_type_id' => $entity_type_id,
'entity' => $entity_id,
'section_storage_type' => $storage_type,
'section_storage' => $storage_id,
'delta' => $delta,
'region' => $region,
'uuid' => $uuid,
......@@ -185,8 +197,8 @@ protected function buildAdministrativeSection(Section $section, EntityInterface
'#title' => $this->t('Add Block'),
'#url' => Url::fromRoute('layout_builder.choose_block',
[
'entity_type_id' => $entity_type_id,
'entity' => $entity_id,
'section_storage_type' => $storage_type,
'section_storage' => $storage_id,
'delta' => $delta,
'region' => $region,
],
......@@ -207,8 +219,8 @@ protected function buildAdministrativeSection(Section $section, EntityInterface
}
$build['#attributes']['data-layout-update-url'] = Url::fromRoute('layout_builder.move_block', [
'entity_type_id' => $entity_type_id,
'entity' => $entity_id,
'section_storage_type' => $storage_type,
'section_storage' => $storage_id,
])->toString();
$build['#attributes']['data-layout-delta'] = $delta;
$build['#attributes']['class'][] = 'layout-builder--layout';
......@@ -223,8 +235,8 @@ protected function buildAdministrativeSection(Section $section, EntityInterface
'#title' => $this->t('Configure section'),
'#access' => $layout instanceof PluginFormInterface,
'#url' => Url::fromRoute('layout_builder.configure_section', [
'entity_type_id' => $entity_type_id,
'entity' => $entity_id,
'section_storage_type' => $storage_type,
'section_storage' => $storage_id,
'delta' => $delta,
]),
'#attributes' => [
......@@ -237,8 +249,8 @@ protected function buildAdministrativeSection(Section $section, EntityInterface
'#type' => 'link',
'#title' => $this->t('Remove section'),
'#url' => Url::fromRoute('layout_builder.remove_section', [
'entity_type_id' => $entity_type_id,
'entity' => $entity_id,
'section_storage_type' => $storage_type,
'section_storage' => $storage_id,
'delta' => $delta,
]),
'#attributes' => [
......@@ -254,30 +266,30 @@ protected function buildAdministrativeSection(Section $section, EntityInterface
/**
* Saves the layout.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity.
* @param \Drupal\layout_builder\SectionStorageInterface $section_storage
* The section storage.
*
* @return \Symfony\Component\HttpFoundation\RedirectResponse
* A redirect response.
*/
public function saveLayout(EntityInterface $entity) {
$entity->save();
$this->layoutTempstoreRepository->delete($entity);
return new RedirectResponse($entity->toUrl()->setAbsolute()->toString());
public function saveLayout(SectionStorageInterface $section_storage) {
$section_storage->save();
$this->layoutTempstoreRepository->delete($section_storage);
return new RedirectResponse($section_storage->getCanonicalUrl()->setAbsolute()->toString());
}
/**
* Cancels the layout.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity.
* @param \Drupal\layout_builder\SectionStorageInterface $section_storage
* The section storage.
*
* @return \Symfony\Component\HttpFoundation\RedirectResponse
* A redirect response.
*/
public function cancelLayout(EntityInterface $entity) {
$this->layoutTempstoreRepository->delete($entity);
return new RedirectResponse($entity->toUrl()->setAbsolute()->toString());
public function cancelLayout(SectionStorageInterface $section_storage) {
$this->layoutTempstoreRepository->delete($section_storage);
return new RedirectResponse($section_storage->getCanonicalUrl()->setAbsolute()->toString());
}
}
......@@ -5,7 +5,7 @@
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\CloseDialogCommand;
use Drupal\Core\Ajax\ReplaceCommand;
use Drupal\Core\Entity\EntityInterface;
use Drupal\layout_builder\SectionStorageInterface;
/**
* Provides AJAX responses to rebuild the Layout Builder.
......@@ -24,15 +24,15 @@ trait LayoutRebuildTrait {
/**
* Rebuilds the layout.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity.
* @param \Drupal\layout_builder\SectionStorageInterface $section_storage
* The section storage.
*
* @return \Drupal\Core\Ajax\AjaxResponse
* An AJAX response to either rebuild the layout and close the dialog, or
* reload the page.
*/
protected function rebuildAndClose(EntityInterface $entity) {
$response = $this->rebuildLayout($entity);
protected function rebuildAndClose(SectionStorageInterface $section_storage) {
$response = $this->rebuildLayout($section_storage);
$response->addCommand(new CloseDialogCommand('#drupal-off-canvas'));
return $response;
}
......@@ -40,17 +40,17 @@ protected function rebuildAndClose(EntityInterface $entity) {
/**
* Rebuilds the layout.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity.
* @param \Drupal\layout_builder\SectionStorageInterface $section_storage
* The section storage.
*
* @return \Drupal\Core\Ajax\AjaxResponse
* An AJAX response to either rebuild the layout and close the dialog, or
* reload the page.
*/
protected function rebuildLayout(EntityInterface $entity) {
protected function rebuildLayout(SectionStorageInterface $section_storage) {
$response = new AjaxResponse();
$layout_controller = $this->classResolver->getInstanceFromDefinition(LayoutBuilderController::class);
$layout = $layout_controller->layout($entity, TRUE);
$layout = $layout_controller->layout($section_storage, TRUE);
$response->addCommand(new ReplaceCommand('#layout-builder', $layout));
return $response;
}
......
......@@ -4,8 +4,8 @@
use Drupal\Core\DependencyInjection\ClassResolverInterface;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\layout_builder\LayoutTempstoreRepositoryInterface;
use Drupal\layout_builder\SectionStorageInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
......@@ -50,8 +50,8 @@ public static function create(ContainerInterface $container) {
/**
* Moves a block to another region.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity.
* @param \Drupal\layout_builder\SectionStorageInterface $section_storage
* The section storage.
* @param int $delta_from
* The delta of the original section.
* @param int $delta_to
......@@ -68,10 +68,8 @@ public static function create(ContainerInterface $container) {
* @return \Drupal\Core\Ajax\AjaxResponse
* An AJAX response.
*/
public function build(EntityInterface $entity, $delta_from, $delta_to, $region_from, $region_to, $block_uuid, $preceding_block_uuid = NULL) {
/** @var \Drupal\layout_builder\SectionStorageInterface $field_list */
$field_list = $entity->layout_builder__layout;
$section = $field_list->getSection($delta_from);
public function build(SectionStorageInterface $section_storage, $delta_from, $delta_to, $region_from, $region_to, $block_uuid, $preceding_block_uuid = NULL) {
$section = $section_storage->getSection($delta_from);
$component = $section->getComponent($block_uuid);
$section->removeComponent($block_uuid);
......@@ -79,7 +77,7 @@ public function build(EntityInterface $entity, $delta_from, $delta_to, $region_f
// If the block is moving from one section to another, update the original
// section and load the new one.
if ($delta_from !== $delta_to) {
$section = $field_list->getSection($delta_to);
$section = $section_storage->getSection($delta_to);
}
// If a preceding block was specified, insert after that. Otherwise add the
......@@ -92,8 +90,8 @@ public function build(EntityInterface $entity, $delta_from, $delta_to, $region_f
$section->appendComponent($component);
}
$this->layoutTempstoreRepository->set($entity);
return $this->rebuildLayout($entity);
$this->layoutTempstoreRepository->set($section_storage);
return $this->rebuildLayout($section_storage);
}
}
......@@ -74,4 +74,55 @@ public function removeSection($delta) {
return $this;
}
/**
* {@inheritdoc}
*/
public function getStorageType() {
return 'overrides';
}
/**
* {@inheritdoc}
*/
public function getStorageId() {
$entity = $this->getEntity();
return $entity->getEntityTypeId() . ':' . $entity->id();
}
/**
* {@inheritdoc}
*/
public function label() {
return $this->getEntity()->label();
}
/**
* {@inheritdoc}
*/
public function save() {
return $this->getEntity()->save();
}
/**
* {@inheritdoc}
*/
public function getCanonicalUrl() {
return $this->getEntity()->toUrl('canonical');
}
/**
* {@inheritdoc}
*/
public function getLayoutBuilderUrl() {
return $this->getEntity()->toUrl('layout-builder');
}
/**
* {@inheritdoc}
*/
public function __wakeup() {
// Ensure the entity is updated with the latest value.
$this->getEntity()->set($this->getName(), $this->getValue());
}
}
......@@ -6,7 +6,6 @@
use Drupal\Core\Block\BlockManagerInterface;
use Drupal\Core\Block\BlockPluginInterface;
use Drupal\Core\DependencyInjection\ClassResolverInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Form\SubformState;
......@@ -18,6 +17,7 @@
use Drupal\layout_builder\Controller\LayoutRebuildTrait;
use Drupal\layout_builder\LayoutTempstoreRepositoryInterface;
use Drupal\layout_builder\Section;
use Drupal\layout_builder\SectionStorageInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
......@@ -88,11 +88,11 @@ abstract class ConfigureBlockFormBase extends FormBase {
protected $region;
/**
* The entity.
* The section storage.
*
* @var \Drupal\Core\Entity\EntityInterface
* @var \Drupal\layout_builder\SectionStorageInterface
*/
protected $entity;
protected $sectionStorage;
/**
* Constructs a new block form.
......@@ -159,8 +159,8 @@ protected function prepareBlock($block_id, array $configuration) {
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity being configured.
* @param \Drupal\layout_builder\SectionStorageInterface $section_storage
* The section storage being configured.
* @param int $delta
* The delta of the section.
* @param string $region
......@@ -173,8 +173,8 @@ protected function prepareBlock($block_id, array $configuration) {
* @return array
* The form array.
*/
public function buildForm(array $form, FormStateInterface $form_state, EntityInterface $entity = NULL, $delta = NULL, $region = NULL, $plugin_id = NULL, array $configuration = []) {
$this->entity = $entity;
public function buildForm(array $form, FormStateInterface $form_state, SectionStorageInterface $section_storage = NULL, $delta = NULL, $region = NULL, $plugin_id = NULL, array $configuration = []) {
$this->sectionStorage = $section_storage;
$this->delta = $delta;
$this->region = $region;
$this->block = $this->prepareBlock($plugin_id, $configuration);
......@@ -246,20 +246,18 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
$configuration = $this->block->getConfiguration();
/** @var \Drupal\layout_builder\SectionStorageInterface $field_list */
$field_list = $this->entity->layout_builder__layout;
$section = $field_list->getSection($this->delta);
$section = $this->sectionStorage->getSection($this->delta);
$this->submitBlock($section, $this->region, $configuration['uuid'], $configuration);
$this->layoutTempstoreRepository->set($this->entity);
$form_state->setRedirectUrl($this->entity->toUrl('layout-builder'));
$this->layoutTempstoreRepository->set($this->sectionStorage);
$form_state->setRedirectUrl($this->sectionStorage->getLayoutBuilderUrl());
}
/**
* {@inheritdoc}
*/
protected function successfulAjaxSubmit(array $form, FormStateInterface $form_state) {
return $this->rebuildAndClose($this->entity);
return $this->rebuildAndClose($this->sectionStorage);
}
/**
......
......@@ -3,7 +3,6 @@
namespace Drupal\layout_builder\Form;
use Drupal\Core\DependencyInjection\ClassResolverInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Form\SubformState;
......@@ -14,6 +13,7 @@
use Drupal\layout_builder\Controller\LayoutRebuildTrait;
use Drupal\layout_builder\LayoutTempstoreRepositoryInterface;
use Drupal\layout_builder\Section;
use Drupal\layout_builder\SectionStorageInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
......@@ -48,11 +48,11 @@ class ConfigureSectionForm extends FormBase {
protected $pluginFormFactory;
/**
* The entity.
* The section storage.
*
* @var \Drupal\Core\Entity\EntityInterface
* @var \Drupal\layout_builder\SectionStorageInterface
*/
protected $entity;
protected $sectionStorage;
/**
* The field delta.
......@@ -105,15 +105,13 @@ public function getFormId() {
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state, EntityInterface $entity = NULL, $delta = NULL, $plugin_id = NULL) {
$this->entity = $entity;
public function buildForm(array $form, FormStateInterface $form_state, SectionStorageInterface $section_storage = NULL, $delta = NULL, $plugin_id = NULL) {
$this->sectionStorage = $section_storage;
$this->delta = $delta;
$this->isUpdate = is_null($plugin_id);
if ($this->isUpdate) {
/** @var \Drupal\layout_builder\SectionStorageInterface $field_list */
$field_list = $this->entity->layout_builder__layout;
$section = $field_list->getSection($this->delta);
$section = $this->sectionStorage->getSection($this->delta);
}
else {
$section = new Section($plugin_id);
......@@ -156,24 +154,22 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
$plugin_id = $this->layout->getPluginId();
$configuration = $this->layout->getConfiguration();
/** @var \Drupal\layout_builder\SectionStorageInterface $field_list */
$field_list = $this->entity->layout_builder__layout;
if ($this->isUpdate) {
$field_list->getSection($this->delta)->setLayoutSettings($configuration);
$this->sectionStorage->getSection($this->delta)->setLayoutSettings($configuration);
}
else {
$field_list->insertSection($this->delta, new Section($plugin_id, $configuration));
$this->sectionStorage->insertSection($this->delta, new Section($plugin_id, $configuration));
}
$this->layoutTempstoreRepository->set($this->entity);
$form_state->setRedirectUrl($this->entity->toUrl('layout-builder'));
$this->layoutTempstoreRepository->set($this->sectionStorage);
$form_state->setRedirectUrl($this->sectionStorage->getLayoutBuilderUrl());
}
/**
* {@inheritdoc}
*/
protected function successfulAjaxSubmit(array $form, FormStateInterface $form_state) {
return $this->rebuildAndClose($this->entity);
return $this->rebuildAndClose($this->sectionStorage);
}
/**
......
......@@ -3,11 +3,11 @@
namespace Drupal\layout_builder\Form;
use Drupal\Core\DependencyInjection\ClassResolverInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\ConfirmFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\layout_builder\Controller\LayoutRebuildTrait;
use Drupal\layout_builder\LayoutTempstoreRepositoryInterface;
use Drupal\layout_builder\SectionStorageInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
......@@ -28,11 +28,11 @@ abstract class LayoutRebuildConfirmFormBase extends ConfirmFormBase {
protected $layoutTempstoreRepository;
/**
* The entity.
* The section storage.
*
* @var \Drupal\Core\Entity\EntityInterface
* @var \Drupal\layout_builder\SectionStorageInterface
*/
protected $entity;
protected $sectionStorage;
/**
* The field delta.
......@@ -68,14 +68,14 @@ public static function create(ContainerInterface $container) {
* {@inheritdoc}
*/
public function getCancelUrl() {
return $this->entity->toUrl('layout-builder', ['query' => ['layout_is_rebuilding' => TRUE]]);
return $this->sectionStorage->getLayoutBuilderUrl()->setOption('query', ['layout_is_rebuilding' => TRUE]);
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state, EntityInterface $entity = NULL, $delta = NULL) {
$this->entity = $entity;
public function buildForm(array $form, FormStateInterface $form_state, SectionStorageInterface $section_storage = NULL, $delta = NULL) {
$this->sectionStorage = $section_storage;
$this->delta = $delta;
$form = parent::buildForm($form, $form_state);
......@@ -92,9 +92,9 @@ public function buildForm(array $form, FormStateInterface $form_state, EntityInt
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$this->handleEntity($this->entity, $form_state);
$this->handleSectionStorage($this->sectionStorage, $form_state);
$this->layoutTempstoreRepository->set($this->entity);
$this->layoutTempstoreRepository->set($this->sectionStorage);
$form_state->setRedirectUrl($this->getCancelUrl());
}
......@@ -103,17 +103,17 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
* {@inheritdoc}
*/
protected function successfulAjaxSubmit(array $form, FormStateInterface $form_state) {
return $this->rebuildAndClose($this->entity);
return $this->rebuildAndClose($this->sectionStorage);
}
/**
* Performs any actions on the layout entity before saving.
* Performs any actions on the section storage before saving.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity.
* @param \Drupal\layout_builder\SectionStorageInterface $section_storage
* The section storage.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*/
abstract protected function handleEntity(EntityInterface $entity, FormStateInterface $form_state);
abstract protected function handleSectionStorage(SectionStorageInterface $section_storage, FormStateInterface $form_state);
}
......@@ -2,8 +2,8 @@
namespace Drupal\layout_builder\Form;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\layout_builder\SectionStorageInterface;
/**
* Provides a form to confirm the removal of a block.
......@@ -50,19 +50,17 @@ public function getFormId() {
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state, EntityInterface $entity = NULL, $delta = NULL, $region = NULL, $uuid = NULL) {
public function buildForm(array $form, FormStateInterface $form_state, SectionStorageInterface $section_storage = NULL, $delta = NULL, $region = NULL, $uuid = NULL) {
$this->region = $region;
$this->uuid = $uuid;
return parent::buildForm($form, $form_state, $entity, $delta);
return parent::buildForm($form, $form_state, $section_storage, $delta);
}
/**
* {@inheritdoc}
*/
protected function handleEntity(EntityInterface $entity, FormStateInterface $form_state) {
/** @var \Drupal\layout_builder\SectionStorageInterface $field_list */
$field_list = $this->entity->layout_builder__layout;
$field_list->getSection($this->delta)->removeComponent($this->uuid);
protected function handleSectionStorage(SectionStorageInterface $section_storage, FormStateInterface $form_state) {
$section_storage->getSection($this->delta)->removeComponent($this->uuid);
}
}
......@@ -2,8 +2,8 @@
namespace Drupal\layout_builder\Form;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\layout_builder\SectionStorageInterface;
/**
* Provides a form to confirm the removal of a section.
......@@ -36,8 +36,8 @@ public function getConfirmText() {
/**
* {@inheritdoc}
*/
protected function handleEntity(EntityInterface $entity, FormStateInterface $form_state) {
$entity->layout_builder__layout->removeItem($this->delta);
protected function handleSectionStorage(SectionStorageInterface $section_storage, FormStateInterface $form_state) {
$section_storage->removeSection($this->delta);
}
}
......@@ -2,9 +2,10 @@
namespace Drupal\layout_builder\Form;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Component\Plugin\ConfigurablePluginInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\layout_builder\Section;
use Drupal\layout_builder\SectionStorageInterface;
/**
* Provides a form to update a block.
......@@ -27,8 +28,8 @@ public function getFormId() {
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity being configured.
* @param \Drupal\layout_builder\SectionStorageInterface $section_storage
* The section storage being configured.
* @param int $delta
* The delta of the section.
* @param string $region
......@@ -41,12 +42,13 @@ public function getFormId() {
* @return array
* The form array.
*/
public function buildForm(array $form, FormStateInterface $form_state, EntityInterface $entity = NULL, $delta = NULL, $region = NULL, $uuid = NULL, array $configuration = []) {
/** @var \Drupal\layout_builder\SectionStorageInterface $field_list */
$field_list = $entity->layout_builder__layout;
$plugin = $field_list->getSection($delta)->getComponent($uuid)->getPlugin();
public function buildForm(array $form, FormStateInterface $form_state, SectionStorageInterface $section_storage = NULL, $delta = NULL, $region = NULL, $uuid = NULL, array $configuration = []) {
$plugin = $section_storage->getSection($delta)->getComponent($uuid)->getPlugin();
if ($plugin instanceof ConfigurablePluginInterface) {
$configuration = $plugin->getConfiguration();
}
return parent::buildForm($form, $form_state, $entity, $delta, $region, $plugin->getPluginId(), $plugin->getConfiguration());
return parent::buildForm($form, $form_state, $section_storage, $delta, $region, $plugin->getPluginId(), $configuration);
}
/**
......
......@@ -2,9 +2,6 @@
namespace Drupal\layout_builder;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\RevisionableInterface;
use Drupal\user\SharedTempStoreFactory;
/**
......@@ -21,97 +18,60 @@ class LayoutTempstoreRepository implements LayoutTempstoreRepositoryInterface {
*/
protected $tempStoreFactory;
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* LayoutTempstoreRepository constructor.
*
* @param \Drupal\user\SharedTempStoreFactory $temp_store_factory
* The shared tempstore factory.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
*/
public function __construct(SharedTempStoreFactory $temp_store_factory, EntityTypeManagerInterface $entity_type_manager) {
public function __construct(SharedTempStoreFactory $temp_store_factory) {
$this->tempStoreFactory = $temp_store_factory;
$this->entityTypeManager = $entity_type_manager;
}
/**
* {@inheritdoc}
*/
public function get(EntityInterface $entity) {
$id = $this->generateTempstoreId($entity);
$tempstore = $this->getTempstore($entity)->get($id);
if (!empty($tempstore['entity'])) {
$entity_type_id = $entity->getEntityTypeId();
$entity = $tempstore['entity'];
public function get(SectionStorageInterface $section_storage) {
$id = $section_storage->getStorageId();
$tempstore = $this->getTempstore($section_storage)->get($id);
if (!empty($tempstore['section_storage'])) {
$storage_type = $section_storage->getStorageType();
$section_storage = $tempstore['section_storage'];
if (!($entity instanceof EntityInterface)) {
throw new \UnexpectedValueException(sprintf('The entry with entity type "%s" and ID "%s" is not a valid entity', $entity_type_id, $id));
}
if (!($section_storage instanceof SectionStorageInterface)) {
throw new \UnexpectedValueException(sprintf('The entry with storage type "%s" and ID "%s" is invalid', $storage_type, $id));
}
return $entity;
}
/**
* {@inheritdoc}
*/
public function getFromId($entity_type_id, $entity_id) {
$entity = $this->entityTypeManager->getStorage($entity_type_id)->loadRevision($entity_id);
return $this->get($entity);
return $section_storage;
}
/**
* {@inheritdoc}
*/
public function set(EntityInterface $entity) {
$id = $this->generateTempstoreId($entity);
$this->getTempstore($entity)->set($id, ['entity' => $entity]);
public function set(SectionStorageInterface $section_storage) {
$id = $section_storage->getStorageId();
$this->getTempstore($section_storage)->set($id, ['section_storage' => $section_storage]);
}
/**
* {@inheritdoc}
*/
public function delete(EntityInterface $entity) {
if ($this->get($entity)) {
$id = $this->generateTempstoreId($entity);
$this->getTempstore($entity)->delete($id);
}
}
/**
* Generates an ID for putting an entity in tempstore.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity being stored.
*
* @return string
* The tempstore ID.
*/
protected function generateTempstoreId(EntityInterface $entity) {
$id = "{$entity->id()}.{$entity->language()->getId()}";
if ($entity instanceof RevisionableInterface) {
$id .= '.' . $entity->getRevisionId();
}
return $id;
public function delete(SectionStorageInterface $section_storage) {
$id = $section_storage->getStorageId();
$this->getTempstore($section_storage)->delete($id);
}
/**
* Gets the shared tempstore.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity being stored.
* @param \Drupal\layout_builder\SectionStorageInterface $section_storage
* The section storage.
*
* @return \Drupal\user\SharedTempStore
* The tempstore.
*/
protected function getTempstore(EntityInterface $entity) {
$collection = $entity->getEntityTypeId() . '.layout_builder__layout';
protected function getTempstore(SectionStorageInterface $section_storage) {
$collection = 'layout_builder.' . $section_storage->getStorageType();
return $this->tempStoreFactory->get($collection);
}
......
......@@ -2,8 +2,6 @@
namespace Drupal\layout_builder;
use Drupal\Core\Entity\EntityInterface;
/**
* Provides an interface for loading layouts from tempstore.
*
......@@ -15,51 +13,34 @@
interface LayoutTempstoreRepositoryInterface {
/**
* Gets the tempstore version of an entity, if it exists.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity to check for in tempstore.
*
* @return \Drupal\Core\Entity\EntityInterface
* Either the version of this entity from tempstore, or the passed entity if
* none exists.
*
* @throw \UnexpectedValueException
* Thrown if a value exists, but is not an entity.
*/
public function get(EntityInterface $entity);
/**
* Loads an entity from tempstore given the entity ID.
* Gets the tempstore version of a section storage, if it exists.
*
* @param string $entity_type_id
* The entity type ID.
* @param string $entity_id
* The entity ID (or revision ID).
* @param \Drupal\layout_builder\SectionStorageInterface $section_storage
* The section storage to check for in tempstore.
*
* @return \Drupal\Core\Entity\EntityInterface
* Either the version of this entity from tempstore, or the entity from
* storage if none exists.
* @return \Drupal\layout_builder\SectionStorageInterface
* Either the version of this section storage from tempstore, or the passed
* section storage if none exists.
*
* @throw \UnexpectedValueException
* Thrown if a value exists, but is not an entity.
* Thrown if a value exists, but is not a section storage.
*/
public function getFromId($entity_type_id, $entity_id);
public function get(SectionStorageInterface $section_storage);
/**
* Stores this entity in tempstore.
* Stores this section storage in tempstore.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity to set in tempstore.
* @param \Drupal\layout_builder\SectionStorageInterface $section_storage
* The section storage to set in tempstore.
*/
public function set(EntityInterface $entity);
public function set(SectionStorageInterface $section_storage);
/**
* Removes the tempstore version of an entity.
* Removes the tempstore version of a section storage.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity to remove from tempstore.
* @param \Drupal\layout_builder\SectionStorageInterface $section_storage
* The section storage to remove from tempstore.
*/
public function delete(EntityInterface $entity);
public function delete(SectionStorageInterface $section_storage);
}
......@@ -7,7 +7,6 @@
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\layout_builder\Plugin\Menu\LayoutBuilderLocalTask;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
......@@ -56,23 +55,20 @@ public function getDerivativeDefinitions($base_plugin_definition) {
'title' => $this->t('Layout'),
'base_route' => "entity.$entity_type_id.canonical",
'entity_type_id' => $entity_type_id,
'class' => LayoutBuilderLocalTask::class,
'cache_contexts' => ['layout_builder_is_active:' . $entity_type_id],
];
$this->derivatives["entity.$entity_type_id.save_layout"] = $base_plugin_definition + [
'route_name' => "entity.$entity_type_id.save_layout",
$this->derivatives["entity.$entity_type_id.layout_builder_save"] = $base_plugin_definition + [
'route_name' => "entity.$entity_type_id.layout_builder_save",
'title' => $this->t('Save Layout'),
'parent_id' => "layout_builder_ui:entity.$entity_type_id.layout_builder",
'entity_type_id' => $entity_type_id,
'class' => LayoutBuilderLocalTask::class,
'cache_contexts' => ['layout_builder_is_active:' . $entity_type_id],
];
$this->derivatives["entity.$entity_type_id.cancel_layout"] = $base_plugin_definition + [
'route_name' => "entity.$entity_type_id.cancel_layout",
$this->derivatives["entity.$entity_type_id.layout_builder_cancel"] = $base_plugin_definition + [
'route_name' => "entity.$entity_type_id.layout_builder_cancel",
'title' => $this->t('Cancel Layout'),
'parent_id' => "layout_builder_ui:entity.$entity_type_id.layout_builder",
'entity_type_id' => $entity_type_id,
'class' => LayoutBuilderLocalTask::class,
'weight' => 5,
'cache_contexts' => ['layout_builder_is_active:' . $entity_type_id],
];
......
<?php
namespace Drupal\layout_builder\Plugin\Field\FieldFormatter;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase;
/**
* Plugin implementation of the 'layout_section' formatter.
*
* @internal
*
* @FieldFormatter(
* id = "layout_section",
* label = @Translation("Layout Section"),
* field_types = {
* "layout_section"
* }
* )
*/
class LayoutSectionFormatter extends FormatterBase {
/**
* {@inheritdoc}
*/
public function viewElements(FieldItemListInterface $items, $langcode) {
$elements = [];
/** @var \Drupal\layout_builder\SectionStorageInterface $items */
foreach ($items->getSections() as $delta => $section) {
$elements[$delta] = $section->toRenderArray();
}
return $elements;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment