View source
<?php
namespace Drupal\layout_builder_restrictions_by_region\Form;
use Drupal\Component\Serialization\Json;
use Drupal\Component\Uuid\UuidInterface;
use Drupal\Core\Block\BlockManagerInterface;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Layout\LayoutPluginManagerInterface;
use Drupal\Core\Plugin\Context\ContextHandlerInterface;
use Drupal\Core\TempStore\PrivateTempStoreFactory;
use Drupal\Core\Url;
use Drupal\layout_builder\Entity\LayoutEntityDisplayInterface;
use Drupal\layout_builder\SectionStorage\SectionStorageManagerInterface;
use Drupal\layout_builder_restrictions\Traits\PluginHelperTrait;
use Drupal\layout_builder_restrictions_by_region\Traits\LayoutBuilderRestrictionsByRegionHelperTrait;
use Symfony\Component\DependencyInjection\ContainerInterface;
class FormAlter implements ContainerInjectionInterface {
use PluginHelperTrait;
use LayoutBuilderRestrictionsByRegionHelperTrait;
use DependencySerializationTrait;
protected $sectionStorageManager;
protected $blockManager;
protected $layoutManager;
protected $contextHandler;
protected $uuid;
protected $privateTempStoreFactory;
public function __construct(SectionStorageManagerInterface $section_storage_manager, BlockManagerInterface $block_manager, LayoutPluginManagerInterface $layout_manager, ContextHandlerInterface $context_handler, UuidInterface $uuid, PrivateTempStoreFactory $private_temp_store_factory) {
$this->sectionStorageManager = $section_storage_manager;
$this->blockManager = $block_manager;
$this->layoutManager = $layout_manager;
$this->contextHandler = $context_handler;
$this->uuid = $uuid;
$this->privateTempStoreFactory = $private_temp_store_factory;
}
public static function create(ContainerInterface $container) {
return new static($container
->get('plugin.manager.layout_builder.section_storage'), $container
->get('plugin.manager.block'), $container
->get('plugin.manager.core.layout'), $container
->get('context.handler'), $container
->get('uuid'), $container
->get('tempstore.private'));
}
public function alterEntityViewDisplayForm(&$form, FormStateInterface &$form_state, $form_id) {
$user_input = $form_state
->getUserInput();
if (!isset($user_input['static_id'])) {
$static_id = $this->uuid
->generate();
$form['static_id'] = [
'#type' => 'hidden',
'#value' => $static_id,
];
}
else {
$static_id = $user_input['static_id'];
}
$display = $form_state
->getFormObject()
->getEntity();
$is_enabled = $display
->isLayoutBuilderEnabled();
if ($is_enabled) {
$form['layout']['layout_builder_restrictions']['messages'] = [
'#markup' => '<div id="layout-builder-restrictions-messages" class="hidden"></div>',
];
$form['#entity_builders'][] = [
$this,
'entityFormEntityBuild',
];
$third_party_settings = $display
->getThirdPartySetting('layout_builder_restrictions', 'entity_view_mode_restriction_by_region', []);
$allowed_layouts = isset($third_party_settings['allowed_layouts']) ? $third_party_settings['allowed_layouts'] : [];
$layout_form = [
'#type' => 'details',
'#title' => $this
->t('Layouts available for sections'),
'#parents' => [
'layout_builder_restrictions',
'allowed_layouts',
],
'#states' => [
'disabled' => [
':input[name="layout[enabled]"]' => [
'checked' => FALSE,
],
],
'invisible' => [
':input[name="layout[enabled]"]' => [
'checked' => FALSE,
],
],
],
];
$layout_form['layout_restriction'] = [
'#type' => 'radios',
'#options' => [
"all" => $this
->t('Allow all existing & new layouts.'),
"restricted" => $this
->t('Allow only specific layouts:'),
],
'#default_value' => !empty($allowed_layouts) ? "restricted" : "all",
];
$entity_view_display_id = $display
->get('id');
$definitions = $this
->getLayoutDefinitions();
foreach ($definitions as $section => $definition) {
$enabled = FALSE;
if (!empty($allowed_layouts) && in_array($section, $allowed_layouts)) {
$enabled = TRUE;
}
$layout_form['layouts'][$section] = [
'#type' => 'checkbox',
'#default_value' => $enabled,
'#description' => [
$definition
->getIcon(60, 80, 1, 3),
[
'#type' => 'container',
'#children' => $definition
->getLabel() . ' (' . $section . ')',
],
],
'#attributes' => [
'data-layout-plugin' => [
$section,
],
],
'#states' => [
'invisible' => [
':input[name="layout_builder_restrictions[allowed_layouts][layout_restriction]"]' => [
'value' => "all",
],
],
],
];
}
$form['layout']['layout_builder_restrictions']['allowed_layouts'] = $layout_form;
$layout_definitions = $definitions;
foreach ($layout_definitions as $section => $definition) {
$regions = $definition
->getRegions();
$regions['all_regions'] = [
'label' => $this
->t('All regions'),
];
$form['layout'][$section] = [
'#type' => 'details',
'#title' => $this
->t('Blocks available for the <em>@layout_label</em> layout', [
'@layout_label' => $definition
->getLabel(),
]),
'#parents' => [
'layout_builder_restrictions',
'allowed_blocks_by_layout',
$section,
],
'#attributes' => [
'data-layout-plugin' => $section,
],
'#states' => [
'disabled' => [
[
':input[name="layout[enabled]"]' => [
'checked' => FALSE,
],
],
'or',
[
'#edit-layout-builder-restrictions-allowed-layouts :input[data-layout-plugin="' . $section . '"]' => [
'checked' => FALSE,
],
],
],
'invisible' => [
[
':input[name="layout[enabled]"]' => [
'checked' => FALSE,
],
],
'or',
[
'#edit-layout-builder-restrictions-allowed-layouts :input[data-layout-plugin="' . $section . '"]' => [
'checked' => FALSE,
],
],
],
],
];
$default_restriction_behavior = 'all';
if (isset($third_party_settings['whitelisted_blocks'][$section]) && !isset($third_party_settings['whitelisted_blocks'][$section]['all_regions'])) {
$default_restriction_behavior = 'per-region';
}
if (isset($third_party_settings['blacklisted_blocks'][$section]) && !isset($third_party_settings['blacklisted_blocks'][$section]['all_regions'])) {
$default_restriction_behavior = 'per-region';
}
if (isset($third_party_settings['restricted_categories'][$section]) && !isset($third_party_settings['restricted_categories'][$section]['all_regions'])) {
$default_restriction_behavior = 'per-region';
}
$form['layout'][$section]['restriction_behavior'] = [
'#type' => 'radios',
'#options' => [
"all" => $this
->t('Apply block restrictions to all regions in layout'),
"per-region" => $this
->t('Apply block restrictions on a region-by-region basis'),
],
'#attributes' => [
'class' => [
'restriction-type',
],
'data-layout-plugin' => $section,
],
'#default_value' => $default_restriction_behavior,
];
$form['layout'][$section]['table'] = [
'#type' => 'table',
'#header' => [
$this
->t('Region'),
$this
->t('Status'),
$this
->t('Operations'),
],
'#attributes' => [
'data-layout' => $section,
],
];
foreach ($regions as $region_id => $region) {
$form['layout'][$section]['table']['#rows'][$region_id] = [
'data-region' => $region_id,
'data' => [
'region_label' => [
'class' => [
'region-label',
],
'data' => [
'#markup' => $region['label']
->render(),
],
],
'status' => [
'class' => [
'restriction-status',
],
'id' => 'restriction-status--' . $section . '--' . $region_id,
'data' => [
'#markup' => '<span class="data">' . $this
->RegionRestrictionStatusString($section, $region_id, $static_id, $entity_view_display_id) . '</span>',
],
],
'operations' => [
'class' => [
'operations',
],
'data' => [
'#type' => 'dropbutton',
'#links' => [
'manage' => [
'title' => $this
->t('Manage allowed blocks'),
'url' => Url::fromRoute("layout_builder_restrictions_by_region.{$form['#entity_type']}_allowed_blocks", [
'static_id' => $static_id,
'entity_view_display_id' => $entity_view_display_id,
'layout_plugin' => $section,
'region_id' => $region_id,
]),
'attributes' => [
'class' => [
'use-ajax',
],
'data-dialog-type' => 'modal',
'data-dialog-options' => Json::encode([
'width' => 800,
]),
],
],
],
],
],
],
];
}
}
$form_state
->setTemporaryValue('static_id', $static_id);
$form['#attached']['library'][] = 'layout_builder_restrictions_by_region/display_mode_form';
}
}
public function entityFormEntityBuild($entity_type_id, LayoutEntityDisplayInterface $display, &$form, FormStateInterface &$form_state) {
$static_id = $form_state
->getTemporaryValue('static_id');
$restriction_types = [
'whitelisted',
'blacklisted',
];
$layout_restriction = $form_state
->getValue([
'layout_builder_restrictions',
'allowed_layouts',
'layout_restriction',
]);
$allowed_layouts = [];
if ($layout_restriction == 'restricted') {
$allowed_layouts = array_keys(array_filter($form_state
->getValue([
'layout_builder_restrictions',
'allowed_layouts',
'layouts',
])));
}
$third_party_settings = $display
->getThirdPartySetting('layout_builder_restrictions', 'entity_view_mode_restriction_by_region');
$third_party_settings['allowed_layouts'] = $allowed_layouts;
$tempstore = $this->privateTempStoreFactory;
$store = $tempstore
->get('layout_builder_restrictions_by_region');
$layout_definitions = $this
->getLayoutDefinitions();
foreach ($allowed_layouts as $section) {
$layout_definition = $layout_definitions[$section];
$regions = $layout_definition
->getRegions();
$regions['all_regions'] = [
'label' => $this
->t('All regions'),
];
$layout_behavior = $form_state
->getValue([
'layout_builder_restrictions',
'allowed_blocks_by_layout',
$section,
]);
$all_regions_temp = $store
->get($static_id . ':' . $section . ':all_regions');
if ($layout_behavior['restriction_behavior'] == 'all' && is_null($all_regions_temp)) {
if (isset($third_party_settings['whitelisted_blocks'][$section]['all_regions'])) {
$all_regions_whitelisted = $third_party_settings['whitelisted_blocks'][$section]['all_regions'];
}
if (isset($third_party_settings['blacklisted_blocks'][$section]['all_regions'])) {
$all_regions_blacklisted = $third_party_settings['blacklisted_blocks'][$section]['all_regions'];
}
if (isset($third_party_settings['restricted_categories'][$section]['all_regions'])) {
$all_regions_restricted_categories = $third_party_settings['restricted_categories'][$section]['all_regions'];
}
foreach ($restriction_types as $logic_type) {
unset($third_party_settings[$logic_type . '_blocks'][$section]);
}
unset($third_party_settings['restricted_categories'][$section]);
if (isset($all_regions_whitelisted)) {
$third_party_settings['whitelisted_blocks'][$section]['all_regions'] = $all_regions_whitelisted;
}
if (isset($all_regions_blacklisted)) {
$third_party_settings['blacklisted_blocks'][$section]['all_regions'] = $all_regions_blacklisted;
}
if (isset($all_regions_restricted_categories)) {
$third_party_settings['restricted_categories'][$section]['all_regions'] = $all_regions_restricted_categories;
}
}
else {
foreach ($restriction_types as $logic_type) {
unset($third_party_settings[$logic_type . '_blocks'][$section]['all_regions']);
}
unset($third_party_settings['restricted_categories'][$section]);
foreach ($regions as $region_id => $region) {
$categories = $store
->get($static_id . ':' . $section . ':' . $region_id);
if (!is_null($categories)) {
foreach ($restriction_types as $logic_type) {
unset($third_party_settings[$logic_type . '_blocks'][$section][$region_id]);
}
foreach ($categories as $category => $settings) {
$restriction_type = $settings['restriction_type'];
if ($restriction_type == 'restrict_all') {
$third_party_settings['restricted_categories'][$section][$region_id][] = $category;
}
elseif (in_array($restriction_type, $restriction_types)) {
if (empty($settings['restrictions'])) {
$third_party_settings[$restriction_type . '_blocks'][$section][$region_id][$category] = [];
}
else {
foreach ($settings['restrictions'] as $block_id => $block_setting) {
$third_party_settings[$restriction_type . '_blocks'][$section][$region_id][$category][] = $block_id;
}
}
}
}
}
}
}
}
foreach ($restriction_types as $logic_type) {
if (isset($third_party_settings[$logic_type . '_blocks'])) {
foreach ($third_party_settings[$logic_type . '_blocks'] as $section => $regions) {
ksort($regions);
$third_party_settings[$logic_type . '_blocks'][$section] = $regions;
}
}
if (isset($third_party_settings[$logic_type . '_blocks'])) {
ksort($third_party_settings[$logic_type . '_blocks']);
}
}
$display
->setThirdPartySetting('layout_builder_restrictions', 'entity_view_mode_restriction_by_region', $third_party_settings);
}
}