class _views_query in Views (for Drupal 7) 5
Hierarchy
- class \_views_query
Expanded class hierarchy of _views_query
File
- ./
views_query.inc, line 282
View source
class _views_query {
/*
* Create the basic query object and fill with default values.
*/
function _views_query($primary_table = 'node', $primary_field = 'nid', $alias_prefix = '') {
$this->primary_table = $primary_table;
$this->primary_field = $primary_field;
$this->joins = array();
$this->where = array();
$this->orderby = array();
$this->groupby = array();
$this->tables = array();
$this->where_args = array();
$this->use_alias_prefix = $alias_prefix;
// Joins care about order, so we put our tables in a queue to make sure
// the order is correct.
$this->tablequeue = array();
if ($primary_field) {
$this->fields = array(
$alias_prefix . "{$primary_table}.{$primary_field}",
);
}
$this->count_field = $alias_prefix . "{$primary_table}.{$primary_field}";
$this->header = array();
}
/*
* Add a field to the query table, possibly with an alias. This will
* automatically call ensure_table to make sure the required table
* exists, *unless* $table is unset.
*/
function add_field($field, $table = '$$', $alias = '') {
if ($table == '$$') {
// I picked $$ because it's not a legal name for a table and NULL is
// actually a valid possibility here, and I can't default to a variable.
$table = $this->primary_table;
}
// We check for this specifically because we don't want to add it aliased.
if ($table == $this->primary_table && $field == $this->primary_field) {
return;
}
if ($table) {
$this
->ensure_table($table);
$table = $this->use_alias_prefix . $table . ".";
}
if ($alias) {
$a = " AS {$this->use_alias_prefix}{$alias}";
}
if (!in_array("{$table}{$field}{$a}", $this->fields)) {
$this->fields[] = "{$table}{$field}{$a}";
}
}
/*
* Set the base field to be distinct.
*/
function set_distinct($value = TRUE) {
if (!($this->no_distinct && $value)) {
$this->distinct = $value;
}
}
/*
* Remove all fields that may've been added; primarily used for summary
* mode where we're changing the query because we didn't get data we needed.
*/
function clear_fields() {
$this->fields = array();
}
/*
* Set what field the query will count() on for paging.
*/
function set_count_field($field) {
$this->count_field = $field;
}
/*
* Add a simple WHERE clause to the query. The caller is responsible for
* ensuring that all fields are fully qualified (TABLE.FIELD) and that
* the table already exists in the query.
*/
function add_where($clause) {
$args = func_get_args();
array_shift($args);
// ditch $clause
if (count($args) == 1 && is_array(reset($args))) {
$args = current($args);
}
if (is_array($args)) {
$this->where[] = $clause;
$this->where_args = array_merge($this->where_args, $args);
}
}
/*
* Add multiple an orderby's. Right now I'm not sure why this function
* is separate from add_orderby above; I don't think it needs to
* be.
*
* NOTE: $alias doesn't work when adding multiple orderbys.
*/
function add_orderby($table, $field, $order, $alias = '') {
if (!$alias && $table) {
$alias = $this->use_alias_prefix . $table;
}
elseif ($alias) {
$alias = $this->use_alias_prefix . $alias;
}
if ($table) {
$this
->ensure_table($table);
}
if (!is_array($field)) {
$field = array(
$field,
);
}
foreach ($field as $f) {
// Only fill out this aliasing if there is a table;
// otherwise we assume it is a formula.
if ($table) {
$as = $alias . '_' . $f;
}
else {
$as = $alias;
}
$this
->add_field($f, $table, $as);
$this->orderby[] = "{$as} {$order}";
if ($this->groupby) {
$this
->add_groupby($as);
}
}
}
/*
* Add a simple GROUP BY clause to the query. The caller is responsible
* for ensuring that the fields are fully qualified and the table is properly
* added.
*/
function add_groupby($clause) {
$this->groupby[] = $clause;
}
/*
* This function will ensure a table exists; if it already exists it won't
* do anything, but if it doesn't it will add the table queue. It will ensure
* a path leads back to the views_get_title table.
*/
function ensure_table($table) {
if ($table == $this->primary_table || $this->tables[$table]) {
return;
}
if ($this
->ensure_path($table)) {
$this
->queue_table($table);
}
}
/*
* This function will add a table to the query.
*
* @param $table
* The name of the table to add. It needs to exist in the global table
* array.
* @param $ensure_path
* If true, it will ensure that a path back to primary_table exists. If false, it
* assumes the caller is already sure about this and does not repeat it.
* @param $howmany
* How many instances of the table to add? (Useful for interesting join
* combos)
* @param $joininfo
* In some join configurations this table may actually join back through
* a different method; this is most likely to be used when tracing
* a hierarchy path. (node->parent->parent2->parent3). This parameter
* will specify how this table joins if it is not the default.
*/
function add_table($table, $ensure_path = false, $howmany = 1, $joininfo = NULL) {
if ($table == $this->primary_table) {
return;
}
if ($ensure_path && !$this
->ensure_path($table)) {
return false;
}
$this->tables[$table] += $howmany;
for ($i = $this->tables[$table] - $howmany + 1; $i <= $this->tables[$table]; $i++) {
if ($joininfo) {
$this->joins[$table][$i] = $joininfo;
}
$this->tablequeue[] = array(
'table' => $table,
'num' => $i,
'alias_prefix' => $this->use_alias_prefix,
);
}
return $this->tables[$table];
}
/*
* Add a table to the queue in the specified position. This is a low level
* operation and should only be performed after all safety checking has been done.
*/
function queue_table($table) {
if (!isset($this->tables[$table])) {
$this->tables[$table] = 1;
}
else {
$this->tables[$table]++;
}
$this->tablequeue[] = array(
'table' => $table,
'num' => $this->tables[$table],
'alias_prefix' => $this->use_alias_prefix,
);
}
/*
* Set the table header; used for click-sorting because it's needed
* info to modify the ORDER BY clause.
*/
function set_header($header) {
$this->header = $header;
}
/*
* Make sure that the specified table can be properly linked to the views_get_title
* table in the JOINs. This function uses recursion. If the tables
* needed to complete the path back to the views_get_title table are not in the
* query they will be added, but additional copies will NOT be added
* if the table is already there.
*/
function ensure_path($table, $traced = array(), $add = array()) {
if ($table == $this->primary_table) {
return true;
}
$table_data = _views_get_tables();
$left_table = $table_data[$table]['join']['left']['table'];
// Does it end at our views_get_title table?
if ($left_table == $this->primary_table) {
// We are done! Add our tables and unwind.
foreach (array_reverse($add) as $table) {
$this
->queue_table($table);
}
return true;
}
// Have we been this way?
if (isset($traced[$left_table])) {
// we looped. Broked.
return false;
}
// Do we have to add this table?
if (!isset($this->tables[$left_table])) {
$add[] = $left_table;
}
// Keep looking.
$traced[$left_table] = 1;
return $this
->ensure_path($left_table, $traced, $add);
}
/*
* Return the alias of a given table in the JOIN queries. If a table is in
* the query multiple times, use this function to figure out what successive
* iterations of the table will be named.
*
* @param $table
* The name of the table in the global table array.
* @param $table_num
* The instance number of the table.
* @param $alias_prefix
* An optional prefix for the table alias.
*/
function get_table_name($table, $table_num, $alias_prefix = null) {
if (is_null($alias_prefix)) {
$alias_prefix = $this->use_alias_prefix;
}
return $table_num < 2 ? $alias_prefix . $table : $alias_prefix . $table . $table_num;
}
/*
* Generate a query and a countquery from all of the information supplied
* to the object.
*
* @param $getcount
* Provide a countquery if this is true, otherwise provide a normal query.
*/
function query($getcount = false) {
$table_data = _views_get_tables();
// Set distinct
if (!$this->no_distinct && $this->distinct && count($this->fields)) {
$field = $this->fields[0];
$this->fields[0] = "DISTINCT({$field})";
$this->count_field = "DISTINCT({$this->count_field})";
//this is only needed once
$this->no_distinct = TRUE;
}
// Add all the tables to the query via joins. We assume all LEFT joins.
foreach ($this->tablequeue as $tinfo) {
$table = $tinfo['table'];
// The real table name may differ from what we're calling it.
$table_real = isset($table_data[$table]['name']) ? $table_data[$table]['name'] : $table;
$table_num = $tinfo['num'];
$table_alias = $this
->get_table_name($table, $table_num, $tinfo['alias_prefix']);
$joininfo = !$this->joins[$table][$table_num] ? $table_data[$table]['join'] : $this->joins[$table][$table_num];
$left_table_alias = isset($joininfo['left']['alias']) ? $joininfo['left']['alias'] : $tinfo['alias_prefix'];
$left_table_alias .= $joininfo['left']['table'];
// the { is a special character which seems to be treated differently
// in PHP5 than PHP4 so we do this a little oddly.
$join_type = $joininfo['type'] == 'inner' ? 'INNER' : 'LEFT';
$joins .= " {$join_type} JOIN {" . $table_real . "} {$table_alias} ON " . $left_table_alias . "." . $joininfo['left']['field'] . " = {$table_alias}." . $joininfo['right']['field'];
if (isset($joininfo['extra'])) {
foreach ($joininfo['extra'] as $field => $value) {
$joins .= " AND {$table_alias}.{$field}";
if (is_array($value) && count($value)) {
$joins .= " IN ('" . implode("','", $value) . "')";
}
else {
if ($value !== NULL) {
$joins .= " = '{$value}'";
}
}
}
}
}
// If it's not a count query, add our fields
if (!$getcount) {
$fields = implode(', ', $this->fields);
// we only add the groupby if we're not counting.
if ($this->groupby) {
$groupby = "GROUP BY " . implode(', ', $this->groupby);
}
// ok, tablesort_sql is really, really (really) annoying.
// 1) it insists on adding the ORDER BY clause.
// 2) You're supposed to give it your stuff as $before, but
// 3) You have to add the comma and
// 4) if it doesn't have anything to add, it returns NOTHING.
// 5) So I'm just going to get what it sends back and chop off
// the orderby, cause otherwise my code is too ugly with
// various checks.
if ($this->header) {
$result = tablesort_sql($this->header);
if ($result) {
$this->orderby[] = str_replace('ORDER BY ', '', $result);
}
}
if ($this->orderby) {
$orderby = "ORDER BY " . implode(', ', $this->orderby);
}
}
else {
$fields = "count({$this->count_field})";
}
if ($this->where) {
$where = "WHERE (" . implode(') AND (', $this->where) . ')';
}
$query = "SELECT {$fields} FROM {" . $this->primary_table . "} {$this->primary_table} {$joins} {$where} {$groupby} {$orderby}";
$replace = array(
'>' => '>',
'<' => '<',
);
$query = strtr($query, $replace);
return $query;
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
_views_query:: |
function | |||
_views_query:: |
function | |||
_views_query:: |
function | |||
_views_query:: |
function | |||
_views_query:: |
function | |||
_views_query:: |
function | |||
_views_query:: |
function | |||
_views_query:: |
function | |||
_views_query:: |
function | |||
_views_query:: |
function | |||
_views_query:: |
function | |||
_views_query:: |
function | |||
_views_query:: |
function | |||
_views_query:: |
function | |||
_views_query:: |
function |