You are here

function finder_build_display_query in Finder 7.2

Does stuff during the display handler's query.

Parameters

&$display_handler: A reference to the views display handler object.

2 calls to finder_build_display_query()
finder_plugin_display::query in views/finder_plugin_display.inc
Inject anything into the query that the display handler needs.
finder_views_query_alter in ./finder.module
Implements hook_views_query_alter().

File

includes/build.inc, line 74
The finder build functions.

Code

function finder_build_display_query(&$display_handler) {
  $finder = $display_handler
    ->get_option('finder');
  foreach (array_keys($finder->find) as $key) {
    ${$key} =& $finder->find[$key];
  }
  if ($mode == 'choices') {

    // We set distinct to reduce results sets somewhat if possible.
    $display_handler->view->query
      ->set_distinct(TRUE, TRUE);
  }
  if (!empty($keywords)) {
    $placeholder_count = 0;

    // Create an array to track wheres, we'll add them to views later.
    $wheres = array();

    // Create a where group called 'finder', for element combination.
    $element_combination = $finder
      ->setting('element_logic');
    $display_handler->view->query
      ->set_where_group($element_combination, 'finder');

    // @todo create a where group for each container element
    if ($mode == 'choices') {
      $display_handler->view->query
        ->set_where_group('OR', 'finder_choices');
    }
    foreach ($keywords as $eid => $keyword_array) {
      $finder_element =& $finder->elements[$eid];
      $element_fields = $finder
        ->esetting($finder_element, 'fields');
      if ($mode == 'results') {

        // For choices these have to be passed in manually through $finder->find, but for results we get them like this:
        $field_logic = $finder
          ->esetting($finder_element, 'field_logic');
        $value_logic = $finder
          ->esetting($finder_element, 'value_logic');
        $nesting_order = $finder
          ->esetting($finder_element, 'nesting_order');

        //$match = $finder->esetting($finder_element, 'match');
      }
      if (!empty($keyword_array)) {
        $clauses = array();
        $clause_args = array();
        foreach ($element_fields as $key => $field) {
          $field_info[$eid][$key] = $field;
          foreach (array_values($keyword_array) as $keyword_position => $keyword) {

            // Get the info we need to add the table/field.
            $delta = $value_logic == 'AND' && count($keyword_array) > 1 ? $keyword_position : 0;
            $field->table_alias[$delta] = finder_alias('table', $eid, $field->table, $field->field, $delta);
            $field->field_alias[$delta] = finder_alias('field', $eid, $field->table, $field->field, $delta);
            $relationship = NULL;
            $join = NULL;
            if (!empty($field->relationship)) {
              $relationship = $display_handler->view->relationship[$field->relationship]->alias;
            }

            // This chunk of code will fix the join directly to the left.  Should we actually be recursing through all the left tables right back to the base table?
            if (empty($relationship)) {
              $relationship = $display_handler->view->query->base_table;
            }
            $join = $display_handler->view->query
              ->get_join_data($field->table, $display_handler->view->query->relationships[$relationship]['base']);
            if (!empty($join)) {
              $join = $display_handler->view->query
                ->adjust_join($join, $relationship);
            }
            if (!empty($join->left_table) && $join->left_table != $display_handler->view->query->base_table) {

              // Check for the long-chain join case that we probably screwed up, and plead for assistance.
              $left_table_join_data = $display_handler->view->query
                ->get_join_data($join->left_table, $display_handler->view->query->relationships[$relationship]['base']);
              if (!empty($left_table_join_data->left_table) && $left_table_join_data->left_table != $display_handler->view->query->base_table && user_access('administer finder')) {

                // Purposefully not enclosed in t() because this is not a typical UI string.
                drupal_set_message("Views join configuration not supported by finder.  Please post in the <a href=\"http://drupal.org/node/add/project-issue/finder\">finder issue queue</a> and attach an export of your finder, or explain what fields you are using.  We need your help to solve this problem.", 'error');
              }

              // Table name supplied here is a combo of the table joined here, and the table we ultimately want to join.
              $join_alias = finder_alias('table', $eid, $field->table . "_" . $join->left_table, $field->field, $delta);
              $join_alias = $display_handler->view->query
                ->add_table($join->left_table, NULL, NULL, $join_alias);
              $join->left_table = $join_alias;
            }
            $join = $join ? $join : $display_handler->view->query
              ->get_join_data($field->table_alias[$delta], $display_handler->view->base_table);
            $table = isset($join->table) ? $join->table : $field->table;
            if ($table == $display_handler->view->base_table) {

              // Don't alias base table here.
              // @todo: rather than 'undoing' stuff here... don't do it in the first place.
              $field->table_alias[$delta] = $display_handler->view->base_table;
            }
            $display_handler->view->query
              ->add_table($field->table, $relationship, $join, $field->table_alias[$delta]);

            // Select the field.
            if ($mode == 'results' && $finder
              ->setting('results_style') == 'custom' || $mode == 'choices' && $eid == $element->id) {

              // If we're doing a custom results page or a choices list, grab the field value, and store the alias.
              $field->field_alias[$delta] = $display_handler->view->query
                ->add_field($field->table_alias[$delta], $field->field, $field->field_alias[$delta]);

              // This if-statement also assumes that $eid == $element->id, but it is not needed to specify this because of the outer if-statement.
              if ($mode == 'choices') {
                $groups[] = $field->field_alias[$delta];
                $wheres['finder_choices'][$eid][] = array(
                  'snippet' => $field->table_alias[$delta] . '.' . $field->field . ' IS NOT NULL',
                  'args' => array(),
                );
              }
            }

            // Add the field to where clauses.
            if ($keyword !== '' && $keyword !== NULL) {
              list($field_name, $value, $op) = array_values((array) $finder
                ->match_args($field->table_alias[$delta] . '.' . $field->field, $keyword, $finder->find['matches'][$eid]['match'], $finder->find['matches'][$eid]['match_x']));
              $outer_key = $nesting_order ? $key : $keyword_position;
              $placeholder = ':finder_keyword_' . $placeholder_count++;
              $expression = $field_name . ' ' . $op . ' ' . $placeholder;
              $clauses[$outer_key][] = $expression;
              $clause_args[$outer_key][$placeholder] = $value;

              // Using same conditions as for when we add a field, because there's no point in adding the match field if not selecting the field.
              if ($mode == 'results' && $finder
                ->setting('results_style') == 'custom' || $mode == 'choices' && $eid == $element->id) {
                $field->field_matched[$delta] = $field->field_alias[$delta] . '_matched';
                $display_handler->view->query
                  ->add_field(NULL, $expression, $field->field_matched[$delta]);
              }
            }
          }
        }

        // Convert where clauses into sql strings and add to view with add_where().
        if (!empty($clauses)) {
          $inner_operator = $nesting_order ? $value_logic : $field_logic;
          $outer_operator = $nesting_order ? $field_logic : $value_logic;
          $inner_clauses = array();
          $inner_clause_args = array();
          foreach ($clauses as $clause) {
            if (!empty($clause)) {
              $inner_clauses[] = finder_implode_wheres($inner_operator, $clause);
            }
          }
          foreach ($clause_args as $clause_arg) {
            foreach ($clause_arg as $inner_clause_arg_key => $inner_clause_arg) {
              $inner_clause_args[$inner_clause_arg_key] = $inner_clause_arg;
            }
          }
          $wheres['finder'][$eid][] = array(
            'snippet' => finder_implode_wheres($outer_operator, $inner_clauses),
            'args' => $inner_clause_args,
          );
        }
      }
    }
    foreach ($wheres as $wheres_group_name => $wheres_group) {
      $formatted_wheres = finder_format_wheres($finder, $finder
        ->root_elements(), $wheres_group);
      foreach ($formatted_wheres as $formatted_where) {

        // ditching empty snippets now falls to finder_format_wheres().

        //if (trim($formatted_where['snippet'])) {
        $display_handler->view->query
          ->add_where_expression($wheres_group_name, $formatted_where['snippet'], $formatted_where['args']);

        //}
      }
    }
  }

  // Add groups.
  foreach ($groups as $group) {
    $display_handler->view->query
      ->add_groupby($group);
  }
}