You are here

class AllowedBlocksForm in Layout Builder Restrictions 8.2

Provides form for designating allowed blocks.

Hierarchy

Expanded class hierarchy of AllowedBlocksForm

File

modules/layout_builder_restrictions_by_region/src/Form/AllowedBlocksForm.php, line 25

Namespace

Drupal\layout_builder_restrictions_by_region\Form
View source
class AllowedBlocksForm extends FormBase {
  use PluginHelperTrait;
  use LayoutBuilderRestrictionsByRegionHelperTrait;

  /**
   * Request stack that controls the lifecycle of requests.
   *
   * @var \Symfony\Component\HttpFoundation\RequestStack
   */
  protected $requestStack;

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

  /**
   * Manages entity type plugin definitions.
   *
   * @var \Drupal\Core\Entity\EntityTypeManager
   */
  protected $entityTypeManager;

  /**
   * Creates a private temporary storage for a collection.
   *
   * @var \Drupal\Core\TempStore\PrivateTempStoreFactory
   */
  protected $privateTempStoreFactory;

  /**
   * The Messenger service.
   *
   * @var \Drupal\Core\Messenger\MessengerInterface
   */
  protected $messenger;

  /**
   * Turns a render array into a HTML string.
   *
   * @var \Drupal\Core\Render\Renderer
   */
  protected $renderer;

  /**
   * An array of allowed block categories, or empty.
   *
   * @var array
   */
  protected $allowedBlockCategories;

  /**
   * Layout/Region-specific selections, prior to full form submit.
   *
   * @var array
   */
  protected $tempData;

  /**
   * An array of whitelisted blocks, by category.
   *
   * @var array
   */
  protected $whitelistedBlocks;

  /**
   * An array of blacklisted blocks, by category.
   *
   * @var array
   */
  protected $blacklistedBlocks;

  /**
   * An array of restricted block categories.
   *
   * @var array
   */
  protected $restrictedCategories;

  /**
   * The machine name of the layout plugin.
   *
   * @var string
   */
  protected $layoutPluginId;

  /**
   * The machine name of the region.
   *
   * @var string
   */
  protected $regionId;

  /**
   * The machine name of the static id.
   *
   * @var string
   */
  protected $staticId;

  /**
   * The ModalFormController constructor.
   *
   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
   *   Request stack that controls the lifecycle of requests.
   * @param \Drupal\Core\Block\LayoutPluginManagerInterface $layout_manager
   *   The layout plugin manager.
   * @param \Drupal\Core\Entity\EntityTypeManager $entity_type_manager
   *   Manages entity type plugin definitions.
   * @param \Drupal\Core\TempStore\PrivateTempStoreFactory $private_temp_store_factory
   *   Creates a private temporary storage for a collection.
   * @param \Drupal\Core\Messenger\MessengerInterface $messenger
   *   The messenger service.
   * @param \Drupal\Core\Render\Renderer $renderer
   *   Turns a render array into a HTML string.
   */
  public function __construct(RequestStack $request_stack, LayoutPluginManagerInterface $layout_manager, EntityTypeManager $entity_type_manager, PrivateTempStoreFactory $private_temp_store_factory, MessengerInterface $messenger, Renderer $renderer) {
    $this->requestStack = $request_stack;
    $this->layoutManager = $layout_manager;
    $this->entityTypeManager = $entity_type_manager;
    $this->privateTempStoreFactory = $private_temp_store_factory;
    $this->messenger = $messenger;
    $this->renderer = $renderer;

    // Build data for current form.
    $current_request = $this->requestStack
      ->getCurrentRequest();
    $entity_view_display_id = $current_request->query
      ->get('entity_view_display_id');
    $display = $this->entityTypeManager
      ->getStorage('entity_view_display')
      ->load($entity_view_display_id);
    $this->layoutPluginId = $current_request->query
      ->get('layout_plugin');
    $this->regionId = $current_request->query
      ->get('region_id');
    $this->allowedBlockCategories = $display
      ->getThirdPartySetting('layout_builder_restrictions', 'allowed_block_categories', []);
    $third_party_settings = $display
      ->getThirdPartySetting('layout_builder_restrictions', 'entity_view_mode_restriction_by_region', []);
    $this->whitelistedBlocks = isset($third_party_settings['whitelisted_blocks'][$this->layoutPluginId][$this->regionId]) ? $third_party_settings['whitelisted_blocks'][$this->layoutPluginId][$this->regionId] : [];
    $this->blacklistedBlocks = isset($third_party_settings['blacklisted_blocks'][$this->layoutPluginId][$this->regionId]) ? $third_party_settings['blacklisted_blocks'][$this->layoutPluginId][$this->regionId] : [];
    $this->restrictedCategories = isset($third_party_settings['restricted_categories'][$this->layoutPluginId][$this->regionId]) ? $third_party_settings['restricted_categories'][$this->layoutPluginId][$this->regionId] : [];
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static($container
      ->get('request_stack'), $container
      ->get('plugin.manager.core.layout'), $container
      ->get('entity_type.manager'), $container
      ->get('tempstore.private'), $container
      ->get('messenger'), $container
      ->get('renderer'));
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'layout_builder_by_region_allowed_blocks';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $current_request = $this->requestStack
      ->getCurrentRequest();
    $static_id = $current_request->query
      ->get('static_id');
    $entity_view_display_id = $current_request->query
      ->get('entity_view_display_id');
    $layout_plugin = $current_request->query
      ->get('layout_plugin');
    $region_id = $current_request->query
      ->get('region_id');
    $display = $this->entityTypeManager
      ->getStorage('entity_view_display')
      ->load($entity_view_display_id);

    // Load tempstore data.
    $tempstore = $this->privateTempStoreFactory;
    $store = $tempstore
      ->get('layout_builder_restrictions_by_region');
    $temp_data = $store
      ->get($static_id . ':' . $layout_plugin . ':' . $region_id);
    $layout_definition = $this->layoutManager
      ->getDefinition($layout_plugin);
    $regions = $layout_definition
      ->getRegions();
    $regions['all_regions'] = [
      'label' => $this
        ->t('All regions'),
    ];
    $region_label = $regions[$region_id]['label']
      ->render();
    $layout_label = $layout_definition
      ->getLabel();
    $form['config_context_markup'] = [
      '#markup' => $this
        ->t('<strong>Layout:</strong> @layout_label<br><strong>Region:</strong> @region_label', [
        '@layout_label' => $layout_label,
        '@region_label' => $region_label,
      ]),
    ];
    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,
      ];
      $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'],
          ]),
        ],
        '#parents' => [
          'allowed_blocks',
          $category,
          'restriction',
        ],
      ];
      $category_form['restriction_behavior']['#default_value'] = $this
        ->getCategoryBehavior($category, $temp_data);
      $category_form['allowed_blocks'] = [
        '#type' => 'container',
        '#states' => [
          'invisible' => [
            [
              ':input[name="allowed_blocks[' . $category . '][restriction]"]' => [
                'value' => "all",
              ],
            ],
            [
              ':input[name="allowed_blocks[' . $category . '][restriction]"]' => [
                'value' => "restrict_all",
              ],
            ],
          ],
        ],
      ];
      foreach ($data['definitions'] as $block_id => $block) {
        $category_form['allowed_blocks'][$block_id] = [
          '#type' => 'checkbox',
          '#title' => $block['admin_label'],
          '#default_value' => $this
            ->getBlockDefault($block_id, $category, $temp_data),
          '#parents' => [
            'allowed_blocks',
            $category,
            'allowed_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="allowed_blocks[' . $category . '][restriction]"]' => [
                'value' => "restricted",
              ],
            ],
          ],
        ];
      }
      $form['allowed_blocks'][$category] = $category_form;
    }
    $form['static_id'] = [
      '#type' => 'hidden',
      '#value' => $static_id,
    ];
    $form['layout_plugin'] = [
      '#type' => 'hidden',
      '#value' => $layout_plugin,
    ];
    $form['region_id'] = [
      '#type' => 'hidden',
      '#value' => $region_id,
    ];
    $form['actions']['submit'] = [
      '#type' => 'submit',
      '#value' => $this
        ->t('Save'),
      '#ajax' => [
        'callback' => '::ajaxSubmit',
        'event' => 'click',
        'url' => Url::fromRoute("layout_builder_restrictions_by_region.{$display->getTargetEntityTypeId()}_allowed_blocks", [
          'static_id' => $static_id,
          'entity_view_display_id' => $entity_view_display_id,
          'layout_plugin' => $layout_plugin,
          'region_id' => $region_id,
        ]),
        'options' => [
          'query' => [
            FormBuilderInterface::AJAX_FORM_REQUEST => TRUE,
          ],
        ],
      ],
    ];
    return $form;
  }

  /**
   * Callback function for AJAX form submission.
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   */
  public function ajaxSubmit(array &$form, FormStateInterface $form_state) {
    $values = $form_state
      ->getValues();
    $static_id = $values['static_id'];
    $layout_plugin = $values['layout_plugin'];
    $region_id = $values['region_id'];
    $categories = $values['allowed_blocks'];
    $block_restrictions = [];
    if (!empty($categories)) {
      foreach ($categories as $category => $category_setting) {
        $restriction_type = $category_setting['restriction'];
        $block_restrictions[$category]['restriction_type'] = $restriction_type;
        if (in_array($restriction_type, [
          'whitelisted',
          'blacklisted',
        ])) {
          foreach ($category_setting['allowed_blocks'] as $block_id => $block_setting) {
            if ($block_setting == '1') {

              // Include only checked blocks.
              $block_restrictions[$category]['restrictions'][$block_id] = $block_setting;
            }
          }
        }
      }
    }

    // Write settings to tempStore.
    $tempstore = $this->privateTempStoreFactory;
    $store = $tempstore
      ->get('layout_builder_restrictions_by_region');
    $store
      ->set($static_id . ':' . $layout_plugin . ':' . $region_id, $block_restrictions);
    $response = new AjaxResponse();
    if ($form_state
      ->getErrors()) {

      // Could there ever be form errors?
      // It's all checkboxes and radio buttons.
    }
    else {
      $command = new CloseModalDialogCommand();
      $response
        ->addCommand($command);
      $this->messenger
        ->addWarning($this
        ->t('There is unsaved Layout Builder Restrictions configuration.'));
      $status_messages = [
        '#type' => 'status_messages',
      ];
      $messages = $this->renderer
        ->renderRoot($status_messages);
      $messages = '<div id="layout-builder-restrictions-messages">' . $messages . '</div>';
      if (!empty($messages)) {
        $response
          ->addCommand(new ReplaceCommand('#layout-builder-restrictions-messages', $messages));
      }
      $region_status = $this
        ->RegionRestrictionStatusString($layout_plugin, $region_id, $static_id, NULL);
      $response
        ->addCommand(new ReplaceCommand('#restriction-status--' . $layout_plugin . '--' . $region_id . ' .data', '<span class="data">' . $region_status . '</span>'));
    }
    return $response;
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
  }

  /**
   * Business logic to set category to 'all', 'whitelisted' or 'blacklisted'.
   *
   * @param string $category
   *   The block's category.
   * @param mixed $temp_data
   *   The data stored between AJAX submits or null.
   *
   * @return string
   *   The value 'all', 'whitelisted', 'blacklisted', or 'restrict_all'.
   */
  protected function getCategoryBehavior($category, $temp_data) {

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

    // Attempt to retrieve default value from tempStore, then from config
    // before settings to 'all'.
    if (!is_null($temp_data[$category]['restriction_type'])) {
      return $temp_data[$category]['restriction_type'];
    }
    else {
      if (isset($this->whitelistedBlocks) && in_array($category, array_keys($this->whitelistedBlocks))) {
        return "whitelisted";
      }
      elseif (isset($this->blacklistedBlocks) && in_array($category, array_keys($this->blacklistedBlocks))) {
        return "blacklisted";
      }
      elseif (in_array($category, $this->restrictedCategories)) {
        return 'restrict_all';
      }
      elseif ($category_is_restricted) {

        // If there is no configuration, but the category hasn't been 'allowed',
        // use 'whitelisted' to preset this as if all blocks were restricted.
        return "restrict_all";
      }
      else {
        return 'all';
      }
    }
  }

  /**
   * Business logic to set category to 'all', 'whitelisted' or 'blacklisted'.
   *
   * @param string $block_id
   *   The Drupal block ID.
   * @param string $category
   *   The block's category.
   * @param mixed $temp_data
   *   The data stored between AJAX submits or null.
   *
   * @return bool
   *   Whether or not the block is stored in the restriction type.
   */
  protected function getBlockDefault($block_id, $category, $temp_data) {

    // Attempt to retrieve default value from tempStore, then from config.
    if (!is_null($temp_data)) {
      if (isset($temp_data[$category]['restrictions'])) {
        return in_array($block_id, array_keys($temp_data[$category]['restrictions']));
      }
      else {
        return FALSE;
      }
    }
    else {
      if (isset($this->whitelistedBlocks[$category])) {
        return in_array($block_id, $this->whitelistedBlocks[$category]);
      }
      if (isset($this->blacklistedBlocks[$category])) {
        return in_array($block_id, $this->blacklistedBlocks[$category]);
      }
      else {
        return FALSE;
      }
    }
    return FALSE;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
AllowedBlocksForm::$allowedBlockCategories protected property An array of allowed block categories, or empty.
AllowedBlocksForm::$blacklistedBlocks protected property An array of blacklisted blocks, by category.
AllowedBlocksForm::$entityTypeManager protected property Manages entity type plugin definitions.
AllowedBlocksForm::$layoutManager protected property The layout manager.
AllowedBlocksForm::$layoutPluginId protected property The machine name of the layout plugin.
AllowedBlocksForm::$messenger protected property The Messenger service. Overrides MessengerTrait::$messenger
AllowedBlocksForm::$privateTempStoreFactory protected property Creates a private temporary storage for a collection.
AllowedBlocksForm::$regionId protected property The machine name of the region.
AllowedBlocksForm::$renderer protected property Turns a render array into a HTML string.
AllowedBlocksForm::$requestStack protected property Request stack that controls the lifecycle of requests. Overrides FormBase::$requestStack
AllowedBlocksForm::$restrictedCategories protected property An array of restricted block categories.
AllowedBlocksForm::$staticId protected property The machine name of the static id.
AllowedBlocksForm::$tempData protected property Layout/Region-specific selections, prior to full form submit.
AllowedBlocksForm::$whitelistedBlocks protected property An array of whitelisted blocks, by category.
AllowedBlocksForm::ajaxSubmit public function Callback function for AJAX form submission.
AllowedBlocksForm::buildForm public function Form constructor. Overrides FormInterface::buildForm
AllowedBlocksForm::create public static function Instantiates a new instance of this class. Overrides FormBase::create
AllowedBlocksForm::getBlockDefault protected function Business logic to set category to 'all', 'whitelisted' or 'blacklisted'.
AllowedBlocksForm::getCategoryBehavior protected function Business logic to set category to 'all', 'whitelisted' or 'blacklisted'.
AllowedBlocksForm::getFormId public function Returns a unique string identifying the form. Overrides FormInterface::getFormId
AllowedBlocksForm::submitForm public function Form submission handler. Overrides FormInterface::submitForm
AllowedBlocksForm::validateForm public function Form validation handler. Overrides FormBase::validateForm
AllowedBlocksForm::__construct public function The ModalFormController constructor.
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
FormBase::$configFactory protected property The config factory. 1
FormBase::$routeMatch protected property The route match.
FormBase::config protected function Retrieves a configuration object.
FormBase::configFactory protected function Gets the config factory for this form. 1
FormBase::container private function Returns the service container.
FormBase::currentUser protected function Gets the current user.
FormBase::getRequest protected function Gets the request object.
FormBase::getRouteMatch protected function Gets the route match.
FormBase::logger protected function Gets the logger for a specific channel.
FormBase::redirect protected function Returns a redirect response object for the specified route. Overrides UrlGeneratorTrait::redirect
FormBase::resetConfigFactory public function Resets the configuration factory.
FormBase::setConfigFactory public function Sets the config factory for this form.
FormBase::setRequestStack public function Sets the request stack object to use.
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.
LayoutBuilderRestrictionsByRegionHelperTrait::entityTypeManager protected function Gets the entity type manager.
LayoutBuilderRestrictionsByRegionHelperTrait::privateTempStoreFactory protected function Gets the private tempStore.
LayoutBuilderRestrictionsByRegionHelperTrait::regionRestrictionStatus protected function Checks if any restrictions are enabled for a given region.
LayoutBuilderRestrictionsByRegionHelperTrait::regionRestrictionStatusString protected function Wrapper function for regionRestrictionStatus() that returns a string.
LinkGeneratorTrait::$linkGenerator protected property The link generator. 1
LinkGeneratorTrait::getLinkGenerator Deprecated protected function Returns the link generator.
LinkGeneratorTrait::l Deprecated protected function Renders a link to a route given a route name and its parameters.
LinkGeneratorTrait::setLinkGenerator Deprecated public function Sets the link generator service.
LoggerChannelTrait::$loggerFactory protected property The logger channel factory service.
LoggerChannelTrait::getLogger protected function Gets the logger for a specific channel.
LoggerChannelTrait::setLoggerFactory public function Injects the logger channel factory.
MessengerTrait::messenger public function Gets the messenger. 29
MessengerTrait::setMessenger public function Sets the messenger.
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.
RedirectDestinationTrait::$redirectDestination protected property The redirect destination service. 1
RedirectDestinationTrait::getDestinationArray protected function Prepares a 'destination' URL query parameter for use with \Drupal\Core\Url.
RedirectDestinationTrait::getRedirectDestination protected function Returns the redirect destination service.
RedirectDestinationTrait::setRedirectDestination public function Sets the redirect destination service.
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.
UrlGeneratorTrait::$urlGenerator protected property The url generator.
UrlGeneratorTrait::getUrlGenerator Deprecated protected function Returns the URL generator service.
UrlGeneratorTrait::setUrlGenerator Deprecated public function Sets the URL generator service.
UrlGeneratorTrait::url Deprecated protected function Generates a URL or path for a specific route based on the given parameters.