00001 <?php
00010 function _views_create_handler($definition, $type = 'handler', $handler_type = NULL) {
00011
00012 if (empty($definition['handler'])) {
00013 vpr('_views_create_handler - type: @type - failed: handler has not been provided.',
00014 array('@type' => isset($handler_type) ? ( $type . '(handler type: ' . $handler_type . ')' ) : $type)
00015 );
00016 return;
00017 }
00018
00019
00020 if (!empty($definition['override handler']) &&
00021 !class_exists($definition['override handler'])) {
00022 vpr(
00023 '_views_create_handler - loading override handler @type failed: class @override_handler could not be loaded. ' .
00024 'Verify the class file has been registered in the corresponding .info-file (files[]).',
00025 array(
00026 '@type' => isset($handler_type) ? ( $type . '(handler type: ' . $handler_type . ')' ) : $type,
00027 '@override_handler' => $definition['override handler']
00028 )
00029 );
00030 return;
00031 }
00032
00033 if (!class_exists($definition['handler'])) {
00034 vpr(
00035 '_views_create_handler - loading handler @type failed: class @handler could not be loaded. ' .
00036 'Verify the class file has been registered in the corresponding .info-file (files[]).',
00037 array(
00038 '@type' => isset($handler_type) ? ( $type . '(handler type: ' . $handler_type . ')' ) : $type,
00039 '@handler' => $definition['handler']
00040 )
00041 );
00042 return;
00043 }
00044
00045 if (!empty($definition['override handler'])) {
00046 $handler = new $definition['override handler'];
00047 }
00048 else {
00049 $handler = new $definition['handler'];
00050 }
00051
00052 $handler->set_definition($definition);
00053 if ($type == 'handler') {
00054 $handler->is_handler = TRUE;
00055 $handler->handler_type = $handler_type;
00056 }
00057 else {
00058 $handler->is_plugin = TRUE;
00059 $handler->plugin_type = $type;
00060 }
00061
00062
00063 $handler->construct();
00064
00065 return $handler;
00066 }
00067
00071 function _views_prepare_handler($definition, $data, $field, $type) {
00072 foreach (array('group', 'title', 'title short', 'help', 'real field') as $key) {
00073 if (!isset($definition[$key])) {
00074
00075 if (!empty($data[$field][$key])) {
00076 $definition[$key] = $data[$field][$key];
00077 }
00078
00079 elseif (!empty($data['table'][$key])) {
00080 $definition[$key] = $data['table'][$key];
00081 }
00082 }
00083 }
00084
00085 return _views_create_handler($definition, 'handler', $type);
00086 }
00087
00091 function views_get_table_join($table, $base_table) {
00092 $data = views_fetch_data($table);
00093 if (isset($data['table']['join'][$base_table])) {
00094 $h = $data['table']['join'][$base_table];
00095 if (!empty($h['handler']) && class_exists($h['handler'])) {
00096 $handler = new $h['handler'];
00097 }
00098 else {
00099 $handler = new views_join();
00100 }
00101
00102
00103 $handler->definition = $h;
00104 if (empty($handler->definition['table'])) {
00105 $handler->definition['table'] = $table;
00106 }
00107
00108 if (empty($handler->definition['left_table'])) {
00109 $handler->definition['left_table'] = $base_table;
00110 }
00111
00112 if (isset($h['arguments'])) {
00113 call_user_func_array(array(&$handler, 'construct'), $h['arguments']);
00114 }
00115 else {
00116 $handler->construct();
00117 }
00118
00119 return $handler;
00120 }
00121
00122
00123 vpr("Missing join: @table @base_table", array('@table' => $table, '@base_table' => $base_table));
00124 }
00125
00152 class views_handler extends views_object {
00158 var $view = NULL;
00159
00165 var $query = NULL;
00166
00170 var $handler_type = NULL;
00171
00175 public $table_alias;
00176
00181 var $real_field;
00182
00186 var $relationship = NULL;
00187
00196 function init(&$view, &$options) {
00197 $this->view = &$view;
00198 $display_id = $this->view->current_display;
00199
00200
00201
00202
00203
00204 if (isset($this->actual_table)) {
00205 $options['table'] = $this->actual_table;
00206 }
00207
00208 if (isset($this->actual_field)) {
00209 $options['field'] = $this->actual_field;
00210 }
00211
00212 $types = views_object_types();
00213 $plural = $this->handler_type;
00214 if (isset($types[$this->handler_type]['plural'])) {
00215 $plural = $types[$this->handler_type]['plural'];
00216 }
00217 if ($this->view->display_handler->is_defaulted($plural)) {
00218 $display_id = 'default';
00219 }
00220
00221 $this->localization_keys = array(
00222 $display_id,
00223 $this->handler_type,
00224 $options['table'],
00225 $options['id']
00226 );
00227
00228 $this->unpack_options($this->options, $options);
00229
00230
00231 if (isset($options['table'])) {
00232 $this->table = $options['table'];
00233 }
00234
00235 if (isset($this->definition['real field'])) {
00236 $this->real_field = $this->definition['real field'];
00237 }
00238
00239 if (isset($this->definition['field'])) {
00240 $this->real_field = $this->definition['field'];
00241 }
00242
00243 if (isset($options['field'])) {
00244 $this->field = $options['field'];
00245 if (!isset($this->real_field)) {
00246 $this->real_field = $options['field'];
00247 }
00248 }
00249
00250 $this->query = &$view->query;
00251 }
00252
00253 function option_definition() {
00254 $options = parent::option_definition();
00255
00256 $options['id'] = array('default' => '');
00257 $options['table'] = array('default' => '');
00258 $options['field'] = array('default' => '');
00259 $options['relationship'] = array('default' => 'none');
00260 $options['group_type'] = array('default' => 'group');
00261 $options['ui_name'] = array('default' => '');
00262
00263 return $options;
00264 }
00265
00269 function ui_name($short = FALSE) {
00270 if (!empty($this->options['ui_name'])) {
00271 $title = check_plain($this->options['ui_name']);
00272 return $title;
00273 }
00274 $title = ($short && isset($this->definition['title short'])) ? $this->definition['title short'] : $this->definition['title'];
00275 return t('!group: !title', array('!group' => $this->definition['group'], '!title' => $title));
00276 }
00277
00285 function get_field($field = NULL) {
00286 if (!isset($field)) {
00287 if (!empty($this->formula)) {
00288 $field = $this->get_formula();
00289 }
00290 else {
00291 $field = $this->table_alias . '.' . $this->real_field;
00292 }
00293 }
00294
00295
00296 if ($this->view->display_handler->use_group_by()) {
00297 $this->view->init_query();
00298 if ($this->query) {
00299 $info = $this->query->get_aggregation_info();
00300 if (!empty($info[$this->options['group_type']]['method']) && function_exists($info[$this->options['group_type']]['method'])) {
00301 return $info[$this->options['group_type']]['method']($this->options['group_type'], $field);
00302 }
00303 }
00304 }
00305
00306 return $field;
00307 }
00308
00317 function sanitize_value($value, $type = NULL) {
00318 switch ($type) {
00319 case 'xss':
00320 $value = filter_xss($value);
00321 break;
00322 case 'url':
00323 $value = check_url($value);
00324 break;
00325 default:
00326 $value = check_plain($value);
00327 break;
00328 }
00329 return $value;
00330 }
00331
00347 function case_transform($string, $option) {
00348 global $multibyte;
00349
00350 switch ($option) {
00351 default:
00352 return $string;
00353 case 'upper':
00354 return drupal_strtoupper($string);
00355 case 'lower':
00356 return drupal_strtolower($string);
00357 case 'ucfirst':
00358 return drupal_strtoupper(drupal_substr($string, 0, 1)) . drupal_substr($string, 1);
00359 case 'ucwords':
00360 if ($multibyte == UNICODE_MULTIBYTE) {
00361 return mb_convert_case($string, MB_CASE_TITLE);
00362 }
00363 else {
00364 return ucwords($string);
00365 }
00366 }
00367 }
00368
00372 function options_validate(&$form, &$form_state) { }
00373
00377 function options_form(&$form, &$form_state) {
00378
00379
00380
00381
00382 $form['#pre_render'][] = 'views_ui_pre_render_add_fieldset_markup';
00383
00384 $form['ui_name'] = array(
00385 '#type' => 'textfield',
00386 '#title' => t('Administrative title'),
00387 '#description' => t('This title will be displayed on the views edit page instead of the default one. This might be useful if you have the same item twice.'),
00388 '#default_value' => $this->options['ui_name'],
00389 '#fieldset' => 'more',
00390 );
00391
00392
00393
00394 $form['more'] = array(
00395 '#type' => 'fieldset',
00396 '#title' => t('More'),
00397 '#collapsible' => TRUE,
00398 '#collapsed' => TRUE,
00399 '#weight' => 150,
00400 );
00401
00402 drupal_alter('views_handler_options', $this->options, $view);
00403 }
00404
00409 function options_submit(&$form, &$form_state) { }
00410
00414 function use_group_by() {
00415 return TRUE;
00416 }
00420 function groupby_form(&$form, &$form_state) {
00421 $view = &$form_state['view'];
00422 $display_id = $form_state['display_id'];
00423 $types = views_object_types();
00424 $type = $form_state['type'];
00425 $id = $form_state['id'];
00426
00427 $form['#title'] = check_plain($view->display[$display_id]->display_title) . ': ';
00428 $form['#title'] .= t('Configure aggregation settings for @type %item', array('@type' => $types[$type]['lstitle'], '%item' => $this->ui_name()));
00429
00430 $form['#section'] = $display_id . '-' . $type . '-' . $id;
00431
00432 $view->init_query();
00433 $info = $view->query->get_aggregation_info();
00434 foreach ($info as $id => $aggregate) {
00435 $group_types[$id] = $aggregate['title'];
00436 }
00437
00438 $form['group_type'] = array(
00439 '#type' => 'select',
00440 '#title' => t('Aggregation type'),
00441 '#default_value' => $this->options['group_type'],
00442 '#description' => t('Select the aggregation function to use on this field.'),
00443 '#options' => $group_types,
00444 );
00445 }
00446
00451 function groupby_form_submit(&$form, &$form_state) {
00452 $item =& $form_state['handler']->options;
00453
00454 $item['group_type'] = $form_state['values']['options']['group_type'];
00455 }
00456
00461 function has_extra_options() { return FALSE; }
00462
00466 function extra_options(&$option) { }
00467
00471 function extra_options_form(&$form, &$form_state) { }
00472
00476 function extra_options_validate($form, &$form_state) { }
00477
00482 function extra_options_submit($form, &$form_state) { }
00483
00487 function can_expose() { return FALSE; }
00488
00493 function expose_options() { }
00494
00498 function exposed_info() { }
00499
00503 function exposed_form(&$form, &$form_state) { }
00504
00508 function exposed_validate(&$form, &$form_state) { }
00509
00513 function exposed_submit(&$form, &$form_state) { }
00514
00518 function expose_form(&$form, &$form_state) { }
00519
00523 function expose_validate($form, &$form_state) { }
00524
00529 function expose_submit($form, &$form_state) { }
00530
00534 function show_expose_button(&$form, &$form_state) { }
00535
00539 function show_expose_form(&$form, &$form_state) {
00540 if (empty($this->options['exposed'])) {
00541 return;
00542 }
00543
00544 $this->expose_form($form, $form_state);
00545
00546
00547
00548
00549
00550 if (!empty($form_state['force_expose_options'])) {
00551 foreach (element_children($form['expose']) as $id) {
00552 if (isset($form['expose'][$id]['#default_value']) && !isset($form['expose'][$id]['#value'])) {
00553 $form['expose'][$id]['#value'] = $form['expose'][$id]['#default_value'];
00554 }
00555 }
00556 }
00557 }
00558
00564 function access() {
00565 if (isset($this->definition['access callback']) && function_exists($this->definition['access callback'])) {
00566 if (isset($this->definition['access arguments']) && is_array($this->definition['access arguments'])) {
00567 return call_user_func_array($this->definition['access callback'], $this->definition['access arguments']);
00568 }
00569 return $this->definition['access callback']();
00570 }
00571
00572 return TRUE;
00573 }
00574
00581 function pre_query() { }
00582
00590 function post_execute(&$values) { }
00591
00595 function placeholder() {
00596 return $this->query->placeholder($this->options['table'] . '_' . $this->options['field']);
00597 }
00598
00603 function set_relationship() {
00604
00605 $this->relationship = NULL;
00606
00607
00608 if (empty($this->options['relationship']) || $this->options['relationship'] == 'none') {
00609 return;
00610 }
00611
00612 $relationship = $this->options['relationship'];
00613
00614
00615 if (empty($this->view->relationship[$relationship])) {
00616 return;
00617 }
00618
00619
00620
00621 if (empty($this->view->relationship[$relationship]->alias)) {
00622 return;
00623 }
00624
00625
00626 $this->relationship = $this->view->relationship[$relationship]->alias;
00627 }
00628
00633 function ensure_my_table() {
00634 if (!isset($this->table_alias)) {
00635 if (!method_exists($this->query, 'ensure_table')) {
00636 vpr(t('Ensure my table called but query has no ensure_table method.'));
00637 return;
00638 }
00639 $this->table_alias = $this->query->ensure_table($this->table, $this->relationship);
00640 }
00641 return $this->table_alias;
00642 }
00643
00647 function admin_summary() { }
00648
00654 function needs_style_plugin() { return FALSE; }
00655
00662 function is_exposed() {
00663 return !empty($this->options['exposed']);
00664 }
00665
00669 function accept_exposed_input($input) { return TRUE; }
00670
00674 function store_exposed_input($input, $status) { return TRUE; }
00675
00683 function get_join() {
00684
00685
00686 if (empty($this->query->relationships[$this->relationship])) {
00687 $base_table = $this->query->base_table;
00688 }
00689 else {
00690 $base_table = $this->query->relationships[$this->relationship]['base'];
00691 }
00692
00693 $join = views_get_table_join($this->table, $base_table);
00694 if ($join) {
00695 return clone $join;
00696 }
00697 }
00698
00710 function validate() { return array(); }
00711
00716 function broken() { }
00717 }
00718
00733 class views_many_to_one_helper {
00734 function views_many_to_one_helper(&$handler) {
00735 $this->handler = &$handler;
00736 }
00737
00738 static function option_definition(&$options) {
00739 $options['reduce_duplicates'] = array('default' => FALSE);
00740 }
00741
00742 function options_form(&$form, &$form_state) {
00743 $form['reduce_duplicates'] = array(
00744 '#type' => 'checkbox',
00745 '#title' => t('Reduce duplicates'),
00746 '#description' => t('This filter can cause items that have more than one of the selected options to appear as duplicate results. If this filter causes duplicate results to occur, this checkbox can reduce those duplicates; however, the more terms it has to search for, the less performant the query will be, so use this with caution. Shouldn\'t be set on single-value fields, as it may cause values to disappear from display, if used on an incompatible field.'),
00747 '#default_value' => !empty($this->handler->options['reduce_duplicates']),
00748 '#weight' => 4,
00749 );
00750 }
00751
00757 function get_field() {
00758 if (!empty($this->formula)) {
00759 return $this->handler->get_formula();
00760 }
00761 else {
00762 return $this->handler->table_alias . '.' . $this->handler->real_field;
00763 }
00764 }
00765
00774 function add_table($join = NULL, $alias = NULL) {
00775
00776 $field = $this->handler->relationship . '_' . $this->handler->table . '.' . $this->handler->field;
00777
00778 if (empty($join)) {
00779 $join = $this->get_join();
00780 }
00781
00782
00783
00784 $relationship = $this->handler->relationship;
00785
00786
00787 if (empty($this->handler->query->relationships[$relationship])) {
00788 $base_table = $this->handler->query->base_table;
00789 }
00790 else {
00791 $base_table = $this->handler->query->relationships[$relationship]['base'];
00792 }
00793
00794
00795
00796 $r_join = clone $join;
00797 while ($r_join->left_table != $base_table) {
00798 $r_join = views_get_table_join($r_join->left_table, $base_table);
00799 }
00800
00801 if ($r_join->table != $join->table) {
00802 $relationship = $this->handler->query->add_relationship($this->handler->table . '_' . $r_join->table, $r_join, $r_join->table, $this->handler->relationship);
00803 }
00804
00805
00806 $alias = $this->handler->query->add_table($this->handler->table, $relationship, $join, $alias);
00807
00808
00809
00810 if (empty($this->handler->view->many_to_one_tables[$field])) {
00811 $this->handler->view->many_to_one_tables[$field] = $this->handler->value;
00812 }
00813 else {
00814 $this->handler->view->many_to_one_tables[$field] = array_merge($this->handler->view->many_to_one_tables[$field], $this->handler->value);
00815 }
00816
00817 return $alias;
00818 }
00819
00820 function get_join() {
00821 return $this->handler->get_join();
00822 }
00823
00828 function summary_join() {
00829 $field = $this->handler->relationship . '_' . $this->handler->table . '.' . $this->handler->field;
00830 $join = $this->get_join();
00831
00832
00833 $options = $this->handler->options;
00834 $view = &$this->handler->view;
00835 $query = &$this->handler->query;
00836
00837 if (!empty($options['require_value'])) {
00838 $join->type = 'INNER';
00839 }
00840
00841 if (empty($options['add_table']) || empty($view->many_to_one_tables[$field])) {
00842 return $query->ensure_table($this->handler->table, $this->handler->relationship, $join);
00843 }
00844 else {
00845 if (!empty($view->many_to_one_tables[$field])) {
00846 foreach ($view->many_to_one_tables[$field] as $value) {
00847 $join->extra = array(
00848 array(
00849 'field' => $this->handler->real_field,
00850 'operator' => '!=',
00851 'value' => $value,
00852 'numeric' => !empty($this->definition['numeric']),
00853 ),
00854 );
00855 }
00856 }
00857 return $this->add_table($join);
00858 }
00859 }
00860
00865 function ensure_my_table() {
00866 if (!isset($this->handler->table_alias)) {
00867
00868
00869 $field = $this->handler->relationship . '_' . $this->handler->table . '.' . $this->handler->field;
00870 if ($this->handler->operator == 'or' && empty($this->handler->options['reduce_duplicates'])) {
00871 if (empty($this->handler->options['add_table']) && empty($this->handler->view->many_to_one_tables[$field])) {
00872
00873
00874 $join = $this->get_join();
00875 if (isset($join)) {
00876 $join->type = 'INNER';
00877 }
00878 $this->handler->table_alias = $this->handler->query->ensure_table($this->handler->table, $this->handler->relationship, $join);
00879 $this->handler->view->many_to_one_tables[$field] = $this->handler->value;
00880 }
00881 else {
00882 $join = $this->get_join();
00883 $join->type = 'LEFT';
00884 if (!empty($this->handler->view->many_to_one_tables[$field])) {
00885 foreach ($this->handler->view->many_to_one_tables[$field] as $value) {
00886 $join->extra = array(
00887 array(
00888 'field' => $this->handler->real_field,
00889 'operator' => '!=',
00890 'value' => $value,
00891 'numeric' => !empty($this->handler->definition['numeric']),
00892 ),
00893 );
00894 }
00895 }
00896
00897 $this->handler->table_alias = $this->add_table($join);
00898 }
00899
00900 return $this->handler->table_alias;
00901 }
00902
00903
00904
00905 if ($this->handler->operator != 'not') {
00906
00907 $this->handler->table_aliases = array();
00908 foreach ($this->handler->value as $value) {
00909 $join = $this->get_join();
00910 if ($this->handler->operator == 'and') {
00911 $join->type = 'INNER';
00912 }
00913 $join->extra = array(
00914 array(
00915 'field' => $this->handler->real_field,
00916 'value' => $value,
00917 'numeric' => !empty($this->handler->definition['numeric']),
00918 ),
00919 );
00920
00921
00922
00923 if (!isset($this->handler->view->many_to_one_aliases[$field][$value])) {
00924 if (!isset($this->handler->view->many_to_one_count[$this->handler->table])) {
00925 $this->handler->view->many_to_one_count[$this->handler->table] = 0;
00926 }
00927 $this->handler->view->many_to_one_aliases[$field][$value] = $this->handler->table . '_value_' . ($this->handler->view->many_to_one_count[$this->handler->table]++);
00928 }
00929 $alias = $this->handler->table_aliases[$value] = $this->add_table($join, $this->handler->view->many_to_one_aliases[$field][$value]);
00930
00931
00932 if (empty($this->handler->table_alias)) {
00933 $this->handler->table_alias = $alias;
00934 }
00935 }
00936 }
00937
00938
00939
00940 else {
00941 $join = $this->get_join();
00942 $join->type = 'LEFT';
00943 $join->extra = array();
00944 $join->extra_type = 'OR';
00945 foreach ($this->handler->value as $value) {
00946 $join->extra[] = array(
00947 'field' => $this->handler->real_field,
00948 'value' => $value,
00949 'numeric' => !empty($this->handler->definition['numeric']),
00950 );
00951 }
00952
00953 $this->handler->table_alias = $this->add_table($join);
00954 }
00955 }
00956 return $this->handler->table_alias;
00957 }
00958
00962 function placeholder() {
00963 return $this->handler->query->placeholder($this->handler->options['table'] . '_' . $this->handler->options['field']);
00964 }
00965
00966 function add_filter() {
00967 if (empty($this->handler->value)) {
00968 return;
00969 }
00970 $this->handler->ensure_my_table();
00971
00972
00973 $field = $this->get_field();
00974 $options = $this->handler->options;
00975 $operator = $this->handler->operator;
00976 $formula = !empty($this->formula);
00977 $value = $this->handler->value;
00978 if (empty($options['group'])) {
00979 $options['group'] = 0;
00980 }
00981
00982
00983
00984 $add_condition = TRUE;
00985 if ($operator == 'not') {
00986 $value = NULL;
00987 $operator = 'IS NULL';
00988 $add_condition = FALSE;
00989 }
00990 elseif ($operator == 'or' && empty($options['reduce_duplicates'])) {
00991 if (count($value) > 1) {
00992 $operator = 'IN';
00993 }
00994 else {
00995 $value = is_array($value) ? array_pop($value) : $value;
00996 $operator = '=';
00997 }
00998 $add_condition = FALSE;
00999 }
01000
01001 if (!$add_condition) {
01002 if ($formula) {
01003 $placeholder = $this->placeholder();
01004 if ($operator == 'IN') {
01005 $operator = "$operator IN($placeholder)";
01006 }
01007 else {
01008 $operator = "$operator $placeholder";
01009 }
01010 $placeholders = array(
01011 $placeholder => $value,
01012 ) + $this->placeholders;
01013 $this->handler->query->add_where_expression($options['group'], "$field $operator", $placeholders);
01014 }
01015 else {
01016 $this->handler->query->add_where($options['group'], $field, $value, $operator);
01017 }
01018 }
01019
01020 if ($add_condition) {
01021 $field = $this->handler->real_field;
01022 $clause = $operator == 'or' ? db_or() : db_and();
01023 foreach ($this->handler->table_aliases as $value => $alias) {
01024 $clause->condition("$alias.$field", $value);
01025 }
01026
01027
01028 $this->handler->query->add_where($options['group'], $clause);
01029 }
01030 }
01031 }
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047 function views_break_phrase_string($str, &$handler = NULL) {
01048 if (!$handler) {
01049 $handler = new stdClass();
01050 }
01051
01052
01053 if (!isset($handler->value)) {
01054 $handler->value = array();
01055 }
01056
01057 if (!isset($handler->operator)) {
01058 $handler->operator = 'or';
01059 }
01060
01061 if ($str == '') {
01062 return $handler;
01063 }
01064
01065 if (preg_match('/^(\w+[+ ])+\w+$/', $str)) {
01066
01067 $handler->operator = 'or';
01068 $handler->value = preg_split('/[+ ]/', $str);
01069 }
01070 else if (preg_match('/^((\w|\s)+,)*(\w|\s)+$/', $str)) {
01071 $handler->operator = 'and';
01072 $handler->value = explode(',', $str);
01073 }
01074
01075
01076 if (!empty($str) && (empty($handler->value) || !is_array($handler->value))) {
01077 $handler->value = array(-1);
01078 return $handler;
01079 }
01080
01081
01082 foreach ($handler->value as $id => $value) {
01083 $handler->value[$id] = (string) $value;
01084 }
01085
01086 return $handler;
01087 }
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100 function views_break_phrase($str, &$handler = NULL) {
01101 if (!$handler) {
01102 $handler = new stdClass();
01103 }
01104
01105
01106
01107 if (!isset($handler->value)) {
01108 $handler->value = array();
01109 }
01110
01111 if (!isset($handler->operator)) {
01112 $handler->operator = 'or';
01113 }
01114
01115 if (empty($str)) {
01116 return $handler;
01117 }
01118
01119 if (preg_match('/^([0-9]+[+ ])+[0-9]+$/', $str)) {
01120
01121 $handler->operator = 'or';
01122 $handler->value = preg_split('/[+ ]/', $str);
01123 }
01124 elseif (preg_match('/^([0-9]+,)*[0-9]+$/', $str)) {
01125 $handler->operator = 'and';
01126 $handler->value = explode(',', $str);
01127 }
01128
01129
01130 if (!empty($str) && (empty($handler->value) || !is_array($handler->value))) {
01131 $handler->value = array(-1);
01132 return $handler;
01133 }
01134
01135
01136 foreach ($handler->value as $id => $value) {
01137 $handler->value[$id] = intval($value);
01138 }
01139
01140 return $handler;
01141 }
01142
01143
01144
01145
01149 function views_get_timezone() {
01150 global $user;
01151 if (variable_get('configurable_timezones', 1) && $user->uid && strlen($user->timezone)) {
01152 $timezone = $user->timezone;
01153 }
01154 else {
01155 $timezone = variable_get('date_default_timezone', 0);
01156 }
01157
01158
01159 $db_type = Database::getConnection()->databaseType();
01160 if (in_array($db_type, array('mysql', 'pgsql'))) {
01161 $offset = '+00:00';
01162 static $already_set = FALSE;
01163 if (!$already_set) {
01164 if ($db_type == 'pgsql') {
01165 db_query("SET TIME ZONE INTERVAL '$offset' HOUR TO MINUTE");
01166 }
01167 elseif ($db_type == 'mysql') {
01168 db_query("SET @@session.time_zone = '$offset'");
01169 }
01170
01171 $already_set = true;
01172 }
01173 }
01174
01175 return $timezone;
01176 }
01177
01192 function views_date_sql_field($field, $field_type = 'int', $set_offset = NULL) {
01193 $db_type = Database::getConnection()->databaseType();
01194 $offset = $set_offset !== NULL ? $set_offset : views_get_timezone();
01195 if (isset($offset) && !is_numeric($offset)) {
01196 $dtz = new DateTimeZone($offset);
01197 $dt = new DateTime("now", $dtz);
01198 $offset_seconds = $dtz->getOffset($dt);
01199 }
01200
01201 switch ($db_type) {
01202 case 'mysql':
01203 switch ($field_type) {
01204 case 'int':
01205 $field = "DATE_ADD('19700101', INTERVAL $field SECOND)";
01206 break;
01207 case 'datetime':
01208 break;
01209 }
01210 if (!empty($offset)) {
01211 $field = "($field + INTERVAL $offset_seconds SECOND)";
01212 }
01213 return $field;
01214 case 'pgsql':
01215 switch ($field_type) {
01216 case 'int':
01217 $field = "TO_TIMESTAMP($field)";
01218 break;
01219 case 'datetime':
01220 break;
01221 }
01222 if (!empty($offset)) {
01223 $field = "($field + INTERVAL '$offset_seconds SECONDS')";
01224 }
01225 return $field;
01226 case 'sqlite':
01227 if (!empty($offset)) {
01228 $field = "($field + '$offset_seconds')";
01229 }
01230 return $field;
01231 }
01232 }
01233
01250 function views_date_sql_format($format, $field, $field_type = 'int', $set_offset = NULL) {
01251 $db_type = Database::getConnection()->databaseType();
01252 $field = views_date_sql_field($field, $field_type, $set_offset);
01253 switch ($db_type) {
01254 case 'mysql':
01255 $replace = array(
01256 'Y' => '%Y',
01257 'y' => '%y',
01258 'M' => '%b',
01259 'm' => '%m',
01260 'n' => '%c',
01261 'F' => '%M',
01262 'D' => '%a',
01263 'd' => '%d',
01264 'l' => '%W',
01265 'j' => '%e',
01266 'W' => '%v',
01267 'H' => '%H',
01268 'h' => '%h',
01269 'i' => '%i',
01270 's' => '%s',
01271 'A' => '%p',
01272 );
01273 $format = strtr($format, $replace);
01274 return "DATE_FORMAT($field, '$format')";
01275 case 'pgsql':
01276 $replace = array(
01277 'Y' => 'YYYY',
01278 'y' => 'YY',
01279 'M' => 'Mon',
01280 'm' => 'MM',
01281 'n' => 'MM',
01282 'F' => 'Month',
01283 'D' => 'Dy',
01284 'd' => 'DD',
01285 'l' => 'Day',
01286 'j' => 'DD',
01287 'W' => 'WW',
01288 'H' => 'HH24',
01289 'h' => 'HH12',
01290 'i' => 'MI',
01291 's' => 'SS',
01292 'A' => 'AM',
01293 );
01294 $format = strtr($format, $replace);
01295 return "TO_CHAR($field, '$format')";
01296 case 'sqlite':
01297 $replace = array(
01298 'Y' => '%Y',
01299 'y' => '%Y',
01300 'M' => '%m',
01301 'm' => '%m',
01302 'n' => '%m',
01303 'F' => '%m',
01304 'D' => '%d',
01305 'd' => '%d',
01306 'l' => '%d',
01307 'j' => '%d',
01308 'W' => '%W',
01309 'H' => '%H',
01310 'h' => '%H',
01311 'i' => '%M',
01312 's' => '%S',
01313 'A' => '',
01314 );
01315 $format = strtr($format, $replace);
01316 return "strftime('$format', $field, 'unixepoch')";
01317 }
01318 }
01319
01336 function views_date_sql_extract($extract_type, $field, $field_type = 'int', $set_offset = NULL) {
01337 $db_type = Database::getConnection()->databaseType();
01338 $field = views_date_sql_field($field, $field_type, $set_offset);
01339
01340
01341
01342 switch ($extract_type) {
01343 case('DATE'):
01344 return $field;
01345 case('YEAR'):
01346 return "EXTRACT(YEAR FROM($field))";
01347 case('MONTH'):
01348 return "EXTRACT(MONTH FROM($field))";
01349 case('DAY'):
01350 return "EXTRACT(DAY FROM($field))";
01351 case('HOUR'):
01352 return "EXTRACT(HOUR FROM($field))";
01353 case('MINUTE'):
01354 return "EXTRACT(MINUTE FROM($field))";
01355 case('SECOND'):
01356 return "EXTRACT(SECOND FROM($field))";
01357 case('WEEK'):
01358 switch ($db_type) {
01359 case('mysql'):
01360
01361 return "WEEK($field, 3)";
01362 case('pgsql'):
01363 return "EXTRACT(WEEK FROM($field))";
01364 }
01365 case('DOW'):
01366 switch ($db_type) {
01367 case('mysql'):
01368
01369
01370 return "INTEGER(DAYOFWEEK($field) - 1)";
01371 case('pgsql'):
01372 return "EXTRACT(DOW FROM($field))";
01373 }
01374 case('DOY'):
01375 switch ($db_type) {
01376 case('mysql'):
01377 return "DAYOFYEAR($field)";
01378 case('pgsql'):
01379 return "EXTRACT(DOY FROM($field))";
01380 }
01381 }
01382 }
01383
01439 class views_join {
01440 var $table = NULL;
01441 var $left_table = NULL;
01442 var $left_field = NULL;
01443 var $field = NULL;
01444 var $extra = NULL;
01445 var $type = NULL;
01446 var $definition = array();
01447
01451 function construct($table = NULL, $left_table = NULL, $left_field = NULL, $field = NULL, $extra = array(), $type = 'LEFT') {
01452 $this->extra_type = 'AND';
01453 if (!empty($table)) {
01454 $this->table = $table;
01455 $this->left_table = $left_table;
01456 $this->left_field = $left_field;
01457 $this->field = $field;
01458 $this->extra = $extra;
01459 $this->type = strtoupper($type);
01460 }
01461 elseif (!empty($this->definition)) {
01462
01463
01464 $this->table = $this->definition['table'];
01465 $this->left_table = $this->definition['left_table'];
01466 $this->left_field = $this->definition['left_field'];
01467 $this->field = $this->definition['field'];
01468 if (!empty($this->definition['extra'])) {
01469 $this->extra = $this->definition['extra'];
01470 }
01471 if (!empty($this->definition['extra type'])) {
01472 $this->extra_type = strtoupper($this->definition['extra type']);
01473 }
01474
01475 $this->type = !empty($this->definition['type']) ? strtoupper($this->definition['type']) : 'LEFT';
01476 }
01477 }
01478
01491 function build_join($select_query, $table, $view_query) {
01492 if (empty($this->definition['table formula'])) {
01493 $right_table = $this->table;
01494 }
01495 else {
01496 $right_table = $this->definition['table formula'];
01497 }
01498
01499 if ($this->left_table) {
01500 $left = $view_query->get_table_info($this->left_table);
01501 $left_field = "$left[alias].$this->left_field";
01502 }
01503 else {
01504
01505 $left_field = $this->left_field;
01506 }
01507
01508 $condition = "$left_field = $table[alias].$this->field";
01509 $arguments = array();
01510
01511
01512 if (isset($this->extra)) {
01513 if (is_array($this->extra)) {
01514 $extras = array();
01515 foreach ($this->extra as $info) {
01516 $extra = '';
01517
01518
01519 $join_table = '';
01520 if (!array_key_exists('table', $info)) {
01521 $join_table = $table['alias'] . '.';
01522 }
01523 elseif (isset($info['table'])) {
01524 $join_table = $info['table'] . '.';
01525 }
01526
01527
01528
01529 if (is_array($info['value']) && count($info['value']) == 1) {
01530 if (empty($info['operator'])) {
01531 $operator = '=';
01532 }
01533 else {
01534 $operator = $info['operator'] == 'NOT IN' ? '!=' : '=';
01535 }
01536 $info['value'] = array_shift($info['value']);
01537 }
01538
01539 if (is_array($info['value'])) {
01540
01541
01542 foreach ($info['value'] as $value) {
01543 $placeholder_i = ':views_join_condition_' . $select_query->nextPlaceholder();
01544 $arguments[$placeholder_i] = $value;
01545 }
01546
01547 $operator = !empty($info['operator']) ? $info['operator'] : 'IN';
01548 $placeholder = '( ' . implode(', ', array_keys($arguments)) . ' )';
01549 }
01550 else {
01551
01552 $operator = !empty($info['operator']) ? $info['operator'] : '=';
01553 $placeholder = ':views_join_condition_' . $select_query->nextPlaceholder();
01554 $arguments[$placeholder] = $info['value'];
01555 }
01556
01557 $extras[] = "$join_table$info[field] $operator $placeholder";
01558 }
01559
01560 if ($extras) {
01561 if (count($extras) == 1) {
01562 $condition .= ' AND ' . array_shift($extras);
01563 }
01564 else {
01565 $condition .= ' AND (' . implode(' ' . $this->extra_type . ' ', $extras) . ')';
01566 }
01567 }
01568 }
01569 elseif ($this->extra && is_string($this->extra)) {
01570 $condition .= " AND ($this->extra)";
01571 }
01572 }
01573
01574 $select_query->addJoin($this->type, $right_table, $table['alias'], $condition, $arguments);
01575 }
01576 }
01577
01587 class views_join_subquery extends views_join {
01588 function construct($table = NULL, $left_table = NULL, $left_field = NULL, $field = NULL, $extra = array(), $type = 'LEFT') {
01589 parent::construct($table, $left_table, $left_field, $field, $extra, $type);
01590 $this->left_query = $this->definition['left_query'];
01591 }
01592
01605 function build_join($select_query, $table, $view_query) {
01606 if (empty($this->definition['table formula'])) {
01607 $right_table = "{" . $this->table . "}";
01608 }
01609 else {
01610 $right_table = $this->definition['table formula'];
01611 }
01612
01613
01614 $condition = "($this->left_query) = $table[alias].$this->field";
01615 $arguments = array();
01616
01617
01618
01619 if (isset($this->extra)) {
01620 if (is_array($this->extra)) {
01621 $extras = array();
01622 foreach ($this->extra as $info) {
01623 $extra = '';
01624
01625
01626 $join_table = '';
01627 if (!array_key_exists('table', $info)) {
01628 $join_table = $table['alias'] . '.';
01629 }
01630 elseif (isset($info['table'])) {
01631 $join_table = $info['table'] . '.';
01632 }
01633
01634 $placeholder = ':views_join_condition_' . $select_query->nextPlaceholder();
01635
01636 if (is_array($info['value'])) {
01637 $operator = !empty($info['operator']) ? $info['operator'] : 'IN';
01638
01639 if (count($info['value']) == 1) {
01640 $info['value'] = array_shift($info['value']);
01641 $operator = $operator == 'NOT IN' ? '!=' : '=';
01642 }
01643 }
01644 else {
01645 $operator = !empty($info['operator']) ? $info['operator'] : '=';
01646 }
01647
01648 $extras[] = "$join_table$info[field] $operator $placeholder";
01649 $arguments[$placeholder] = $info['value'];
01650 }
01651
01652 if ($extras) {
01653 if (count($extras) == 1) {
01654 $condition .= ' AND ' . array_shift($extras);
01655 }
01656 else {
01657 $condition .= ' AND (' . implode(' ' . $this->extra_type . ' ', $extras) . ')';
01658 }
01659 }
01660 }
01661 elseif ($this->extra && is_string($this->extra)) {
01662 $condition .= " AND ($this->extra)";
01663 }
01664 }
01665
01666 $select_query->addJoin($this->type, $right_table, $table['alias'], $condition, $arguments);
01667 }
01668 }
01669