You are here

function filter_harmonizer_views_exposed_form_submit in Views Filter Harmonizer 7

Supplementary submit handler for 'views_exposed_form'.

@todo: Refactor this mess. Especially all the debug msgs.

1 string reference to 'filter_harmonizer_views_exposed_form_submit'
filter_harmonizer_form_views_exposed_form_alter in ./filter_harmonizer.module
Implements hook_form_FORMID_alter().

File

./filter_harmonizer.module, line 114
filter_harmonizer.module For Views where both exposed and contextual filters are active on a page.

Code

function filter_harmonizer_views_exposed_form_submit(&$form, &$form_state) {
  if (empty($form_state['view']) || empty($form_state['display']->handler)) {
    return;
  }
  if (isset($form_state['display']->display_options['enabled']) && !$form_state['display']->display_options['enabled']) {
    return;
  }
  $view_display = $form_state['display']->handler;
  if (!($contextual_handlers = $view_display
    ->get_handlers('argument'))) {
    return;
  }
  if (!($filter_handlers = $view_display
    ->get_handlers('filter'))) {
    return;
  }
  $view = $form_state['view'];
  $display_id = $form_state['display']->id;

  // For attachments: if the attachment isn't coupled to both the contextual
  // and regular filters of its page/master, then we have nothing to harmonize.
  $is_inherit_contextual = $view->display_handler
    ->get_option('inherit_arguments');
  $is_inherit_regular = $view->display_handler
    ->get_option('inherit_exposed_filters');
  if ($is_inherit_contextual === 0 || $is_inherit_regular === 0) {
    return;
  }
  $view_args =& drupal_static(__FUNCTION__);
  if (!isset($view_args)) {
    $view_args = $view->args;
  }

  // As we haven't run the query yet we dont know for sure if the output is
  // going to be paged...
  // Note that the first page of a sequence does NOT have a 'page=..'
  $is_paged = $view->display[$display_id]->handler
    ->use_pager() && isset($_GET['page']);
  $is_filter_harmonizer_always = variable_get('filter_harmonizer_always', FALSE);
  $is_merge_filter_values = variable_get('filter_harmonizer_merge_filter_values', FALSE);
  $is_fill_exposed_form = variable_get('filter_harmonizer_fill_exposed', TRUE);
  $filter_harmonizer_contextual_filters = variable_get('filter_harmonizer_contextual_filters', array());
  $is_debug = filter_harmonizer_debug_flag();
  $is_initial_page_load = filter_harmonizer_is_new_page();
  if ($is_debug) {
    if ($is_initial_page_load) {
      drupal_set_message(t('Views Filter Harmonizer - Initial page load.'));
    }
    elseif ($is_paged) {
      drupal_set_message(t('Views Filter Harmonizer - View is paged. Treating as initial page load.'));
    }
  }
  $replace_args = array();
  $num_harmonized = 0;
  foreach ($contextual_handlers as $field_name => $contextual_filter) {
    $is_harmonize = $is_filter_harmonizer_always || !empty($filter_harmonizer_contextual_filters[$view->name][$display_id][$field_name]);
    $contextual_is_empty = !isset($contextual_filter->position) || !isset($view_args[$contextual_filter->position]);
    $contextual_value = $contextual_is_empty ? $contextual_filter
      ->get_default_argument() : $view_args[$contextual_filter->position];

    // Initialise the replacement args with the current contextual filter value.
    $replace_args[$field_name] = $contextual_value;
    if ($is_harmonize && isset($filter_handlers[$field_name])) {

      // This regular (exposed) filter has a companion contextual filter on the
      // same display and harmonization is requested.
      $num_harmonized++;
      if ($contextual_value == $contextual_filter->options['exception']['value']) {
        $contextual_is_empty = TRUE;
      }
      if (strpos($contextual_value, '|') === FALSE) {

        // If "Allow mutliple values" is ticked, replace Views contextual OR
        // operator, i.e. the space or +, by a more unique separator '|'.
        if (!empty($contextual_filter->options['break_phrase'])) {
          $contextual_value = str_replace(array(
            ' ',
            '+',
          ), '|', $contextual_value);

          // With "Allow multiple values" ticked, filter arguments that contain
          // spaces MUST be entered with dashes instead: 'United-Kingdom'.
          // Now that spaces have been converted to '|', we can transform
          // dashes to spaces.
          $contextual_value = str_replace('-', ' ', $contextual_value);
        }
      }
      $regular_filter = $filter_handlers[$field_name];
      $key = $regular_filter
        ->is_a_group() ? 'group_info' : 'expose';
      $form_field_name = $regular_filter->options[$key]['identifier'];
      if (isset($form_state['values'][$form_field_name])) {
        $regular_value = _filter_harmonizer_flatten($form_state['values'][$form_field_name]);
        $regular_is_empty = filter_harmonizer_filter_is_empty($form_state['values'][$form_field_name], $regular_filter);
      }
      else {
        $regular_value = '';
        $regular_is_empty = TRUE;
      }
      $msg = NULL;
      if ($is_debug) {
        $msg = t('Views Filter Harmonizer - @display %view, @filter.<br/>Exposed filter value: %regular-val. Contextual filter value: %context-val', array(
          '%view' => $view
            ->get_human_name(),
          '@display' => $display_id,
          '@filter' => $field_name,
          '%regular-val' => $regular_is_empty ? t('EMPTY') : $regular_value,
          '%context-val' => $contextual_is_empty ? t('EMPTY/all (no action required)') : $contextual_value,
        ));
      }
      $form_options = isset($form[$form_field_name]['#options']) ? $form[$form_field_name]['#options'] : NULL;
      if ($contextual_is_empty) {

        // As this is mainly for display concatenate with '+' rather than '|'.
        if (!$regular_is_empty) {
          $replace_args[$field_name] = implode('+', filter_harmonizer_convert_regular_to_contextual_value($form_options, $contextual_filter, $regular_value));
        }
      }
      else {

        // Auto-clear the contextual filter when the exposed filter is clear,
        // except on initial page load, which is the only time the contextual
        // filter is obeyed. In this case we visualise the contextual filter
        // value on the exposed filter.
        $is_multi = $regular_filter->options[$key]['multiple'];
        if (($is_initial_page_load || $is_paged) && ($regular_is_empty || $is_multi)) {
          $filter_values = filter_harmonizer_convert_contextual_to_regular_value($contextual_filter, $regular_filter, $contextual_value);
          if (isset($msg)) {
            $msg .= ', ' . t('converted: %value', array(
              '%value' => is_array($filter_values) ? implode('|', $filter_values) : $filter_values,
            ));
          }
          if ($is_multi && !$regular_is_empty && $is_merge_filter_values && is_array($filter_values)) {

            // Special case [#2297687].
            // If the regular filter allows multiple selections and isn't empty,
            // project the current contextual filter args onto the exposed
            // filter, while at the same time unsetting the contextual filter to
            // 'all'.
            $filter_values = array_merge(array_filter(explode('|', $regular_value)), $filter_values);
            $filter_values = array_unique($filter_values);
            if (isset($msg)) {
              $msg .= '<br/>' . t('Merged: %value. Setting it on exposed, unsetting contextual.', array(
                '%value' => implode('|', $filter_values),
              ));
            }
            filter_harmonizer_set_exposed_filter($form_state, $form_field_name, $filter_values);
            filter_harmonizer_unset_contextual_filter($contextual_filter, $filter_values);

            // For display concatenate with '+' rather than '|'.
            $replace_args[$field_name] = implode('+', filter_harmonizer_convert_regular_to_contextual_value($form_options, $contextual_filter, implode('|', $filter_values)));
          }
          else {
            if (isset($msg)) {
              $msg .= '. ' . t('Filter values remain.');
            }
          }

          // Show the contextual filter value on the exposed filter form.
          if ($is_fill_exposed_form) {
            filter_harmonizer_visualise_exposed_filter($form[$form_field_name], $filter_values);
          }

          // Allow other modules to alter the process by
          // implementing hook_filter_harmonizer_filter_set_alter().
          $data = array(
            $form,
            $form_state,
            $contextual_filter,
            $regular_filter,
            $filter_values,
          );
          drupal_alter('filter_harmonizer_set', $data);
        }
        else {
          if (isset($msg)) {
            $msg .= '<br/>' . t('Exposed filter override applies, unsetting contextual filter.');
          }
          filter_harmonizer_unset_contextual_filter($contextual_filter, $regular_value);

          // As this is mainly for display concatenate with '+' rather than '|'.
          $replace_args[$field_name] = implode('+', filter_harmonizer_convert_regular_to_contextual_value($form_options, $contextual_filter, $regular_value));
        }
      }
      drupal_set_message($msg);
    }
    elseif ($is_debug) {
      drupal_set_message(t('Views Filter Harmonizer - @display %view, @filter: this contextual filter is not configured as a companion of any exposed filter. No harmonization will take place.', array(
        '%view' => $view
          ->get_human_name(),
        '@display' => $display_id,
        '@filter' => $field_name,
      )), 'warning');
    }
  }
  if ($num_harmonized > 0 && variable_get('filter_harmonizer_adjust_browser_url', FALSE)) {
    filter_harmonizer_set_browser_url_tail($replace_args);
  }
}