htools-8.x-1.x-dev/src/Plugin/views/display/LayoutBuilder.php

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

namespace Drupal\htools\Plugin\views\display;

use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Path\CurrentPathStack;
use Drupal\Core\Url;
use Drupal\path_alias\AliasManagerInterface;
use Drupal\views\Plugin\views\display\DisplayPluginBase;
use Drupal\views\Plugin\views\display\DisplayRouterInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\RouteCollection;

/**
 * The plugin that handles an embed display.
 *
 * @ingroup views_display_plugins
 *
 * @todo: Wait until annotations/plugins support access methods.
 * no_ui => !\Drupal::config('views.settings')->get('ui.show.display_embed'),
 *
 * @ViewsDisplay(
 *   id = "layout_builder",
 *   title = @Translation("Layout Builder"),
 *   help = @Translation("Provide a display which can be embedded using the
 *   views api."), theme = "views_view", uses_hook_block = FALSE,
 *   uses_menu_links = FALSE
 * )
 */
class LayoutBuilder extends DisplayPluginBase implements DisplayRouterInterface {

  /**
   * Current path.
   *
   * @var \Drupal\Core\Path\CurrentPathStack
   */
  protected $currentPath;

  /**
   * PrismaEmbed::aliasManager.
   *
   * @var \Drupal\Core\Path\AliasManagerInterface
   */
  protected $aliasManager;

  /**
   * {@inheritdoc}
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, CurrentPathStack $currentPath, AliasManagerInterface $aliasManager) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->currentPath = $currentPath;
    $this->aliasManager = $aliasManager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('path.current'),
      $container->get('path_alias.manager')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function optionsSummary(&$categories, &$options) {
    parent::optionsSummary($categories, $options);

    $categories['page'] = [
      'title' => $this->t('Page settings'),
      'column' => 'second',
      'build' => [
        '#weight' => -10,
      ],
    ];

    if ($this->getOption('path') === TRUE) {
      $path = '';
    }
    else {
      $path = strip_tags($this->getOption('path'));
    }


    if (empty($path)) {
      $path = $this->t('No path is set (Current url will be use)');
    }
    else {
      $path = '/' . $path;
    }

    $options['path'] = [
      'category' => 'page',
      'title' => $this->t('Path'),
      'value' => views_ui_truncate($path, 50),
    ];

    $regions = [];
    foreach ($this->getOption('regions') as $reg => $v) {
      if ($v) {
        $regions[] = $reg;
      }
    }
    $options['regions'] = [
      'category' => 'page',
      'title' => $this->t('Regions'),
      'value' => !empty($regions) ? implode(', ', $regions) : 'configure',
    ];

  }

  /**
   * {@inheritdoc}
   */
  public function buildOptionsForm(&$form, FormStateInterface $form_state) {
    parent::buildOptionsForm($form, $form_state);

    switch ($form_state->get('section')) {
      case 'path':
        $url = Url::fromRoute('<none>', [], ['absolute' => TRUE]);
        $form['#title'] .= $this->t('The menu path or URL of this view');
        $form['path'] = [
          '#type' => 'textfield',
          '#title' => $this->t('Path'),
          '#description' => $this->t('This view will be displayed by visiting this path on your site. You may use "%" in your URL to represent values that will be used for contextual filters: For example, "node/%/feed". If needed you can even specify named route parameters like taxonomy/term/%taxonomy_term'),
          '#default_value' => $this->getOption('path'),
          '#field_prefix' => '<span dir="ltr">' . $url->toString(),
          '#field_suffix' => '</span>&lrm;',
          '#attributes' => ['dir' => LanguageInterface::DIRECTION_LTR],
          // Account for the leading backslash.
          '#maxlength' => 254,
        ];
        break;
      case 'regions':
        $form['#title'] .= $this->t('The regions of view to want to show or hide');
        $regions = static::getRegions();
        $default = array_filter($this->getOption('regions'));
        $form['regions'] = [
          '#type' => 'checkboxes',
          '#title' => $this->t('View Regions'),
          '#default_value' => array_keys($default),
          '#options' => $regions,
        ];
        break;
    }
  }

  public static function getRegions() {
    return [
      'header' => t('Header'),
      'footer' => t('Footer'),
      'empty' => t('Empty'),
      'exposed' => t('Exposed form'),
      'more' => t('More link'),
      'feed_icons' => t('Feed Icons'),
      'rows' => t('Rows of content'),
      'pager' => t('Pager'),
      'attachment_before' => t('Attachment before'),
      'attachment_after' => t('Attachment after'),
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function validateOptionsForm(&$form, FormStateInterface $form_state) {
    parent::validateOptionsForm($form, $form_state);

    if ($form_state->get('section') == 'path') {
      $errors = $this->validatePath($form_state->getValue('path'));
      foreach ($errors as $error) {
        $form_state->setError($form['path'], $error);
      }

      // Automatically remove '/' and trailing whitespace from path.
      $form_state->setValue('path', trim($form_state->getValue('path'), '/ '));
    }
  }

  /**
   * Validates the path of the display.
   *
   * @param string $path
   *   The path to validate.
   *
   * @return array
   *   A list of error strings.
   */
  protected function validatePath($path) {
    $errors = [];
    if (strpos($path, '%') === 0) {
      $errors[] = $this->t('"%" may not be used for the first segment of a path.');
    }

    $parsed_url = UrlHelper::parse($path);

    if (!empty($parsed_url['query'])) {
      $errors[] = $this->t('No query allowed.');
    }

    if (!parse_url('internal:/' . $path)) {
      $errors[] = $this->t('Invalid path. Valid characters are alphanumerics as well as "-", ".", "_" and "~".');
    }

    $path_sections = explode('/', $path);
    // Symfony routing does not allow to use numeric placeholders.
    // @see \Symfony\Component\Routing\RouteCompiler
    $numeric_placeholders = array_filter($path_sections, function ($section) {
      return (preg_match('/^%(.*)/', $section, $matches)
        && is_numeric($matches[1]));
    });
    if (!empty($numeric_placeholders)) {
      $errors[] = $this->t("Numeric placeholders may not be used. Please use plain placeholders (%).");
    }
    return $errors;
  }

  /**
   * {@inheritdoc}
   */
  public function submitOptionsForm(&$form, FormStateInterface $form_state) {
    parent::submitOptionsForm($form, $form_state);

    if ($form_state->get('section') === 'path') {
      $this->setOption('path', $form_state->getValue('path'));
    }
    if ($form_state->get('section') === 'regions') {
      $this->setOption('regions', $form_state->getValue('regions'));
    }
  }

  /**
   * {@inheritdoc}
   */
  public function buildRenderable(array $args = [], $cache = TRUE) {
    $build = parent::buildRenderable($args, $cache);
    $build['#embed'] = TRUE;
    return $build;
  }

  /**
   * {@inheritdoc}
   */
  public function hasPath() {
    return FALSE;
  }

  /**
   * {@inheritdoc}
   */
  public function elementPreRender(array $element) {
    $element = parent::elementPreRender($element);
    $regions = $this->getOption('regions');
    foreach ($regions as $reg => $v) {
      if (!$v) {
        unset($element['#' . $reg]);
      }
    }
    if (!empty($element['#exposed']) && empty($element['#exposed']['#build_id'])) {
      foreach ($element['#exposed'] as $key => $region) {
        $element['#exposed_region_' . $key] = $region;
      }
      unset($element['#exposed']);
    }
    return $element;
  }

  /**
   * {@inheritdoc}
   */
  public function execute() {
    // Prior to this being called, the $view should already be set to this
    // display, and arguments should be set on the view.
    $this->view->build();

    if (!empty($this->view->build_info['fail'])) {
      throw new NotFoundHttpException();
    }

    if (!empty($this->view->build_info['denied'])) {
      throw new AccessDeniedHttpException();
    }

    // And now render the view.
    $render = $this->view->render();

    return $render;
  }

  /**
   * {@inheritdoc}
   */
  public function collectRoutes(RouteCollection $collection) {
    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function alterRoutes(RouteCollection $collection) {
    $view_route_names = [];
    return $view_route_names;
  }

  /**
   * {@inheritdoc}
   */
  public function getUrlInfo() {
    $url = Url::fromUserInput($this->getPath());
    return $url;
  }

  /**
   * {@inheritdoc}
   */
  public function getPath() {
    $path = $this->getOption('path');
    if (empty($path)) {
      $useAjax = $this->usesAJAX();

      if ($useAjax) {
        $request = $this->view->getRequest();
        $params = $request->request->all();

        // @TODO Read POST parameters from request object.
        if (!empty($params['ajax_page_state']) &&
          !empty($_POST['view_base_path'])) {
          $path = $_POST['view_base_path'];
        }
      }
    }
    if (empty($path)) {
      $current_path = $this->currentPath->getPath();
      $path = $this->aliasManager->getAliasByPath($current_path);
    }
    return $path;
  }

  /**
   * {@inheritdoc}
   */
  public function getRouteName() {
    // return empty routename for fix exposed form action url.
    return '';
    $url = Url::fromUserInput($this->getPath());
    return $url->getRouteName();
  }

  /**
   * {@inheritdoc}
   */
  public function getAlteredRouteNames() {
    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function render() {
    $build = parent::render();
    $exposed_form_plugin_id = $this->view->display_handler->getPlugin('exposed_form')->getPluginId();
    if ($exposed_form_plugin_id === 'exposed_form_region') {
      $build['#theme'] = 'views_view__layout_builder__efr';
    }
    return $build;
  }

  /**
   * {@inheritdoc}
   */
  protected function defineOptions() {
    $options = parent::defineOptions();
    $options['path'] = ['default' => ''];
    $options['regions'] = [
      'default' => [
        'header' => TRUE,
        'footer' => TRUE,
        'empty' => TRUE,
        'exposed' => TRUE,
        'more' => TRUE,
        'feed_icons' => TRUE,
        'rows' => TRUE,
        'pager' => TRUE,
        'attachment_before' => TRUE,
        'attachment_after' => TRUE,
      ],
    ];

    return $options;
  }
}

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

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