You are here

class views_join in Views (for Drupal 7) 7.3

Same name and namespace in other branches
  1. 6.3 includes/handlers.inc \views_join
  2. 6.2 includes/handlers.inc \views_join

A function class to represent a join and create the SQL necessary to implement the join.

This is the Delegation pattern. If we had PHP5 exclusively, we would declare this an interface.

Extensions of this class can be used to create more interesting joins.

'join' definition:

  • table: table to join (right table)
  • field: field to join on (right field)
  • left_table: The table we join to
  • left_field: The field we join to
  • type: either LEFT (default) or INNER
  • extra: An array of extra conditions on the join. Each condition is either a string that's directly added, or an array of items:
  • - table: If not set, current table; if NULL, no table. If you specify a table in cached definition, Views will try to load from an existing alias. If you use realtime joins, it works better.
  • - field: Field or formula in formulas we can reference the right table by using %alias
  • operator: Defaults to =.
  • value: Must be set. If an array, operator will be defaulted to IN.
  • numeric: If true, the value will not be surrounded in quotes.
  • extra type: How all the extras will be combined. Either AND or OR. Defaults to AND.

Hierarchy

Expanded class hierarchy of views_join

See also

SelectQueryInterface::addJoin()

Related topics

File

includes/handlers.inc, line 1580
Defines the various handler objects to help build and display views.

View source
class views_join {
  public $table = NULL;
  public $left_table = NULL;
  public $left_field = NULL;
  public $field = NULL;
  public $extra = NULL;
  public $type = NULL;
  public $definition = array();

  /**
   * Construct the views_join object.
   */
  public function construct($table = NULL, $left_table = NULL, $left_field = NULL, $field = NULL, $extra = array(), $type = 'LEFT') {
    $this->extra_type = 'AND';
    if (!empty($table)) {
      $this->table = $table;
      $this->left_table = $left_table;
      $this->left_field = $left_field;
      $this->field = $field;
      $this->extra = $extra;
      $this->type = strtoupper($type);
    }
    elseif (!empty($this->definition)) {

      // If no arguments, construct from definition. These four must exist or
      // it will throw notices.
      $this->table = $this->definition['table'];
      $this->left_table = $this->definition['left_table'];
      $this->left_field = $this->definition['left_field'];
      $this->field = $this->definition['field'];
      if (!empty($this->definition['extra'])) {
        $this->extra = $this->definition['extra'];
      }
      if (!empty($this->definition['extra type'])) {
        $this->extra_type = strtoupper($this->definition['extra type']);
      }
      $this->type = !empty($this->definition['type']) ? strtoupper($this->definition['type']) : 'LEFT';
    }
  }

  /**
   * Build the SQL for the join this object represents.
   *
   * When possible, try to use table alias instead of table names.
   *
   * @param SelectQueryInterface $select_query
   *   An Implements SelectQueryInterface.
   * @param string $table
   *   The base table to join.
   * @param views_plugin_query $view_query
   *   The source query, Implements views_plugin_query.
   */
  public function build_join($select_query, $table, $view_query) {
    if (empty($this->definition['table formula'])) {
      $right_table = $this->table;
    }
    else {
      $right_table = $this->definition['table formula'];
    }
    if ($this->left_table) {
      $left = $view_query
        ->get_table_info($this->left_table);
      $left_field = "{$left['alias']}.{$this->left_field}";
    }
    else {

      // This can be used if left_field is a formula or something. It should be
      // used only *very* rarely.
      $left_field = $this->left_field;
    }
    $condition = "{$left_field} = {$table['alias']}.{$this->field}";
    $arguments = array();

    // Tack on the extra.
    if (isset($this->extra)) {

      // If extra has been provided as string instead of an array, convert it
      // to an array.
      if (!is_array($this->extra)) {
        $this->extra = array(
          $this->extra,
        );
      }
      $extras = array();
      foreach ($this->extra as $info) {
        if (is_array($info)) {
          $extra = '';

          // Figure out the table name. Remember, only use aliases provided if
          // at all possible.
          $join_table = '';
          if (!array_key_exists('table', $info)) {
            $join_table = $table['alias'] . '.';
          }
          elseif (isset($info['table'])) {

            // If we're aware of a table alias for this table, use the table
            // alias instead of the table name.
            if (isset($left) && $left['table'] == $info['table']) {
              $join_table = $left['alias'] . '.';
            }
            else {
              $join_table = $info['table'] . '.';
            }
          }

          // Convert a single-valued array of values to the single-value case,
          // and transform from IN() notation to = notation.
          if (is_array($info['value']) && count($info['value']) == 1) {
            if (empty($info['operator'])) {
              $operator = '=';
            }
            else {
              $operator = $info['operator'] == 'NOT IN' ? '!=' : '=';
            }
            $info['value'] = array_shift($info['value']);
          }
          if (is_array($info['value'])) {
            $value_placeholders = array();

            // With an array of values, we need multiple placeholders and the
            // 'IN' operator is implicit.
            foreach ($info['value'] as $value) {
              $placeholder_i = $view_query
                ->placeholder('views_join_condition_');
              $value_placeholders[] = $placeholder_i;
              $arguments[$placeholder_i] = $value;
            }
            $operator = !empty($info['operator']) ? $info['operator'] : 'IN';
            $placeholder = '( ' . implode(', ', $value_placeholders) . ' )';
          }
          else {

            // With a single value, the '=' operator is implicit.
            $operator = !empty($info['operator']) ? $info['operator'] : '=';
            $placeholder = $view_query
              ->placeholder('views_join_condition_');
            $arguments[$placeholder] = $info['value'];
          }
          $extras[] = "{$join_table}{$info['field']} {$operator} {$placeholder}";
        }
        elseif (is_string($info)) {
          $extras[] = $info;
        }
      }
      if ($extras) {
        if (count($extras) == 1) {
          $condition .= ' AND (' . array_shift($extras) . ')';
        }
        else {
          $condition .= ' AND (' . implode(' ' . $this->extra_type . ' ', $extras) . ')';
        }
      }
    }
    $select_query
      ->addJoin($this->type, $right_table, $table['alias'], $condition, $arguments);
  }

}

Members

Namesort descending Modifiers Type Description Overrides
views_join::$definition public property
views_join::$extra public property
views_join::$field public property
views_join::$left_field public property
views_join::$left_table public property
views_join::$table public property
views_join::$type public property
views_join::build_join public function Build the SQL for the join this object represents. 1
views_join::construct public function Construct the views_join object. 1