You are here

class FormAlter in Layout Builder Restrictions 8.2

Same name in this branch
  1. 8.2 src/Form/FormAlter.php \Drupal\layout_builder_restrictions\Form\FormAlter
  2. 8.2 modules/layout_builder_restrictions_by_region/src/Form/FormAlter.php \Drupal\layout_builder_restrictions_by_region\Form\FormAlter
Same name and namespace in other branches
  1. 8 src/Form/FormAlter.php \Drupal\layout_builder_restrictions\Form\FormAlter

Supplement form UI to add setting for which blocks & layouts are available.

Hierarchy

Expanded class hierarchy of FormAlter

1 file declares its use of FormAlter
layout_builder_restrictions.module in ./layout_builder_restrictions.module
Module file for layout builder restrictions.

File

src/Form/FormAlter.php, line 19

Namespace

Drupal\layout_builder_restrictions\Form
View source
class FormAlter implements ContainerInjectionInterface {
  use PluginHelperTrait;
  use DependencySerializationTrait;

  /**
   * The section storage manager.
   *
   * @var \Drupal\layout_builder\SectionStorage\SectionStorageManagerInterface
   */
  protected $sectionStorageManager;

  /**
   * The block manager.
   *
   * @var \Drupal\Core\Block\BlockManagerInterface
   */
  protected $blockManager;

  /**
   * The layout manager.
   *
   * @var \Drupal\Core\Layout\LayoutPluginManagerInterface
   */
  protected $layoutManager;

  /**
   * The context handler.
   *
   * @var \Drupal\Core\Plugin\Context\ContextHandlerInterface
   */
  protected $contextHandler;

  /**
   * FormAlter constructor.
   *
   * @param \Drupal\layout_builder\SectionStorage\SectionStorageManagerInterface $section_storage_manager
   *   The section storage manager.
   * @param \Drupal\Core\Block\BlockManagerInterface $block_manager
   *   The block manager.
   * @param \Drupal\Core\Block\LayoutPluginManagerInterface $layout_manager
   *   The layout plugin manager.
   * @param \Drupal\Core\Plugin\Context\ContextHandlerInterface $context_handler
   *   The context handler.
   */
  public function __construct(SectionStorageManagerInterface $section_storage_manager, BlockManagerInterface $block_manager, LayoutPluginManagerInterface $layout_manager, ContextHandlerInterface $context_handler) {
    $this->sectionStorageManager = $section_storage_manager;
    $this->blockManager = $block_manager;
    $this->layoutManager = $layout_manager;
    $this->contextHandler = $context_handler;
  }

  /**
   * {@inheritdoc}
   */
  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'));
  }

  /**
   * The actual form elements.
   */
  public function alterEntityViewDisplayFormAllowedBlockCategories(&$form, FormStateInterface $form_state, $form_id) {
    $display = $form_state
      ->getFormObject()
      ->getEntity();
    $is_enabled = $display
      ->isLayoutBuilderEnabled();
    if ($is_enabled) {
      $form['#entity_builders'][] = [
        $this,
        'entityFormEntityBuild',
      ];
      $allowed_block_categories = $display
        ->getThirdPartySetting('layout_builder_restrictions', 'allowed_block_categories', []);
      $form['layout']['layout_builder_restrictions']['allowed_block_categories'] = [
        '#title' => $this
          ->t('Default restriction for new categories of blocks not listed below.'),
        '#description_display' => 'before',
        '#type' => 'radios',
        '#options' => [
          "allowed" => $this
            ->t('Allow all blocks from newly available categories.'),
          "restricted" => $this
            ->t('Restrict all blocks from newly available categories.'),
        ],
        '#parents' => [
          'layout_builder_restrictions',
          'allowed_block_categories',
        ],
        '#default_value' => !empty($allowed_block_categories) ? "restricted" : "allowed",
      ];
    }
  }

  /**
   * The actual form elements.
   */
  public function alterEntityViewDisplayForm(&$form, FormStateInterface $form_state, $form_id) {
    $display = $form_state
      ->getFormObject()
      ->getEntity();
    $is_enabled = $display
      ->isLayoutBuilderEnabled();
    if ($is_enabled) {
      $form['#entity_builders'][] = [
        $this,
        'entityFormEntityBuild',
      ];

      // Block settings.
      $form['layout']['layout_builder_restrictions']['allowed_blocks'] = [
        '#type' => 'details',
        '#title' => $this
          ->t('Blocks available for placement (all layouts & regions)'),
        '#states' => [
          'disabled' => [
            ':input[name="layout[enabled]"]' => [
              'checked' => FALSE,
            ],
          ],
          'invisible' => [
            ':input[name="layout[enabled]"]' => [
              'checked' => FALSE,
            ],
          ],
        ],
      ];
      $third_party_settings = $display
        ->getThirdPartySetting('layout_builder_restrictions', 'entity_view_mode_restriction', []);
      $whitelisted_blocks = isset($third_party_settings['whitelisted_blocks']) ? $third_party_settings['whitelisted_blocks'] : [];
      $blacklisted_blocks = isset($third_party_settings['blacklisted_blocks']) ? $third_party_settings['blacklisted_blocks'] : [];
      $restricted_categories = isset($third_party_settings['restricted_categories']) ? $third_party_settings['restricted_categories'] : [];
      $allowed_block_categories = $display
        ->getThirdPartySetting('layout_builder_restrictions', 'allowed_block_categories', []);
      foreach ($this
        ->getBlockDefinitions($display) as $category => $data) {
        $title = $data['label'];
        if (!empty($data['translated_label'])) {
          $title = $data['translated_label'];
        }
        $category_form = [
          '#type' => 'fieldset',
          '#title' => $title,
          '#parents' => [
            'layout_builder_restrictions',
            'allowed_blocks',
          ],
        ];

        // Check whether this is a newly available category that has been
        // restricted previously.
        $category_is_restricted = !empty($allowed_block_categories) && !in_array($category, $allowed_block_categories);

        // The category is 'restricted' if it's already been specified as such,
        // or if the default behavior for new categories indicate such.
        if (in_array($category, array_keys($whitelisted_blocks))) {
          $category_setting = 'whitelisted';
        }
        elseif (in_array($category, array_keys($blacklisted_blocks))) {
          $category_setting = 'blacklisted';
        }
        elseif ($category_is_restricted) {
          $category_setting = 'restrict_all';
        }
        elseif (in_array($category, $restricted_categories)) {
          $category_setting = 'restrict_all';
        }
        else {
          $category_setting = 'all';
        }
        $category_form['restriction_behavior'] = [
          '#type' => 'radios',
          '#options' => [
            "all" => $this
              ->t('Allow all existing & new %category blocks.', [
              '%category' => $data['label'],
            ]),
            "restrict_all" => $this
              ->t('Restrict all existing & new %category blocks.', [
              '%category' => $data['label'],
            ]),
            "whitelisted" => $this
              ->t('Allow specific %category blocks:', [
              '%category' => $data['label'],
            ]),
            "blacklisted" => $this
              ->t('Restrict specific %category blocks:', [
              '%category' => $data['label'],
            ]),
          ],
          '#default_value' => $category_setting,
          '#parents' => [
            'layout_builder_restrictions',
            'allowed_blocks',
            $category,
            'restriction',
          ],
        ];
        $category_form['available_blocks'] = [
          '#type' => 'container',
          '#states' => [
            'invisible' => [
              [
                ':input[name="layout_builder_restrictions[allowed_blocks][' . $category . '][restriction]"]' => [
                  'value' => "all",
                ],
              ],
              [
                ':input[name="layout_builder_restrictions[allowed_blocks][' . $category . '][restriction]"]' => [
                  'value' => "restrict_all",
                ],
              ],
            ],
          ],
        ];
        foreach ($data['definitions'] as $block_id => $block) {
          $enabled = FALSE;
          if ($category_setting == 'whitelisted' && isset($whitelisted_blocks[$category]) && in_array($block_id, $whitelisted_blocks[$category])) {
            $enabled = TRUE;
          }
          elseif ($category_setting == 'blacklisted' && isset($blacklisted_blocks[$category]) && in_array($block_id, $blacklisted_blocks[$category])) {
            $enabled = TRUE;
          }
          $category_form['available_blocks'][$block_id] = [
            '#type' => 'checkbox',
            '#title' => $block['admin_label'],
            '#default_value' => $enabled,
            '#parents' => [
              'layout_builder_restrictions',
              'allowed_blocks',
              $category,
              'available_blocks',
              $block_id,
            ],
          ];
        }
        if ($category == 'Custom blocks' || $category == 'Custom block types') {
          $category_form['description'] = [
            '#type' => 'container',
            '#children' => $this
              ->t('<p>In the event both <em>Custom Block Types</em> and <em>Custom Blocks</em> restrictions are enabled, <em>Custom Block Types</em> restrictions are disregarded.</p>'),
            '#states' => [
              'visible' => [
                ':input[name="layout_builder_restrictions[allowed_blocks][' . $category . '][restriction]"]' => [
                  'value' => "restricted",
                ],
              ],
            ],
          ];
        }
        $form['layout']['layout_builder_restrictions']['allowed_blocks'][$category] = $category_form;
      }

      // Layout settings.
      $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",
      ];
      $definitions = $this
        ->getLayoutDefinitions();
      foreach ($definitions as $plugin_id => $definition) {
        $enabled = FALSE;
        if (!empty($allowed_layouts) && in_array($plugin_id, $allowed_layouts)) {
          $enabled = TRUE;
        }
        $layout_form['layouts'][$plugin_id] = [
          '#type' => 'checkbox',
          '#default_value' => $enabled,
          '#description' => [
            $definition
              ->getIcon(60, 80, 1, 3),
            [
              '#type' => 'container',
              '#children' => $definition
                ->getLabel() . ' (' . $plugin_id . ')',
            ],
          ],
          '#states' => [
            'invisible' => [
              ':input[name="layout_builder_restrictions[allowed_layouts][layout_restriction]"]' => [
                'value' => "all",
              ],
            ],
          ],
        ];
      }
      $form['layout']['layout_builder_restrictions']['allowed_layouts'] = $layout_form;
    }
  }

  /**
   * Save allowed blocks & layouts for the given entity view mode.
   */
  public function entityFormEntityBuild($entity_type_id, LayoutEntityDisplayInterface $display, &$form, FormStateInterface &$form_state) {
    $third_party_settings = $display
      ->getThirdPartySetting('layout_builder_restrictions', 'entity_view_mode_restriction');
    $block_restrictions = $this
      ->setAllowedBlocks($form_state);
    $third_party_settings['whitelisted_blocks'] = isset($block_restrictions['whitelisted']) ? $block_restrictions['whitelisted'] : [];
    $third_party_settings['blacklisted_blocks'] = isset($block_restrictions['blacklisted']) ? $block_restrictions['blacklisted'] : [];
    $third_party_settings['restricted_categories'] = $block_restrictions['restricted_categories'];
    $third_party_settings['allowed_layouts'] = $this
      ->setAllowedLayouts($form_state);
    $allowed_block_categories = $this
      ->setAllowedBlockCategories($form_state, $display);

    // Save!
    $display
      ->setThirdPartySetting('layout_builder_restrictions', 'allowed_block_categories', $allowed_block_categories);
    $display
      ->setThirdPartySetting('layout_builder_restrictions', 'entity_view_mode_restriction', $third_party_settings);
  }

  /**
   * Helper function to prepare saved allowed blocks.
   *
   * @param Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   *
   * @return array
   *   An array of layout names or empty.
   */
  protected function setAllowedBlocks(FormStateInterface $form_state) {
    $categories = $form_state
      ->getValue([
      'layout_builder_restrictions',
      'allowed_blocks',
    ]);
    $block_restrictions = [];
    $block_restrictions['restricted_categories'] = [];
    if (!empty($categories)) {
      foreach ($categories as $category => $settings) {
        $restriction_type = $settings['restriction'];
        if (in_array($restriction_type, [
          'whitelisted',
          'blacklisted',
        ])) {
          $block_restrictions[$restriction_type][$category] = [];
          foreach ($settings['available_blocks'] as $block_id => $block_setting) {
            if ($block_setting == '1') {

              // Include only checked blocks.
              $block_restrictions[$restriction_type][$category][] = $block_id;
            }
          }
        }
        elseif ($restriction_type === "restrict_all") {
          $block_restrictions['restricted_categories'][] = $category;
        }
      }
    }
    return $block_restrictions;
  }

  /**
   * Helper function to prepare saved allowed layouts.
   *
   * @param Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   *
   * @return array
   *   An array of layout names or empty.
   */
  protected function setAllowedLayouts(FormStateInterface $form_state) {

    // Set allowed layouts.
    $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',
      ])));
    }
    return $allowed_layouts;
  }

  /**
   * Helper function to prepare saved block definition categories.
   *
   * @return array
   *   An array of block category names or empty.
   */
  protected function setAllowedBlockCategories(FormStateInterface $form_state, LayoutEntityDisplayInterface $display) {

    // Set default for allowed block categories.
    $block_category_default = $form_state
      ->getValue([
      'layout_builder_restrictions',
      'allowed_block_categories',
    ]);
    if ($block_category_default == 'restricted') {

      // Create a whitelist of categories whose blocks should be allowed.
      // Newly available categories' blocks not in this list will be
      // disallowed.
      $allowed_block_categories = array_keys($this
        ->getBlockDefinitions($display));
    }
    else {

      // The UI choice indicates that all newly available categories'
      // blocks should be allowed by default. Represent this in the schema
      // as an empty array.
      $allowed_block_categories = [];
    }
    return $allowed_block_categories;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
FormAlter::$blockManager protected property The block manager.
FormAlter::$contextHandler protected property The context handler.
FormAlter::$layoutManager protected property The layout manager.
FormAlter::$sectionStorageManager protected property The section storage manager.
FormAlter::alterEntityViewDisplayForm public function The actual form elements.
FormAlter::alterEntityViewDisplayFormAllowedBlockCategories public function The actual form elements.
FormAlter::create public static function Instantiates a new instance of this class. Overrides ContainerInjectionInterface::create
FormAlter::entityFormEntityBuild public function Save allowed blocks & layouts for the given entity view mode.
FormAlter::setAllowedBlockCategories protected function Helper function to prepare saved block definition categories.
FormAlter::setAllowedBlocks protected function Helper function to prepare saved allowed blocks.
FormAlter::setAllowedLayouts protected function Helper function to prepare saved allowed layouts.
FormAlter::__construct public function FormAlter constructor.
LayoutBuilderContextTrait::$contextRepository protected property The context repository.
LayoutBuilderContextTrait::contextRepository protected function Gets the context repository service.
LayoutBuilderContextTrait::getAvailableContexts protected function Provides all available contexts, both global and section_storage-specific.
PluginHelperTrait::blockManager private function Gets the block manager.
PluginHelperTrait::categoryIsRestricted public function Helper function to check the default block category whitelist.
PluginHelperTrait::contextHandler private function Gets the context handler.
PluginHelperTrait::entityTypeBundleInfo private function Gets the entity bundle interface.
PluginHelperTrait::getBlockDefinitions protected function Gets block definitions appropriate for an entity display.
PluginHelperTrait::getDefinitionsByUntranslatedCategory protected function Generate a categorized list of blocks, based on the untranslated category.
PluginHelperTrait::getGroupedDefinitions public function Method to categorize blocks in a multilingual-friendly way.
PluginHelperTrait::getInlineBlockPlugins public function Gets a list of all plugins available as Inline Blocks.
PluginHelperTrait::getLayoutDefinitions protected function Gets layout definitions.
PluginHelperTrait::getSortedDefinitions protected function Sort block categories alphabetically.
PluginHelperTrait::getUntranslatedCategory public function Helper function to return an untranslated block Category.
PluginHelperTrait::getValuefromSectionStorage public function A helper function to return values derivable from section storage.
PluginHelperTrait::layoutManager private function Gets the layout plugin manager.
PluginHelperTrait::sectionStorageManager private function Gets the section storage manager.
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.