Skip to content
Snippets Groups Projects

Respect Layout Builder settings in AJAX callback for updating content.

1 file
+ 113
53
Compare changes
  • Side-by-side
  • Inline
@@ -10,6 +10,8 @@ use Drupal\Core\Ajax\HtmlCommand;
use Drupal\Core\Ajax\InvokeCommand;
use Drupal\Core\Ajax\MessageCommand;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
use Drupal\Core\Entity\EntityFormBuilder;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityRepositoryInterface;
@@ -69,6 +71,13 @@ class FrontendEditingController extends ControllerBase {
*/
protected $userData;
/**
* The entity display repository.
*
* @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface
*/
protected $entityDisplayRepository;
/**
* FrontendEditingController constructor.
*
@@ -82,13 +91,16 @@ class FrontendEditingController extends ControllerBase {
* The paragraphs' helper.
* @param \Drupal\user\UserDataInterface $userData
* The user data storage.
* @param \Drupal\Core\Entity\EntityDisplayRepositoryInterface $entity_display_repository
* The entity display repository.
*/
public function __construct(RendererInterface $renderer, EntityFormBuilder $builder, EntityRepositoryInterface $entity_repository, ParagraphsHelperInterface $paragraphs_helper, UserDataInterface $userData) {
public function __construct(RendererInterface $renderer, EntityFormBuilder $builder, EntityRepositoryInterface $entity_repository, ParagraphsHelperInterface $paragraphs_helper, UserDataInterface $userData, EntityDisplayRepositoryInterface $entity_display_repository) {
$this->renderer = $renderer;
$this->builder = $builder;
$this->entityRepository = $entity_repository;
$this->paragraphsHelper = $paragraphs_helper;
$this->userData = $userData;
$this->entityDisplayRepository = $entity_display_repository;
}
/**
@@ -100,7 +112,8 @@ class FrontendEditingController extends ControllerBase {
$container->get('entity.form_builder'),
$container->get('entity.repository'),
$container->get('frontend_editing.paragraphs_helper'),
$container->get('user.data')
$container->get('user.data'),
$container->get('entity_display.repository'),
);
}
@@ -467,54 +480,32 @@ class FrontendEditingController extends ControllerBase {
*/
protected function ajaxUpdateParagraphs(ParagraphInterface $paragraph, $message, $view_mode_id = 'default') {
$response = new AjaxResponse();
if ($message) {
$response->addCommand(new MessageCommand($message, NULL, ['type' => 'error']));
}
if ($view_mode_id == '_custom') {
if ($view_mode_id === '_custom') {
$view_mode_id = 'default';
}
$field_formatter_settings = $view_mode_id;
// Get the info about parent entity.
$parent_entity = $paragraph->getParentEntity();
$parent_field_name = $paragraph->get('parent_field_name')->value;
// Load the view display. We need to know whether it uses layout builder.
$view_display_id = implode('.', [$parent_entity->getEntityTypeId(), $parent_entity->bundle(), $view_mode_id]);
/** @var \Drupal\Core\Entity\Display\EntityViewDisplayInterface $view_display */
$view_display = $this->entityTypeManager()->getStorage('entity_view_display')->load($view_display_id);
if ($view_display) {
$is_layout_builder = (bool) $view_display->getThirdPartySetting('layout_builder', 'enabled');
if ($is_layout_builder) {
$layout_builder_field_block_id_parts = [
'field_block',
$parent_entity->getEntityTypeId(),
$parent_entity->bundle(),
$parent_field_name,
];
$layout_builder_field_block_id = implode(':', $layout_builder_field_block_id_parts);
$sections = $view_display->getThirdPartySetting('layout_builder', 'sections');
/** @var \Drupal\layout_builder\Section $section */
foreach ($sections as $section) {
foreach ($section->getComponents() as $component) {
if ($component->getPluginId() == $layout_builder_field_block_id) {
$configuration = $component->get('configuration');
if (!empty($configuration['formatter'])) {
$field_formatter_settings = $configuration['formatter'];
break 2;
}
}
}
}
}
}
$updated_content = $parent_entity->get($parent_field_name)
->view($field_formatter_settings);
foreach (Element::getVisibleChildren($updated_content) as $delta) {
$item = $updated_content[$delta];
if (!empty($item['#pre_render'])) {
$updated_content[$delta]['#parent_field_view_mode'] = $updated_content['#view_mode'];
}
}
$selector = '[data-frontend-editing="' . $paragraph->getParentEntity()->getEntityTypeId() . '--' . $paragraph->getParentEntity()->id() . '--' . $paragraph->get('parent_field_name')->value . '--' . $view_mode_id . '"]';
// Get updated content of the field paragraph belongs to.
$updated_content = $this->getEntityFieldRender($parent_entity, $parent_field_name, $view_mode_id);
// Replace old field render with new one.
$selector_value = implode('--', [
$parent_entity->getEntityTypeId(),
$parent_entity->id(),
$parent_field_name,
$view_mode_id,
]);
$selector = '[data-frontend-editing="' . $selector_value . '"]';
$response->addCommand(new HtmlCommand($selector, $updated_content));
return $response;
}
@@ -539,43 +530,112 @@ class FrontendEditingController extends ControllerBase {
if (!$request->isXmlHttpRequest()) {
throw new NotFoundHttpException();
}
$response = new AjaxResponse();
if (empty($view_mode)) {
$view_mode = 'default';
}
$entity = NULL;
try {
$entity = $this->entityTypeManager()
->getStorage($entity_type_id)
->load($entity_id);
}
catch (InvalidPluginDefinitionException | PluginNotFoundException $e) {
$message = $this->t('Entity of type @type and id @id was not found',
$message = $this->t('Unable to load entity of type @type and id @id',
['@type' => $entity_type_id, '@id' => $entity_id]
);
$response->addCommand(new MessageCommand($message, NULL, ['type' => 'error']));
}
if (!$entity) {
$message = $this->t('Entity of type @type and id @id was not found',
['@type' => $entity_type_id, '@id' => $entity_id]
);
$response->addCommand(new MessageCommand($message, NULL, ['type' => 'error']));
}
// If there are errors, early return and reload the page.
if (!empty($response->getCommands())) {
$response->addCommand(new ReloadWindowCommand());
return $response;
}
$updated_content = $entity->get($field_name)->view($view_mode);
foreach (Element::getVisibleChildren($updated_content) as $delta) {
$item = $updated_content[$delta];
// Get updated content of the edited field.
$updated_content = $this->getEntityFieldRender($entity, $field_name, $view_mode);
// Replace old field render with new one.
$selector_value = implode('--', [
$entity_type_id,
$entity_id,
$field_name,
$view_mode,
]);
$selector = '[data-frontend-editing="' . $selector_value . '"]';
$response->addCommand(new HtmlCommand($selector, $updated_content));
return $response;
}
/**
* Get the render array of entity field.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity.
* @param string $field_name
* The requested entity field.
* @param string $view_mode
* The render view mode.
*
* @return array
* The renderable array.
*/
protected function getEntityFieldRender(EntityInterface $entity, $field_name, $view_mode = 'default') {
$view_display = $this->entityDisplayRepository->getViewDisplay(
$entity->getEntityTypeId(),
$entity->bundle(),
$view_mode
);
// Retrieve field settings from layout builder
// if entity uses layout builder for provided view mode.
if ($view_display instanceof EntityViewDisplayInterface) {
$is_layout_builder = (bool) $view_display->getThirdPartySetting('layout_builder', 'enabled', FALSE);
if ($is_layout_builder) {
$layout_builder_field_block_id_parts = [
'field_block',
$entity->getEntityTypeId(),
$entity->bundle(),
$field_name,
];
$layout_builder_field_block_id = implode(':', $layout_builder_field_block_id_parts);
$sections = $view_display->getThirdPartySetting('layout_builder', 'sections', []);
/** @var \Drupal\layout_builder\Section $section */
foreach ($sections as $section) {
foreach ($section->getComponents() as $component) {
if ($component->getPluginId() === $layout_builder_field_block_id) {
$configuration = $component->get('configuration');
if (!empty($configuration['formatter'])) {
$field_formatter_settings = $configuration['formatter'];
break 2;
}
}
}
}
}
}
$elements = $entity->get($field_name)->view($field_formatter_settings ?? $view_mode);
foreach (Element::getVisibleChildren($elements) as $delta) {
$item = $elements[$delta];
if (!empty($item['#pre_render'])) {
$updated_content[$delta]['#parent_field_view_mode'] = $updated_content['#view_mode'];
$elements[$delta]['#parent_field_view_mode'] = $elements['#view_mode'];
}
}
$selector = '[data-frontend-editing="' . $entity_type_id . '--' . $entity_id . '--' . $field_name . '--' . $view_mode . '"]';
$response->addCommand(new HtmlCommand($selector, $updated_content));
return $response;
return $elements;
}
/**
Loading