panopoly_magic-8.x-2.x-dev/src/Plugin/views/display/MagicBlock.php

src/Plugin/views/display/MagicBlock.php
<?php

namespace Drupal\panopoly_magic\Plugin\views\display;

use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
use Drupal\Core\Form\FormState;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\TypedData\TypedDataManagerInterface;
use Drupal\ctools_views\Plugin\Display\Block;
use Drupal\views\Plugin\Block\ViewsBlock;
use Drupal\views\Plugin\views\filter\FilterPluginBase;
use Drupal\views\Plugin\views\sort\SortPluginBase;
use Drupal\views\Plugin\views\ViewsHandlerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Provides display type overrides for the Block display.
 *
 * phpcs:disable Drupal.NamingConventions.ValidVariableName.LowerCamelName
 */
final class MagicBlock extends Block {

  /**
   * The entity display repository.
   *
   * @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface
   */
  protected $entityDisplayRepository;

  /**
   * The typed data manager.
   *
   * @var \Drupal\Core\TypedData\TypedDataManagerInterface
   */
  protected $typedDataManager;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    /** @var self $instance */
    $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
    $instance->setEntityDisplayRepository($container->get('entity_display.repository'));
    $instance->setTypedDataManager($container->get('typed_data_manager'));
    return $instance;
  }

  /**
   * Set the entity display repository.
   *
   * @param \Drupal\Core\Entity\EntityDisplayRepositoryInterface $entity_display_repository
   *   The entity display repository.
   */
  public function setEntityDisplayRepository(EntityDisplayRepositoryInterface $entity_display_repository) {
    $this->entityDisplayRepository = $entity_display_repository;
  }

  /**
   * Sets the typed data manager.
   *
   * @param \Drupal\Core\TypedData\TypedDataManagerInterface $typed_data_manager
   *   The typed data manager.
   */
  public function setTypedDataManager(TypedDataManagerInterface $typed_data_manager) {
    $this->typedDataManager = $typed_data_manager;
  }

  /**
   * {@inheritdoc}
   */
  public function optionsSummary(&$categories, &$options) {
    parent::optionsSummary($categories, $options);
    $filtered_allow = array_filter($this->getOption('allow'));
    if (isset($filtered_allow['display_type'])) {
      if ($options['allow']['value'] === $this->t('None')) {
        $options['allow']['value'] = $this->t('Display type');
      }
      else {
        $options['allow']['value'] .= ', ' . $this->t('Display type');
      }
    }
    if (isset($filtered_allow['exposed_form'])) {
      if ($options['allow']['value'] === $this->t('None')) {
        $options['allow']['value'] = $this->t('Use exposed form as block configuration');
      }
      else {
        $options['allow']['value'] .= ', ' . $this->t('Use exposed form as block configuration');
      }
    }
    if (isset($filtered_allow['use_pager'])) {
      if ($options['allow']['value'] === $this->t('None')) {
        $options['allow']['value'] = $this->t('Use pager');
      }
      else {
        $options['allow']['value'] .= ', ' . $this->t('Use pager');
      }

      if (isset($filtered_allow['no_pager_by_default'])) {
        $options['allow']['value'] .= ', ' . $this->t('No pager by default');
      }
    }

    $options['magic_arguments'] = [
      'category' => 'block',
      'title' => $this->t('Argument input'),
      'value' => $this->t('Edit'),
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function buildOptionsForm(&$form, FormStateInterface $form_state) {
    parent::buildOptionsForm($form, $form_state);
    switch ($form_state->get('section')) {
      case 'allow':
        $form['allow']['#options']['display_type'] = $this->t('Display type');
        $form['allow']['#options']['exposed_form'] = $this->t('Use exposed form as block configuration');
        $form['allow']['#options']['use_pager'] = $this->t('Use pager');
        $form['allow']['#options']['no_pager_by_default'] = $this->t('No pager by default (only works if "Use pager" is enabled)');
        break;

      case 'magic_arguments':
        $form['#title'] .= $this->t('Argument input');

        $context_options = [];
        foreach ($this->typedDataManager->getDefinitions() as $data_type_id => $data_type_definition) {
          if (in_array($data_type_id, ['any'])) {
            continue;
          }
          if (isset($data_type_definition['no_ui']) && $data_type_definition['no_ui']) {
            continue;
          }
          if (strpos($data_type_id, 'field_item:') === 0) {
            continue;
          }
          $context_options[$data_type_id] = t('@label (@machine_name)', [
            '@label' => $data_type_definition['label'],
            '@machine_name' => $data_type_id,
          ]);
        }
        asort($context_options);

        $defaults = $this->getOption('magic_arguments') ?: [];
        $form['magic_arguments'] = [
          '#tree' => TRUE,
        ];
        foreach ($this->view->getDisplay()->getHandlers('argument') as $id => $handler) {
          $default = $defaults[$id] ?: [];
          $form['magic_arguments'][$id] = [
            '#title' => $handler->adminLabel(),
            '#type' => 'fieldset',
          ];
          $form['magic_arguments'][$id]['type'] = [
            '#title' => $this->t('Type'),
            '#type' => 'select',
            '#options' => [
              'none' => $this->t('No value'),
              'context' => $this->t('From context'),
            ],
            '#default_value' => $default['type'] ?: 'none',
          ];
          $form['magic_arguments'][$id]['context'] = [
            '#title' => $this->t('Required context'),
            '#type' => 'select',
            '#description' => $this->t('If "From context" is selected, which type of context to use.'),
            '#options' => $context_options,
            '#states' => [
              'visible' => [
                ':input[name="magic_arguments[title][type]"]' => ['value' => 'context'],
              ],
            ],
            '#default_value' => $default['context'] ?: '',
          ];
          $form['magic_arguments'][$id]['context_token'] = [
            '#title' => $this->t('Value token'),
            '#type' => 'textfield',
            '#description' => $this->t('Enter a token to get a sub-value from the context entity, using the entity type as a prefix, ex: <code>[node:title]</code> or <code>[node:field_name]</code>. Leave blank if the whole context value should be used.'),
            '#states' => [
              'visible' => [
                ':input[name="magic_arguments[title][type]"]' => ['value' => 'context'],
              ],
            ],
            '#default_value' => $default['context_token'] ?: '',
          ];
          $form['magic_arguments'][$id]['context_optional'] = [
            '#title' => $this->t('Context is optional'),
            '#type' => 'checkbox',
            '#description' => $this->t('This context need not be present for the block to function. If you plan to use this, ensure that the argument handler can handle empty values gracefully.'),
            '#states' => [
              'visible' => [
                ':input[name="magic_arguments[title][type]"]' => ['value' => 'context'],
              ],
            ],
            '#default_value' => (bool) $default['context_optional'] ?: FALSE,
          ];
        }
        break;
    }
  }

  /**
   * Perform any necessary changes to the form values prior to storage.
   *
   * There is no need for this function to actually store the data.
   */
  public function submitOptionsForm(&$form, FormStateInterface $form_state) {
    parent::submitOptionsForm($form, $form_state);
    $section = $form_state->get('section');
    if ($section === 'magic_arguments') {
      $this->setOption($section, $form_state->getValue($section));
    }
  }

  /**
   * {@inheritdoc}
   */
  public function getArgumentText() {
    $text = parent::getArgumentText();
    $text['description'] = $this->t("The contextual filter values are provided by the 'Argument input' configuration. If not configured, no contextual filter value will be available unless you select 'Provide default'.");
    return $text;
  }

  /**
   * {@inheritdoc}
   */
  public function blockForm(ViewsBlock $block, array &$form, FormStateInterface $form_state) {
    $form = parent::blockForm($block, $form, $form_state);

    $form['override']['#type'] = 'container';
    $form['override']['#weight'] = 50;

    $allow_settings = array_filter($this->getOption('allow'));
    $block_configuration = $block->getConfiguration();

    if (!empty($allow_settings['use_pager'])) {
      $form['override']['use_pager'] = [
        '#type' => 'checkbox',
        '#title' => $this->t('Use pager'),
        '#default_value' => $block_configuration['use_pager'] ?? empty($allow_settings['no_pager_by_default']),
        '#weight' => -10,
      ];
    }

    if (!empty($allow_settings['display_type']) && $this->view->getBaseEntityType() !== FALSE) {
      $this->buildBlockFormDisplayType($form, $block_configuration);
    }

    if (!empty($allow_settings['exposed_form'])) {
      $this->buildBlockFormExposedForm($form, $block_configuration);
    }

    return $form;
  }

  /**
   * Builds the 'Display type' part of the block form.
   *
   * @param array $form
   *   The block form.
   * @param array $block_configuration
   *   The block configuration.
   */
  protected function buildBlockFormDisplayType(array &$form, array $block_configuration) {
    $current_row_plugin = $this->getOption('row')['type'];

    // Set to default view settings if there isn't one.
    if (empty($block_configuration['view_settings'])) {
      // Normalize the "entity" row plugin derivatives.
      $block_configuration['view_settings'] = $this->convertViewSettings($current_row_plugin);
    }
    $block_configuration['view_settings'] = $this->convertViewSettings($block_configuration['view_settings']);

    // Add information about the View Mode.
    $form['override']['display_settings']['view_settings'] = [
      '#type' => 'radios',
      '#prefix' => '<div class="view-settings-wrapper">',
      '#suffix' => '</div>',
      '#title' => $this->t('Display Type'),
      '#default_value' => $block_configuration['view_settings'],
      '#weight' => 10,
      '#options' => [
        'fields' => $this->t('Fields'),
        'rendered_entity' => $this->t('Content'),
        'table' => $this->t('Table'),
      ],
    ];

    // Add header column options for table views.
    $form['override']['display_settings']['header_type'] = [
      '#type' => 'select',
      '#title' => $this->t('Column Header'),
      '#options' => [
        'none' => $this->t('None'),
        'titles' => $this->t('Titles'),
      ],
      '#default_value' => !empty($block_configuration['header_type']) ? $block_configuration['header_type'] : 'none',
      '#states' => [
        'visible' => [
          ':input[name="settings[override][display_settings][view_settings]"]' => ['value' => 'table'],
        ],
      ],
      '#weight' => 11,
    ];

    // Update field overrides to be dependent on the view settings selection.
    if (!empty($form['override']['order_fields'])) {
      $form['override']['order_fields']['#weight'] = 15;
      // @note states target js-form-wrapper, which tables do not have by default.
      $form['override']['order_fields']['#attributes']['class'][] = 'js-form-wrapper';
      $form['override']['order_fields']['#attributes']['class'][] = 'form-wrapper';
      $form['override']['order_fields']['#states'] = [
        // The inverted logic here isn't optimal, and in the future may be
        // better achieved via OR'd conditions.
        // @link http://drupal.org/node/735528 @endlink
        'invisible' => [
          ':input[name="settings[override][display_settings][view_settings]"]' => ['value' => 'rendered_entity'],
        ],
      ];
    }

    // Get view modes for entity.
    $view_modes = $this->viewModeOptions($this->view->getBaseEntityType()->id());
    $options_default_view_mode = ($current_row_plugin === 'fields') ? 'teaser' : 'full';
    $row_options = $this->getOption('row');
    if (!empty($row_options['view_mode'])) {
      $options_default_view_mode = $this->getOption('row')['view_mode'];
    }
    if (!array_key_exists($options_default_view_mode, $view_modes)) {
      $options_default_view_mode = key($view_modes);
    }
    // Add specific style options.
    $form['override']['display_settings']['content_settings'] = [
      '#type' => 'container',
      '#states' => [
        'visible' => [
          ':input[name="settings[override][display_settings][view_settings]"]' => ['value' => 'rendered_entity'],
        ],
      ],
      '#weight' => 15,
    ];
    // @todo finish porting visibility on lines 1177-1192.
    $form['override']['display_settings']['content_settings']['view_mode'] = [
      '#type' => 'radios',
      '#title' => $this->t('View mode'),
      '#options' => $view_modes,
      '#default_value' => !empty($block_configuration['view_mode']) ? $block_configuration['view_mode'] : $options_default_view_mode,
    ];
  }

  /**
   * Rewrites the '#states' on exposed Views forms to work on the block form.
   *
   * @param array $element
   *   The Form API element.
   * @param string $parent_string
   *   The string to inject representing the parent of this form element.
   */
  protected function rewriteFormElementStates(array &$element, $parent_string) {
    if (!empty($element['#states'])) {
      foreach ($element['#states'] as $state_name => $state) {
        foreach ($state as $spec_index => $specs) {
          $new_specs = [];
          foreach ($specs as $selector => $value) {
            $selector = preg_replace('/name="([a-zA-Z0-9_]+)/', "name=\"{$parent_string}[\\1]", $selector);
            $new_specs[$selector] = $value;
          }
          $element['#states'][$state_name][$spec_index] = $new_specs;
        }
      }
    }

    foreach (Element::children($element) as $name) {
      $this->rewriteFormElementStates($element[$name], $parent_string);
    }
  }

  /**
   * Builds the exposed form part of the block configuration.
   *
   * @param array $form
   *   The block form.
   * @param array $block_configuration
   *   The block configuration.
   */
  protected function buildBlockFormExposedForm(array &$form, array $block_configuration) {
    // Get the exposed form values into their handlers.
    $this->view->setExposedInput($block_configuration['exposed_form']['filters'] ?? []);
    $this->view->build();

    $form['override']['exposed_form'] = [
      '#type' => 'container',
      '#tree' => TRUE,
    ];
    $filters = $this->getExposedFilters();
    $form['override']['exposed_form']['filters'] = [
      '#type' => 'container',
      '#tree' => TRUE,
      '#access' => count($filters) > 0,
    ];

    $filter_form_state = $this->createFormStateForExposedFilters($this->view->getExposedInput());
    foreach ($filters as $filter) {
      assert($filter instanceof FilterPluginBase);
      $filter->buildExposedForm($form['override']['exposed_form']['filters'], $filter_form_state);

      if (!empty($filter->options['expose']['identifier'])) {
        $identifier = $filter->options['expose']['identifier'];
        $element_name = $identifier;
        if (!empty($filter->options['expose']['use_operator']) && !empty($filter->options['expose']['operator_id'])) {
          $element_name .= "_wrapper";
          $form['override']['exposed_form']['filters'][$identifier . '_wrapper']['#parents'] = [
            'settings',
            'override',
            'exposed_form',
            'filters',
            $identifier,
          ];
        }
        $form['override']['exposed_form']['filters'][$element_name]['#title'] = $filter->options['expose']['label'];
        $this->rewriteFormElementStates($form['override']['exposed_form']['filters'][$element_name], "settings[override][exposed_form][filters][{$identifier}]");
      }
    }

    // Modify the way ctools exposes sorts to match Panopoly 1.x functionality.
    $sorts = array_filter($this->getHandlers('sort'), static function (SortPluginBase $plugin) {
      return $plugin->isExposed();
    });
    $form['override']['exposed_form']['sort'] = [
      '#type' => 'container',
      'sort_order' => [
        '#title' => $this->t('Sort order'),
        '#type' => 'radios',
        '#options' => [
          'ASC' => $this->t('Sort ascending'),
          'DESC' => $this->t('Sort descending'),
        ],
        '#default_value' => $block_configuration['exposed_form']['sort']['sort_order'] ?? 'ASC',
      ],
      'sort_by' => [
        '#title' => $this->t('Sort by'),
        '#type' => 'select',
        '#options' => array_map(static function (ViewsHandlerInterface $plugin) {
          // @todo exposed info label instead
          return $plugin->adminLabel();
        }, $sorts),
        '#default_value' => $block_configuration['exposed_form']['sort']['sort_by'] ?? '',
      ],
      '#access' => count($sorts) > 0,
    ];
  }

  /**
   * Gets the exposed filter handlers.
   *
   * @return \Drupal\views\Plugin\views\filter\FilterPluginBase[]
   *   The exposed filter handlers.
   */
  protected function getExposedFilters() {
    return array_filter($this->getHandlers('filter'), static function (FilterPluginBase $plugin) {
      return $plugin->isExposed();
    });
  }

  /**
   * {@inheritdoc}
   */
  public function blockSubmit(ViewsBlock $block, $form, FormStateInterface $form_state) {
    // Stash the 'items_per_page' so we can restore it later. This is removed
    // from values in \Drupal\views\Plugin\views\display\Block::blockSubmit()
    // which breaks the AJAX submit for preview.
    $items_per_page = $form_state->getValue(['override', 'items_per_page']);

    parent::blockSubmit($block, $form, $form_state);

    // Restore this so AJAX works as it should!
    if ($items_per_page) {
      $form_state->setValue(['override', 'items_per_page'], $items_per_page);
    }

    $configuration = $block->getConfiguration();
    $allow_settings = array_filter($this->getOption('allow'));

    if (!empty($allow_settings['use_pager'])) {
      $use_pager = $form_state->getValue(['override', 'use_pager']);
      $configuration['use_pager'] = (bool) $use_pager;
    }

    if (!empty($allow_settings['display_type'])) {
      $display_settings = $form_state->getValue(['override', 'display_settings']);
      foreach ($display_settings as $setting => $value) {
        // Flatten content_settings.
        if ($setting === 'content_settings') {
          foreach ($value as $k => $v) {
            $configuration[$k] = $v;
          }
        }
        else {
          $configuration[$setting] = $value;
        }
      }
    }

    if (!empty($allow_settings['exposed_form'])) {
      $sort = $form_state->getValue(['override', 'exposed_form', 'sort']);
      foreach ($sort as $setting => $value) {
        $configuration['exposed_form']['sort'][$setting] = $value;
      }

      $filter_values = $form_state->getValue([
        'override',
        'exposed_form',
        'filters',
      ]);
      foreach ($this->getExposedFilters() as $filter) {
        if (empty($filter->options['expose']['identifier'])) {
          continue;
        }
        $identifier = $filter->options['expose']['identifier'];

        if (!empty($filter->options['expose']['use_operator']) && !empty($filter->options['expose']['operator_id'])) {
          $operator = $filter->options['expose']['operator_id'];

          $configuration['exposed_form']['filters'][$identifier] = $filter_values[$identifier][$identifier];
          $configuration['exposed_form']['filters'][$operator] = $filter_values[$identifier][$operator];
        }
        else {
          $configuration['exposed_form']['filters'][$identifier] = $filter_values[$identifier];
        }
      }
    }
    $block->setConfiguration($configuration);
  }

  /**
   * {@inheritdoc}
   */
  public function preBlockBuild(ViewsBlock $block) {
    $config = $block->getConfiguration();
    [, $display_id] = explode('-', $block->getDerivativeId(), 2);

    // @see panopoly_magic_views_pre_view().
    $allow_settings = array_filter($this->getOption('allow'));
    if (!empty($allow_settings['display_type']) && !empty($config['view_settings'])) {
      $view_settings = $this->convertViewSettings($config['view_settings']);
      $view_entity_type = $this->view->getBaseEntityType();

      // Set the style plugin to a table style.
      // Determine that this was previously a field view, which has been
      // overridden to a node view in the pane config.
      if ($view_settings === 'rendered_entity' && $view_entity_type) {
        $this->options['defaults']['row'] = FALSE;
        $this->options['row']['type'] = 'entity:' . $view_entity_type->id();
        if (!empty($config['view_mode'])) {
          // Transfer over the row options from default if set to use.
          if (!empty($this->options['defaults']['row_options'])) {
            $this->options['defaults']['row_options'] = FALSE;
          }
          $this->options['row']['options']['view_mode'] = $config['view_mode'];
        }
      }
      elseif ($view_settings === 'fields') {
        $this->options['defaults']['row'] = FALSE;
        $this->options['row']['type'] = 'fields';
      }
      elseif ($view_settings === 'table') {
        // Find the currently active field definition, else break out as table
        // needs fields.
        if (!empty($this->options['fields'])) {
          $fields = &$this->options['fields'];
        }
        elseif (empty($this->default_display->options['defaults']['fields']) && isset($this->view->display_handler->options['fields'])) {
          $fields = &$this->default_display->options['fields'];
        }
        else {
          // If no fields, don't try to display as table.
          return;
        }

        $this->options['defaults']['style'] = FALSE;
        $this->options['style']['type'] = 'table';

        // Set or remove header labels depending on user selection.
        $use_header_titles = !empty($config['header_type']) && $config['header_type'] === 'titles';
        foreach ($fields as $field_key => &$field) {
          if ($use_header_titles && !empty($field['admin_label']) && empty($field['label'])) {
            $field['label'] = $field['admin_label'];
          }
          elseif (!$use_header_titles) {
            $field['label'] = '';
          }
          // Hide empty columns.
          if (!empty($this->options['row']['hide_empty'])) {
            $this->options['style'][$field_key]['empty_column'] = TRUE;
          }
        }
        unset($field);
      }
    }

    // The ctools Block plugin invokes the style plugin and instantiates it
    // first, so we run it after we've adjusted row and style options.
    parent::preBlockBuild($block);

    if (!empty($allow_settings['use_pager'])) {
      // Disable pager if configured to not "Use pager".
      $use_pager = $config['use_pager'] ?? empty($allow_settings['no_pager_by_default']);
      if (!$use_pager) {
        $pager = $this->view->display_handler->getOption('pager');
        if (!empty($pager) && !in_array($pager['type'], ['none', 'some'])) {
          $pager['type'] = 'some';
          $this->view->display_handler->setOption('pager', $pager);
        }
      }
    }

    if (!empty($allow_settings['exposed_form'])) {
      // Add exposed filter values.
      $filter_values = $config['exposed_form']['filters'] ?? [];
      foreach ($this->getExposedFilters() as $filter) {
        if ($this->filterHasValue($filter, $filter_values) && $this->filterValidateExposed($filter, $filter_values)) {
          // The values were accepted. Make it no longer exposed, in order to
          // prevent it being rendered on the form.
          $filter->options['exposed'] = FALSE;
        }
        elseif (empty($filter->options['expose']['required'])) {
          // The values weren't accepted, so remove the filter entirely.
          $filter_name = $filter->options['id'];
          $this->view->removeHandler($display_id, 'filter', $filter_name);
          unset($this->handlers['filter'][$filter_name]);
        }
      }

      // Only use the selected exposed sort.
      if (!empty($config['exposed_form']['sort'])) {
        $sort_order = $config['exposed_form']['sort']['sort_order'];
        $sort_by = $config['exposed_form']['sort']['sort_by'];
      }
      else {
        $sort_order = $sort_by = [];
      }
      $sorts = $this->view->getHandlers('sort', $display_id);
      foreach ($sorts as $sort_name => $sort) {
        if (empty($sort['exposed'])) {
          continue;
        }
        if ($sort_name !== $sort_by) {
          $this->view->removeHandler($display_id, 'sort', $sort_name);
          unset($this->handlers['sort'][$sort_name]);
        }
        else {
          $sort['order'] = $sort_order;
          $sort['exposed'] = FALSE;
          $this->view->setHandler($display_id, 'sort', $sort_name, $sort);
        }
      }
    }
  }

  /**
   * Creates a form state for exposed filters.
   *
   * @param array $filter_values
   *   The filter values.
   *
   * @return \Drupal\Core\Form\FormState
   *   The form state.
   */
  protected function createFormStateForExposedFilters(array $filter_values): FormState {
    $filter_form_state = (new FormState())
      ->setStorage([
        'view' => $this->view,
        'display' => &$this->view->display_handler->display,
        'rerender' => TRUE,
      ])
      ->setMethod('get')
      ->setAlwaysProcess()
      ->disableRedirect()
      ->setUserInput($filter_values)
      ->setValues($filter_values)
      ->set('exposed', TRUE);

    return $filter_form_state;
  }

  /**
   * Checks if the given filter has a value in the given array of values.
   *
   * @param \Drupal\views\Plugin\views\filter\FilterPluginBase $filter
   *   The filter.
   * @param array $filter_values
   *   The values to check.
   *
   * @return bool
   *   Returns TRUE if a value is found; otherwise FALSE.
   */
  protected function filterHasValue($filter, array $filter_values): bool {
    $identifier = $filter->options['expose']['identifier'];
    if (!isset($filter_values[$identifier])) {
      return FALSE;
    }

    if (!empty($filter->options['expose']['use_operator']) && !empty($filter->options['expose']['operator_id'])) {
      $operator = $filter->options['expose']['operator_id'];
      if (!isset($filter_values[$operator])) {
        return FALSE;
      }
    }

    return TRUE;
  }

  /**
   * Validates the given filter as if it were submitted on a form.
   *
   * @param \Drupal\views\Plugin\views\filter\FilterPluginBase $filter
   *   The filter.
   * @param array $filter_values
   *   The values to check.
   *
   * @return bool
   *   Returns TRUE if a value is found; otherwise FALSE.
   */
  protected function filterValidateExposed($filter, array $filter_values): bool {
    $form = [];
    $form_state = $this->createFormStateForExposedFilters($filter_values);
    $filter->buildExposedForm($form, $form_state);

    $filter->validateExposed($form, $form_state);

    return $filter->acceptExposedInput($filter_values);
  }

  /**
   * Convert with legacy 'nodes' and others (such as 'files') view settings.
   *
   * @todo copy and paste; used to help handle `entity:` derivatives.
   *
   * @param string $view_setting
   *   The view setting value.
   *
   * @return string
   *   The converted setting value.
   */
  protected function convertViewSettings(string $view_setting): string {
    // The 'fields' and 'table' view settings apply to any entity type.
    if (in_array($view_setting, ['fields', 'table'])) {
      return $view_setting;
    }

    // We convert other view settings to 'rendered_entity' (which could be
    // 'entity:node' or 'entity:file' and others specific to an entity type).
    return 'rendered_entity';
  }

  /**
   * Get view mode options for an entity type.
   *
   * @param string $id
   *   The entity type ID.
   *
   * @return array
   *   The view mode options.
   */
  protected function viewModeOptions(string $id): array {
    $options = $this->entityDisplayRepository->getViewModeOptions($id);
    // When selecting full, locally the site becomes unavailable with a 502
    // gateway timeout. Default and full should be the same.
    unset($options['full']);
    return $options;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc