00001 <?php
00011 class views_plugin_query_default extends views_plugin_query {
00012
00016 var $table_queue = array();
00017
00021 var $tables = array();
00022
00027 var $relationships = array();
00028
00034 var $where = array();
00040 var $having = array();
00045 var $group_operator = 'AND';
00046
00050 var $orderby = array();
00051
00055 var $groupby = array();
00056
00061 var $header = array();
00062
00066 var $distinct = FALSE;
00067
00068 var $has_aggregate = FALSE;
00069
00073 var $get_count_optimized = NULL;
00074
00080 var $pager = NULL;
00081
00085 var $field_aliases = array();
00086
00090 var $tags = array();
00091
00095 function init($base_table = 'node', $base_field = 'nid', $options) {
00096 parent::init($base_table, $base_field, $options);
00097 $this->base_table = $base_table;
00098 $this->base_field = $base_field;
00099 $this->relationships[$base_table] = array(
00100 'link' => NULL,
00101 'table' => $base_table,
00102 'alias' => $base_table,
00103 'base' => $base_table
00104 );
00105
00106
00107 $this->table_queue[$base_table] = array(
00108 'alias' => $base_table,
00109 'table' => $base_table,
00110 'relationship' => $base_table,
00111 'join' => NULL,
00112 );
00113
00114
00115 $this->tables[$base_table][$base_table] = array(
00116 'count' => 1,
00117 'alias' => $base_table,
00118 );
00119
00131 $this->count_field = array(
00132 'table' => $base_table,
00133 'field' => $base_field,
00134 'alias' => $base_field,
00135 'count' => TRUE,
00136 );
00137 }
00138
00139
00140
00141
00145 function set_distinct($value = TRUE) {
00146 if (!(isset($this->no_distinct) && $value)) {
00147 $this->distinct = $value;
00148 }
00149 }
00150
00154 function set_count_field($table, $field, $alias = NULL) {
00155 if (empty($alias)) {
00156 $alias = $table . '_' . $field;
00157 }
00158 $this->count_field = array(
00159 'table' => $table,
00160 'field' => $field,
00161 'alias' => $alias,
00162 'count' => TRUE,
00163 );
00164 }
00165
00170 function set_header($header) {
00171 $this->header = $header;
00172 }
00173
00174 function option_definition() {
00175 $options = parent::option_definition();
00176 $options['disable_sql_rewrite'] = array(
00177 'default' => FALSE,
00178 'translatable' => FALSE,
00179 'bool' => TRUE,
00180 );
00181 $options['distinct'] = array(
00182 'default' => FALSE,
00183 'bool' => TRUE,
00184 );
00185 $options['slave'] = array(
00186 'default' => FALSE,
00187 'bool' => TRUE,
00188 );
00189 $options['query_comment'] = array(
00190 'default' => '',
00191 'bool' => FALSE,
00192 );
00193
00194 return $options;
00195 }
00196
00200 function options_form(&$form, &$form_state) {
00201 parent::options_form($form, $form_state);
00202
00203 $form['disable_sql_rewrite'] = array(
00204 '#title' => t('Disable SQL rewriting'),
00205 '#description' => t('Disabling SQL rewriting will disable node_access checks as well as other modules that implement hook_query_alter().'),
00206 '#type' => 'checkbox',
00207 '#default_value' => !empty($this->options['disable_sql_rewrite']),
00208 '#suffix' => '<div class="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. Please use this option only if you understand and accept this security risk.') . '</div>',
00209 );
00210 $form['distinct'] = array(
00211 '#type' => 'checkbox',
00212 '#title' => t('Distinct'),
00213 '#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.'),
00214 '#default_value' => !empty($this->options['distinct']),
00215 );
00216 $form['slave'] = array(
00217 '#type' => 'checkbox',
00218 '#title' => t('Use Slave Server'),
00219 '#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.'),
00220 '#default_value' => !empty($this->options['slave']),
00221 );
00222 $form['query_comment'] = array(
00223 '#type' => 'textfield',
00224 '#title' => t('Query Comment'),
00225 '#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.'),
00226 '#default_value' => $this->options['query_comment'],
00227 );
00228 }
00229
00230
00231
00232
00261 function add_relationship($alias, $join, $base, $link_point = NULL) {
00262 if (empty($link_point)) {
00263 $link_point = $this->base_table;
00264 }
00265 elseif (!array_key_exists($link_point, $this->relationships)) {
00266 return FALSE;
00267 }
00268
00269
00270 $alias_base = $alias;
00271 $count = 1;
00272 while (!empty($this->relationships[$alias])) {
00273 $alias = $alias_base . '_' . $count++;
00274 }
00275
00276
00277 if ($link_point && isset($this->relationships[$link_point])) {
00278 $join = $this->adjust_join($join, $link_point);
00279 }
00280
00281
00282
00283 $this->table_queue[$alias] = array(
00284 'table' => $join->table,
00285 'num' => 1,
00286 'alias' => $alias,
00287 'join' => $join,
00288 'relationship' => $link_point,
00289 );
00290
00291 $this->relationships[$alias] = array(
00292 'link' => $link_point,
00293 'table' => $join->table,
00294 'base' => $base,
00295 );
00296
00297 $this->tables[$this->base_table][$alias] = array(
00298 'count' => 1,
00299 'alias' => $alias,
00300 );
00301
00302 return $alias;
00303 }
00304
00335 function add_table($table, $relationship = NULL, $join = NULL, $alias = NULL) {
00336 if (!$this->ensure_path($table, $relationship, $join)) {
00337 return FALSE;
00338 }
00339
00340 if ($join && $relationship) {
00341 $join = $this->adjust_join($join, $relationship);
00342 }
00343
00344 return $this->queue_table($table, $relationship, $join, $alias);
00345 }
00346
00374 function queue_table($table, $relationship = NULL, $join = NULL, $alias = NULL) {
00375
00376 if (isset($this->table_queue[$alias])) {
00377 return $alias;
00378 }
00379
00380 if (empty($relationship)) {
00381 $relationship = $this->base_table;
00382 }
00383
00384 if (!array_key_exists($relationship, $this->relationships)) {
00385 return FALSE;
00386 }
00387
00388 if (!$alias && $join && $relationship && !empty($join->adjusted) && $table != $join->table) {
00389 if ($relationship == $this->base_table) {
00390 $alias = $table;
00391 }
00392 else {
00393 $alias = $relationship . '_' . $table;
00394 }
00395 }
00396
00397
00398
00399 if (isset($this->table_queue[$alias])) {
00400 return $alias;
00401 }
00402
00403 $alias = $this->mark_table($table, $relationship, $alias);
00404
00405
00406 if (!isset($alias)) {
00407 $alias = $this->tables[$relationship][$table]['alias'] . $this->tables[$relationship][$table]['count'];
00408 }
00409
00410
00411
00412 if ($table != $alias) {
00413 $this->mark_table($alias, $this->base_table, $alias);
00414 }
00415
00416
00417 if (!isset($join)) {
00418 $join = $this->get_join_data($table, $this->relationships[$relationship]['base']);
00419 if (empty($join)) {
00420 return FALSE;
00421 }
00422
00423 $join = $this->adjust_join($join, $relationship);
00424 }
00425
00426 $this->table_queue[$alias] = array(
00427 'table' => $table,
00428 'num' => $this->tables[$relationship][$table]['count'],
00429 'alias' => $alias,
00430 'join' => $join,
00431 'relationship' => $relationship,
00432 );
00433
00434 return $alias;
00435 }
00436
00437 function mark_table($table, $relationship, $alias) {
00438
00439 if (empty($this->tables[$relationship][$table])) {
00440 if (!isset($alias)) {
00441 $alias = '';
00442 if ($relationship != $this->base_table) {
00443
00444
00445 $alias = $relationship . '__';
00446 }
00447 $alias .= $table;
00448 }
00449 $this->tables[$relationship][$table] = array(
00450 'count' => 1,
00451 'alias' => $alias,
00452 );
00453 }
00454 else {
00455 $this->tables[$relationship][$table]['count']++;
00456 }
00457
00458 return $alias;
00459 }
00460
00479 function ensure_table($table, $relationship = NULL, $join = NULL) {
00480
00481 if (empty($relationship)) {
00482 $relationship = $this->base_table;
00483 }
00484
00485
00486
00487
00488
00489 if ($relationship == $this->base_table && !empty($this->tables[$relationship][$table])) {
00490 return $this->tables[$relationship][$table]['alias'];
00491 }
00492
00493 if (!array_key_exists($relationship, $this->relationships)) {
00494 return FALSE;
00495 }
00496
00497 if ($table == $this->relationships[$relationship]['base']) {
00498 return $relationship;
00499 }
00500
00501
00502 if (!isset($join)) {
00503 $join = $this->get_join_data($table, $this->relationships[$relationship]['base']);
00504 }
00505
00506
00507 if (empty($join)) {
00508 return;
00509 }
00510
00511
00512
00513
00514 $join = $this->adjust_join($join, $relationship);
00515
00516 if ($this->ensure_path($table, $relationship, $join)) {
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538 foreach ($this->table_queue as $queued_table) {
00539
00540
00541
00542 if ($queued_table['relationship'] == $relationship && $queued_table['join'] == $join) {
00543 return $queued_table['alias'];
00544 }
00545 }
00546
00547 return $this->queue_table($table, $relationship, $join);
00548 }
00549 }
00550
00558 function ensure_path($table, $relationship = NULL, $join = NULL, $traced = array(), $add = array()) {
00559 if (!isset($relationship)) {
00560 $relationship = $this->base_table;
00561 }
00562
00563 if (!array_key_exists($relationship, $this->relationships)) {
00564 return FALSE;
00565 }
00566
00567
00568 if (!isset($join)) {
00569 $join = $this->get_join_data($table, $this->relationships[$relationship]['base']);
00570 }
00571
00572
00573 if (empty($join)) {
00574 return FALSE;
00575 }
00576
00577
00578 if (isset($this->tables[$relationship][$table]) ||
00579 ($join && $join->left_table == $relationship) ||
00580 ($join && $join->left_table == $this->relationships[$relationship]['table'])) {
00581
00582
00583 foreach (array_reverse($add) as $table => $path_join) {
00584 $this->queue_table($table, $relationship, $this->adjust_join($path_join, $relationship));
00585 }
00586 return TRUE;
00587 }
00588
00589
00590 if (isset($traced[$join->left_table])) {
00591
00592 return FALSE;
00593 }
00594
00595
00596 $left_join = $this->get_join_data($join->left_table, $this->relationships[$relationship]['base']);
00597 if (!isset($this->tables[$relationship][$join->left_table])) {
00598 $add[$join->left_table] = $left_join;
00599 }
00600
00601
00602 $traced[$join->left_table] = TRUE;
00603 return $this->ensure_path($join->left_table, $relationship, $left_join, $traced, $add);
00604 }
00605
00610 function adjust_join($join, $relationship) {
00611 if (!empty($join->adjusted)) {
00612 return $join;
00613 }
00614
00615 if (empty($relationship) || empty($this->relationships[$relationship])) {
00616 return $join;
00617 }
00618
00619
00620 if ($relationship != $this->base_table) {
00621
00622
00623
00624
00625 $join = clone $join;
00626
00627
00628 if ($join->left_table != $this->relationships[$relationship]['table'] &&
00629 $join->left_table != $this->relationships[$relationship]['base'] &&
00630 !isset($this->tables[$relationship][$join->left_table]['alias'])) {
00631 $this->ensure_table($join->left_table, $relationship);
00632 }
00633
00634
00635 if ($join->left_table == $this->relationships[$relationship]['table']) {
00636 $join->left_table = $relationship;
00637 }
00638
00639 elseif (isset($this->tables[$relationship][$join->left_table]['alias'])) {
00640 $join->left_table = $this->tables[$relationship][$join->left_table]['alias'];
00641 }
00642
00643 elseif (isset($this->table_queue[$relationship]['alias'])) {
00644 $join->left_table = $this->table_queue[$relationship]['alias'];
00645 }
00646 }
00647
00648 $join->adjusted = TRUE;
00649 return $join;
00650 }
00651
00663 function get_join_data($table, $base_table) {
00664
00665
00666 if (!empty($this->table_queue[$table])) {
00667 $table = $this->table_queue[$table]['table'];
00668 }
00669 return views_get_table_join($table, $base_table);
00670 }
00671
00678 function get_table_info($table) {
00679 if (!empty($this->table_queue[$table])) {
00680 return $this->table_queue[$table];
00681 }
00682
00683
00684 if (!empty($this->tables[$this->base_table][$table])) {
00685 $alias = $this->tables[$this->base_table][$table]['alias'];
00686 if (!empty($this->table_queue[$alias])) {
00687 return $this->table_queue[$alias];
00688 }
00689 }
00690 }
00691
00714 function add_field($table, $field, $alias = '', $params = array()) {
00715
00716 if ($table == $this->base_table && $field == $this->base_field && empty($alias)) {
00717 $alias = $this->base_field;
00718 }
00719
00720 if ($table && empty($this->table_queue[$table])) {
00721 $this->ensure_table($table);
00722 }
00723
00724 if (!$alias && $table) {
00725 $alias = $table . '_' . $field;
00726 }
00727
00728
00729 $alias = $alias ? $alias : $field;
00730
00731
00732
00733
00734
00735 $alias = strtolower(substr($alias, 0, 60));
00736
00737
00738 $field_info = array(
00739 'field' => $field,
00740 'table' => $table,
00741 'alias' => $alias,
00742 ) + $params;
00743
00744
00745
00746
00747 $base = $alias;
00748 $counter = 0;
00749 while (!empty($this->fields[$alias]) && $this->fields[$alias] != $field_info) {
00750 $field_info['alias'] = $alias = $base . '_' . ++$counter;
00751 }
00752
00753 if (empty($this->fields[$alias])) {
00754 $this->fields[$alias] = $field_info;
00755 }
00756
00757
00758 $this->field_aliases[$table][$field] = $alias;
00759
00760 return $alias;
00761 }
00762
00767 function clear_fields() {
00768 $this->fields = array();
00769 }
00770
00793 function add_where($group, $field, $value = NULL, $operator = NULL) {
00794
00795
00796 if (empty($group)) {
00797 $group = 0;
00798 }
00799
00800
00801 if (!isset($this->where[$group])) {
00802 $this->set_where_group('AND', $group);
00803 }
00804
00805 $this->where[$group]['conditions'][] = array(
00806 'field' => $field,
00807 'value' => $value,
00808 'operator' => $operator,
00809 );
00810 }
00811
00831 function add_where_expression($group, $snippet, $args = array()) {
00832
00833
00834 if (empty($group)) {
00835 $group = 0;
00836 }
00837
00838
00839 if (!isset($this->where[$group])) {
00840 $this->set_where_group('AND', $group);
00841 }
00842
00843 $this->where[$group]['conditions'][] = array(
00844 'field' => $snippet,
00845 'value' => $args,
00846 'operator' => 'formula',
00847 );
00848 }
00849
00874 function add_having($group, $field, $value = NULL, $operator = NULL) {
00875
00876
00877 if (empty($group)) {
00878 $group = 0;
00879 }
00880
00881
00882 if (!isset($this->having[$group])) {
00883 $this->set_where_group('AND', $group, 'having');
00884 }
00885
00886
00887 $this->having[$group]['conditions'][] = array(
00888 'field' => $field,
00889 'value' => $value,
00890 'operator' => $operator,
00891 );
00892 }
00893
00912 function add_having_expression($group, $snippet, $args = array()) {
00913
00914
00915 if (empty($group)) {
00916 $group = 0;
00917 }
00918
00919
00920 if (!isset($this->having[$group])) {
00921 $this->set_where_group('AND', $group, 'having');
00922 }
00923
00924
00925 $this->having[$group]['conditions'][] = array(
00926 'field' => $snippet,
00927 'value' => $args,
00928 'operator' => 'formula',
00929 );
00930 }
00931
00951 function add_orderby($table, $field = NULL, $order = 'ASC', $alias = '', $params = array()) {
00952
00953
00954 if ($table && $table != 'rand') {
00955 $this->ensure_table($table);
00956 }
00957
00958
00959
00960 if (!$alias && $table) {
00961 $as = $table . '_' . $field;
00962 }
00963 else {
00964 $as = $alias;
00965 }
00966
00967 if ($field) {
00968 $as = $this->add_field($table, $field, $as, $params);
00969 }
00970
00971 $this->orderby[] = array(
00972 'field' => $as,
00973 'direction' => strtoupper($order)
00974 );
00975
00986 }
00987
00993 function add_groupby($clause) {
00994
00995 if (!in_array($clause, $this->groupby)) {
00996 $this->groupby[] = $clause;
00997 }
00998 }
00999
01005 function get_field_alias($table_alias, $field) {
01006 return isset($this->field_aliases[$table_alias][$field]) ? $this->field_aliases[$table_alias][$field] : FALSE;
01007 }
01008
01014 function add_tag($tag) {
01015 $this->tags[] = $tag;
01016 }
01017
01021 function placeholder($base = 'views') {
01022 static $placeholders = array();
01023 if (!isset($placeholders[$base])) {
01024 $placeholders[$base] = 0;
01025 return ':' . $base;
01026 }
01027 else {
01028 return ':' . $base . ++$placeholders[$base];
01029 }
01030 }
01031
01043 function build_condition($where = 'where') {
01044 $has_condition = FALSE;
01045 $has_arguments = FALSE;
01046 $has_filter = FALSE;
01047
01048 $main_group = db_and();
01049 $filter_group = $this->group_operator == 'OR' ? db_or() : db_and();
01050
01051 foreach ($this->$where as $group => $info) {
01052
01053 if (!empty($info['conditions'])) {
01054 $sub_group = $info['type'] == 'OR' ? db_or() : db_and();
01055 foreach ($info['conditions'] as $key => $clause) {
01056
01057
01058
01059 if (is_object($clause['value']) && $clause['value'] instanceof SelectQuery) {
01060 $clause['value'] = clone $clause['value'];
01061 }
01062 if ($clause['operator'] == 'formula') {
01063 $has_condition = TRUE;
01064 $sub_group->where($clause['field'], $clause['value']);
01065 }
01066 else {
01067 $has_condition = TRUE;
01068 $sub_group->condition($clause['field'], $clause['value'], $clause['operator']);
01069 }
01070 }
01071
01072
01073 if ($group != 0) {
01074 $has_filter = TRUE;
01075 $filter_group->condition($sub_group);
01076 }
01077 else {
01078 $has_arguments = TRUE;
01079 $main_group->condition($sub_group);
01080 }
01081 }
01082 }
01083
01084 if ($has_filter) {
01085 $main_group->condition($filter_group);
01086 }
01087
01088 if (!$has_arguments && $has_condition) {
01089 return $filter_group;
01090 }
01091 if ($has_arguments && $has_condition) {
01092 return $main_group;
01093 }
01094 }
01095
01099 function compile_fields($fields_array, $query) {
01100 $non_aggregates = array();
01101 foreach ($fields_array as $field) {
01102 $string = '';
01103 if (!empty($field['table'])) {
01104 $string .= $field['table'] . '.';
01105 }
01106 $string .= $field['field'];
01107 $fieldname = (!empty($field['alias']) ? $field['alias'] : $string);
01108
01109 if (!empty($field['distinct'])) {
01110 throw new Exception("Column-level distinct is not supported anymore.");
01111 }
01112
01113 if (!empty($field['count'])) {
01114
01115 $field['function'] = 'count';
01116
01117
01118 }
01119
01120 if (!empty($field['function'])) {
01121 $info = $this->get_aggregation_info();
01122 if (!empty($info[$field['function']]['method']) && function_exists($info[$field['function']]['method'])) {
01123 $string = $info[$field['function']]['method']($field['function'], $string);
01124 $placeholders = !empty($field['placeholders']) ? $field['placeholders'] : array();
01125 $query->addExpression($string, $fieldname, $placeholders);
01126 }
01127
01128 $this->has_aggregate = TRUE;
01129 }
01130
01131 elseif (empty($field['table'])) {
01132 $placeholders = !empty($field['placeholders']) ? $field['placeholders'] : array();
01133 $query->addExpression($string, $fieldname, $placeholders);
01134 }
01135
01136 elseif ($this->distinct && !in_array($fieldname, $this->groupby)) {
01137
01138
01139 $query->addField(!empty($field['table']) ? $field['table'] : $this->base_table, $field['field'], $fieldname);
01140 }
01141 elseif (empty($field['aggregate'])) {
01142 $non_aggregates[] = $fieldname;
01143 $query->addField(!empty($field['table']) ? $field['table'] : $this->base_table, $field['field'], $fieldname);
01144 }
01145
01146
01147 if (!empty($field['distinct']) && empty($field['function'])) {
01148 $distinct[] = $string;
01149 }
01150 else {
01151 $fields[] = $string;
01152 }
01153
01154 if ($this->get_count_optimized) {
01155
01156 break;
01157 }
01158 }
01159 return array(
01160 $non_aggregates,
01161 );
01162 }
01163
01171 function query($get_count = FALSE) {
01172
01173 if (empty($this->no_distinct) && $this->distinct && !empty($this->fields)) {
01174 $base_field_alias = $this->add_field($this->base_table, $this->base_field);
01175 $this->add_groupby($base_field_alias);
01176 $distinct = TRUE;
01177 }
01178
01183 $fields_array = $this->fields;
01184 if ($get_count && !$this->groupby) {
01185 foreach ($fields_array as $field) {
01186 if (!empty($field['distinct']) || !empty($field['function'])) {
01187 $this->get_count_optimized = FALSE;
01188 break;
01189 }
01190 }
01191 }
01192 else {
01193 $this->get_count_optimized = FALSE;
01194 }
01195 if (!isset($this->get_count_optimized)) {
01196 $this->get_count_optimized = TRUE;
01197 }
01198
01199 $options = array();
01200 $target = 'default';
01201 $key = 'default';
01202
01203 if (isset($this->view->base_database)) {
01204 $key = $this->view->base_database;
01205 }
01206
01207
01208 if (!empty($this->options['slave'])) {
01209 $target = 'slave';
01210 }
01211
01212
01213
01214 $query = Database::getConnection($target, $key)
01215 ->select($this->base_table, $this->base_table, $options)
01216 ->addTag('views')
01217 ->addTag('views_' . $this->view->name);
01218
01219
01220 foreach ($this->tags as $tag) {
01221 $query->addTag($tag);
01222 }
01223
01224 if (!empty($distinct)) {
01225 $query->distinct();
01226 }
01227
01228 $joins = $where = $having = $orderby = $groupby = '';
01229 $fields = $distinct = array();
01230
01231
01232 foreach ($this->table_queue as $table) {
01233 if (is_object($table['join'])) {
01234 $table['join']->build_join($query, $table, $this);
01235 }
01236 }
01237
01238 $this->has_aggregate = FALSE;
01239 $non_aggregates = array();
01240
01241 list($non_aggregates) = $this->compile_fields($fields_array, $query);
01242
01243 if (count($this->having)) {
01244 $this->has_aggregate = TRUE;
01245 }
01246 if ($this->has_aggregate && (!empty($this->groupby) || !empty($non_aggregates))) {
01247 $groupby = array_unique(array_merge($this->groupby, $non_aggregates));
01248 foreach ($groupby as $field) {
01249 $query->groupBy($field);
01250 }
01251 if (!empty($this->having) && $condition = $this->build_condition('having')) {
01252 $query->havingCondition($condition);
01253 }
01254 }
01255
01256 if (!$this->get_count_optimized) {
01257
01258 if ($this->orderby) {
01259 foreach ($this->orderby as $order) {
01260 if ($order['field'] == 'rand_') {
01261 $query->orderRandom();
01262 }
01263 else {
01264 $query->orderBy($order['field'], $order['direction']);
01265 }
01266 }
01267 }
01268 }
01269
01270 if (!empty($this->where) && $condition = $this->build_condition('where')) {
01271 $query->condition($condition);
01272 }
01273
01274
01275 if (!empty($this->options['query_comment'])) {
01276 $query->comment($this->options['query_comment']);
01277 }
01278
01279
01280 $query->addMetaData('views_substitutions', module_invoke_all('views_query_substitutions', $this));
01281
01282 return $query;
01283 }
01284
01288 function get_where_args() {
01289 $args = array();
01290 foreach ($this->where as $group => $where) {
01291 $args = array_merge($args, $where['args']);
01292 }
01293 foreach ($this->having as $group => $having) {
01294 $args = array_merge($args, $having['args']);
01295 }
01296 return $args;
01297 }
01298
01302 function alter(&$view) {
01303 foreach (module_implements('views_query_alter') as $module) {
01304 $function = $module . '_views_query_alter';
01305 $function($view, $this);
01306 }
01307 }
01308
01312 function build(&$view) {
01313
01314 if (!empty($this->options['distinct'])) {
01315 $this->set_distinct();
01316 }
01317
01318
01319 $this->view = $view;
01320
01321 $view->init_pager();
01322
01323
01324 $this->pager->query();
01325
01326 $view->build_info['query'] = $this->query();
01327 $view->build_info['count_query'] = $this->query(TRUE);
01328 }
01329
01337 function execute(&$view) {
01338 $external = FALSE;
01339 $query = $view->build_info['query'];
01340 $count_query = $view->build_info['count_query'];
01341
01342 $query->addMetaData('view', $view);
01343 $count_query->addMetaData('view', $view);
01344
01345 if (empty($this->options['disable_sql_rewrite'])) {
01346 $base_table_data = views_fetch_data($this->base_table);
01347 if (isset($base_table_data['table']['base']['access query tag'])) {
01348 $access_tag = $base_table_data['table']['base']['access query tag'];
01349 $query->addTag($access_tag);
01350 $count_query->addTag($access_tag);
01351 }
01352 }
01353
01354 $items = array();
01355 if ($query) {
01356 $additional_arguments = module_invoke_all('views_query_substitutions', $view);
01357
01358
01359
01360
01361
01362
01363
01364
01365 $count_query->preExecute();
01366
01367
01368 $count_query = $count_query->countQuery();
01369
01370
01371
01372
01373 if (!empty($additional_arguments)) {
01374
01375
01376 }
01377
01378 $start = microtime(TRUE);
01379
01380
01381 try {
01382 if ($this->pager->use_count_query() || !empty($view->get_total_rows)) {
01383 $this->pager->execute_count_query($count_query);
01384 }
01385
01386
01387 $this->pager->pre_execute($query);
01388
01389 if (!empty($this->limit) || !empty($this->offset)) {
01390
01391 $limit = intval(!empty($this->limit) ? $this->limit : 999999);
01392 $offset = intval(!empty($this->offset) ? $this->offset : 0);
01393 $query->range($offset, $limit);
01394 }
01395
01396 $result = $query->execute();
01397
01398 $view->result = array();
01399 foreach ($result as $item) {
01400 $view->result[] = $item;
01401 }
01402
01403 $this->pager->post_execute($view->result);
01404
01405 if ($this->pager->use_pager()) {
01406 $view->total_rows = $this->pager->get_total_items();
01407 }
01408 }
01409 catch (Exception $e) {
01410 $view->result = array();
01411 if (!empty($view->live_preview)) {
01412 drupal_set_message(time());
01413 drupal_set_message($e->getMessage(), 'error');
01414 }
01415 else {
01416 vpr('Exception in @human_name[@view_name]: @message', array('@human_name' => $view->human_name, '@view_name' => $view->name, '@message' => $e->getMessage()));
01417 }
01418 }
01419
01420 }
01421 $view->execute_time = microtime(TRUE) - $start;
01422 }
01423
01424 function add_signature(&$view) {
01425 $view->query->add_field(NULL, "'" . $view->name . ':' . $view->current_display . "'", 'view_name');
01426 }
01427
01428 function get_aggregation_info() {
01429
01430
01431 return array(
01432 'group' => array(
01433 'title' => t('Group results together'),
01434 'is aggregate' => FALSE,
01435 ),
01436 'count' => array(
01437 'title' => t('Count'),
01438 'method' => 'views_query_default_aggregation_method_simple',
01439 'handler' => array(
01440 'argument' => 'views_handler_argument_group_by_numeric',
01441 'field' => 'views_handler_field_numeric',
01442 'filter' => 'views_handler_filter_group_by_numeric',
01443 'sort' => 'views_handler_sort_group_by_numeric',
01444 ),
01445 ),
01446 'count_distinct' => array(
01447 'title' => t('Count DISTINCT'),
01448 'method' => 'views_query_default_aggregation_method_distinct',
01449 'handler' => array(
01450 'argument' => 'views_handler_argument_group_by_numeric',
01451 'field' => 'views_handler_field_numeric',
01452 'filter' => 'views_handler_filter_group_by_numeric',
01453 'sort' => 'views_handler_sort_group_by_numeric',
01454 ),
01455 ),
01456 'sum' => array(
01457 'title' => t('Sum'),
01458 'method' => 'views_query_default_aggregation_method_simple',
01459 'handler' => array(
01460 'argument' => 'views_handler_argument_group_by_numeric',
01461 'filter' => 'views_handler_filter_group_by_numeric',
01462 'sort' => 'views_handler_sort_group_by_numeric',
01463 ),
01464 ),
01465 'avg' => array(
01466 'title' => t('Average'),
01467 'method' => 'views_query_default_aggregation_method_simple',
01468 'handler' => array(
01469 'argument' => 'views_handler_argument_group_by_numeric',
01470 'filter' => 'views_handler_filter_group_by_numeric',
01471 'sort' => 'views_handler_sort_group_by_numeric',
01472 ),
01473 ),
01474 'min' => array(
01475 'title' => t('Minimum'),
01476 'method' => 'views_query_default_aggregation_method_simple',
01477 'handler' => array(
01478 'argument' => 'views_handler_argument_group_by_numeric',
01479 'filter' => 'views_handler_filter_group_by_numeric',
01480 'sort' => 'views_handler_sort_group_by_numeric',
01481 ),
01482 ),
01483 'max' => array(
01484 'title' => t('Maximum'),
01485 'method' => 'views_query_default_aggregation_method_simple',
01486 'handler' => array(
01487 'argument' => 'views_handler_argument_group_by_numeric',
01488 'filter' => 'views_handler_filter_group_by_numeric',
01489 'sort' => 'views_handler_sort_group_by_numeric',
01490 ),
01491 ),
01492 );
01493 }
01494
01499 function get_result_entities($results, $relationship = NULL) {
01500 $base_table = $this->base_table;
01501 $base_table_alias = $base_table;
01502
01503 if (!empty($relationship)) {
01504 foreach ($this->view->relationship as $current) {
01505 if ($current->alias == $relationship) {
01506 $base_table = $current->definition['base'];
01507 $base_table_alias = $relationship;
01508 break;
01509 }
01510 }
01511 }
01512 $table_data = views_fetch_data($base_table);
01513
01514
01515 if (!isset($table_data['table']['entity type'])) {
01516 return FALSE;
01517 }
01518 $entity_type = $table_data['table']['entity type'];
01519 $info = entity_get_info($entity_type);
01520 $id_alias = $this->get_field_alias($base_table_alias, $info['entity keys']['id']);
01521
01522
01523 $ids = array();
01524 foreach ($results as $key => $result) {
01525 if (isset($result->$id_alias)) {
01526 $ids[$key] = $result->$id_alias;
01527 }
01528 }
01529
01530 $entities = entity_load($entity_type, $ids);
01531
01532 $result = array();
01533 foreach ($ids as $key => $id) {
01534 $result[$key] = isset($entities[$id]) ? $entities[$id] : FALSE;
01535 }
01536 return array($entity_type, $result);
01537 }
01538 }
01539
01540 function views_query_default_aggregation_method_simple($group_type, $field) {
01541 return strtoupper($group_type) . '(' . $field . ')';
01542 }
01543
01544 function views_query_default_aggregation_method_distinct($group_type, $field) {
01545 $group_type = str_replace('_distinct', '', $group_type);
01546 return strtoupper($group_type) . '(DISTINCT ' . $field . ')';
01547 }