real_args = $view->args;
$view->real_url = calendar_real_url($view, $view->args);
$display_formats = calendar_get_formats($view);
$calendar_fields = calendar_fields();
// Embedded calendar views can have additional arguments.
if ($view->build_type == 'block' || $view->build_type == 'embed') {
$block_identifier = isset($view->block_identifier) ? $view->block_identifier : 'mini';
$pos = calendar_arg_positions($view);
// If we don't have any calendar arguments, look in the block_identifier for them.
if ($pos[0] >= count($view->args) && !empty($_GET[$block_identifier])) {
// Add the arguments from the block_identifier query param.
$view->real_args = $view->args = array_merge($view->args, explode('/', str_replace($view->real_url .'/', '', $_GET[$block_identifier])));
// Filter the query based on the newly acquired arguments.
foreach ($view->argument as $delta => $argument) {
// Special handling for OG gid argument.
// Find a default value for the gid when used in a block.
if ($argument['type'] == 'gid') {
$groupnodes = calendar_og_groups($view);
$view->args[$delta] = $groupnodes[0];
$query->ensure_table('og_ancestry');
$query->add_where("og_ancestry.group_nid IN (%d)", implode(',', $groupnodes));
}
if (!empty($view->args[$delta]) && $view->args[$delta] != CALENDAR_EMPTY_ARG) {
if ($argument['type'] == 'calendar_year') {
calendar_filter_year($query, $view->args[$delta]);
}
elseif ($argument['type'] == 'calendar_month') {
calendar_filter_month($query, $view->args[$delta]);
}
elseif ($argument['type'] == 'calendar_day') {
calendar_filter_day($query, $view->args[$delta]);
}
elseif ($argument['type'] == 'calendar_week') {
calendar_filter_week($query, $view->args[$delta]);
}
}
}
}
}
// If no arguments are provided, and this is not the ical view,
// default to current month view.
if (empty($view->args) || !calendar_is_calendar_arg($view)) {
// See what type of view the ical view is looking for from the args.
// Find the position of the last non-empty arugment.
if (is_array($view->args) && in_array('ical', $view->args)) {
$pos = 0;
foreach ($view->args as $delta => $arg) {
if ($arg == 'ical') {
// It was the previous argument, back up one position.
$pos--;
break;
}
elseif ($arg != CALENDAR_EMPTY_ARG) {
$pos++;
}
}
$query->calendar_type = str_replace('calendar_', '', $view->argument[$pos]['type']);
}
else {
$query->calendar_type = 'month';
}
foreach ($view->argument as $delta => $argument) {
if ($argument['type'] == 'calendar_year' && !$view->args[$delta]) {
$view->args[$delta] = date_format($now, 'Y');
calendar_filter_year($query, date_format($now, 'Y'));
}
elseif (($argument['type'] == 'calendar_month' || $argument['type'] == 'calendar_week') && !$view->args[$delta]) {
$view->args[$delta] = date_format($now, 'm');
calendar_filter_month($query, date_format($now, 'm'));
}
elseif ($argument['type'] == 'calendar_day' && !$view->args[$delta]) {
$view->args[$delta] = CALENDAR_EMPTY_ARG;
}
else {
$view->args[$delta] = !empty($view->real_args[$delta]) ? $view->real_args[$delta] : CALENDAR_EMPTY_ARG;
}
}
// Default arguments are real arguments, too.
$view->real_args = $view->args;
}
foreach ($view->argument as $delta => $argument) {
if (in_array($argument['type'], calendar_args())) {
// make sure 'display all values' is selected for the calendar arguments
// summary views are meaningless and create errors in this context
$view->argument[$delta]['argdefault'] = 2;
// Pad any unused values in the view arguments with
// CALENDAR_EMPTY_ARG to indicate all values.
if (empty($view->args[$delta])) {
$view->args[$delta] = CALENDAR_EMPTY_ARG;
}
}
// Calendar_week and Calendar_month can swap positions as the second arg
// in the url. Do some work here to make sure we know which is which and
// swap view data to match it. The difference between a calendar_month
// arg and a calendar_week arg is the preceding 'W'
if ($argument['type'] == 'calendar_week' || $argument['type'] == 'calendar_month') {
if (strstr($view->args[$delta], 'W')) {
calendar_filter_week($query, $view->args[$delta]);
$view->argument[$delta]['type'] = 'calendar_week';
$view->argument[$delta]['id'] = 'calendar_week';
$view->argument[$delta + 1]['type'] = 'calendar_day';
$view->argument[$delta + 1]['id'] = 'calendar_day';
// Make sure that there is no day set for the week view.
$view->args[$delta + 1] = CALENDAR_EMPTY_ARG;
}
// if this is not a week argument and view was created with a
// week argument, change it back
elseif (($view->build_type == 'page' || $view->build_type == 'embed')
&& $view->argument[$delta]['type'] == 'calendar_week') {
calendar_filter_month($query, $view->args[$delta]);
$view->argument[$delta]['type'] = 'calendar_month';
$view->argument[$delta]['id'] = 'calendar_month';
$view->argument[$delta + 1]['type'] = 'calendar_day';
$view->argument[$delta + 1]['id'] = 'calendar_day';
}
}
}
// Make sure the calendar query gets inserted. May not have finished yet
// on views like year or year/month.
if (!$query->calendar_finished) {
calendar_build_filter($query, $view);
}
$view->calendar_type = $query->calendar_type;
$view->year = $query->year;
$view->month = $query->month;
$view->day = $query->day;
$view->week = $query->week;
$view->min_date = $query->min_date;
$view->max_date = $query->max_date;
$view->min_date_date = date_format($view->min_date, DATE_FORMAT_DATE);
$view->max_date_date = date_format($view->max_date, DATE_FORMAT_DATE);
// See if we're outside the allowed date range for our argument.
$view_dates = calendar_year_range($view);
$view_min_year = $view_dates[0];
$view_max_year = $view_dates[1];
if (date_format($view->min_date, 'Y') < $view_min_year
|| date_format($view->max_date, 'Y') > $view_max_year) {
drupal_not_found();
exit;
}
// Identify the kind of display we're using for this view.
// Check first for 'view' in url to get displays set by the switch
// block, then for 'calendar_display_format' variable to get displays
// set in the setup, default to normal calendar display.
if ($view->build_type == 'block') {
$view->calendar_display = $display_formats['block'];
$view->mini = TRUE;
}
elseif (isset($_GET['view']) && $view->build_type == 'page') {
$view->calendar_display = !empty($_GET['view']) ? check_plain($_GET['view']) : 'calendar';
}
elseif ($view->build_type == 'page' || $view->build_type == 'embed') {
$display_formats = calendar_get_formats($view);
$view->calendar_display = $display_formats[$view->calendar_type];
}
// Global used to turn on the "Switch calendar" block.
if ($view->build_type == 'page') {
$GLOBALS['calendar_is_calendar'] = TRUE;
}
return;
}
/**
* Build calendar
*
* @param unknown_type $view
* @param unknown_type $items
* @param unknown_type $params
* @return themed table
*/
function calendar_build_calendar($view, $items, $params) {
// Remove nodes outside the selected date range.
$values = array();
foreach ($items as $delta => $item) {
if (empty($item->calendar_start_date) || empty($item->calendar_end_date)) {
continue;
}
$item_start = date_format($item->calendar_start_date, DATE_FORMAT_DATE);
$item_end = date_format($item->calendar_end_date, DATE_FORMAT_DATE);
if (($item_start >= $view->min_date_date && $item_start <= $view->max_date_date)
|| ($item_end >= $view->min_date_date && $item_end <= $view->max_date_date)) {
$values[$item_start][$item_start][] = $item;
}
}
$items = $values;
ksort($items);
$rows = array();
$curday = drupal_clone($view->min_date);
switch ($view->calendar_type) {
case 'year':
$rows = array();
for ($i = 1; $i <= 12; $i++) {
$rows[$i] = calendar_build_month($curday, $view, $items, $params);
}
break;
case 'month':
$rows = calendar_build_month($curday, $view, $items, $params);
break;
case 'day':
$rows = calendar_build_day($curday, $view, $items, $params);
break;
case 'week':
$rows = calendar_build_week($curday, $view, $items, $params);
// Merge the day names in as the first row.
if (!empty($view->mini)) {
$len = variable_get('calendar_day_header_'. $view->name, 1);
}
else {
$len = variable_get('calendar_full_day_header_'. $view->name, 3);
}
$rows = array_merge(array(calendar_week_header($view->mini, $params['with_weekno'], $len)), $rows);
break;
}
$output = theme('calendar_links', $view, $view->build_type != 'block');
$output .= theme('calendar_nav', $view);
$header = in_array($view->calendar_type, array('month', 'week')) ? array_shift($rows) : array();
$output .= theme('calendar_'. $view->calendar_type, $view, $header, $rows);
return $output;
}
/**
* Build one month.
*/
function calendar_build_month(&$curday, $view, $items, $params) {
$month = date_format($curday, 'n');
date_modify($curday, '-' . strval(date_format($curday, 'j')-1) . ' days');
$rows = array();
do {
$rows = array_merge($rows, calendar_build_week($curday, $view, $items, $params, TRUE));
$curday_date = date_format($curday, DATE_FORMAT_DATE);
$curday_month = date_format($curday, 'n');
} while ($curday_month == $month && $curday_date <= $view->max_date_date);
// Merge the day names in as the first row.
if (!empty($view->mini)) {
$len = variable_get('calendar_day_header_'. $view->name, 1);
}
else {
$len = variable_get('calendar_full_day_header_'. $view->name, 3);
}
$rows = array_merge(array(calendar_week_header($view->mini, $params['with_weekno'], $len)), $rows);
return $rows;
}
/**
* Build one week row.
*/
function calendar_build_week(&$curday, $view, $items, $params, $check_month = FALSE) {
$curday_date = date_format($curday, DATE_FORMAT_DATE);
$weekdays = calendar_untranslated_days($results, $view);
$today = date_format(date_now(date_default_timezone_name()), DATE_FORMAT_DATE);
$month = date_format($curday, 'n');
$week = date_week($curday_date);
$first_day = variable_get('date_first_day', 0);
// move backwards to the first day of the week
$day_wday = date_format($curday, 'w');
date_modify($curday, '-' . strval((7 + $day_wday - $first_day) % 7) . ' days');
$curday_date = date_format($curday, DATE_FORMAT_DATE);
// If we're displaying the week number, add it as the
// first cell in the week.
$display_formats = calendar_get_formats($view);
if ($params['with_weekno'] && $view->calendar_type != 'day') {
if (!empty($display_formats['week'])) {
if ($view->build_type == 'embed') {
$url = $view->page_url .'/'. $view->year .'/W'. $week;
$block_identifier = isset($view->block_identifier) ? $view->block_identifier : 'mini';
$query_string = (!empty($params['append']) ? $params['append'] .'&' : '') . $block_identifier .'='. $view->real_path .'/'. $view->year .'/W'. $week;
}
else {
$url = $view->real_url .'/'. $view->year .'/W'. $week;
$query_string = $params['append'];
}
$weekno = l($week, $url, NULL, $query_string);
}
else {
// Do not link week numbers, if Week views are disabled.
$weekno = $week;
}
$rows[$week][] = array(
'data' => $weekno,
'class' => 'week',
);
}
for ($i = 0; $i < 7; $i++) {
$curday_date = date_format($curday, DATE_FORMAT_DATE);
$class = strtolower($weekdays[$i] .
($view->mini ? ' mini' : ''));
if ($check_month && ($curday_date < $view->min_date_date || $curday_date > $view->max_date_date || date_format($curday, 'n') != $month)) {
$class .= ' empty';
$content = theme('calendar_empty_day');
}
else {
$content = calendar_build_day($curday, $view, $items, $params);
$class .= ($curday_date == $today ? ' today' : '') . ($curday_date < $today ? ' past' : '') . ($curday_date > $today ? ' future' : '');
}
$rows[$week][] = array(
'data' => $view->mini ? $content : '
'. $content .'
',
'class' => $class, 'id' => $view->name . '-' . $curday_date);
date_modify($curday, '+1 day');
}
return $rows;
}
/**
* Build the contents of a single day for the $rows results.
*/
function calendar_build_day($curday, $view, $items, $params) {
$curday_date = date_format($curday, DATE_FORMAT_DATE);
$inner = '';
$selected = FALSE;
$max_events = variable_get('calendar_limit_'. $view->name, 5);
$view->style_max_items_behavior = variable_get('calendar_limit_behavior_'. $view->name, 'more');
$types = array();
foreach ($items as $date => $day) {
if ($date == $curday_date) {
$count = 0;
$selected = TRUE;
ksort($day);
foreach ($day as $time) {
foreach ($time as $item) {
$count++;
if (!$view->mini && ($max_events == 0 || ($max_events > 0 && $count <= $max_events) || $view->calendar_type == 'day')) {
$theme = isset($item->calendar_node_theme) ? $item->calendar_node_theme : 'calendar_node_'. $view->calendar_type;
$inner .= theme($theme, $item, $view);
}
$types[$item->type] = $item;
}
}
}
}
if (empty($inner) && !$view->mini) {
$inner = theme('calendar_empty_day');
}
// we have too many events on this day. use the theme('calendar_multiple_')
if (!$view->mini && !($max_events == 0 || ( $max_events > 0 && $count <= $max_events ) || $view->calendar_type == 'day')) {
if ($view->style_max_items_behavior == 'hide') {
$inner = '';
}
$inner .= theme('calendar_multiple_node_'. $view->calendar_type, $curday_date, $count, $view, $types);
}
$content = theme('calendar_date_box', $curday_date, $view, $items, $params, $selected) . $inner;
return $content;
}
/**
* Formats the weekday information into table header format
*
* @ingroup event_support
* @return array with weekday table header data
*/
function calendar_week_header($mini = FALSE, $with_week = TRUE, $len = 1) {
// create week header
$untranslated_days = calendar_untranslated_days();
if ($len == 99) {
$translated_days = date_week_days_ordered(date_week_days(TRUE));
}
else {
$translated_days = date_week_days_ordered(date_week_days_abbr(TRUE));
}
if ($with_week) {
$row[] = array('header' => TRUE, 'class' => "days week", 'data' => ' ');
}
foreach ($untranslated_days as $delta => $day) {
$label = $mini ? drupal_substr($translated_days[$delta], 0 , $len) : $translated_days[$delta];
$row[] = array('header' => TRUE, 'class' => "days ". $day, 'data' => $label);
}
return $row;
}
/**
* Array of untranslated day name abbreviations, forced to lowercase
* and ordered appropriately for the site setting for the first day of week.
*
* The untranslated day abbreviation is used in css classes.
*/
function calendar_untranslated_days() {
$untranslated_days = date_week_days_ordered(date_week_days_untranslated());
foreach ($untranslated_days as $delta => $day) {
$untranslated_days[$delta] = strtolower(substr($day, 0, 3));
}
return $untranslated_days;
}
/**
* Compile the filter query for this view.
*
* Create date objects for the minimum and maximum possible dates for this
* view and store them in the query (and ultimately in the view),
* then create the query needed to find dates in that range.
*
* @param object $query
* @param object $view
*/
function calendar_build_filter(&$query, &$view) {
$now = date_now();
if ($query->calendar_type == 'week' && calendar_part_is_valid($query->week, 'week')) {
$range = date_week_range($query->week, $query->year);
$date = $range[0];
$max_date = $range[1];
}
else {
$month = calendar_part_is_valid($query->month, 'month') ? $query->month : 1;
$day = calendar_part_is_valid($query->day, 'day') ? $query->day : 1;
$year = calendar_part_is_valid($query->year, 'year') ? $query->year : date_format($now, 'Y');
$date = date_create($year .'-'. date_pad($month) .'-'. date_pad($day) .' 00:00:00', date_default_timezone());
$max_date = drupal_clone($date);
date_modify($max_date, '+1 '. $query->calendar_type);
date_modify($max_date, '-1 second');
}
$query->min_date = $date;
$query->max_date = $max_date;
// find all datetime fields in this view and add filters for them to the query
$queries = array();
foreach ($view->field as $delta => $field) {
$query_strings = calendar_build_field_query($query, $field);
if (!empty($query_strings)) $queries = array_merge($queries, $query_strings);
$view->date_fields[] = $field;
}
// bring the node type into the query so we can use it in the theme
$query->add_field('type', 'node');
if ($queries) $query->add_where(implode(" OR ", $queries));
return;
}
/**
* Build a filtering query for an individual date field
*
* @param object $query - the query object
* @param array $field - the view field array
*/
function calendar_build_field_query(&$query, $field) {
require_once('./'. drupal_get_path('module', 'date_api') .'/date_api_sql.inc');
$queries = array();
$fields = calendar_fields();
$field_name = $field['field'];
$this_field = $fields[$field_name];
$view_fields[] = $field_name;
$field_type = strstr($this_field['type'], 'string') ? DATE_ISO : DATE_UNIX;
// Create minimum and maximum comparison dates in DATETIME format.
$min_compare = drupal_clone($query->min_date);
$max_compare = drupal_clone($query->max_date);
$min = date_format($min_compare, DATE_FORMAT_DATETIME);
$max = date_format($max_compare, DATE_FORMAT_DATETIME);
if (array_key_exists($field_name, $fields)) {
$query->ensure_table($this_field['table'], $this_field['table']);
$tz_handling = $this_field['tz_handling'];
$date_handler = new date_sql_handler();
$date_handler->construct($field_type);
$date_handler->db_timezone = date_get_timezone_db($tz_handling);
$date_handler->local_timezone = date_get_timezone($tz_handling, date_default_timezone_name());
if ($tz_handling == 'date') {
$date_handler->local_timezone_field = $fields['tz_field'];
$date_handler->offset_field = $fields['offset_field'];
}
// Figure out where this field is in the query's field array
// so we know which query field to adjust.
foreach ($query->fields as $delta => $query_field) {
if (strstr($query_field, $this_field['fullname'] .' AS')) {
$field_delta = $delta;
}
}
if ($this_field['fromto'] && $this_field['fromto'][0] != $this_field['fromto'][1]) {
// Format dates with from and to times into a single value that is made
// up of the two local DATETIME values separated with a pipe (|).
$queries[] = "(". $date_handler->sql_where_date('DATE', $this_field['fromto'][1], '>=', $min) .
" AND ". $date_handler->sql_where_date('DATE', $this_field['fromto'][0], '<=', $max) .")";
}
else {
$queries[] = "(". $date_handler->sql_where_date('DATE', $this_field['fullname'], '>=', $min) .
' AND '. $date_handler->sql_where_date('DATE', $this_field['fullname'], '<=', $max) .")";
}
}
return $queries;
}
/**
* Take the array of items and alter it to an array of
* calendar nodes that the theme can handle.
*
* Iterate through each datefield in the view and each item
* returned by the query, and create pseudo date nodes.
*
* If there is more than one date field in the node, this will create
* multiple nodes, one each with the right calendar date for that
* field's value. If a field value has a date range that covers more than
* one day, separate nodes will be created for each day in the field's
* day range, limited to the minimum and maximum dates for the view.
*
* When we finish, we will have a distinct node for each distinct day
* and date field.
*/
function calendar_build_nodes(&$view, &$items, $display_type) {
if (empty($view->min_date) || empty($view->max_date)) {
return $items;
}
// Midnights are determined based on the same timezone as the View uses
$display_timezone = date_timezone_get($view->min_date);
$display_timezone_name = timezone_name_get($display_timezone);
// Translate the view min and max dates to UTC values
// so we can compare UTC dates to the view range.
$min_utc = drupal_clone($view->min_date);
date_timezone_set($min_utc, timezone_open('UTC'));
$max_utc = drupal_clone($view->max_date);
date_timezone_set($max_utc, timezone_open('UTC'));
$min_zone_string = array(); // Will cache $min_utc-strings in various timezones
$max_zone_string = array();
$view->nodes_per_page = 0;
$type_names = node_get_types('names');
$fields = calendar_fields();
foreach($fields as $field) {
$datefields[] = $field['query_name'];
}
$view_fields = _views_get_fields();
$field_names = (array) array_keys($fields);
$nodes = array();
$i = 0;
// explode out field and format info from the view
foreach ($view->field as $delta => $data) {
if ($fields[$data['id']]['visible'] !== FALSE && array_key_exists($data['field'], $fields)) {
if (in_array($data['field'], $field_names)) {
$field = $fields[$data['field']];
$field_type = strstr($field['type'], 'string') ? 'string' : 'timestamp';
$tz_handling = $field['tz_handling'];
$label = $field['label'];
$fromto = $field['fromto'];
$fromto_alias = array(str_replace('.', '_', $fromto[0]), str_replace('.', '_', $fromto[1]));
$tz_alias = str_replace('.', '_', $field['timezone_field']);
if (strstr($field['type'], 'cck')) {
$format = date_formatter_format($data['options'], $field['field_name']);
}
else {
switch ($data['handler']) {
case 'views_handler_field_date_large':
$format = variable_get('date_format_long', 'l, F j, Y - H:i');
break;
case 'views_handler_field_date':
$format = variable_get('date_format_medium', 'D, m/d/Y - H:i');
break;
case 'views_handler_field_date_custom':
$format = $data['options'];
break;
case 'views_handler_field_since':
case 'views_handler_field_date_small':
default:
$format = variable_get('date_format_short', 'm/d/Y - H:i');
break;
}
}
// If there are multiple date fields in this calendar we may get
// duplicate items from the other date fields, so add a way to
// make sure each individual date field only gets added to the
// calendar one time.
$processed = array();
foreach ($items as $pos => $item) {
$delta = !empty($field['delta_field']) && !empty($item->{$field['delta_field']}) ? $item->{$field['delta_field']} : 0;
$real_field = $field['field_name'];
if (substr($field['type'], 0, 3) == 'cck') {
$real_field = str_replace(array('_value2', '_value'), '', $field['field_name']);
}
$id = 'calendar:'. $item->nid .':'. $real_field .':'. $delta;
if (!in_array($id, $processed) && isset($item->{$field['query_name']}) && isset($item->{$fromto_alias[0]})) {
// Create from and to date values for each item, adjusted to
// the correct timezone.
$values = array(
$item->$fromto_alias[0],
isset($item->$fromto_alias[1]) ? $item->$fromto_alias[1] : $item->$fromto_alias[0],
);
$db_tz = date_get_timezone_db($tz_handling, isset($item->$tz_alias) ? $item->$tz_alias : $display_timezone_name);
$to_zone = date_get_timezone($tz_handling, isset($item->$tz_alias) ? $item->$tz_alias : $display_timezone_name);
// Now $display_timezone determines how $item is split into
// one entry per day, while $to_zone determines how date is displayed.
// For now, use the date fields's timezone for the day splitting.
$display_timezone_name = $to_zone;
$values_display = array();
// Start date
$date = date_make_date($values[0], $db_tz, $field['sql_type']);
if ($db_tz != $to_zone) {
date_timezone_set($date, timezone_open($to_zone));
}
$values[0] = date_format($date, DATE_FORMAT_DATETIME);
if ($display_timezone_name != $to_zone) {
date_timezone_set($date, $display_timezone);
$values_display[0] = date_format($date, DATE_FORMAT_DATETIME);
}
else {
$values_display[0] = $values[0];
}
// End date
$date = date_make_date($values[1], $db_tz, $field['sql_type']);
if ($db_tz != $to_zone) {
date_timezone_set($date, timezone_open($to_zone));
}
$values[1] = date_format($date, DATE_FORMAT_DATETIME);
if ($display_timezone_name != $to_zone) {
date_timezone_set($date, $display_timezone);
$values_display[1] = date_format($date, DATE_FORMAT_DATETIME);
}
else {
$values_display[1] = $values[1];
}
// Now $values contain start and end date of a node,
// expressed as strings in the display (local) timezone.
// $values_utc does the same in UTC timezone.
// Get calendar min and max day (not time) as strings in the
// $display_timezone. Cache in $min_zone_string and $max_zone_string,
// since many items or fields typically use the samee timezone.
if (!isset($min_zone_string[$display_timezone_name])) {
$date = drupal_clone($view->min_date);
date_timezone_set($date, $display_timezone);
$min_zone_string[$display_timezone_name] = date_format($date, DATE_FORMAT_DATE);
$date = drupal_clone($view->max_date);
date_timezone_set($date, $display_timezone);
$max_zone_string[$display_timezone_name] = date_format($date, DATE_FORMAT_DATE);
}
// Create a node for each date within the field's date range,
// limited to the view's date range (regarding only day, not time).
$now = max($min_zone_string[$display_timezone_name], substr($values_display[0], 0, 10));
$to = min($max_zone_string[$display_timezone_name], substr($values_display[1], 0, 10));
$next = date_make_date($now, $display_timezone);
if ($display_timezone_name != $to_zone) {
// Make $start and $end (derived from $node) use the timezone $to_zone, just as $values[..] do
date_timezone_set($next, timezone_open($to_zone));
}
if (empty($to)) {
$to = $now;
}
// $now and $next are midnight (in display timezone) on the first day where node will occur.
// $to is midnight on the last day where node will occur.
// All three were limited by the min-max date range of the view.
while ($now <= $to) {
$node = drupal_clone($item);
// Make sure the pseudo node has the same properties a
// regular node would have.
if (isset($node->node_title) && !isset($node->title)) {
$node->title = $node->node_title;
}
if (isset($node->node_type) && !isset($node->type)) {
$node->type = $node->node_type;
}
$node->label = $label;
$node->format = $format;
$node->format_time = variable_get('calendar_time_format_'. $view->name, 'H:i');
$node->url = calendar_get_node_link($node);
// Convert the table.field format in the fromto fields
// to the table_field format used by the Views formatters.
$node->{str_replace('.', '_', $fromto[0])} = $values[0];
$node->{str_replace('.', '_', $fromto[1])} = $values[1];
// Flag which datefield this node is using, in case
// there are multiple date fields in the view.
$node->datefield = $field['query_name'];
// If there are other datefields in the View, get rid
// of them in this pseudo node. There should only be one
// date in each calendar node.
foreach ($node as $key => $val) {
if ($key != $field['query_name'] && in_array($key, $datefields)) {
unset($node->$key);
foreach ($fields as $other_fields) {
// If the unused date has other fields, unset them, too.
if ($other_fields['query_name'] == $key) {
foreach ($other_fields['related_fields'] as $related_field) {
$key2 = str_replace('.', '_', $related_field);
unset($node->$key2);
}
}
}
}
}
// Get start and end of current day
$start = date_format($next, DATE_FORMAT_DATETIME);
date_modify($next, '+1 day');
date_modify($next, '-1 second');
$end = date_format($next, DATE_FORMAT_DATETIME);
// Get intersection of current day and the node value's duration (as strings in $to_zone timezone)
$node->calendar_start = $values[0] < $start ? $start : $values[0];
$node->calendar_end = !empty($values[1]) ? ($values[1] > $end ? $end : $values[1]) : $node->calendar_start;
// Make date objects
$node->calendar_start_date = date_create($node->calendar_start, timezone_open($to_zone));
$node->calendar_end_date = date_create($node->calendar_end, timezone_open($to_zone));
// Change string timezones into
// calendar_start and calendar_end are UTC dates as formatted strings
$node->calendar_start = date_format($node->calendar_start_date, DATE_FORMAT_DATETIME);
$node->calendar_end = date_format($node->calendar_end_date, DATE_FORMAT_DATETIME);
unset($node->calendar_fields);
if (isset($node) && (empty($node->calendar_start))) {
// if no date for the node and no date in the item
// there is no way to display it on the calendar
unset($node);
}
else {
$node->date_id = $id .':'. $pos;
if ($view->build_type == 'page' && $view->calendar_type != 'year') {
calendar_node_stripe($view, $node, $field['query_name'], $field['query_name']);
}
$nodes[$node->calendar_start][] = $node;
unset($node);
}
date_modify($next, '+1 second');
$processed[] = $id;
$now = date_format($next, DATE_FORMAT_DATE);
}
}
}
}
}
}
return $nodes;
}
function calendar_get_paths($view) {
$path = array();
$prev_date = drupal_clone($view->min_date);
date_modify($prev_date, '-1 '. $view->calendar_type);
$next_date = drupal_clone($view->min_date);
date_modify($next_date, '+1 '. $view->calendar_type);
$path = calendar_get_url($view, $view->args, TRUE);
// reverse through the path, creating a $nextpath and $prevpath arrays
$formats = array('day' => 'j', 'month' => 'm', 'year' => 'Y', 'week' => 'W');
for ($x = count($path); $x >= 0; $x--) {
$type = $path[$x]['type'];
if (in_array($type, array_keys($formats)) && $path[$x]['path'] != CALENDAR_EMPTY_ARG) {
if ($type != 'week') {
$nextpath[$x] = $type == 'year' && isset($next_year) ? $next_year : date_format($next_date, $formats[$type]);
$prevpath[$x] = $type == 'year' && isset($prev_year) ? $prev_year : date_format($prev_date, $formats[$type]);
}
else {
if (date_format($prev_date, 'Y') < $view->year) {
$prev_week = calendar_max_weeks(date_format($prev_date, 'Y'));
}
else {
$prev_week = $view->week - 1;
}
if (date_format($next_date, 'Y') > $view->year) {
$next_week = 1;
}
else {
$next_week = $view->week + 1;
}
$nextpath[$x] = 'W'. $next_week;
$prevpath[$x] = 'W'. $prev_week;
}
}
// Non-date path elements just get passed through.
elseif (!empty($path[$x]['path'])) {
$nextpath[$x] = $path[$x]['path'];
$prevpath[$x] = $path[$x]['path'];
}
}
// See if back/next navigation will take us outside
// the allowed date range for our argument.
$view_dates = calendar_year_range($view);
$view_min_year = $view_dates[0];
$view_max_year = $view_dates[1];
if (date_format($prev_date, 'Y') < $view_min_year) {
$prevpath = array();
}
if (date_format($next_date, 'Y') > $view_max_year) {
$nextpath = array();
}
return array($prevpath, $nextpath);
}