drupal/core/modules/layout_builder/layout_builder.module

190 lines
6.9 KiB
Plaintext

<?php
/**
* @file
* Provides hook implementations for Layout Builder.
*/
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
/**
* Implements hook_help().
*/
function layout_builder_help($route_name) {
switch ($route_name) {
case 'help.page.layout_builder':
$output = '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('Layout Builder provides layout building utility.') . '</p>';
$output .= '<p>' . t('For more information, see the <a href=":layout-builder-documentation">online documentation for the Layout Builder module</a>.', [':layout-builder-documentation' => 'https://www.drupal.org/docs/8/core/modules/layout_builder']) . '</p>';
return $output;
}
}
/**
* Implements hook_entity_type_alter().
*/
function layout_builder_entity_type_alter(array &$entity_types) {
/** @var \Drupal\Core\Entity\EntityTypeInterface[] $entity_types */
foreach ($entity_types as $entity_type) {
if ($entity_type->entityClassImplements(FieldableEntityInterface::class) && $entity_type->hasLinkTemplate('canonical') && $entity_type->hasViewBuilderClass()) {
$entity_type->setLinkTemplate('layout-builder', $entity_type->getLinkTemplate('canonical') . '/layout');
}
}
}
/**
* Removes the Layout Builder field both visually and from the #fields handling.
*
* This prevents any interaction with this field. It is rendered directly
* in layout_builder_entity_view_alter().
*
* @internal
*/
function _layout_builder_hide_layout_field(array &$form) {
unset($form['fields']['layout_builder__layout']);
$key = array_search('layout_builder__layout', $form['#fields']);
if ($key !== FALSE) {
unset($form['#fields'][$key]);
}
}
/**
* Implements hook_form_FORM_ID_alter() for \Drupal\field_ui\Form\EntityFormDisplayEditForm.
*/
function layout_builder_form_entity_form_display_edit_form_alter(&$form, FormStateInterface $form_state) {
_layout_builder_hide_layout_field($form);
}
/**
* Implements hook_form_FORM_ID_alter() for \Drupal\field_ui\Form\EntityViewDisplayEditForm.
*/
function layout_builder_form_entity_view_display_edit_form_alter(&$form, FormStateInterface $form_state) {
/** @var \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display */
$display = $form_state->getFormObject()->getEntity();
$entity_type = \Drupal::entityTypeManager()->getDefinition($display->getTargetEntityTypeId());
_layout_builder_hide_layout_field($form);
// @todo Expand to work for all view modes in
// https://www.drupal.org/node/2907413.
if (!in_array($display->getMode(), ['full', 'default'], TRUE)) {
return;
}
$form['layout'] = [
'#type' => 'details',
'#open' => TRUE,
'#title' => t('Layout options'),
'#tree' => TRUE,
];
// @todo Unchecking this box is a destructive action, this should be made
// clear to the user in https://www.drupal.org/node/2914484.
$form['layout']['allow_custom'] = [
'#type' => 'checkbox',
'#title' => t('Allow each @entity to have its layout customized.', [
'@entity' => $entity_type->getSingularLabel(),
]),
'#default_value' => $display->getThirdPartySetting('layout_builder', 'allow_custom', FALSE),
];
$form['#entity_builders'][] = 'layout_builder_form_entity_view_display_edit_entity_builder';
}
/**
* Entity builder for layout options on the entity view display form.
*
* @see layout_builder_form_entity_view_display_edit_form_alter()
*/
function layout_builder_form_entity_view_display_edit_entity_builder($entity_type_id, EntityViewDisplayInterface $display, &$form, FormStateInterface &$form_state) {
$new_value = (bool) $form_state->getValue(['layout', 'allow_custom'], FALSE);
$display->setThirdPartySetting('layout_builder', 'allow_custom', $new_value);
}
/**
* Implements hook_ENTITY_TYPE_presave().
*/
function layout_builder_entity_view_display_presave(EntityViewDisplayInterface $display) {
$original_value = isset($display->original) ? $display->original->getThirdPartySetting('layout_builder', 'allow_custom', FALSE) : FALSE;
$new_value = $display->getThirdPartySetting('layout_builder', 'allow_custom', FALSE);
if ($original_value !== $new_value) {
$entity_type_id = $display->getTargetEntityTypeId();
$bundle = $display->getTargetBundle();
if ($new_value) {
layout_builder_add_layout_section_field($entity_type_id, $bundle);
}
elseif ($field = FieldConfig::loadByName($entity_type_id, $bundle, 'layout_builder__layout')) {
$field->delete();
}
}
}
/**
* Adds a layout section field to a given bundle.
*
* @param string $entity_type_id
* The entity type ID.
* @param string $bundle
* The bundle.
* @param string $field_name
* (optional) The name for the layout section field. Defaults to
* 'layout_builder__layout'.
*
* @return \Drupal\field\FieldConfigInterface
* A layout section field.
*/
function layout_builder_add_layout_section_field($entity_type_id, $bundle, $field_name = 'layout_builder__layout') {
$field = FieldConfig::loadByName($entity_type_id, $bundle, $field_name);
if (!$field) {
$field_storage = FieldStorageConfig::loadByName($entity_type_id, $field_name);
if (!$field_storage) {
$field_storage = FieldStorageConfig::create([
'entity_type' => $entity_type_id,
'field_name' => $field_name,
'type' => 'layout_section',
]);
$field_storage->save();
}
$field = FieldConfig::create([
'field_storage' => $field_storage,
'bundle' => $bundle,
'label' => t('Layout'),
]);
$field->save();
}
return $field;
}
/**
* Implements hook_entity_view_alter().
*/
function layout_builder_entity_view_alter(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display) {
if ($display->getThirdPartySetting('layout_builder', 'allow_custom', FALSE) && !$entity->layout_builder__layout->isEmpty()) {
$sections = $entity->layout_builder__layout->getSections();
foreach ($sections as $delta => $section) {
$build['_layout_builder'][$delta] = $section->toRenderArray();
}
// If field layout is active, that is all that needs to be removed.
if (\Drupal::moduleHandler()->moduleExists('field_layout') && isset($build['_field_layout'])) {
unset($build['_field_layout']);
return;
}
/** @var \Drupal\Core\Field\FieldDefinitionInterface[] $field_definitions */
$field_definitions = \Drupal::service('entity_field.manager')->getFieldDefinitions($display->getTargetEntityTypeId(), $display->getTargetBundle());
// Remove all display-configurable fields.
foreach (array_keys($display->getComponents()) as $name) {
if ($name !== 'layout_builder__layout' && isset($field_definitions[$name]) && $field_definitions[$name]->isDisplayConfigurable('view')) {
unset($build[$name]);
}
}
}
}