| [ Index ] |
PHP Cross Reference of Drupal 6 (yi-drupal) |
[Summary view] [Print] [Text view]
1 <?php 2 // $Id: calendar.module,v 1.121.2.43 2010/12/31 16:25:43 karens Exp $ 3 define('CALENDAR_SHOW_ALL', 0); 4 define('CALENDAR_HIDE_ALL', -1); 5 6 /** 7 * Implementation of hook_views_api(). 8 * 9 * This one is used as the base to reduce errors when updating. 10 */ 11 function calendar_views_api() { 12 return array( 13 'api' => 2, 14 'path' => drupal_get_path('module', 'calendar') .'/includes', 15 ); 16 } 17 18 /** 19 * @file 20 * Adds calendar filtering and displays to Views. 21 */ 22 /** 23 * Implementation of hook_help(). 24 */ 25 function calendar_help($section, $arg) { 26 switch ($section) { 27 case 'admin/help#calendar': 28 return t("<p>View complete documentation at !link.</p>", array('!link' => 'http://drupal.org/node/120710')); 29 } 30 } 31 32 function calendar_init() { 33 // If the multiday module is enabled, let it control the css. 34 if (module_exists('calendar_multiday') || substr($_GET['q'], 0, 24) == 'admin/build/modules/list') { 35 return; 36 } 37 // The css for Farbtastic color picker, painless to add it here 38 // even though it isn't needed everywhere. 39 drupal_add_css('misc/farbtastic/farbtastic.css'); 40 drupal_add_css(drupal_get_path('module', 'calendar') .'/calendar.css'); 41 require_once('./'. drupal_get_path('module', 'calendar') .'/theme/theme.inc'); 42 } 43 44 function calendar_theme() { 45 if (module_exists('calendar_multiday')) { 46 return array(); 47 } 48 $path = drupal_get_path('module', 'calendar'); 49 $base = array( 50 'file' => 'theme.inc', 51 'path' => "$path/theme", 52 ); 53 return array( 54 'calendar_day_node' => $base + array( 55 'template' => 'calendar-day-node', 56 'arguments' => array('node' => NULL, 'view' => NULL), 57 ), 58 'calendar_month_node' => $base + array( 59 'template' => 'calendar-month-node', 60 'arguments' => array('node' => NULL, 'view' => NULL), 61 ), 62 'calendar_week_node' => $base + array( 63 'template' => 'calendar-week-node', 64 'arguments' => array('node' => NULL, 'view' => NULL), 65 ), 66 'calendar_month_multiple_node' => $base + array( 67 'template' => 'calendar-month-multiple-node', 68 'arguments' => array('curday' => NULL, 'count' => NULL, 'view' => NULL, 'types' => NULL), 69 ), 70 'calendar_week_multiple_node' => $base + array( 71 'template' => 'calendar-week-multiple-node', 72 'arguments' => array('curday' => NULL, 'count' => NULL, 'view' => NULL, 'types' => NULL), 73 ), 74 'calendar_datebox' => $base + array( 75 'template' => 'calendar-datebox', 76 'arguments' => array( 77 'date' => NULL, 'view' => NULL, 'items' => NULL, 'selected' => NULL), 78 ), 79 'calendar_date_combo' => $base + array( 80 'arguments' => array('node', 'lable', 'view'), 81 ), 82 'calendar_empty_day' => $base + array( 83 'arguments' => array('curday', 'view'), 84 ), 85 'calendar_stripe_legend' => $base + array( 86 'arguments' => array('stripe_labels'), 87 ), 88 'calendar_stripe_stripe' => $base + array( 89 'arguments' => array('node'), 90 ), 91 'calendar_colorpicker' => $base + array( 92 'arguments' => array('element'), 93 ), 94 'calendar_colorfield' => $base + array( 95 'arguments' => array('element'), 96 ), 97 'calendar_time_row_heading' => $base + array( 98 'arguments' => array('start_time', 'next_start_time', 'curday_date'), 99 ), 100 ); 101 } 102 103 /** 104 * TODO need to identify type of timezone handling needed for each date field 105 */ 106 function calendar_offset($field_name) { 107 $default_offset = variable_get('date_default_timezone', 0); 108 $configurable_zones = variable_get('configurable_timezones', 1); 109 } 110 111 /** 112 * A function to test the validity of various date parts 113 */ 114 function calendar_part_is_valid($value, $type) { 115 if ( !preg_match('/^[0-9]*$/', $value) ) { 116 return false; 117 } 118 $value = intval($value); 119 if ($value <= 0) return false; 120 switch ($type) { 121 case 'year': 122 if ($value < DATE_MIN_YEAR) return false; 123 break; 124 case 'month': 125 if ($value < 0 || $value > 12) return false; 126 break; 127 case 'day': 128 if ($value < 0 || $value > 31) return false; 129 break; 130 case 'week': 131 if ($value < 0 || $value > 53) return false; 132 } 133 return true; 134 } 135 136 /** 137 * implementation of hook_block() 138 */ 139 function calendar_block($op = 'list', $delta = 0) { 140 switch ($op) { 141 case 'list' : 142 $blocks[0]['info'] = t('Calendar Legend.'); 143 return $blocks; 144 break; 145 case 'view' : 146 switch ($delta) { 147 case 0: 148 $block['subject'] = t('Calendar Legend'); 149 $content = theme('calendar_stripe_legend'); 150 $block['content'] = !empty($content) ? '<div class="calendar legend">'. $content .'</div>' : ''; 151 return $block; 152 } 153 } 154 } 155 156 /** 157 * Calendar display types 158 */ 159 function calendar_display_types() { 160 return array('year' => t('Year'), 'month' => t('Month'), 'day' => t('Day'), 'week' => t('Week')); 161 } 162 163 /** 164 * Figure out which type of display to use, 165 * based on the current argument. 166 * 167 * @return year, month, day, or week. 168 */ 169 function calendar_current_type($view) { 170 if (!is_object($view) || !isset($view->argument) || !is_array($view->argument)) { 171 if (!empty($view->date_info->default_display)) { 172 return $view->date_info->default_display; 173 } 174 return FALSE; 175 } 176 $i = 0; 177 $date_handler = new date_sql_handler(); 178 foreach ($view->argument as $argument) { 179 if ($argument['id'] == 'date_argument') { 180 $parts = array_keys($date_handler->arg_parts($view->args[$i])); 181 break; 182 } 183 $i++; 184 } 185 return array_pop($parts); 186 } 187 188 /** 189 * Create a stripe. 190 * 191 * @param $node - the node object 192 * @param $query_name - the views queryname for this date field 193 * @param $delta - the delta for this field, used to distinguish fields that appear more than once in the calendar 194 * @param $stripe - the hex code for this stripe. 195 * @param $label - the label to give this stripe. 196 * 197 * TODO Reconsider use of $GLOBALS as a method of triggering the legend, there 198 * may be a better way. 199 */ 200 function calendar_node_stripe($view, &$node, $query_name, $delta, $stripe = NULL, $label = '') { 201 $colors = isset($view->date_info->calendar_colors) ? $view->date_info->calendar_colors : array(); 202 if (empty($colors)) { 203 return; 204 } 205 206 $type_names = node_get_types('names'); 207 $type = $node->raw->node_type; 208 if(!(isset($node->stripe))){ 209 $node->stripe = array(); 210 $node->stripe_label = array(); 211 } 212 if (!$label && array_key_exists($type, $type_names)) { 213 $label = $type_names[$type]; 214 } 215 if (!$stripe) { 216 if (array_key_exists($type, $colors)) { 217 $stripe = $colors[$type]; 218 } 219 else { 220 $stripe = ''; 221 } 222 } 223 224 $node->stripe[] = $stripe; 225 $node->stripe_label[] = $label; 226 $GLOBALS['calendar_stripe_labels'][][$type] = array('stripe' => $stripe, 'label' => $label); 227 return $stripe; 228 } 229 230 /** 231 * Create a stripe based on a taxonomy term. 232 * 233 * @param $node - the node object 234 * @param $query_name - the views queryname for this date field 235 * @param $delta - the delta for this field, used to distinguish fields that appear more than once in the calendar 236 * @param $stripe - the hex code for this stripe. 237 * @param $label - the label to give this stripe. 238 * 239 * TODO Reconsider use of $GLOBALS as a method of triggering the legend, there 240 * may be a better way. 241 */ 242 243 function calendar_node_taxonomy_stripe($view, &$node, $query_name, $delta, $stripe = NULL, $label = '') { 244 $colors_taxonomy = isset($view->date_info->calendar_colors_taxonomy) ? $view->date_info->calendar_colors_taxonomy : array(); 245 if (empty($colors_taxonomy)) { 246 return; 247 } 248 249 // Rename the vid added by Views to the normal name that 250 // taxonomy will expect, it's in the raw results. 251 $node->vid = $node->raw->node_vid; 252 $terms_for_node = taxonomy_node_get_terms($node); 253 if(!(isset($node->stripe))){ 254 $node->stripe = array(); 255 $node->stripe_label = array(); 256 } 257 if (count($terms_for_node)){ 258 foreach($terms_for_node as $term_for_node){ 259 if (!array_key_exists($term_for_node->tid, $colors_taxonomy)) { 260 continue; 261 } 262 $stripe = $colors_taxonomy[$term_for_node->tid]; 263 $stripe_label = $term_for_node->name; 264 $node->stripe[] = $stripe; 265 $node->stripe_label[] = $stripe_label; 266 $GLOBALS['calendar_stripe_labels'][][$term_for_node->tid] = array('stripe' => $stripe, 'label' => $stripe_label); 267 } 268 } 269 else { 270 $node->stripe[] = ''; 271 $node->stripe_label[] = ''; 272 } 273 return; 274 } 275 276 277 /** 278 * Create a stripe based on group. 279 * 280 * @param $node - the node object 281 * @param $query_name - the views queryname for this date field 282 * @param $delta - the delta for this field, used to distinguish fields that appear more than once in the calendar 283 * @param $stripe - the hex code for this stripe. 284 * @param $label - the label to give this stripe. 285 * 286 * TODO Reconsider use of $GLOBALS as a method of triggering the legend, there 287 * may be a better way. 288 */ 289 function calendar_node_group_stripe($view, &$node, $query_name, $delta, $stripe = NULL, $label = '') { 290 $colors_group = isset($view->date_info->calendar_colors_group) ? $view->date_info->calendar_colors_group : array(); 291 if (empty($colors_group)) { 292 return; 293 } 294 if (!function_exists('og_get_node_groups')) { 295 return; 296 } 297 298 $groups_for_node = og_get_node_groups($node); 299 if(!(isset($node->stripe))){ 300 $node->stripe = array(); 301 $node->stripe_label = array(); 302 } 303 if (count($groups_for_node)){ 304 foreach($groups_for_node as $gid => $group_name){ 305 if (!array_key_exists($gid, $colors_group)) { 306 continue; 307 } 308 $stripe = $colors_group[$gid]; 309 $stripe_label = $group_name; 310 $node->stripe[] = $stripe; 311 $node->stripe_label[] = $stripe_label; 312 $GLOBALS['calendar_stripe_labels'][][$gid] = array('stripe' => $stripe, 'label' => $stripe_label); 313 } 314 } 315 else { 316 $node->stripe[] = ''; 317 $node->stripe_label[] = ''; 318 } 319 return $stripe; 320 } 321 322 323 /** 324 * Helper function to figure out a group gid to use in blocks. 325 * 326 * @return an array of group nodes that are relevant. 327 * @todo this may need more work. 328 */ 329 function calendar_og_groups($view) { 330 if (!$groupnode = og_get_group_context()) { 331 global $user; 332 $groupnodes = array_keys($user->og_groups); 333 } 334 else { 335 $groupnodes = array($groupnode->nid); 336 } 337 return $groupnodes; 338 } 339 340 /** 341 * A selector to jump to a new date in the calendar. 342 * 343 * @param unknown_type $view 344 * @return unknown 345 */ 346 function calendar_date_select($view) { 347 return '<div class="calendar-date-select">'. drupal_get_form('calendar_date_select_form', $view) .'</div>'; 348 } 349 350 /** 351 * The date selector form. 352 * 353 * @param object $view 354 * @return the form element 355 * 356 * @TODO is the title desired here or does it take up too much space?? 357 */ 358 function calendar_date_select_form(&$form_state, $view) { 359 $format = date_limit_format(variable_get('date_format_short', 'm/d/Y - H:i'), array('year', 'month', 'day')); 360 $form['calendar_goto'] = array( 361 //'#title' => t('Calendar date'), 362 '#type' => module_exists('date_popup') ? 'date_popup' : 'date_select', 363 '#default_value' => date_format($view->date_info->min_date, 'Y-m-d'), 364 '#date_timezone' => date_default_timezone_name(), 365 '#date_format' => $format, 366 ); 367 $form['calendar_type'] = array( 368 '#type' => 'hidden', 369 '#value' => $view->date_info->calendar_type, 370 ); 371 $form['view_name'] = array( 372 '#type' => 'hidden', 373 '#value' => $view->name, 374 ); 375 $form['view_url'] = array( 376 '#type' => 'hidden', 377 '#value' => $view->get_url(), 378 ); 379 $pos = calendar_arg_position($view); 380 $form['calendar_previous_arg'] = array( 381 '#type' => 'hidden', 382 '#value' => $view->args[$pos], 383 ); 384 $form['submit'] = array( 385 '#type' => 'submit', 386 '#value' => t('Change date'), 387 ); 388 return $form; 389 } 390 391 function calendar_arg_position($view) { 392 $pos = 0; 393 foreach ($view->argument as $argument) { 394 if ($argument->definition['handler'] == 'date_api_argument_handler') { 395 return $pos; 396 } 397 $pos++; 398 } 399 } 400 /** 401 * Get the url for a calendar node. 402 * 403 * @param $node - a calendar node object 404 * @param $default - a default url to use when nothing specific is provided. 405 */ 406 function calendar_get_node_link($node, $default = NULL) { 407 if (isset($node->url)) { 408 return url($node->url, array('absolute' => TRUE)); 409 } 410 elseif (empty($node->remote) && is_numeric($node->nid)) { 411 return url("node/$node->nid", array('absolute' => TRUE)); 412 } 413 elseif (!empty($default)) { 414 return url($default, array('absolute' => TRUE)); 415 } 416 } 417 418 function calendar_groupby_times($type = '') { 419 $times = array(); 420 switch ($type) { 421 case 'hour': 422 for ($i = 0; $i <= 23; $i++) { 423 $times[] = date_pad($i) .':00:00'; 424 } 425 break; 426 case 'half': 427 for ($i = 0; $i <= 23; $i++) { 428 $times[] = date_pad($i) .':00:00'; 429 $times[] = date_pad($i) .':30:00'; 430 } 431 break; 432 default: 433 break; 434 } 435 return $times; 436 } 437 438 /** 439 * Define some error messages. 440 */ 441 function calendar_errors($error) { 442 switch ($error) { 443 case 'missing_argument_default': 444 return t("The Date argument in this view must be set up to provide a default value set to the current date. Edit the argument, find 'Action to take if argument is not present.', choose 'Provide default argument', then select 'Current date'."); 445 } 446 } 447 /** 448 * Implementation of hook_elements. 449 * 450 * Much of the colorpicker code was adapted from the Colorpicker module. 451 * That module has no stable release yet nor any D6 branch. 452 * 453 * TODO Consider dropping the duplicate code and adding a dependency 454 * when that module is more stable, if calendar module customizations will 455 * work in it. 456 */ 457 function calendar_elements() { 458 // the Farbtastic colorpicker 459 $type['calendar_colorpicker'] = array( 460 '#attributes' => array('class' => 'calendar_colorpicker'), 461 '#input' => TRUE, 462 ); 463 464 // a textfield to associate with the Farbtastic colorpicker 465 $type['calendar_colorfield'] = array( 466 '#attributes' => array('class' => 'calendar_colorfield'), 467 '#input' => TRUE, 468 '#validate' => array('calendar_validate_hex_color' => array()) 469 ); 470 return $type; 471 } 472 473 /** 474 * Check to make sure the user has entered a valid 6 digit hex color. 475 */ 476 function calendar_validate_hex_color($element) { 477 if (!$element['#required'] && empty($element['#value'])) { 478 return; 479 } 480 if (!preg_match('/^#(?:(?:[a-f\d]{3}){1,2})$/i', $element['#value'])) { 481 form_error($element, "'". check_plain($element['#value']) ."'". t(' is not a valid hex color')); 482 } 483 else { 484 form_set_value($element, $element['#value']); 485 } 486 } 487 488 /** 489 * Format calendar_colorpicker. 490 */ 491 function theme_calendar_colorpicker($element) { 492 493 $output = ''; 494 $output .= '<div id="'. $element['#id'] .'" '. drupal_attributes($element['#attributes']) .' ></div>'; 495 return theme('form_element', $element, $output); 496 } 497 498 /** 499 * Format calendar_color textfield. 500 */ 501 function theme_calendar_colorfield($element) { 502 $size = isset($element['#size']) ? ' size="' . $element['#size'] . '"' : ''; 503 $maxlength = isset($element['#maxlength']) ? 'maxlength="'.$element['#maxlength'] .'"' : ''; 504 $output = ''; 505 if (isset($element['#calendar_colorpicker'])) { 506 $element['#attributes']['class'] .= ' edit-'. str_replace("_", "-", $element['#calendar_colorpicker']); 507 } 508 $output .= '<input type="text" name="'. $element['#name'] .'" id="'. $element['#id'] .'" '. $maxlength . $size .' value="'. check_plain($element['#value']) .'"'. drupal_attributes($element['#attributes']) .' />'; 509 return theme('form_element', $element, $output); 510 } 511 512 /** 513 * Add link to calendar to nodes. 514 * 515 * Controlled by value of 'calendar_date_link' in the view. 516 */ 517 function calendar_link($type, $object, $teaser = FALSE) { 518 if ($type == 'node' && !$teaser) { 519 $path = variable_get('calendar_date_link_'. $object->type, NULL); 520 if (!empty($path)) { 521 return array('calendar_link' => array( 522 'title' => t('Calendar'), 523 'href' => $path, 524 'attributes' => array('title' => t('View the calendar.')), 525 )); 526 } 527 } 528 } 529 530 /** 531 * Callback to remove a default calendar from the system. 532 */ 533 function calendar_remove($view_name) { 534 // Remove any variable that creates a default view with this name. 535 $calendar_options = variable_get('calendar_default_view_options', array()); 536 if (array_key_exists($view_name, $calendar_options)) { 537 unset($calendar_options[$view_name]); 538 } 539 variable_set('calendar_default_view_options', $calendar_options); 540 // Delete it from the database, if stored there. 541 if ($view = views_get_view($view_name)) { 542 $view->delete(); 543 } 544 views_invalidate_cache(); 545 } 546 547 /** 548 * Formats the weekday information into table header format 549 * 550 * @ingroup event_support 551 * @return array with weekday table header data 552 */ 553 function calendar_week_header($view) { 554 $len = isset($view->date_info->style_name_size) ? $view->date_info->style_name_size : (!empty($view->date_info->mini) ? 1 : 3); 555 $with_week = !empty($view->date_info->style_with_weekno); 556 557 // create week header 558 $untranslated_days = calendar_untranslated_days(); 559 if ($len == 99) { 560 $translated_days = date_week_days_ordered(date_week_days(TRUE)); 561 } 562 else { 563 $translated_days = date_week_days_ordered(date_week_days_abbr(TRUE)); 564 } 565 if ($with_week) { 566 $row[] = array('header' => TRUE, 'class' => "days week", 'data' => ' '); 567 } 568 foreach ($untranslated_days as $delta => $day) { 569 $label = $len < 3 ? drupal_substr($translated_days[$delta], 0 , $len) : $translated_days[$delta]; 570 $row[] = array('header' => TRUE, 'class' => "days ". $day, 'data' => $label); 571 } 572 return $row; 573 } 574 /** 575 * Array of untranslated day name abbreviations, forced to lowercase 576 * and ordered appropriately for the site setting for the first day of week. 577 * 578 * The untranslated day abbreviation is used in css classes. 579 */ 580 function calendar_untranslated_days() { 581 $untranslated_days = date_week_days_ordered(date_week_days_untranslated()); 582 foreach ($untranslated_days as $delta => $day) { 583 $untranslated_days[$delta] = strtolower(substr($day, 0, 3)); 584 } 585 return $untranslated_days; 586 } 587 588 /** 589 * Take the array of items and alter it to an array of 590 * calendar nodes that the theme can handle. 591 * 592 * Iterate through each datefield in the view and each item 593 * returned by the query, and create pseudo date nodes. 594 * 595 * If there is more than one date field in the node, this will create 596 * multiple nodes, one each with the right calendar date for that 597 * field's value. If a field value has a date range that covers more than 598 * one day, separate nodes will be created for each day in the field's 599 * day range, limited to the minimum and maximum dates for the view. 600 * 601 * When we finish, we will have a distinct node for each distinct day 602 * and date field. 603 */ 604 function calendar_build_nodes(&$view, &$items) { 605 if (empty($view->date_info->min_date) || empty($view->date_info->max_date)) { 606 return $items; 607 } 608 // Midnights are determined based on the same timezone as the View uses 609 $display_timezone = date_timezone_get($view->date_info->min_date); 610 $display_timezone_name = timezone_name_get($display_timezone); 611 612 // Translate the view min and max dates to UTC values 613 // so we can compare UTC dates to the view range. 614 $min_utc = drupal_clone($view->date_info->min_date); 615 date_timezone_set($min_utc, timezone_open('UTC')); 616 $max_utc = drupal_clone($view->date_info->max_date); 617 date_timezone_set($max_utc, timezone_open('UTC')); 618 $min_zone_string = array(); // Will cache $min_utc-strings in various timezones 619 $max_zone_string = array(); 620 $view->date_info->nodes_per_page = 0; 621 $type_names = node_get_types('names'); 622 $datefields = array(); 623 $fields = date_api_fields($view->base_table); 624 if (!empty($view->filter['date_filter'])) { 625 $date_filter = $view->filter['date_filter']; 626 foreach ($view->filter['date_filter']->options['date_fields'] as $name) { 627 $datefields[] = $fields['name'][$name]['query_name']; 628 } 629 } 630 if (!empty($view->argument['date_argument'])) { 631 $date_filter = $view->argument['date_argument']; 632 foreach ($view->argument['date_argument']->options['date_fields'] as $name) { 633 $datefields[] = $fields['name'][$name]['query_name']; 634 } 635 } 636 $view_fields = date_api_views_fetch_fields('node', 'field'); 637 $field_names = (array) array_keys($fields['name']); 638 $nodes = array(); 639 $i = 0; 640 foreach ($date_filter->options['date_fields'] as $name) { 641 $field = $fields['name'][$name]; 642 $field_type = strstr($field['type'], 'string') ? 'string' : 'timestamp'; 643 $alias = $field['query_name']; 644 $field_name = $field['field_name']; 645 $fromto = $field['fromto']; 646 $tz_handling = $field['tz_handling']; 647 $label = isset($view->field[$name]) ? $view->field[$name]['label'] : $field['field_name']; 648 $tz_alias = str_replace('.', '_', $field['timezone_field']); 649 $db_tz = date_get_timezone_db($field['tz_handling']); 650 $local_tz = date_get_timezone($field['tz_handling'], 'date'); 651 $field_name = $field['field_name']; 652 $rrule_field = str_replace(array('_value2', '_value'), '_rrule', $alias); 653 654 // Set a flag to tell us if individual multi-day dates need to be 655 // split into separate nodes. 656 $split_dates = TRUE; 657 if (strstr($view->current_display, '_ical')) { 658 $split_dates = FALSE; 659 } 660 661 // If there is no field for this item, just default to the site format. 662 if (!isset($view->field[$field_name])) { 663 $format = variable_get('date_format_short', 'm/d/Y - H:i'); 664 } 665 else { 666 if (strstr($field['type'], 'cck')) { 667 $format = $view->field[$field_name]->options['format']; 668 $cck_field_name = str_replace(array('_value2', '_value'), '', $field_name); 669 $format = date_formatter_format($format, $cck_field_name); 670 } 671 else { 672 $format = $view->field[$field_name]->options['date_format']; 673 $cck_field_name = NULL; 674 switch ($format) { 675 case 'long': 676 $format = variable_get('date_format_long', 'l, F j, Y - H:i'); 677 break; 678 case 'medium': 679 $format = variable_get('date_format_medium', 'D, m/d/Y - H:i'); 680 break; 681 case 'custom': 682 $format = $view->field[$field_name]->options['custom_date_format']; 683 break; 684 case 'time ago': 685 break; 686 default: 687 $format = variable_get('date_format_short', 'm/d/Y - H:i'); 688 break; 689 } 690 } 691 } 692 693 // set the domain part of the id 694 $domain = check_plain($_SERVER['SERVER_NAME']); 695 696 // If there are multiple date fields in this calendar we may get 697 // duplicate items from the other date fields, so add a way to 698 // make sure each individual date field only gets added to the 699 // calendar one time. 700 $processed = array(); 701 $rrule_processed = array(); 702 foreach ($items as $pos => $item) { 703 $delta = !empty($field['delta_field']) && !empty($item->{$field['delta_field']}) ? $item->{$field['delta_field']} : 0; 704 $real_field = $field_name; 705 if (substr($field['type'], 0, 3) == 'cck') { 706 $real_field = str_replace(array('_value2', '_value'), '', $field_name); 707 } 708 709 $id = 'calendar.'. $item->{$view->base_field} .'.'. $real_field .'.'. $delta; 710 711 // When creating iCal feeds for repeating dates we don't want all 712 // the multiple values, send only the first value. 713 if (strstr($view->current_display, '_ical')) { 714 if (!isset($rrule_processed[$item->nid])) { 715 $rrule_processed[$item->nid] = TRUE; 716 } 717 else { 718 continue; 719 } 720 } 721 722 if (!in_array($id, $processed) && !empty($item->calendar_fields->$alias)) { 723 724 // Create from and to date values for each item, adjusted to 725 // the correct timezone. 726 $values[0] = !empty($item->calendar_fields->$fromto[0]) ? $item->calendar_fields->$fromto[0] : $item->calendar_fields->$alias; 727 $values[1] = !empty($item->calendar_fields->$fromto[1]) ? $item->calendar_fields->$fromto[1] : $item->calendar_fields->$alias; 728 729 $db_tz = date_get_timezone_db($tz_handling, isset($item->$tz_alias) ? $item->$tz_alias : $display_timezone_name); 730 $to_zone = date_get_timezone($tz_handling, isset($item->$tz_alias) ? $item->$tz_alias : $display_timezone_name); 731 732 // Now $display_timezone determines how $item is split into 733 // one entry per day, while $to_zone determines how date is displayed. 734 // For now, use the date fields's timezone for the day splitting. 735 $display_timezone_name = $to_zone; 736 $values_display = array(); 737 738 // Start date 739 $date = date_make_date($values[0], $db_tz, $field['sql_type']); 740 if ($db_tz != $to_zone) { 741 date_timezone_set($date, timezone_open($to_zone)); 742 } 743 $values[0] = date_format($date, DATE_FORMAT_DATETIME); 744 745 if ($display_timezone_name != $to_zone) { 746 date_timezone_set($date, $display_timezone); 747 $values_display[0] = date_format($date, DATE_FORMAT_DATETIME); 748 } 749 else { 750 $values_display[0] = $values[0]; 751 } 752 753 // End date 754 $date = date_make_date($values[1], $db_tz, $field['sql_type']); 755 if ($db_tz != $to_zone) { 756 date_timezone_set($date, timezone_open($to_zone)); 757 } 758 $values[1] = date_format($date, DATE_FORMAT_DATETIME); 759 if ($display_timezone_name != $to_zone) { 760 date_timezone_set($date, $display_timezone); 761 $values_display[1] = date_format($date, DATE_FORMAT_DATETIME); 762 } 763 else { 764 $values_display[1] = $values[1]; 765 } 766 767 // Now $values contain start and end date of a node, 768 // expressed as strings in the display (local) timezone. 769 // $values_utc does the same in UTC timezone. 770 // Get calendar min and max day (not time) as strings in the 771 // $display_timezone. Cache in $min_zone_string and $max_zone_string, 772 // since many items or fields typically use the samee timezone. 773 if (!isset($min_zone_string[$display_timezone_name])) { 774 $date = drupal_clone($view->date_info->min_date); 775 date_timezone_set($date, $display_timezone); 776 $min_zone_string[$display_timezone_name] = date_format($date, DATE_FORMAT_DATE); 777 $date = drupal_clone($view->date_info->max_date); 778 date_timezone_set($date, $display_timezone); 779 $max_zone_string[$display_timezone_name] = date_format($date, DATE_FORMAT_DATE); 780 } 781 782 // Create a node for each date within the field's date range, 783 // limited to the view's date range (regarding only day, not time). 784 $now = max($min_zone_string[$display_timezone_name], substr($values_display[0], 0, 10)); 785 $to = min($max_zone_string[$display_timezone_name], substr($values_display[1], 0, 10)); 786 $next = date_make_date($now, $display_timezone); 787 788 if ($display_timezone_name != $to_zone) { 789 // Make $start and $end (derived from $node) use the timezone $to_zone, just as $values[..] do 790 date_timezone_set($next, timezone_open($to_zone)); 791 } 792 if (empty($to)) { 793 $to = $now; 794 } 795 796 // $now and $next are midnight (in display timezone) on the first day where node will occur. 797 // $to is midnight on the last day where node will occur. 798 // All three were limited by the min-max date range of the view. 799 while ($now <= $to) { 800 $node = drupal_clone($item); 801 802 // Make sure the pseudo node has the same properties a 803 // regular node would have. 804 if (isset($node->node_title) && !isset($node->title)) { 805 $node->title = $node->node_title; 806 } 807 if (isset($node->node_type) && !isset($node->type)) { 808 $node->type = $node->node_type; 809 } 810 $exceptions = array('format_interval', 'time ago'); 811 $node->label = $label; 812 $node->format = $format; 813 if (!in_array($node->format, $exceptions)) { 814 if (!isset($formats[$format])) { 815 $formats[$format] = date_limit_format($format, array('hour', 'minute', 'second')); 816 $node->format_time = $formats[$format]; 817 } 818 } 819 else { 820 $node->format_time = ''; 821 } 822 $node->url = calendar_get_node_link($node); 823 824 //$node->$fromto[0] = $values[0]; 825 //$node->$fromto[1] = $values[1]; 826 827 // Flag which datefield this node is using, in case 828 // there are multiple date fields in the view. 829 $node->datefield = $alias; 830 // If there are other datefields in the View, get rid 831 // of them in this pseudo node. There should only be one 832 // date in each calendar node. 833 foreach ($node as $key => $val) { 834 if ($key != $alias && in_array($key, $datefields)) { 835 unset($node->$key); 836 foreach ($fields['name'] as $other_fields) { 837 // If the unused date has other fields, unset them, too. 838 if ($other_fields['query_name'] == $key) { 839 foreach ($other_fields['related_fields'] as $related_field) { 840 $key2 = str_replace('.', '_', $related_field); 841 unset($node->$key2); 842 } 843 } 844 } 845 } 846 } 847 // If we don't deconstruct dates into individual date parts, 848 // use date values as-is. 849 if (!$split_dates) { 850 $node->calendar_start = $values[0]; 851 $node->calendar_end = $values[1]; 852 } 853 // Split dates get intersection of current day and the node 854 // value's duration (as strings in $to_zone timezone) 855 else { 856 // Get start and end of current day 857 $start = date_format($next, DATE_FORMAT_DATETIME); 858 date_modify($next, '+1 day'); 859 date_modify($next, '-1 second'); 860 $end = date_format($next, DATE_FORMAT_DATETIME); 861 $node->calendar_start = $values[0] < $start ? $start : $values[0]; 862 $node->calendar_end = !empty($values[1]) ? ($values[1] > $end ? $end : $values[1]) : $node->calendar_start; 863 } 864 $node->date_start = date_create($values[0], timezone_open($to_zone)); 865 $node->date_end = date_create(!empty($values[1]) ? $values[1] : $values[0], timezone_open($to_zone));; 866 867 // Make date objects 868 $node->calendar_start_date = date_create($node->calendar_start, timezone_open($to_zone)); 869 $node->calendar_end_date = date_create($node->calendar_end, timezone_open($to_zone)); 870 871 // Change string timezones into 872 // calendar_start and calendar_end are UTC dates as formatted strings 873 $node->calendar_start = date_format($node->calendar_start_date, DATE_FORMAT_DATETIME); 874 $node->calendar_end = date_format($node->calendar_end_date, DATE_FORMAT_DATETIME); 875 876 if (substr($real_field, 0, 9) == 'field_') { 877 $cck_field = content_fields($cck_field_name); 878 $granularity = $cck_field['granularity']; 879 $increment = $cck_field['widget']['increment']; 880 } 881 else { 882 $granularity = 'second'; 883 $increment = 1; 884 } 885 $node->calendar_all_day = date_is_all_day($node->calendar_end, $node->calendar_end, $granularity, $increment); 886 887 // Flag all day values specifically set in date. 888 $all_day_field = str_replace(array('_value2', '_value'), '_all_day', $node->datefield); 889 if (!empty($all_day_field) && !empty($item->$all_day_field)) { 890 $node->calendar_all_day = TRUE; 891 } 892 893 unset($node->calendar_fields); 894 if (isset($node) && (empty($node->calendar_start))) { 895 // if no date for the node and no date in the item 896 // there is no way to display it on the calendar 897 unset($node); 898 } 899 else { 900 calendar_node_stripe($view, $node, $alias, $alias); 901 calendar_node_taxonomy_stripe($view, $node, $alias, $alias); 902 calendar_node_group_stripe($view, $node, $alias, $alias); 903 $node->date_id = $id .'.'. $pos; 904 905 $nodes[] = $node; 906 unset($node); 907 } 908 $processed[] = $id; 909 if ($split_dates) { 910 date_modify($next, '+1 second'); 911 $now = date_format($next, DATE_FORMAT_DATE); 912 } 913 else { 914 break; 915 } 916 } 917 } 918 } 919 } 920 return $nodes; 921 }
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 |