getRouteObject()->getOption('_layout_builder')) { $output = '

' . t('This layout builder tool allows you to configure the layout of the main content area.') . '

'; if (\Drupal::currentUser()->hasPermission('administer blocks')) { $output .= '

' . t('To manage other areas of the page, use the block administration page.', ['@block-ui' => Url::fromRoute('block.admin_display')->toString()]) . '

'; } else { $output .= '

' . t('To manage other areas of the page, use the block administration page.') . '

'; } return $output; } switch ($route_name) { case 'help.page.layout_builder': $output = '

' . t('About') . '

'; $output .= '

' . t('Layout Builder provides layout building utility.') . '

'; $output .= '

' . t('For more information, see the online documentation for the Layout Builder module.', [':layout-builder-documentation' => 'https://www.drupal.org/docs/8/core/modules/layout_builder']) . '

'; return $output; } } /** * Implements hook_entity_type_alter(). */ function layout_builder_entity_type_alter(array &$entity_types) { /** @var \Drupal\Core\Entity\EntityTypeInterface[] $entity_types */ $entity_types['entity_view_display'] ->setClass(LayoutBuilderEntityViewDisplay::class) ->setStorageClass(LayoutBuilderEntityViewDisplayStorage::class) ->setFormClass('edit', LayoutBuilderEntityViewDisplayForm::class); } /** * 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) { // Hides the Layout Builder field. It is rendered directly in // \Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay::buildMultiple(). unset($form['fields'][OverridesSectionStorage::FIELD_NAME]); $key = array_search(OverridesSectionStorage::FIELD_NAME, $form['#fields']); if ($key !== FALSE) { unset($form['#fields'][$key]); } } /** * Implements hook_field_config_insert(). */ function layout_builder_field_config_insert(FieldConfigInterface $field_config) { // Clear the sample entity for this entity type and bundle. $sample_entity_generator = \Drupal::service('layout_builder.sample_entity_generator'); $sample_entity_generator->delete($field_config->getTargetEntityTypeId(), $field_config->getTargetBundle()); \Drupal::service('plugin.manager.block')->clearCachedDefinitions(); } /** * Implements hook_field_config_delete(). */ function layout_builder_field_config_delete(FieldConfigInterface $field_config) { // Clear the sample entity for this entity type and bundle. $sample_entity_generator = \Drupal::service('layout_builder.sample_entity_generator'); $sample_entity_generator->delete($field_config->getTargetEntityTypeId(), $field_config->getTargetBundle()); \Drupal::service('plugin.manager.block')->clearCachedDefinitions(); } /** * Implements hook_entity_view_alter(). * * ExtraFieldBlock block plugins add placeholders for each extra field which is * configured to be displayed. Those placeholders are replaced by this hook. * Modules that implement hook_entity_extra_field_info() use their * implementations of hook_entity_view_alter() to add the rendered output of * the extra fields they provide, so we cannot get the rendered output of extra * fields before this point in the view process. * layout_builder_module_implements_alter() moves this implementation of * hook_entity_view_alter() to the end of the list. * * @see \Drupal\layout_builder\Plugin\Block\ExtraFieldBlock::build() * @see layout_builder_module_implements_alter() */ function layout_builder_entity_view_alter(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display) { if ($display instanceof LayoutEntityDisplayInterface) { /** @var \Drupal\Core\Entity\EntityFieldManagerInterface $field_manager */ $field_manager = \Drupal::service('entity_field.manager'); $extra_fields = $field_manager->getExtraFields($entity->getEntityTypeId(), $entity->bundle()); if (!empty($extra_fields['display'])) { foreach ($extra_fields['display'] as $field_name => $extra_field) { // If the extra field is not set replace with an empty array to avoid // the placeholder text from being rendered. $replacement = isset($build[$field_name]) ? $build[$field_name] : []; ExtraFieldBlock::replaceFieldPlaceholder($build, $replacement, $field_name); // After the rendered field in $build has been copied over to the // ExtraFieldBlock block we must remove it from its original location or // else it will be rendered twice. unset($build[$field_name]); } } } } /** * Implements hook_builder_module_implements_alter(). */ function layout_builder_module_implements_alter(&$implementations, $hook) { if ($hook === 'entity_view_alter') { // Ensure that this module's implementation of hook_entity_view_alter() runs // last so that other modules that use this hook to render extra fields will // run before it. $group = $implementations['layout_builder']; unset($implementations['layout_builder']); $implementations['layout_builder'] = $group; } } /** * Implements hook_entity_presave(). */ function layout_builder_entity_presave(EntityInterface $entity) { if (\Drupal::moduleHandler()->moduleExists('block_content')) { /** @var \Drupal\layout_builder\InlineBlockEntityOperations $entity_operations */ $entity_operations = \Drupal::classResolver(InlineBlockEntityOperations::class); $entity_operations->handlePreSave($entity); } } /** * Implements hook_entity_delete(). */ function layout_builder_entity_delete(EntityInterface $entity) { if (\Drupal::moduleHandler()->moduleExists('block_content')) { /** @var \Drupal\layout_builder\InlineBlockEntityOperations $entity_operations */ $entity_operations = \Drupal::classResolver(InlineBlockEntityOperations::class); $entity_operations->handleEntityDelete($entity); } } /** * Implements hook_cron(). */ function layout_builder_cron() { if (\Drupal::moduleHandler()->moduleExists('block_content')) { /** @var \Drupal\layout_builder\InlineBlockEntityOperations $entity_operations */ $entity_operations = \Drupal::classResolver(InlineBlockEntityOperations::class); $entity_operations->removeUnused(); } } /** * Implements hook_plugin_filter_TYPE_alter(). */ function layout_builder_plugin_filter_block_alter(array &$definitions, array $extra, $consumer) { // @todo Determine the 'inline_block' blocks should be allowed outside // of layout_builder https://www.drupal.org/node/2979142. if ($consumer !== 'layout_builder' || !isset($extra['list']) || $extra['list'] !== 'inline_blocks') { foreach ($definitions as $id => $definition) { if ($definition['id'] === 'inline_block') { unset($definitions[$id]); } } } } /** * Implements hook_ENTITY_TYPE_access(). */ function layout_builder_block_content_access(EntityInterface $entity, $operation, AccountInterface $account) { /** @var \Drupal\block_content\BlockContentInterface $entity */ if ($operation === 'view' || $entity->isReusable() || empty(\Drupal::service('inline_block.usage')->getUsage($entity->id()))) { // If the operation is 'view' or this is reusable block or if this is // non-reusable that isn't used by this module then don't alter the access. return AccessResult::neutral(); } if ($account->hasPermission('configure any layout')) { return AccessResult::allowed(); } return AccessResult::forbidden(); } /** * Implements hook_plugin_filter_TYPE__CONSUMER_alter(). */ function layout_builder_plugin_filter_block__block_ui_alter(array &$definitions, array $extra) { foreach ($definitions as $id => $definition) { // Filter out any layout_builder definition with required contexts. if ($definition['provider'] === 'layout_builder' && !empty($definition['context'])) { /** @var \Drupal\Core\Plugin\Context\ContextDefinitionInterface $context */ foreach ($definition['context'] as $context) { if ($context->isRequired()) { unset($definitions[$id]); break; } } } } }