You are here

function ViewsDependentFilter::buildExposedForm in Views Dependent Filters 8

Make our changes to the form but don't return anything ourselves.

Overrides FilterPluginBase::buildExposedForm

File

src/Plugin/views/filter/ViewsDependentFilter.php, line 251

Class

ViewsDependentFilter
Filters by given list of related content title options.

Namespace

Drupal\views_dependent_filter\Plugin\views\filter

Code

function buildExposedForm(&$form, FormStateInterface $form_state) {
  $filters = $this->view->display_handler
    ->getHandlers('filter');

  // Build an array of dependency info.
  $dependency_info = array(
    // An array keyed by controller filter IDs, where the values are arrays
    // of their possible values.
    // In practice there is only one controller filter, but technically there
    // could be several. The problem is that the admin UI to set them up
    // would become a nightmare, and there's the matter of whether to combine
    // them with AND or OR. Hence one for later, if ever required.
    'controllers' => array(),
    // An array of dependent filter IDs.
    'dependents' => array(),
    // A lookup of filter IDs to filter URL identifiers.
    'identifiers' => array(),
  );
  if (!empty($this->options['controller_filter'])) {
    $controller_filter = $this->options['controller_filter'];
    $dependency_info['controllers'][$controller_filter] = array();
    if (!empty($this->options['controller_values'])) {
      if (is_array($this->options['controller_values'])) {

        // Filter out the crud from Form API checkboxes and get rid of the
        // keys to avoid confusion: we compare on values further down.
        $controller_values = array_values(array_filter($this->options['controller_values']));
      }
      else {
        $controller_values = array(
          $this->options['controller_values'],
        );
      }
      $dependency_info['controllers'][$controller_filter] = $controller_values;
      $identifier = $filters[$controller_filter]->options['expose']['identifier'];
      $dependency_info['identifiers'][$controller_filter] = $identifier;
    }
  }
  $dependency_info['dependents'] = array_values(array_filter($this->options['dependent_filters']));

  // Populate the identifiers lookup with our dependent filters.
  foreach ($dependency_info['dependents'] as $dependent_filter_id) {
    $identifier = $filters[$dependent_filter_id]->options['expose']['identifier'];
    $dependency_info['identifiers'][$dependent_filter_id] = $identifier;
  }

  //dsm($form_state['input'], 'input');
  $filters = $this->view->display_handler
    ->getHandlers('filter');
  foreach ($dependency_info['controllers'] as $filter_id => $controller_values) {

    // Get the form identifier.
    $identifier = $filters[$filter_id]->options['expose']['identifier'];

    // Get the input for this filter.
    $input =& $form_state
      ->getUserInput()[$identifier];

    // Convert values for non-multiple filters to an array.
    if (!$this->view->filter[$filter_id]->options['expose']['multiple']) {
      $input = array(
        $input,
      );
    }
    $intersection = array_intersect($input, $controller_values);
    if (!count($intersection)) {
      $this->filters_kill = $dependency_info['dependents'];
    }
  }

  // We can kill the dependent filters now.
  // $this->filters_disable();
  // ...alternatively, leave them there so their form is shown, but prevent
  // them from collecting input.
  // This means the form element can be subject to CTools dependent visiblity
  // and means the user can refine their filtering without an interim
  // submission of the form.
  // @todo: Allow this as an option, ie have a 'no js' version which would
  // just kill dependent filters now.
  // To make the dependent filters change their visibility we need to add a
  // CTools dependent property, but we can't do that here as the form
  // elements for these don't exist yet.
  // Only way to do this is to register an #after_build on the whole form
  // which lives in module code rather than in this handler.
  // Add our settings to the form state as an array, as we need to account
  // for the possiblity that more than one copy of this handler may be
  // playing at once!
  $form_state->dependent_exposed_filters[] = $dependency_info;
  $form['#after_build'] = array(
    'views_dependent_filters_exposed_form_after_build',
  );

  // Some clean-up for things that come later.
  // Mark ourselves not being exposed now we've done our work. This isn't
  // necessary for Views itself, but allows compatibility with the
  // better_exposed_filters module whose exposed_form_alter() tries to work
  // with all exposed filters.
  $this->options['exposed'] = FALSE;

  // We do nada to the form ourselves.
  return;
}