You are here

function select_translation_filter_handler::better_query in Select translation 7

A query that doesn't use correlated sub-queries.

Thus executing faster for larger data sets.

1 call to select_translation_filter_handler::better_query()
select_translation_filter_handler::query in ./select_translation_filter_handler.inc
Executes the query.

File

./select_translation_filter_handler.inc, line 114
Views select translation filter handler.

Class

select_translation_filter_handler

Code

function better_query() {
  global $language_content;
  $default_language = language_default('language');
  $current_language = $language_content->language;

  // Limit the language list to default only, if the option was selected and
  // default_language == current_language.
  if ($this->options['default_language_only'] && $default_language == $current_language) {
    $list = array(
      'default',
    );
  }
  else {
    $list = array();
    if ($this->value == 'original') {
      $list = array(
        'current',
      );
    }
    elseif ($this->value == 'default') {
      $list = array(
        'current',
        'default',
      );
    }
    elseif (!empty($this->options['priorities'])) {
      $list = explode(',', $this->options['priorities']);
      foreach ($list as $i => $v) {
        $list[$i] = strtolower(trim($v));
      }
    }
    $list[] = 'original';
  }
  foreach ($list as $i => $v) {
    if ($list[$i] == 'current') {
      $list[$i] = $current_language;
    }
    elseif ($list[$i] == 'default') {
      $list[$i] = $default_language;
    }
  }
  $list = array_unique($list);

  // Now build the query.
  $query = $this->query;

  /* @var $query views_plugin_query_default */
  $alias = $query
    ->ensure_table('node');
  $condition_holder = db_or();

  // First include nodes that don't have translations, if option was checked.
  if ($this->options['include_content_without_translation']) {
    $condition_holder
      ->condition("{$alias}.tnid", 0);
  }
  $i = 0;
  $exclude = array();

  // Now go through each language.
  foreach ($list as $language) {
    $add_new_join = FALSE;
    if ($language != 'original') {

      // Create a views join on the node table, and add it as a relationship.
      // This is used to find if there are translations of a certain language.
      $join = new views_join();
      $add_new_join = TRUE;
      $sub_query_alias = 'nt' . $i;

      // Because domain module uses node_access, and rewrites the query to add
      // exists clauses for each left joined node table (maybe specific to all
      // node access modules), thus breaking the listing, we wrap the table in
      // a sub-query, avoiding the exists clause.
      $this
        ->node_access_join($join, $language, $alias, $sub_query_alias);

      // Add the join as a relationship.
      $query
        ->add_relationship($sub_query_alias, $join, 'node');
    }
    if ($language == 'original') {

      // Include nodes that are the base of a translation (aka original).
      $and = db_and()
        ->where("{$alias}.nid = {$alias}.tnid");
    }
    else {

      // Include nodes of specified language.
      $and = db_and()
        ->condition("{$alias}.language", $language);
    }

    // Add the currently processed language only if previous languages were
    // not found.
    foreach ($exclude as $e) {
      $and
        ->where($e);
    }
    $condition_holder
      ->condition($and);

    // Add to excludes the currently processed translation language.
    if (isset($sub_query_alias) && $add_new_join) {
      $exclude[] = $sub_query_alias . '.nid IS NULL';
      ++$i;
    }
  }

  // Include site default nodes in place of unpublished translations.
  if ($this->options['include_content_with_unpublished_translation']) {
    $sub_query_alias = 'nt' . $i;
    $join = new views_join();

    // Join with the currently selected language.
    $this
      ->node_access_join($join, $current_language, 'node', $sub_query_alias);

    // Add the join as a relationship.
    $query
      ->add_relationship($sub_query_alias, $join, 'node');

    // The default language node will be selected, if the current language
    // (translated) node is unpublished.
    $condition_holder
      ->condition(db_and()
      ->condition("{$alias}.language", $default_language)
      ->condition("{$sub_query_alias}.status", NODE_NOT_PUBLISHED));
  }

  // Add in the conditions.
  $query
    ->add_where($this->options['group'], $condition_holder);
}