class Sql extends QueryPluginBase {
var $table_queue = array();
var $tables = array();
var $relationships = array();
var $where = array();
var $having = array();
var $group_operator = 'AND';
var $orderby = array();
var $groupby = array();
var $fields = array();
var $distinct = FALSE;
var $has_aggregate = FALSE;
var $get_count_optimized = NULL;
var $field_aliases = array();
var $tags = array();
var $no_distinct;
public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
parent::init($view, $display, $options);
$base_table = $this->view->storage
->get('base_table');
$base_field = $this->view->storage
->get('base_field');
$this->relationships[$base_table] = array(
'link' => NULL,
'table' => $base_table,
'alias' => $base_table,
'base' => $base_table,
);
$this->table_queue[$base_table] = array(
'alias' => $base_table,
'table' => $base_table,
'relationship' => $base_table,
'join' => NULL,
);
$this->tables[$base_table][$base_table] = array(
'count' => 1,
'alias' => $base_table,
);
$this->count_field = array(
'table' => $base_table,
'field' => $base_field,
'alias' => $base_field,
'count' => TRUE,
);
}
protected function setDistinct($value = TRUE) {
if (!(isset($this->no_distinct) && $value)) {
$this->distinct = $value;
}
}
function set_count_field($table, $field, $alias = NULL) {
if (empty($alias)) {
$alias = $table . '_' . $field;
}
$this->count_field = array(
'table' => $table,
'field' => $field,
'alias' => $alias,
'count' => TRUE,
);
}
protected function defineOptions() {
$options = parent::defineOptions();
$options['disable_sql_rewrite'] = array(
'default' => FALSE,
'translatable' => FALSE,
'bool' => TRUE,
);
$options['distinct'] = array(
'default' => FALSE,
'bool' => TRUE,
);
$options['slave'] = array(
'default' => FALSE,
'bool' => TRUE,
);
$options['query_comment'] = array(
'default' => '',
);
$options['query_tags'] = array(
'default' => array(),
);
return $options;
}
public function buildOptionsForm(&$form, &$form_state) {
parent::buildOptionsForm($form, $form_state);
$form['disable_sql_rewrite'] = array(
'#title' => t('Disable SQL rewriting'),
'#description' => t('Disabling SQL rewriting will disable node_access checks as well as other modules that implement hook_query_alter().'),
'#type' => 'checkbox',
'#default_value' => !empty($this->options['disable_sql_rewrite']),
'#suffix' => '<div class="messages messages--warning sql-rewrite-warning js-hide">' . t('WARNING: Disabling SQL rewriting means that node access security is disabled. This may allow users to see data they should not be able to see if your view is misconfigured. Use this option only if you understand and accept this security risk.') . '</div>',
);
$form['distinct'] = array(
'#type' => 'checkbox',
'#title' => t('Distinct'),
'#description' => t('This will make the view display only distinct items. If there are multiple identical items, each will be displayed only once. You can use this to try and remove duplicates from a view, though it does not always work. Note that this can slow queries down, so use it with caution.'),
'#default_value' => !empty($this->options['distinct']),
);
$form['slave'] = array(
'#type' => 'checkbox',
'#title' => t('Use Slave Server'),
'#description' => t('This will make the query attempt to connect to a slave server if available. If no slave server is defined or available, it will fall back to the default server.'),
'#default_value' => !empty($this->options['slave']),
);
$form['query_comment'] = array(
'#type' => 'textfield',
'#title' => t('Query Comment'),
'#description' => t('If set, this comment will be embedded in the query and passed to the SQL server. This can be helpful for logging or debugging.'),
'#default_value' => $this->options['query_comment'],
);
$form['query_tags'] = array(
'#type' => 'textfield',
'#title' => t('Query Tags'),
'#description' => t('If set, these tags will be appended to the query and can be used to identify the query in a module. This can be helpful for altering queries.'),
'#default_value' => implode(', ', $this->options['query_tags']),
'#element_validate' => array(
'views_element_validate_tags',
),
);
}
public function submitOptionsForm(&$form, &$form_state) {
$element = array(
'#parents' => array(
'query',
'options',
'query_tags',
),
);
$value = explode(',', NestedArray::getValue($form_state['values'], $element['#parents']));
$value = array_filter(array_map('trim', $value));
form_set_value($element, $value, $form_state);
}
public function addRelationship($alias, JoinPluginBase $join, $base, $link_point = NULL) {
if (empty($link_point)) {
$link_point = $this->view->storage
->get('base_table');
}
elseif (!array_key_exists($link_point, $this->relationships)) {
return FALSE;
}
$alias_base = $alias;
$count = 1;
while (!empty($this->relationships[$alias])) {
$alias = $alias_base . '_' . $count++;
}
if ($link_point && isset($this->relationships[$link_point])) {
$join = $this
->adjust_join($join, $link_point);
}
$this->table_queue[$alias] = array(
'table' => $join->table,
'num' => 1,
'alias' => $alias,
'join' => $join,
'relationship' => $link_point,
);
$this->relationships[$alias] = array(
'link' => $link_point,
'table' => $join->table,
'base' => $base,
);
$this->tables[$this->view->storage
->get('base_table')][$alias] = array(
'count' => 1,
'alias' => $alias,
);
return $alias;
}
public function addTable($table, $relationship = NULL, JoinPluginBase $join = NULL, $alias = NULL) {
if (!$this
->ensurePath($table, $relationship, $join)) {
return FALSE;
}
if ($join && $relationship) {
$join = $this
->adjust_join($join, $relationship);
}
return $this
->queueTable($table, $relationship, $join, $alias);
}
public function queueTable($table, $relationship = NULL, JoinPluginBase $join = NULL, $alias = NULL) {
if (isset($this->table_queue[$alias])) {
return $alias;
}
if (empty($relationship)) {
$relationship = $this->view->storage
->get('base_table');
}
if (!array_key_exists($relationship, $this->relationships)) {
return FALSE;
}
if (!$alias && $join && $relationship && !empty($join->adjusted) && $table != $join->table) {
if ($relationship == $this->view->storage
->get('base_table')) {
$alias = $table;
}
else {
$alias = $relationship . '_' . $table;
}
}
if (isset($this->table_queue[$alias])) {
return $alias;
}
$alias = $this
->markTable($table, $relationship, $alias);
if (!isset($alias)) {
$alias = $this->tables[$relationship][$table]['alias'] . $this->tables[$relationship][$table]['count'];
}
if ($table != $alias) {
$this
->markTable($alias, $this->view->storage
->get('base_table'), $alias);
}
if (!isset($join)) {
$join = $this
->getJoinData($table, $this->relationships[$relationship]['base']);
if (empty($join)) {
return FALSE;
}
$join = $this
->adjust_join($join, $relationship);
}
$this->table_queue[$alias] = array(
'table' => $table,
'num' => $this->tables[$relationship][$table]['count'],
'alias' => $alias,
'join' => $join,
'relationship' => $relationship,
);
return $alias;
}
protected function markTable($table, $relationship, $alias) {
if (empty($this->tables[$relationship][$table])) {
if (!isset($alias)) {
$alias = '';
if ($relationship != $this->view->storage
->get('base_table')) {
$alias = $relationship . '__';
}
$alias .= $table;
}
$this->tables[$relationship][$table] = array(
'count' => 1,
'alias' => $alias,
);
}
else {
$this->tables[$relationship][$table]['count']++;
}
return $alias;
}
function ensure_table($table, $relationship = NULL, JoinPluginBase $join = NULL) {
if (empty($relationship)) {
$relationship = $this->view->storage
->get('base_table');
}
if ($relationship == $this->view->storage
->get('base_table') && !empty($this->tables[$relationship][$table])) {
return $this->tables[$relationship][$table]['alias'];
}
if (!array_key_exists($relationship, $this->relationships)) {
return FALSE;
}
if ($table == $this->relationships[$relationship]['base']) {
return $relationship;
}
if (!isset($join)) {
$join = $this
->getJoinData($table, $this->relationships[$relationship]['base']);
}
if (empty($join)) {
return;
}
$join = $this
->adjust_join($join, $relationship);
if ($this
->ensurePath($table, $relationship, $join)) {
foreach ($this->table_queue as $queued_table) {
if ($queued_table['relationship'] == $relationship && $queued_table['join'] == $join) {
return $queued_table['alias'];
}
}
return $this
->queueTable($table, $relationship, $join);
}
}
protected function ensurePath($table, $relationship = NULL, $join = NULL, $traced = array(), $add = array()) {
if (!isset($relationship)) {
$relationship = $this->view->storage
->get('base_table');
}
if (!array_key_exists($relationship, $this->relationships)) {
return FALSE;
}
if (!isset($join)) {
$join = $this
->getJoinData($table, $this->relationships[$relationship]['base']);
}
if (empty($join)) {
return FALSE;
}
if (isset($this->tables[$relationship][$table]) || $join && $join->leftTable == $relationship || $join && $join->leftTable == $this->relationships[$relationship]['table']) {
foreach (array_reverse($add) as $table => $path_join) {
$this
->queueTable($table, $relationship, $this
->adjust_join($path_join, $relationship));
}
return TRUE;
}
if (isset($traced[$join->leftTable])) {
return FALSE;
}
$left_join = $this
->getJoinData($join->leftTable, $this->relationships[$relationship]['base']);
if (!isset($this->tables[$relationship][$join->leftTable])) {
$add[$join->leftTable] = $left_join;
}
$traced[$join->leftTable] = TRUE;
return $this
->ensurePath($join->leftTable, $relationship, $left_join, $traced, $add);
}
function adjust_join($join, $relationship) {
if (!empty($join->adjusted)) {
return $join;
}
if (empty($relationship) || empty($this->relationships[$relationship])) {
return $join;
}
if ($relationship != $this->view->storage
->get('base_table')) {
$join = clone $join;
if ($join->leftTable != $this->relationships[$relationship]['table'] && $join->leftTable != $this->relationships[$relationship]['base'] && !isset($this->tables[$relationship][$join->leftTable]['alias'])) {
$this
->ensure_table($join->leftTable, $relationship);
}
if ($join->leftTable == $this->relationships[$relationship]['table']) {
$join->leftTable = $relationship;
}
elseif (isset($this->tables[$relationship][$join->leftTable]['alias'])) {
$join->leftTable = $this->tables[$relationship][$join->leftTable]['alias'];
}
elseif (isset($this->table_queue[$relationship]['alias'])) {
$join->leftTable = $this->table_queue[$relationship]['alias'];
}
}
$join->adjusted = TRUE;
return $join;
}
public function getJoinData($table, $base_table) {
if (!empty($this->table_queue[$table])) {
$table = $this->table_queue[$table]['table'];
}
return HandlerBase::getTableJoin($table, $base_table);
}
public function getTableInfo($table) {
if (!empty($this->table_queue[$table])) {
return $this->table_queue[$table];
}
if (!empty($this->tables[$this->view->storage
->get('base_table')][$table])) {
$alias = $this->tables[$this->view->storage
->get('base_table')][$table]['alias'];
if (!empty($this->table_queue[$alias])) {
return $this->table_queue[$alias];
}
}
}
public function addField($table, $field, $alias = '', $params = array()) {
if ($table == $this->view->storage
->get('base_table') && $field == $this->view->storage
->get('base_field') && empty($alias)) {
$alias = $this->view->storage
->get('base_field');
}
if ($table && empty($this->table_queue[$table])) {
$this
->ensure_table($table);
}
if (!$alias && $table) {
$alias = $table . '_' . $field;
}
$alias = $alias ? $alias : $field;
$alias = strtolower(substr($alias, 0, 60));
$field_info = array(
'field' => $field,
'table' => $table,
'alias' => $alias,
) + $params;
$base = $alias;
$counter = 0;
while (!empty($this->fields[$alias]) && $this->fields[$alias] != $field_info) {
$field_info['alias'] = $alias = $base . '_' . ++$counter;
}
if (empty($this->fields[$alias])) {
$this->fields[$alias] = $field_info;
}
$this->field_aliases[$table][$field] = $alias;
return $alias;
}
public function clearFields() {
$this->fields = array();
}
public function addWhere($group, $field, $value = NULL, $operator = NULL) {
if (empty($group)) {
$group = 0;
}
if (!isset($this->where[$group])) {
$this
->setWhereGroup('AND', $group);
}
$this->where[$group]['conditions'][] = array(
'field' => $field,
'value' => $value,
'operator' => $operator,
);
}
function add_where_expression($group, $snippet, $args = array()) {
if (empty($group)) {
$group = 0;
}
if (!isset($this->where[$group])) {
$this
->setWhereGroup('AND', $group);
}
$this->where[$group]['conditions'][] = array(
'field' => $snippet,
'value' => $args,
'operator' => 'formula',
);
}
public function addHavingExpression($group, $snippet, $args = array()) {
if (empty($group)) {
$group = 0;
}
if (!isset($this->having[$group])) {
$this
->setWhereGroup('AND', $group, 'having');
}
$this->having[$group]['conditions'][] = array(
'field' => $snippet,
'value' => $args,
'operator' => 'formula',
);
}
public function addOrderBy($table, $field = NULL, $order = 'ASC', $alias = '', $params = array()) {
if ($table && $table != 'rand') {
$this
->ensure_table($table);
}
if (!$alias && $table) {
$as = $table . '_' . $field;
}
else {
$as = $alias;
}
if ($field) {
$as = $this
->addField($table, $field, $as, $params);
}
$this->orderby[] = array(
'field' => $as,
'direction' => strtoupper($order),
);
}
public function addGroupBy($clause) {
if (!in_array($clause, $this->groupby)) {
$this->groupby[] = $clause;
}
}
protected function getFieldAlias($table_alias, $field) {
return isset($this->field_aliases[$table_alias][$field]) ? $this->field_aliases[$table_alias][$field] : FALSE;
}
public function addTag($tag) {
$this->tags[] = $tag;
}
function placeholder($base = 'views') {
static $placeholders = array();
if (!isset($placeholders[$base])) {
$placeholders[$base] = 0;
return ':' . $base;
}
else {
return ':' . $base . ++$placeholders[$base];
}
}
protected function buildCondition($where = 'where') {
$has_condition = FALSE;
$has_arguments = FALSE;
$has_filter = FALSE;
$main_group = db_and();
$filter_group = $this->group_operator == 'OR' ? db_or() : db_and();
foreach ($this->{$where} as $group => $info) {
if (!empty($info['conditions'])) {
$sub_group = $info['type'] == 'OR' ? db_or() : db_and();
foreach ($info['conditions'] as $key => $clause) {
if (is_object($clause['value']) && $clause['value'] instanceof SelectQuery) {
$clause['value'] = clone $clause['value'];
}
if ($clause['operator'] == 'formula') {
$has_condition = TRUE;
$sub_group
->where($clause['field'], $clause['value']);
}
else {
$has_condition = TRUE;
$sub_group
->condition($clause['field'], $clause['value'], $clause['operator']);
}
}
if ($group != 0) {
$has_filter = TRUE;
$filter_group
->condition($sub_group);
}
else {
$has_arguments = TRUE;
$main_group
->condition($sub_group);
}
}
}
if ($has_filter) {
$main_group
->condition($filter_group);
}
if (!$has_arguments && $has_condition) {
return $filter_group;
}
if ($has_arguments && $has_condition) {
return $main_group;
}
}
protected function getNonAggregates() {
$non_aggregates = array();
foreach ($this->fields as $field) {
$string = '';
if (!empty($field['table'])) {
$string .= $field['table'] . '.';
}
$string .= $field['field'];
$fieldname = !empty($field['alias']) ? $field['alias'] : $string;
if (!empty($field['count'])) {
$field['function'] = 'count';
}
if (!empty($field['function'])) {
$this->has_aggregate = TRUE;
}
elseif (empty($field['table'])) {
$non_aggregates[] = $fieldname;
}
elseif (empty($field['aggregate'])) {
$non_aggregates[] = $fieldname;
}
if ($this->get_count_optimized) {
break;
}
}
return $non_aggregates;
}
protected function compileFields($query) {
foreach ($this->fields as $field) {
$string = '';
if (!empty($field['table'])) {
$string .= $field['table'] . '.';
}
$string .= $field['field'];
$fieldname = !empty($field['alias']) ? $field['alias'] : $string;
if (!empty($field['count'])) {
$field['function'] = 'count';
}
if (!empty($field['function'])) {
$info = $this
->getAggregationInfo();
if (!empty($info[$field['function']]['method']) && is_callable(array(
$this,
$info[$field['function']]['method'],
))) {
$string = $this::$info[$field['function']]['method']($field['function'], $string);
$placeholders = !empty($field['placeholders']) ? $field['placeholders'] : array();
$query
->addExpression($string, $fieldname, $placeholders);
}
$this->has_aggregate = TRUE;
}
elseif (empty($field['table'])) {
$placeholders = !empty($field['placeholders']) ? $field['placeholders'] : array();
$query
->addExpression($string, $fieldname, $placeholders);
}
elseif ($this->distinct && !in_array($fieldname, $this->groupby)) {
$query
->addField(!empty($field['table']) ? $field['table'] : $this->view->storage
->get('base_table'), $field['field'], $fieldname);
}
elseif (empty($field['aggregate'])) {
$query
->addField(!empty($field['table']) ? $field['table'] : $this->view->storage
->get('base_table'), $field['field'], $fieldname);
}
if ($this->get_count_optimized) {
break;
}
}
}
public function query($get_count = FALSE) {
if (empty($this->no_distinct) && $this->distinct && !empty($this->fields)) {
$base_field_alias = $this
->addField($this->view->storage
->get('base_table'), $this->view->storage
->get('base_field'));
$this
->addGroupBy($base_field_alias);
$distinct = TRUE;
}
if ($get_count && !$this->groupby) {
foreach ($this->fields as $field) {
if (!empty($field['distinct']) || !empty($field['function'])) {
$this->get_count_optimized = FALSE;
break;
}
}
}
else {
$this->get_count_optimized = FALSE;
}
if (!isset($this->get_count_optimized)) {
$this->get_count_optimized = TRUE;
}
$options = array();
$target = 'default';
$key = 'default';
if (isset($this->view->base_database)) {
$key = $this->view->base_database;
}
if (!empty($this->options['slave'])) {
$target = 'slave';
}
$query = Database::getConnection($target, $key)
->select($this->view->storage
->get('base_table'), $this->view->storage
->get('base_table'), $options)
->addTag('views')
->addTag('views_' . $this->view->storage
->id());
foreach ($this->tags as $tag) {
$query
->addTag($tag);
}
if (!empty($distinct)) {
$query
->distinct();
}
$joins = $where = $having = $orderby = $groupby = '';
$fields = $distinct = array();
foreach ($this->table_queue as $table) {
if (is_object($table['join'])) {
$table['join']
->buildJoin($query, $table, $this);
}
}
$this->has_aggregate = FALSE;
$non_aggregates = $this
->getNonAggregates();
if (count($this->having)) {
$this->has_aggregate = TRUE;
}
$groupby = array();
if ($this->has_aggregate && (!empty($this->groupby) || !empty($non_aggregates))) {
$groupby = array_unique(array_merge($this->groupby, $non_aggregates));
}
$entity_tables = $this
->getEntityTables();
if ($entity_tables) {
$params = array();
if ($groupby) {
$params = array(
'function' => 'min',
);
}
foreach ($entity_tables as $table_alias => $table) {
$info = entity_get_info($table['entity_type']);
$base_field = empty($table['revision']) ? $info['entity_keys']['id'] : $info['entity_keys']['revision'];
$this
->addField($table_alias, $base_field, '', $params);
}
}
$this
->compileFields($query);
if ($groupby) {
foreach ($groupby as $field) {
$query
->groupBy($field);
}
if (!empty($this->having) && ($condition = $this
->buildCondition('having'))) {
$query
->havingCondition($condition);
}
}
if (!$this->get_count_optimized) {
if ($this->orderby) {
foreach ($this->orderby as $order) {
if ($order['field'] == 'rand_') {
$query
->orderRandom();
}
else {
$query
->orderBy($order['field'], $order['direction']);
}
}
}
}
if (!empty($this->where) && ($condition = $this
->buildCondition('where'))) {
$query
->condition($condition);
}
if (!empty($this->options['query_comment'])) {
$query
->comment($this->options['query_comment']);
}
if (!empty($this->options['query_tags'])) {
foreach ($this->options['query_tags'] as $tag) {
$query
->addTag($tag);
}
}
$query
->addMetaData('views_substitutions', \Drupal::moduleHandler()
->invokeAll('views_query_substitutions', array(
$this->view,
)));
return $query;
}
function get_where_args() {
$args = array();
foreach ($this->where as $group => $where) {
$args = array_merge($args, $where['args']);
}
foreach ($this->having as $group => $having) {
$args = array_merge($args, $having['args']);
}
return $args;
}
function alter(ViewExecutable $view) {
\Drupal::moduleHandler()
->invokeAll('views_query_alter', array(
$view,
$this,
));
}
function build(ViewExecutable $view) {
if (!empty($this->options['distinct'])) {
$this
->setDistinct(TRUE);
}
$this->view = $view;
$view
->initPager();
$view->pager
->query();
$view->build_info['query'] = $this
->query();
$view->build_info['count_query'] = $this
->query(TRUE);
}
function execute(ViewExecutable $view) {
$external = FALSE;
$query = $view->build_info['query'];
$count_query = $view->build_info['count_query'];
$query
->addMetaData('view', $view);
$count_query
->addMetaData('view', $view);
if (empty($this->options['disable_sql_rewrite'])) {
$base_table_data = Views::viewsData()
->get($this->view->storage
->get('base_table'));
if (isset($base_table_data['table']['base']['access query tag'])) {
$access_tag = $base_table_data['table']['base']['access query tag'];
$query
->addTag($access_tag);
$count_query
->addTag($access_tag);
}
}
$items = array();
if ($query) {
$additional_arguments = \Drupal::moduleHandler()
->invokeAll('views_query_substitutions', array(
$view,
));
$count_query
->preExecute();
$count_query = $count_query
->countQuery();
if (!empty($additional_arguments)) {
}
$start = microtime(TRUE);
try {
if ($view->pager
->useCountQuery() || !empty($view->get_total_rows)) {
$view->pager
->executeCountQuery($count_query);
}
$view->pager
->preExecute($query);
if (!empty($this->limit) || !empty($this->offset)) {
$limit = intval(!empty($this->limit) ? $this->limit : 999999);
$offset = intval(!empty($this->offset) ? $this->offset : 0);
$query
->range($offset, $limit);
}
$result = $query
->execute();
$view->result = array();
foreach ($result as $item) {
$view->result[] = $item;
}
$view->pager
->postExecute($view->result);
if ($view->pager
->useCountQuery() || !empty($view->get_total_rows)) {
$view->total_rows = $view->pager
->getTotalItems();
}
$this
->loadEntities($view->result);
} catch (DatabaseExceptionWrapper $e) {
$view->result = array();
if (!empty($view->live_preview)) {
drupal_set_message($e
->getMessage(), 'error');
}
else {
throw new DatabaseExceptionWrapper(format_string('Exception in @label[@view_name]: @message', array(
'@label' => $view->storage
->label(),
'@view_name' => $view->storage
->id(),
'@message' => $e
->getMessage(),
)));
}
}
}
else {
$start = microtime(TRUE);
}
$view->execute_time = microtime(TRUE) - $start;
}
public function getEntityTables() {
$entity_tables = array();
$views_data = Views::viewsData();
$base_table_data = $views_data
->get($this->view->storage
->get('base_table'));
if (isset($base_table_data['table']['entity type'])) {
$entity_tables[$this->view->storage
->get('base_table')] = array(
'base' => $this->view->storage
->get('base_table'),
'relationship_id' => 'none',
'entity_type' => $base_table_data['table']['entity type'],
'revision' => FALSE,
);
}
foreach ($this->view->relationship as $relationship_id => $relationship) {
$table_data = $views_data
->get($relationship->definition['base']);
if (isset($table_data['table']['entity type'])) {
$entity_tables[$relationship->alias] = array(
'base' => $relationship->definition['base'],
'relationship_id' => $relationship_id,
'entity_type' => $table_data['table']['entity type'],
'revision' => FALSE,
);
}
}
foreach ($entity_tables as $table_alias => $table) {
$info = entity_get_info($table['entity_type']);
if (isset($info['revision table']) && $info['revision table'] == $table['base']) {
$entity_tables[$table_alias]['revision'] = TRUE;
}
}
return $entity_tables;
}
function loadEntities(&$results) {
$entity_tables = $this
->getEntityTables();
if (empty($entity_tables)) {
return;
}
foreach ($results as $index => $result) {
$results[$index]->_entity = FALSE;
$results[$index]->_relationship_entities = array();
}
$ids_by_table = array();
foreach ($entity_tables as $table_alias => $table) {
$entity_type = $table['entity_type'];
$info = entity_get_info($entity_type);
$id_key = empty($table['revision']) ? $info['entity_keys']['id'] : $info['entity_keys']['revision'];
$id_alias = $this
->getFieldAlias($table_alias, $id_key);
foreach ($results as $index => $result) {
if (isset($result->{$id_alias}) && $result->{$id_alias} != '') {
$ids_by_table[$table_alias][$index] = $result->{$id_alias};
}
}
}
foreach ($ids_by_table as $table_alias => $ids) {
$table = $entity_tables[$table_alias];
$entity_type = $table['entity_type'];
$relationship_id = $table['relationship_id'];
if ($table['revision']) {
$entities = array();
foreach ($ids as $index => $revision_id) {
$entity = entity_revision_load($entity_type, $revision_id);
if ($entity) {
$entities[$revision_id] = $entity;
}
}
}
else {
$entities = entity_load_multiple($entity_type, $ids);
}
foreach ($ids as $index => $id) {
$entity = isset($entities[$id]) ? $entities[$id] : FALSE;
if ($relationship_id == 'none') {
$results[$index]->_entity = $entity;
}
else {
$results[$index]->_relationship_entities[$relationship_id] = $entity;
}
}
}
}
public function addSignature(ViewExecutable $view) {
$view->query
->addField(NULL, "'" . $view->storage
->id() . ':' . $view->current_display . "'", 'view_name');
}
public function getAggregationInfo() {
return array(
'group' => array(
'title' => t('Group results together'),
'is aggregate' => FALSE,
),
'count' => array(
'title' => t('Count'),
'method' => 'aggregationMethodSimple',
'handler' => array(
'argument' => 'groupby_numeric',
'field' => 'numeric',
'filter' => 'groupby_numeric',
'sort' => 'groupby_numeric',
),
),
'count_distinct' => array(
'title' => t('Count DISTINCT'),
'method' => 'aggregationMethodDistinct',
'handler' => array(
'argument' => 'groupby_numeric',
'field' => 'numeric',
'filter' => 'groupby_numeric',
'sort' => 'groupby_numeric',
),
),
'sum' => array(
'title' => t('Sum'),
'method' => 'aggregationMethodSimple',
'handler' => array(
'argument' => 'groupby_numeric',
'field' => 'numeric',
'filter' => 'groupby_numeric',
'sort' => 'groupby_numeric',
),
),
'avg' => array(
'title' => t('Average'),
'method' => 'aggregationMethodSimple',
'handler' => array(
'argument' => 'groupby_numeric',
'field' => 'numeric',
'filter' => 'groupby_numeric',
'sort' => 'groupby_numeric',
),
),
'min' => array(
'title' => t('Minimum'),
'method' => 'aggregationMethodSimple',
'handler' => array(
'argument' => 'groupby_numeric',
'field' => 'numeric',
'filter' => 'groupby_numeric',
'sort' => 'groupby_numeric',
),
),
'max' => array(
'title' => t('Maximum'),
'method' => 'aggregationMethodSimple',
'handler' => array(
'argument' => 'groupby_numeric',
'field' => 'numeric',
'filter' => 'groupby_numeric',
'sort' => 'groupby_numeric',
),
),
'stddev_pop' => array(
'title' => t('Standard deviation'),
'method' => 'aggregationMethodSimple',
'handler' => array(
'argument' => 'groupby_numeric',
'field' => 'numeric',
'filter' => 'groupby_numeric',
'sort' => 'groupby_numeric',
),
),
);
}
public function aggregationMethodSimple($group_type, $field) {
return strtoupper($group_type) . '(' . $field . ')';
}
public function aggregationMethodDistinct($group_type, $field) {
$group_type = str_replace('_distinct', '', $group_type);
return strtoupper($group_type) . '(DISTINCT ' . $field . ')';
}
public function getDateField($field) {
$db_type = Database::getConnection()
->databaseType();
$offset = $this
->setupTimezone();
if (isset($offset) && !is_numeric($offset)) {
$dtz = new \DateTimeZone($offset);
$dt = new \DateTime('now', $dtz);
$offset_seconds = $dtz
->getOffset($dt);
}
switch ($db_type) {
case 'mysql':
$field = "DATE_ADD('19700101', INTERVAL {$field} SECOND)";
if (!empty($offset)) {
$field = "({$field} + INTERVAL {$offset_seconds} SECOND)";
}
break;
case 'pgsql':
$field = "TO_TIMESTAMP({$field})";
if (!empty($offset)) {
$field = "({$field} + INTERVAL '{$offset_seconds} SECONDS')";
}
break;
case 'sqlite':
if (!empty($offset)) {
$field = "({$field} + '{$offset_seconds}')";
}
break;
}
return $field;
}
public function setupTimezone() {
$timezone = drupal_get_user_timezone();
$db_type = Database::getConnection()
->databaseType();
if (in_array($db_type, array(
'mysql',
'pgsql',
))) {
$offset = '+00:00';
static $already_set = FALSE;
if (!$already_set) {
if ($db_type == 'pgsql') {
Database::getConnection()
->query("SET TIME ZONE INTERVAL '{$offset}' HOUR TO MINUTE");
}
elseif ($db_type == 'mysql') {
Database::getConnection()
->query("SET @@session.time_zone = '{$offset}'");
}
$already_set = TRUE;
}
}
return $timezone;
}
public function getDateFormat($field, $format) {
$db_type = Database::getConnection()
->databaseType();
switch ($db_type) {
case 'mysql':
$replace = array(
'Y' => '%Y',
'y' => '%y',
'M' => '%b',
'm' => '%m',
'n' => '%c',
'F' => '%M',
'D' => '%a',
'd' => '%d',
'l' => '%W',
'j' => '%e',
'W' => '%v',
'H' => '%H',
'h' => '%h',
'i' => '%i',
's' => '%s',
'A' => '%p',
);
$format = strtr($format, $replace);
return "DATE_FORMAT({$field}, '{$format}')";
case 'pgsql':
$replace = array(
'Y' => 'YYYY',
'y' => 'YY',
'M' => 'Mon',
'm' => 'MM',
'n' => 'MM',
'F' => 'Month',
'D' => 'Dy',
'd' => 'DD',
'l' => 'Day',
'j' => 'DD',
'W' => 'WW',
'H' => 'HH24',
'h' => 'HH12',
'i' => 'MI',
's' => 'SS',
'A' => 'AM',
);
$format = strtr($format, $replace);
return "TO_CHAR({$field}, '{$format}')";
case 'sqlite':
$replace = array(
'Y' => '%Y',
'y' => '%Y',
'M' => '%m',
'm' => '%m',
'n' => '%m',
'F' => '%m',
'D' => '%d',
'd' => '%d',
'l' => '%d',
'j' => '%d',
'W' => '%W',
'H' => '%H',
'h' => '%H',
'i' => '%M',
's' => '%S',
'A' => '',
);
$format = strtr($format, $replace);
return "strftime('{$format}', {$field}, 'unixepoch')";
}
}
}