htools-8.x-1.x-dev/modules/htools_entity_views_filter/src/Form/EntityViewsFilterForm.php

modules/htools_entity_views_filter/src/Form/EntityViewsFilterForm.php
<?php

namespace Drupal\htools_entity_views_filter\Form;

use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Ajax\ReplaceCommand;
use Drupal\Core\Entity\ContentEntityForm;
use Drupal\Core\EventSubscriber\AjaxResponseSubscriber;
use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
use Drupal\Core\Form\FormBuilder;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\Core\Render\Element;
use Drupal\Core\Render\RenderContext;
use Drupal\Core\Url;
use Drupal\htools_entity_views_filter\Entity\EntityViewsFilterType;
use Drupal\views\Ajax\ScrollTopCommand;
use Drupal\views\Ajax\ViewAjaxResponse;
use Drupal\views\Entity\View;
use Drupal\views\ViewExecutable;
use Drupal\views\Views;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

/**
 * Form controller for Entity views filter edit forms.
 *
 * @ingroup entity_views_filter
 */
class EntityViewsFilterForm extends ContentEntityForm {

  /**
   * The current user account.
   *
   * @var \Drupal\Core\Session\AccountProxyInterface
   */
  protected $account;

  /**
   * The factory to load a view executable with.
   *
   * @var \Drupal\views\ViewExecutableFactory
   */
  protected $executableFactory;

  /**
   * The renderer.
   *
   * @var \Drupal\Core\Render\RendererInterface
   */
  protected $renderer;

  /**
   * True when the build of the form is in the refresh method.
   *
   * @var bool
   */
  protected $ajaxRefreshing;

  /**
   * The form builder.
   *
   * @var \Drupal\Core\Form\FormBuilderInterface
   */
  protected $formBuilder;

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

  /**
   * The request stack.
   *
   * @var \Symfony\Component\HttpFoundation\RequestStack
   */
  protected $requestStack;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    // Instantiates this form class.
    $instance = parent::create($container);
    $instance->account = $container->get('current_user');
    $instance->executableFactory = $container->get('views.executable');
    $instance->renderer = $container->get('renderer');
    $instance->ajaxRefreshing = FALSE;
    $instance->formBuilder = $container->get('form_builder');
    $instance->currentPath = $container->get('path.current');
    $instance->requestStack = $container->get('request_stack');
    return $instance;
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    $form_id = parent::getFormId();
    if ($this->ajaxRefreshing === FALSE) {
      return $form_id;
    }
    return $form_id . '_form_ajax_refreshing';
  }

  /**
   *
   */
  public function setAjaxRefreshing($state) {
    $this->ajaxRefreshing = $state;
  }

  /**
   *
   */
  public function getAjaxRefreshing() {
    return $this->ajaxRefreshing;
  }

  /**
   * {@inheritdoc}
   */
  public function processForm($element, FormStateInterface $form_state, $form) {
    $element = parent::processForm($element, $form_state, $form);
    if ($this->ajaxRefreshing === FALSE) {
      return $element;
    }
    $form_id = parent::getFormId();
    $element['#form_id'] = $form_id;
    unset($element['#id']);
    $this->formBuilder->prepareForm($form_id, $element, $form_state);
    return $element;
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    // Remove button and internal Form API values from submitted values.
    $form_state->cleanValues();
    $this->entity = $this->buildEntity($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function form(array $form, FormStateInterface $form_state) {
    $form = parent::form($form, $form_state);
    $form['#action'] = $this->buildFormAction();
    return $form;
  }

  /**
   * Builds the $form['#action'].
   *
   * @return string
   *   The URL to be used as the $form['#action'].
   */
  protected function buildFormAction() {
    // @todo Use <current> instead of the master request in
    //   https://www.drupal.org/node/2505339.
    $request = $this->requestStack->getMainRequest();
    $request_uri = $request->getRequestUri();

    // Prevent cross site requests via the Form API by using an absolute URL
    // when the request uri starts with multiple slashes..
    if (strpos($request_uri, '//') === 0) {
      $request_uri = $request->getUri();
    }

    // @todo Remove this parsing once these are removed from the request in
    //   https://www.drupal.org/node/2504709.
    $parsed = UrlHelper::parse($request_uri);
    unset($parsed['query'][FormBuilder::AJAX_FORM_REQUEST], $parsed['query'][MainContentViewSubscriber::WRAPPER_FORMAT]);
    return $parsed['path'];
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $bundle = EntityViewsFilterType::load($this->entity->bundle());
    if ($bundle === NULL) {
      return parent::buildForm($form, $form_state);
    }
    /* @var \Drupal\htools_entity_views_filter\Entity\EntityViewsFilter $entity */
    $form = parent::buildForm($form, $form_state);

    if (!empty($bundle->get('autosubmit_exclude_textfield'))) {
      foreach (Element::children($form) as $element) {
        if (isset($form[$element]['#type']) && $form[$element]['#type'] === 'textfield') {
          $form[$element]['#attributes'] = ['data-evf-auto-submit-exclude' => ''];
        }
      }
    }

    // Apply auto-submit values.
    if (!empty($bundle->get('autosubmit'))) {
      $form['#attached']['library'][] = 'htools_entity_views_filter/autosubmit';
      $form = array_merge_recursive($form, [
        '#attributes' => [
          'data-evf-auto-submit-full-form' => '',
          'data-evf-auto-submit' => '',
        ],
      ]);
    }

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function actions(array $form, FormStateInterface $form_state) {
    $actions = parent::actions($form, $form_state);
    $bundle = EntityViewsFilterType::load($this->entity->bundle());
    if ($bundle === NULL) {
      return $actions;
    }
    $submit_button = $bundle->get('submit_button') ? $bundle->get('submit_button') : 'Search';
    $actions['submit']['#value'] = $this->t($submit_button);

    // Apply auto-submit values.
    if (!empty($bundle->get('autosubmit'))) {
      $actions['submit']['#attributes']['data-evf-auto-submit-click'] = '';
      if (!empty($bundle->get('autosubmit_hide'))) {
        $actions['submit']['#attributes']['class'][] = 'js-hide';
      }
    }

    // Apply ajax-submit values.
    $view = $form_state->get('view');
    if ($view instanceof ViewExecutable && !empty($view->display_handler) && $view->display_handler->ajaxEnabled() === TRUE) {
      $actions['submit']['#ajax'] = [
        'callback' => [$this, 'refresh'],
        'submit' => ['view_dom_id' => $view->dom_id],
      ];
    }

    return $actions;
  }

  /**
   * {@inheritdoc}
   */
  public function save(array $form, FormStateInterface $form_state) {
    $view_instance = $form_state->get('view');
    $entity = $this->entity;
    $status = parent::save($form, $form_state);
    $bundle = EntityViewsFilterType::load($this->entity->bundle());
    $view_name = $bundle->get('view_name');
    $view_display_id = $bundle->get('view_display_id');
    /** @var \Drupal\views\ViewExecutable $view */
    $view = Views::getView($view_name);
    $view->build($view_display_id);
    $filters = $view->getHandlers('filter');
    $view_url = $view->getPath();
    $field_mapping = $bundle->get('field_mapping');

    $querystring = [];
    foreach ($filters as $filter_id => $filter) {
      if ($filter['exposed'] === TRUE) {
        $field_name = $field_mapping[$filter_id]['field_name'];
        if ($entity->get($field_name)->isEmpty()) {
          continue;
        }
        $field_property = $field_mapping[$filter_id]['field_property'];
        $values = $entity->get($field_name)->getValue();

        $identifier = $filter['expose']['identifier'];
        if (!empty($values)) {
          if ($values[0][$field_property] == '0') {
            $querystring[$identifier] = 'All';
          }
          elseif ($filter['expose']['multiple'] == 1) {
            if (count($values) > 1) {
              foreach ($values as $rawvalue) {
                $value = $rawvalue[$field_property];
                $querystring[$identifier][$value] = $value;
              }
            }
            else {
              $value = $values[0][$field_property];
              $querystring[$identifier][$value] = $value;
            }
          }
          else {
            $value = $values[0][$field_property];
            $querystring[$identifier] = $value;
          }
        }
        elseif (isset($querystring)) {
          unset($querystring[$identifier]);
        }
      }
    }
    $sorts = ['sort_by', 'sort_order', 'sort_bef_combine'];
    foreach ($sorts as $sort_id) {
      if (!empty($field_mapping[$sort_id]['field_name'])) {
        $field_name = $field_mapping[$sort_id]['field_name'];
        $field_property = $field_mapping[$sort_id]['field_property'];
        $values = $entity->get($field_name)->getValue();
        $querystring[$field_name] = !empty($values[0][$field_property]) ? $values[0][$field_property] : '';
        if ($view_instance instanceof ViewExecutable && !empty($view_instance->display_handler) && $view_instance->display_handler->ajaxEnabled() === FALSE && $entity->get($field_name)
          ->isEmpty()) {
          unset($querystring[$field_name]);
        }
      }
    }

    if ($view_instance instanceof ViewExecutable && !empty($view_instance->display_handler) && $view_instance->display_handler->ajaxEnabled() === TRUE) {
      $form_state->set('exposed_values', $querystring);
      return $status;
    }

    $redirect_path = '/' . $view_url . '?' . http_build_query($querystring);
    $url = Url::fromUserInput($redirect_path);
    $form_state->setRedirectUrl($url);
    return $status;
  }

  /**
   * Ajax callback to refresh views.
   *
   * @param array $form
   *   The form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   *
   * @return \Drupal\Core\Ajax\AjaxResponse
   *   The response.
   *
   * @throws \Drupal\Core\Entity\EntityStorageException
   */
  public function refresh(array $form, FormStateInterface $form_state) {
    $bundle = EntityViewsFilterType::load($this->entity->bundle());
    /** @var \Drupal\views\ViewExecutable $view_instance */
    $view_instance = $form_state->get('view');
    /** @var \Drupal\views\Plugin\views\cache\CachePluginBase $cache_plugin */
    $cache_plugin = $view_instance->display_handler->getPlugin('cache');
    $cache_plugin->getCacheBackend()
      ->invalidate($cache_plugin->generateResultsKey());
    $exposed_values = $form_state->get('exposed_values');
    $inputs = $form_state->getUserInput();
    $dom_id = $inputs['view_dom_id'];

    $request = $this->requestStack->getMasterRequest();
    $keys = [
      'view_name',
      'view_display_id',
      'view_args',
      'view_path',
      'view_dom_id',
      'pager_element',
      'view_base_path',
      AjaxResponseSubscriber::AJAX_REQUEST_PARAMETER,
      FormBuilderInterface::AJAX_FORM_REQUEST,
      MainContentViewSubscriber::WRAPPER_FORMAT,
    ];
    foreach ($keys as $key) {
      $request->query->remove($key);
      $request->request->remove($key);
    }

    // Add all POST data, because AJAX is always a post and many things,
    // such as tablesorts, exposed filters and paging assume GET.
    $query_all = $request->query->all();
    foreach ($exposed_values as $k => $v) {
      if (!empty($v)) {
        $query_all[$k] = $v;
      }
      elseif (isset($query_all[$k])) {
        unset($query_all[$k]);
      }
    }
    $request->query->replace($query_all);

    $response = new ViewAjaxResponse();
    $name = $bundle->get('view_name');
    $display_id = $bundle->get('view_display_id');
    // Load the view.
    if (!$entity = View::load($name)) {
      throw new NotFoundHttpException();
    }
    $view = $this->executableFactory->get($entity);
    if ($view && $view->access($display_id) && $view->setDisplay($display_id) && $view->display_handler->ajaxEnabled()) {
      $view->ajaxRefreshing = TRUE;
      $args = $view_instance->args;
      $view->setArguments($args);
      $response->setView($view);

      // $preview = $view->buildRenderable($display_id, $args);.
      $selector = '.js-view-dom-id-' . $dom_id;
      $context = new RenderContext();
      $preview = $this->renderer->executeInRenderContext($context, function () use ($view, $display_id, $args) {
        return $view->preview($display_id, $args);
      });
      if (!$context->isEmpty()) {
        $bubbleable_metadata = $context->pop();
        BubbleableMetadata::createFromRenderArray($preview)
          ->merge($bubbleable_metadata)
          ->applyTo($preview);
      }

      $response->addCommand(new ReplaceCommand($selector, $preview));
      $response->addCommand(new ScrollTopCommand($selector));
      return $response;
    }
    throw new AccessDeniedHttpException();
  }

}

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

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