| [ Index ] |
PHP Cross Reference of Drupal 6 (yi-drupal) |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Date API argument handler. 4 */ 5 class date_api_argument_handler extends views_handler_argument_date { 6 var $offset = NULL; 7 8 function construct() { 9 parent::construct(); 10 require_once('./'. drupal_get_path('module', 'date_api') .'/date_api_sql.inc'); 11 $this->date_handler = new date_sql_handler(); 12 $this->date_handler->construct(); 13 } 14 15 /** 16 * Get granularity and use it to create the formula and a format 17 * for the results. 18 */ 19 function init(&$view, $options) { 20 parent::init($view, $options); 21 22 // Identify the type of display we're using. 23 $this->display_handler = $view->display_handler->definition['handler']; 24 25 // Add a date handler to the display. 26 $date_handler = $this->date_handler; 27 $date_handler->granularity = $this->options['granularity']; 28 $this->format = $date_handler->views_formats($date_handler->granularity, 'display'); 29 $this->sql_format = $date_handler->views_formats($date_handler->granularity, 'sql'); 30 31 if (empty($this->view->date_info)) $this->view->date_info = new stdClass(); 32 33 // Set the view range, do this only if not already set in case there are multiple date arguments. 34 if (empty($this->view->date_info->min_allowed_year)) { 35 $range = date_range_years($this->options['year_range']); 36 $this->view->date_info->min_allowed_year = !empty($range) && is_array($range) ? $range[0] : variable_get('min_allowed_year', 100); 37 $this->view->date_info->max_allowed_year = !empty($range) && is_array($range) ? $range[1] : variable_get('max_allowed_year', 4000); 38 } 39 if (empty($this->view->date_info->date_fields)) { 40 $this->view->date_info->date_fields = array(); 41 } 42 $this->view->date_info->date_fields = array_merge($this->view->date_info->date_fields, $this->options['date_fields']); 43 } 44 45 /** 46 * Default value for the date_fields option. 47 */ 48 function option_definition() { 49 $options = parent::option_definition(); 50 $options['date_fields'] = array('default' => array()); 51 $options['year_range'] = array('default' => '-3:+3', 'export' => 'export_plugin'); 52 $options['date_method'] = array('default' => 'OR', 'export' => 'export_plugin'); 53 $options['granularity'] = array('default' => 'month', 'export' => 'export_plugin'); 54 $options['default_argument_type'] = array('default' => 'date', 'export' => 'export_plugin'); 55 return $options; 56 } 57 58 /** 59 * Make sure our custom options get exported. 60 * Handle the options we know about, pass the rest to the parent plugin. 61 */ 62 function export_plugin($indent, $prefix, $storage, $option, $definition, $parents) { 63 $output = ''; 64 if (in_array($option, array('year_range', 'granularity', 'default_argument_type', 'date_method'))) { 65 $name = $this->options[$option]; 66 $output .= $indent . $prefix . "['$option'] = '$name';\n"; 67 return $output; 68 } 69 return parent::export_plugin($indent, $prefix, $storage, $option, $definition, $parents); 70 } 71 72 /** 73 * Add a form element to select date_fields for this argument. 74 */ 75 function options_form(&$form, &$form_state) { 76 parent::options_form($form, $form_state); 77 $options = $this->date_handler->date_parts(); 78 unset($options['second'], $options['minute']); 79 $options += array('week' => date_t('Week', 'datetime')); 80 $form['granularity'] = array( 81 '#title' => t('Granularity'), 82 '#type' => 'radios', 83 '#options' => $options, 84 '#default_value' => $this->options['granularity'], 85 '#multiple' => TRUE, 86 '#description' => t("Select the type of date value to be used in defaults, summaries, and navigation. For example, a granularity of 'month' will set the default date to the current month, summarize by month in summary views, and link to the next and previous month when using date navigation."), 87 ); 88 89 $form['year_range'] = array( 90 '#title' => t('Date year range'), 91 '#type' => 'textfield', 92 '#default_value' => $this->options['year_range'], 93 '#description' => t("Set the allowable minimum and maximum year range for this argument, either a -X:+X offset from the current year, like '-3:+3' or an absolute minimum and maximum year, like '2005:2010'. When the argument is set to a date outside the range, the page will be returned as 'Page not found (404)'."), 94 ); 95 96 $fields = date_api_fields($this->definition['base']); 97 $options = array(); 98 foreach ($fields['name'] as $name => $field) { 99 $options[$name] = $field['label']; 100 } 101 102 // If this argument was added as a CCK field argument and no other date field 103 // has been chosen, update the default with the right date. 104 if (empty($this->options['date_fields']) && $this->field != 'date_argument') { 105 $this->options['date_fields'] = array($this->table .'.'. $this->field); 106 } 107 108 $form['date_fields'] = array( 109 '#title' => t('Date field(s)'), 110 '#type' => 'checkboxes', 111 '#options' => $options, 112 '#default_value' => $this->options['date_fields'], 113 '#multiple' => TRUE, 114 '#description' => t("Select one or more date fields to filter with this argument. Do not select both the 'From date' and 'To date' for CCK date fields, only one of them is needed."), 115 ); 116 $form['date_method'] = array( 117 '#title' => t('Method'), 118 '#type' => 'radios', 119 '#options' => array('OR' => t('OR'), 'AND' => t('AND')), 120 '#default_value' => $this->options['date_method'], 121 '#description' => t('Method of handling multiple date fields in the same query. Return items that have any matching date field (date = field_1 OR field_2), or only those with matches in all selected date fields (date = field_1 AND field_2).'), 122 ); 123 124 } 125 126 function options_validate($form, &$form_state) { 127 // It is very important to call the parent function here: 128 parent::options_validate($form, $form_state); 129 130 if ($form_state['values']['form_id'] == 'views_ui_config_item_form') { 131 $check_fields = array_filter($form_state['values']['options']['date_fields']); 132 if (empty($check_fields)) { 133 form_error($form['date_fields'], t('You must select at least one date field for this argument.')); 134 } 135 if (!preg_match('/^(?:\-[0-9]{1,4}|[0-9]{4}):(?:[\+|\-][0-9]{1,4}|[0-9]{4})$/', $form_state['values']['options']['year_range'])) { 136 form_error($form['year_range'], t('Date year range must be in the format -9:+9, 2005:2010, -9:2010, or 2005:+9')); 137 } 138 } 139 } 140 141 function options_submit($form, &$form_state) { 142 // It is very important to call the parent function here: 143 parent::options_submit($form, $form_state); 144 145 if ($form_state['values']['form_id'] == 'views_ui_config_item_form') { 146 $form_state['values']['options']['date_fields'] = array_filter($form_state['values']['options']['date_fields']); 147 } 148 } 149 150 // Update the summary values to show selected granularity. 151 function admin_summary() { 152 $fields = date_api_fields($this->definition['base']); 153 if (!empty($this->options['date_fields'])) { 154 $output = array(); 155 foreach ($this->options['date_fields'] as $field) { 156 $output[] = $fields['name'][$field]['label']; 157 } 158 return implode('<br />'. $this->options['date_method'] .' ', $output); 159 } 160 else { 161 return parent::admin_summary(); 162 } 163 } 164 165 /** 166 * Set the empty argument value to the current date, 167 * formatted appropriately for this argument. 168 */ 169 function get_default_argument($raw = FALSE) { 170 $granularity = $this->options['granularity']; 171 if (!$raw && $this->options['default_argument_type'] == 'date') { 172 if ($granularity == 'week') { 173 $now = date_now(); 174 $week = date_week(date_format($now, 'Y-m-d')); 175 return date_format($now, 'Y') .'-W'. $week; 176 } 177 else { 178 return date($this->format(), time()); 179 } 180 } 181 else { 182 return parent::get_default_argument($raw); 183 } 184 } 185 186 function format() { 187 if (!empty($this->options['granularity'])) { 188 $date_handler = new date_sql_handler(); 189 return $date_handler->views_formats($this->options['granularity']); 190 } 191 else { 192 return !empty($this->options[$this->option_name]) ? $this->options[$this->option_name] : 'Y-m'; 193 } 194 } 195 196 /** 197 * Provide a link to the next level of the view from the summary. 198 */ 199 function summary_name($data) { 200 $format = $this->date_handler->views_formats($this->options['granularity'], 'display'); 201 $value = $data->{$this->name_alias}; 202 $range = $this->date_handler->arg_range($value); 203 return date_format_date($range[0], 'custom', $format); 204 } 205 206 /** 207 * Provide the argument to use to link from the summary to the next level; 208 * this will be called once per row of a summary, and used as part of 209 * $view->get_url(). 210 * 211 * @param $data 212 * The query results for the row. 213 */ 214 function summary_argument($data) { 215 $format = $this->date_handler->views_formats($this->options['granularity'], 'sql'); 216 $value = $data->{$this->name_alias}; 217 $range = $this->date_handler->arg_range($value); 218 return date_format_date($range[0], 'custom', $format); 219 } 220 221 /** 222 * Provide a link to the next level of the view from the argument. 223 */ 224 function title() { 225 $format = $this->date_handler->views_formats($this->options['granularity'], 'display'); 226 $range = $this->date_handler->arg_range($this->argument); 227 return date_format_date($range[0], 'custom', $format); 228 } 229 230 /** 231 * Create a summary query that matches the granularity. 232 * 233 * Needed or Views will do a groupby on the complete date instead 234 * of only the part of the date actually used in the argument. 235 */ 236 function summary_query() { 237 $this->get_query_fields(); 238 239 // No way to do summaries on more than one field at a time. 240 if (count($this->query_fields) > 1) { 241 return; 242 } 243 244 // Cause query->ensure_table to perform the correct join. 245 $this->table = $this->query_fields[0]['field']['table_name']; 246 $this->ensure_my_table(); 247 248 $field = $this->query_fields[0]['field']; 249 $date_handler = $this->query_fields[0]['date_handler']; 250 251 // Get the SQL format for this granularity, like Y-m, 252 // and use that as the grouping value. 253 $format = $date_handler->views_formats($this->options['granularity'], 'sql'); 254 $this->formula = $date_handler->sql_format($format, $date_handler->sql_field($field['fullname'], $this->offset)); 255 256 // Add the computed field. 257 $this->base_alias = $this->name_alias = $this->query->add_field(NULL, $this->formula, $field['query_name']); 258 259 return $this->summary_basics(FALSE); 260 } 261 262 function get_query_fields() { 263 $fields = date_api_fields($this->definition['base']); 264 $fields = $fields['name']; 265 $min_date = isset($this->min_date) ? $this->min_date : NULL; 266 $min_utc = isset($this->min_utc) ? $this->min_utc : NULL; 267 $max_date = isset($this->max_date) ? $this->max_date : NULL; 268 $max_utc = isset($this->max_utc) ? $this->max_utc : NULL; 269 $this->query_fields = array(); 270 foreach ($this->options['date_fields'] as $delta => $name) { 271 if (array_key_exists($name, $fields) && $field = $fields[$name]) { 272 $date_handler = new date_sql_handler(); 273 $date_handler->construct($field['sql_type'], date_default_timezone_name()); 274 $date_handler->granularity = $this->options['granularity']; 275 date_views_set_timezone($date_handler, $this, $field); 276 $this->query_fields[] = array('field' => $field, 'date_handler' => $date_handler); 277 } 278 } 279 } 280 281 /** 282 * Make sure the date field is added to the query. 283 * 284 * Do this in pre_query() so it will get done even if the argument 285 * is the wildcard, since query() is skipped when the wildcard is used. 286 */ 287 function pre_query() { 288 // Unset invalid date values before the query runs. 289 if (!empty($this->view->args) && count($this->view->args) > $this->position) { 290 $argument = $this->view->args[$this->position]; 291 $parts = $this->date_handler->arg_parts($argument); 292 if (empty($parts[0]['date']) && empty($parts[0]['period'])) { 293 unset($this->view->args[$this->position]); 294 } 295 } 296 // Setting the offset to avoid trying to use timezone adjustments for dates that don't need it. 297 $this->offset = in_array($this->date_handler->granularity, array('hour', 'minute', 'sec')) ? NULL : 0; 298 } 299 300 /** 301 * Set up the query for this argument. 302 * 303 * The argument sent may be found at $this->argument. 304 */ 305 function query() { 306 $block_identifier = date_block_identifier($this->view); 307 if (!empty($this->view->block_identifier) || isset($_GET[$block_identifier])) { 308 // Retrieve the block arguments in a way that will work for 309 // urls like user/%/calendar/2009-04. 310 if (!empty($_GET[$block_identifier])) { 311 $path_args = explode('/', $this->view->get_path()); 312 $mini_args = explode('/', $_GET[$block_identifier]); 313 foreach ($path_args as $pos => $key) { 314 if ($path_args[$pos] != '%') { 315 unset($mini_args[$pos]); 316 } 317 } 318 // Get rid of gaps in the array caused by embedded args. 319 $mini_args = array_values($mini_args); 320 $this->view->args = $mini_args; 321 } 322 $i = 0; 323 foreach ($this->view->argument as $argument) { 324 if ($argument->field == 'date_argument') { 325 $this->argument = $this->view->args[$argument->position]; 326 break; 327 } 328 $i++; 329 } 330 } 331 $parts = $this->date_handler->arg_parts($this->argument); 332 333 foreach ($parts as $type) { 334 foreach ($type as $part) { 335 foreach ($part as $key => $value) { 336 if (!empty($value)) { 337 // The last part evaluated is the one that will 'stick' 338 // as the date type. 339 $this->granularity = $key; 340 $this->$key = $value; 341 } 342 } 343 } 344 } 345 346 $range = $this->date_handler->arg_range($this->argument); 347 $min_date = $range[0]; 348 $max_date = $range[1]; 349 $this->min_date = $min_date; 350 $this->max_date = $max_date; 351 352 // See if we're outside the allowed date range for our argument. 353 if (date_format($min_date, 'Y') < $this->view->date_info->min_allowed_year || date_format($max_date, 'Y') > $this->view->date_info->max_allowed_year) { 354 $this->forbid = TRUE; 355 $this->query->add_where('date', "0=1"); 356 return; 357 } 358 359 // The second option seems to work better in the block view if 360 // set to something other than the original value. 361 // Need to keep an eye on this to be sure nothing else breaks. 362 //$format = $this->date_handler->views_formats($this->options['granularity'], 'sql'); 363 $format = $this->date_handler->views_formats($this->granularity, 'sql'); 364 $this->get_query_fields(); 365 if (!empty($this->query_fields)) { 366 // Use set_where_group() with the selected date_method 367 // of 'AND' or 'OR' to create the where clause. 368 $this->query->set_where_group($this->options['date_method'], 'date'); 369 foreach ($this->query_fields as $query_field) { 370 $field = $query_field['field']; 371 if ($field['table_name'] != $this->table || !empty($this->relationship)) { 372 $this->related_table_alias = $this->query->queue_table($field['table_name'], $this->relationship); 373 } 374 $date_handler = $query_field['date_handler']; 375 $table_alias = !empty($this->related_table_alias) ? $this->related_table_alias : $field['table_name']; 376 $from_field = str_replace($field['table_name'] .'_', $table_alias .'.', $field['fromto'][0]); 377 $to_field = str_replace($field['table_name'] .'_', $table_alias .'.', $field['fromto'][1]); 378 379 if ($this->granularity != 'week') { 380 $from = $date_handler->sql_where_format($format, $from_field, '<=', date_format($max_date, $format), $this->offset); 381 $to = $date_handler->sql_where_format($format, $to_field, '>=', date_format($min_date, $format), $this->offset); 382 } 383 else { 384 $format = DATE_FORMAT_DATETIME; 385 $from = $date_handler->sql_where_date('DATE', $from_field, '<=', date_format($max_date, $format), $this->offset); 386 $to = $date_handler->sql_where_date('DATE', $to_field, '>=', date_format($min_date, $format), $this->offset); 387 } 388 $sql = str_replace('***table***', $field['table_name'], "($from AND $to)"); 389 if ($sql) { 390 $this->query->add_where('date', $sql); 391 } 392 } 393 } 394 } 395 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Mon Jul 9 18:01:44 2012 | Cross-referenced by PHPXref 0.7 |