You are here

public function EntityReferenceFilterAjaxController::ajaxFiltersValuesRebuild in Views Reference Filter 8

Loads and renders a view via AJAX.

Parameters

\Symfony\Component\HttpFoundation\Request $request: The current request object.

Return value

\Drupal\Core\Ajax\AjaxResponse The ajax response.

Throws

\Symfony\Component\HttpKernel\Exception\NotFoundHttpException Thrown when the view was not found.

\Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException Thrown when the view isn't accessible.

See also

\Drupal\views\Controller\ViewAjaxController::ajaxView()

1 string reference to 'EntityReferenceFilterAjaxController::ajaxFiltersValuesRebuild'
entityreference_filter.routing.yml in ./entityreference_filter.routing.yml
entityreference_filter.routing.yml

File

src/Controller/EntityReferenceFilterAjaxController.php, line 153

Class

EntityReferenceFilterAjaxController
Defines a controller to build dependent entityreference filters.

Namespace

Drupal\entityreference_filter\Controller

Code

public function ajaxFiltersValuesRebuild(Request $request) {
  $view_data = $request->request
    ->get('view');
  $name = $view_data['view_name'] ?? FALSE;
  $display_id = $view_data['view_display_id'] ?? FALSE;
  $dependent_filters_data = $request->request
    ->get('dependent_filters_data');
  $form_id = $request->request
    ->get('form_id');
  if (!empty($name) && !empty($display_id) && !empty($dependent_filters_data) && !empty($form_id)) {
    $response = new AjaxResponse();

    // Load the view to rebuild the filters for.

    /** @var \Drupal\views\ViewEntityInterface $entity */
    if (!($entity = $this->storage
      ->load($name))) {
      throw new NotFoundHttpException();
    }
    $view = $this->executableFactory
      ->get($entity);
    if ($view && $view
      ->access($display_id) && $view
      ->setDisplay($display_id)) {

      /** @var \Drupal\views\Plugin\views\exposed_form\ExposedFormPluginInterface $exposed_plugin **/
      $exposed_plugin = $view->display_handler
        ->getPlugin('exposed_form');
      $exposed_plugin_options = $exposed_plugin->options ?? NULL;

      // Rebuild filters options.
      foreach ($dependent_filters_data as $dependent_filter_name => $dependent_filter_data) {
        $filters = $view
          ->getHandlers('filter', $display_id);
        $reference_display = !empty($filters[$dependent_filter_name]['reference_display']) ? $filters[$dependent_filter_name]['reference_display'] : FALSE;
        $reference_arguments = !empty($filters[$dependent_filter_name]['reference_arguments']) ? $filters[$dependent_filter_name]['reference_arguments'] : FALSE;
        if ($reference_display && $reference_arguments) {
          [
            $filter_view_name,
            $filter_display_id,
          ] = explode(':', $reference_display);
          $filter_view = Views::getView($filter_view_name);

          // No view or access.
          if (!$filter_view || !$filter_view
            ->access($filter_display_id)) {
            $this->loggerChannel
              ->warning('The view %view_name is no longer eligible for the filter.', [
              '%view_name' => $filter_view_name,
            ]);
            throw new NotFoundHttpException();
          }
          if ($filter_view instanceof ViewExecutable) {
            $new_options = [];
            $args = $this
              ->extractViewArgs($request, $dependent_filter_name, $filters);

            // Cache is controlled by the filter view itself.
            $filter_view
              ->setDisplay($filter_display_id);
            $filter_view
              ->setItemsPerPage(0);

            // Set `entity_reference_options` for the new EntityReference view display implementation.
            $entity_reference_options = [
              'limit' => NULL,
            ];
            $filter_view->displayHandlers
              ->get($filter_display_id)
              ->setOption('entity_reference_options', $entity_reference_options);
            $results = $filter_view
              ->executeDisplay($filter_display_id, $args);
            $filter_is_required = $filters[$dependent_filter_name]['expose']['required'];
            $filter_is_multiple = $filters[$dependent_filter_name]['expose']['multiple'];
            $filter_type = $filters[$dependent_filter_name]['type'];

            // -Any- option
            if (!$filter_is_required && $filter_type === 'select' && !$filter_is_multiple) {
              $new_options['All'] = $this
                ->t('- Any -');
            }
            foreach ($results as $renderable) {
              $entity = $renderable["#row"]->_entity;
              $option = $this->renderer
                ->renderPlain($renderable);
              $new_options[$entity
                ->id()] = strip_tags($option);
            }

            // Rewrite options with Better Exposed Filters.
            if ($exposed_plugin_options && $this->moduleHandler
              ->moduleExists('better_exposed_filters')) {
              $rewrite_to = $exposed_plugin_options['bef']['filter'][$dependent_filter_name]['advanced']['rewrite']['filter_rewrite_values'] ?? NULL;
              if ($rewrite_to) {
                $new_options = BetterExposedFiltersHelper::rewriteOptions($new_options, $rewrite_to);
              }
            }

            // Build options string, selector and add Ajax command to return.
            $options_str = '';
            foreach ($new_options as $val => $label) {
              $options_str .= "<option value=\"{$val}\">{$label}</option>";
            }

            // Build command and send.
            $selector = '#' . $form_id . ' [name="' . $dependent_filter_name . '"],#' . $form_id . ' [name="' . $dependent_filter_name . '[]"]';
            $has_values = !empty($results);
            $hide_empty_filter = $filters[$dependent_filter_name]['hide_empty_filter'] ?? FALSE;
            $command_options = [
              'hide_empty_filter' => $hide_empty_filter,
              'has_values' => $has_values,
            ];
            $response
              ->addCommand(new EntityReferenceFilterInsertNoWrapCommand($selector, $options_str, $command_options));

            // If chosen is applied, it can't be updated by attachBehavior().
            $response
              ->addCommand(new InvokeCommand($selector, 'trigger', [
              'liszt:updated',
            ]));
            $response
              ->addCommand(new InvokeCommand($selector, 'trigger', [
              'chosen:updated',
            ]));

            // Options are changed, so run 'change' handlers.
            $response
              ->addCommand(new InvokeCommand($selector, 'trigger', [
              'change',
            ]));
          }
        }
      }
      return $response;
    }
    throw new AccessDeniedHttpException();
  }
  throw new NotFoundHttpException();
}