display_builder-1.0.x-dev/modules/display_builder_views/src/Plugin/views/display_extender/DisplayBuilder.php

modules/display_builder_views/src/Plugin/views/display_extender/DisplayBuilder.php
<?php

declare(strict_types=1);

namespace Drupal\display_builder_views\Plugin\views\display_extender;

use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\Context\EntityContext;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Url;
use Drupal\display_builder\DisplayBuilderHelpers;
use Drupal\display_builder\Entity\DisplayBuilder as DisplayBuilderConfigEntity;
use Drupal\display_builder_views\DisplayBuilderViewsManager;
use Drupal\ui_patterns\Plugin\Context\RequirementsContext;
use Drupal\views\Attribute\ViewsDisplayExtender;
use Drupal\views\Plugin\views\display_extender\DisplayExtenderPluginBase;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Styles display extender plugin.
 *
 * @ingroup views_display_extender_plugins
 */
#[ViewsDisplayExtender(
  id: 'display_builder',
  title: new TranslatableMarkup('Display builder extender'),
  help: new TranslatableMarkup('Use display builder as output for this view.'),
  no_ui: FALSE,
)]
class DisplayBuilder extends DisplayExtenderPluginBase {

  private const VIEWS_PREFIX = 'views_';

  /**
   * The display builder storage.
   *
   * @var \Drupal\Core\Entity\EntityStorageInterface
   */
  protected $displayBuilderConfigStorage;

  /**
   * The display builder state manager.
   *
   * @var \Drupal\display_builder\StateManager\StateManagerInterface
   */
  protected $stateManager;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): self {
    $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
    $instance->displayBuilderConfigStorage = $container->get('entity_type.manager')->getStorage('display_builder');
    $instance->stateManager = $container->get('display_builder.state_manager');

    return $instance;
  }

  /**
   * {@inheritdoc}
   *
   * @phpstan-ignore-next-line
   */
  public function buildOptionsForm(&$form, FormStateInterface $form_state): void {
    if ($form_state->get('section') !== 'display_builder') {
      return;
    }

    $form['#title'] .= $this->t('Display Builder');

    $display_builder_id = $this->options['display_builder_id'] ?? NULL;

    // @todo no change or selection for now, just inform about the builder id.
    if ($display_builder_id) {
      $url = Url::fromRoute('display_builder_views.views.manage', ['builder_id' => $display_builder_id]);
      $options = [
        $display_builder_id => $display_builder_id,
        '_none' => $this->t('Disable (Detach existing builder)'),
      ];
      $form['display_builder_id'] = [
        '#type' => 'select',
        '#title' => $this->t('Display Builder'),
        '#description' => $this->t('Display builder used to manage this view. <a href="@url" target="_blank">Edit here</a>', ['@url' => $url->toString()]),
        '#options' => $options,
        '#default_value' => $display_builder_id,
        '#required' => TRUE,
      ];
    }
    else {
      $form['display_builder_id'] = [
        '#type' => 'select',
        '#title' => $this->t('Display Builder'),
        '#description' => $this->t('Create the associated Display Builder or ignore.'),
        '#options' => ['_new' => $this->t('Create the display Builder'), '_none' => $this->t('None (Ignore)')],
        '#default_value' => '_new',
        '#required' => TRUE,
      ];
    }

    $builder_config_id = $this->options['builder_config_id'] ?? DisplayBuilderConfigEntity::DISPLAY_BUILDER_CONFIG;

    $displayBuilderConfig = $this->displayBuilderConfigStorage->loadMultiple();

    $options = [];

    foreach ($displayBuilderConfig as $entityId => $configEntity) {
      $options[$entityId] = $configEntity->label();
    }

    $form['builder_config_id'] = [
      '#type' => 'select',
      '#title' => $this->t('Default display builder config'),
      '#description' => $this->t('Display builder configuration used when editing the associated display builder.'),
      '#options' => $options,
      '#default_value' => $builder_config_id,
    ];
  }

  /**
   * {@inheritdoc}
   *
   * @phpstan-ignore-next-line
   */
  public function submitOptionsForm(&$form, FormStateInterface $form_state): void {
    if ($form_state->get('section') !== 'display_builder') {
      return;
    }

    $display_builder_id = $form_state->getValue('display_builder_id');

    if ($display_builder_id === '_none') {
      unset($this->options['builder_config_id'], $this->options['display_builder_id']);

      return;
    }

    $builder_config_id = $form_state->getValue('builder_config_id');
    $this->options['builder_config_id'] = $builder_config_id;

    // Create a new display builder and set empty data in the view display
    // option. Add view uuid to allow save with ON_SAVE event.
    if ($display_builder_id === '_new') {
      $display_builder_id = \sprintf('%s%s', self::VIEWS_PREFIX, uniqid());

      $contexts = [];
      // Mark for usage with views.
      $contexts = RequirementsContext::addToContext([DisplayBuilderViewsManager::VIEWS_CONTEXT_REQUIREMENT], $contexts);
      // Add view entity that we need in our sources or even UI Patterns Views
      // sources.
      $contexts['ui_patterns_views:view_entity'] = EntityContext::fromEntity($this->view->storage->load($this->view->id()));

      // Get fixtures if exist, fallback to default mimicking the standard view
      // blocks without markup.
      $builder_data = DisplayBuilderHelpers::getFixtureDataFromModule('display_builder_views');
      $this->stateManager->create($display_builder_id, $builder_config_id, $builder_data, $contexts);
    }

    // Re-set even if change is not yet allowed.
    $this->options['display_builder_id'] = $display_builder_id;
  }

  /**
   * {@inheritdoc}
   *
   * @phpstan-ignore-next-line
   */
  public function optionsSummary(&$categories, &$options): void {
    if (!$this->isApplicable()) {
      return;
    }
    $is_display_builder = FALSE;

    if (isset($this->options['display_builder_id'])) {
      $is_display_builder = $this->options['display_builder_id'];
    }

    $options['display_builder'] = [
      'category' => 'other',
      'title' => $this->t('Display Builder'),
      'desc' => $this->t('Use display builder as output for this view.'),
      'value' => $is_display_builder ? $this->t('Yes') : $this->t('No'),
    ];
  }

  /**
   * If display builder can be applied to this display.
   *
   * @return bool
   *   Applicable or not.
   */
  private function isApplicable(): bool {
    $display = $this->view->getDisplay();
    $display_definition = $display->getPluginDefinition();

    // @phpstan-ignore-next-line
    if (!isset($display_definition['class'])) {
      return FALSE;
    }

    // Do not include with feed and entity reference, as they have no output to
    // apply a display builder to.
    if ($display_definition['class'] === 'Drupal\views\Plugin\views\display\Feed') {
      return FALSE;
    }

    if ($display_definition['class'] === 'Drupal\views\Plugin\views\display\EntityReference') {
      return FALSE;
    }

    // @todo safer to not allow third party display?
    // phpcs:disable
    // if (str_contains($display_definition['class'], 'Drupal\views\Plugin\views\display')) {
    //   return FALSE;
    // }
    // phpcs:enable

    return TRUE;
  }

}

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

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