event_start). * Optionally, an end value ($node->event_end) and a time zone offset value * in the same format as drupal core ($node->tz). If a node has no end * value, it is rendered on only one day. If no time zone value is displayed * the time is rendered with no time zone offset (GMT). * @param $module - String containing the name of the module calling the function * @param $title - A string value that will be printed into the header of the calendar * @param $params - an optional array of additional values that may be needed * $params[force_week] - a week number to limit the displayed calendar to only that week * $params[with_weekno] - add a column for the week number to the calendar * $params[hide_header] - true to omit td header row(s) * $params[as_array] - true to return the rows array instead of the themed table * $params[mini] - this is a mini calendar, don't display item details * $params[url] - an url to use as a base url in month and days * $params[append] - a query string to append to urls * $params[stripe] - an node field to use instead of nid for stripes * $params[limit] - an array of a minimum and maximum timestamp to include on the calendar used in case node array has values that overlap periods * @return Themed calendar view of nodes or array of calendar rows */ function calendar_get_calendar($view, $nodes, $module, $title = NULL, $params = array()) { calendar_load_date_api(); $today = calendar_user_date(); if ($params['limit'][0]) { $min_date = $params['limit'][0]; $max_date = $params['limit'][1]; } else { $min_date = 0; $max_date = 999999999999; } $data = array(); foreach ($nodes as $nid => $node) { $node->stripe = $params['stripe'] ? $node->$params['stripe'] : $node->nid; $calendar = new stdClass(); $nodes[$node->nid] = $node; $calendar->nid = $node->nid; // $node_start and $node_end are local timestamp values if ($min_date - $node->start_offset > $node->calendar_start) { $node->calendar_start = $min_date - $node->start_offset; } if ($max_date - $node->end_offset < $node->calendar_end) { $node->calendar_end = $max_date - $node->end_offset; } $node_start = date_gmmktime(array( 'mon' => calendar_event_date('m', $node->calendar_start, $node->start_offset), 'mday' => calendar_event_date('d', $node->calendar_start, $node->start_offset), 'year' => calendar_event_date('Y', $node->calendar_start, $node->start_offset), )); if ($node->calendar_end) { $node_end = date_gmmktime(array( 'mon' => calendar_event_date('m', $node->calendar_end, $node->end_offset), 'mday' => calendar_event_date('d', $node->calendar_end, $node->end_offset), 'year' => calendar_event_date('Y', $node->calendar_end, $node->end_offset), )); } else { $node_end = $node_start; } if ($node_start == $node_end) { $calendar->calendar_state = 'singleday'; $calendar->stamp = $node_start; $calendar->stripe = $node->stripe; $data[date_format_date('Y', $node_start)][date_format_date('m', $node_start)][date_format_date('j', $node_start)][] = $calendar; } else { // roll through each day the calendar occurs and set an entry for each for ($x = $node_start; $x <= $node_end; $x += 86400) { if ($x == $node_end) { $calendar = new StdClass(); $calendar->nid = $node->nid; $calendar->stripe = $node->stripe; $calendar->calendar_state = 'end'; $calendar->stamp = $x; $data[date_format_date('Y', $x)][date_format_date('m', $x)][date_format_date('j', $x)][] = $calendar; } elseif ($x == $node_start) { $calendar = new StdClass(); $calendar->nid = $node->nid; $calendar->stripe = $node->stripe; $calendar->calendar_state = 'start'; $calendar->stamp = $x; $data[date_format_date('Y', $x)][date_format_date('m', $x)][date_format_date('j', $x)][] = $calendar; } else { $calendar = new StdClass(); $calendar->nid = $node->nid; $calendar->stripe = $node->stripe; $calendar->calendar_state = 'ongoing'; $calendar->stamp = $x; $data[date_format_date('Y', $x)][date_format_date('m', $x)][date_format_date('j', $x)][] = $calendar; } } } } // order the years, months and days ksort($data, SORT_NUMERIC); foreach($data as $year => $months) { ksort($data[$year], SORT_NUMERIC); foreach($data[$year] as $month => $days) { ksort($data[$year][$month], SORT_NUMERIC); } } $weekdays = calendar_week_days(); switch ($view) { case 'day': case 'table': foreach ($data as $year => $months) { if(count($data) > 1 && !$params['hide_header']) { // add year heading $rows[][] = array( 'class' => 'heading year', 'id' => 'year'.$year, 'data' => $year); } foreach($months as $month => $days) { foreach($days as $day => $calendars) { $content = theme('calendar_date_box', $year, $month, $day, 'table', $params['mini'], !empty($calendars), $params['url'], $params['append']); foreach($calendars as $calendar) { if(!$month_name) { $month_name = date_format_date('M', $calendar->stamp); $dow = _calendar_day_of_week($calendar->stamp); } $node = $nodes[$calendar->nid]; $node->calendar_state = $calendar->calendar_state; if($output = module_invoke($module, 'calendar_node_'. $view, $node)) { $content .= $output; } else { $content .= theme('calendar_node_'. $view, $node); } } $rows[][] = array( 'class' => strtolower("$month_name ". $weekdays[$dow]['day'] . ($calendar->stamp == $today ? ' today' : '')), 'id' => strtolower($month_name . $day), 'data' => $content); $month_name = NULL; } } } break; case 'week': case 'month': case 'year': $colspan = $params['with_weekno'] ? '8' : '7'; foreach ($data as $year => $months) { $month_rows[] = $title; if(count($data) > 1 && !$params['hide_header']) { // add year heading $rows[][] = array( 'class' => 'heading year', 'id' => 'year'. $year, 'data' => $year, 'colspan' => $colspan); } foreach ($months as $month => $days) { // timestamp of first day in month $curstamp = date_gmmktime(array( 'mon' => $month, 'mday' => 1, 'year' => $year, )); // timestamp of last day in month $lastday = date_gmmktime(array( 'mon' => $month, 'mday' => date_format_date('t', $curstamp), 'year' => $year, )); // pad the first week row array to fill up days in the previous month we don't build $row = array_fill(0, 6, theme('calendar_empty_day')); // get the day of week offset value for the first day of the month $start = $offset = _calendar_day_of_week($curstamp); // get name of month $month_name = date_format_date('M', $curstamp); $month_link = $params['url'] ? l($month_name, $params['url'] .'/'. $year .'/'. intval($month), NULL, $params['append']) : $month_name; // set week counter $week = 0; if (!$params['hide_header']) { $rows[][] = array( 'class' => 'heading month', 'id' => 'month'. $month, 'data' => $month_name, 'colspan' => $colspan); } $rows[] = calendar_week_header($params['mini'], $params['with_weekno']); while ($curstamp <= $lastday) { for ($x = $start; $x < 7; $x++) { $cur_day = (($week * 7) + ($x + 1) - $offset); $selected = FALSE; if(is_array($days[$cur_day])) { // make sure dummy nodes added to create blank calendars don't get marked as having content foreach ($items = $days[$cur_day] as $item) { if ($item->nid) { $selected = TRUE; } } } $content = theme('calendar_date_box', $year, $month, $cur_day, $view, $params['mini'], $selected, $params['url'], $params['append']); // render nodes for the day if(is_array($days[$cur_day]) && !$params['mini']) { foreach($days[$cur_day] as $calendar) { $node = $nodes[$calendar->nid]; $node->calendar_state = $calendar->calendar_state; if($output = module_invoke($module, 'calendar_node_'. $view, $node)) { $content .= $output; } elseif (!$params['mini'] && $node->nid != 0) { $content .= theme('calendar_node_'. $view, $node); } } } $row[$x] = array( 'class' => strtolower("$month_name ". $weekdays[$x]['day'] . ($curstamp == $today ? ' today' : '') . ($params['mini'] ? ' mini' : '')), 'id' => strtolower($month_name . $cur_day), 'data' => $params['mini'] ? $content : '
'. $content .'
'); $curstamp += 86400; if ($curstamp > $lastday) { $x = 8; } } $cur_week = date_format_date('W', $curstamp); // print week unless this is a week view and force_week is set and this is not the forced week if (!($view == 'week' && $params['force_week'] && $params['force_week'] != date_format_date('W', $curstamp))) { if ($params['with_weekno']) { $week_row = array(0 => array( 'class' => 'week', 'data' => l(sprintf('%02d', $cur_week), $params['url'] .'/'. $year .'/W'. $cur_week, NULL, $params['append']), )); $rows[] = array_merge($week_row, array_pad($row, 7, theme('calendar_empty_day'))); } else { $rows[] = array_pad($row, 7, theme('calendar_empty_day')); } } $week++; $start = 0; $row = array(); } if ($view == 'year' && !$params['as_array']) { $header = array($month_name ? array('class' => 'heading', 'data' => $month_link, 'colspan' => $colspan) : array()); $output = theme('calendar_month', 'page', $header, $rows); unset($rows); $month_rows[] = $output; } } } break; } // if only the rows array is requested, return it if ($params['as_array']) return $rows; $header = $title ? array(array('class' => 'heading', 'data' => $title, 'colspan' => $colspan)) : array(); $op = $params['mini'] ? 'mini' : 'page'; return theme('calendar_'. $view, $op, $header, $rows, $month_rows); } /** * Formats local time values to GMT timestamp using time zone offset supplied. * All time values in the database are GMT and translated here prior to insertion. * * Time zone settings are applied in the following order: * 1. If supplied, time zone offset is applied * 2. If user time zones are enabled, user time zone offset is applied * 3. If neither 1 nor 2 apply, the site time zone offset is applied * * @param $format The date() format to apply to the timestamp. * @param $timestamp The GMT timestamp value. * @param $offset Time zone offset to apply to the timestamp. * @ingroup event_support * @return date_format_date() formatted date value */ function calendar_mktime($hour, $minute, $second, $month, $day, $year, $offset = NULL) { global $user; calendar_load_date_api(); $timestamp = date_gmmktime(array( 'hours' => $hour, 'minutes' => $minute, 'seconds' => $second, 'mon' => $month, 'day' => $day, 'year' => $year, )); if (isset($offset)) { return $timestamp - $offset; } elseif (variable_get('configurable_timezones', 1) && $user->uid && strlen($user->timezone) && (variable_get('event_timezone_display', 'event') == 'user')) { return $timestamp - $user->timezone; } else { return $timestamp - variable_get('date_default_timezone', 0); } } /** * Returns a local timestamp (as defined by the user or site's timezone) for * midnight GMT. * @return integer timestamp */ function calendar_user_date($part = 'timestamp') { global $user; static $date; calendar_load_date_api(); if (!$date) { $now = date_time(); $date = date_gmmktime(array( 'mon' => date_format_date('m', $now), 'mday' => date_format_date('j', $now), 'year' => date_format_date('Y', $now), )); } switch ($part) { case ('year'): return date_format_date('Y', $date); case ('month'): return date_format_date('m', $date); case ('day'): return date_format_date('j', $date); case ('hour'): return date_format_date('H', $date); case ('minute'): return date_format_date('i', $date); case ('week'): return date_format_date('W', $date); default: return $date; } } /** * Formats a GMT timestamp to local date values using time zone offset supplied. * All timestamp values in event nodes are GMT and translated for display here. * * Time zone settings are applied in the following order * 1. If supplied, time zone offset is applied * 2. If user time zones are enabled, user time zone offset is applied * 3. If neither 1 nor 2 apply, the site time zone offset is applied * * @param $format The date() format to apply to the timestamp. * @param $timestamp The GMT timestamp value. * @param $offset Time zone offset to apply to the timestamp. * @ingroup event_support * @return date_format_date() formatted date value */ function calendar_event_date($format, $timestamp, $offset = null) { global $user; calendar_load_date_api(); if (isset($offset)) { $timestamp += $offset; } elseif (variable_get('configurable_timezones', 1) && $user->uid && strlen($user->timezone)) { $timestamp += $user->timezone; } else { $timestamp += variable_get('date_default_timezone', 0); } // make sure we apply the site first day of the week setting for dow requests if ($format == 'w') { $result = calendar_day_of_week($timestamp); } else { $result = date_format_date($format, $timestamp); } return $result; } /** * Returns week day names and thier translated values, corrected for the start of week day settings (mon or sun) * * @ingroup event_support * @return an associative array containing weekday names */ function calendar_week_days() { static $weekdays; if (!$weekdays) { switch (variable_get('date_first_day', 1)) { case 1: $weekdays = array(array('day' => 'Mon', 't' => t('Mon')), array('day' => 'Tue', 't' => t('Tue')), array('day' => 'Wed', 't' => t('Wed')), array('day' => 'Thu', 't' => t('Thu')), array('day' => 'Fri', 't' => t('Fri')), array('day' => 'Sat', 't' => t('Sat')), array('day' => 'Sun', 't' => t('Sun'))); break; case 2: $weekdays = array(array('day' => 'Tue', 't' => t('Tue')), array('day' => 'Wed', 't' => t('Wed')), array('day' => 'Thu', 't' => t('Thu')), array('day' => 'Fri', 't' => t('Fri')), array('day' => 'Sat', 't' => t('Sat')), array('day' => 'Sun', 't' => t('Sun')), array('day' => 'Mon', 't' => t('Mon'))); break; case 3: $weekdays = array(array('day' => 'Wed', 't' => t('Wed')), array('day' => 'Thu', 't' => t('Thu')), array('day' => 'Fri', 't' => t('Fri')), array('day' => 'Sat', 't' => t('Sat')), array('day' => 'Sun', 't' => t('Sun')), array('day' => 'Mon', 't' => t('Mon')), array('day' => 'Tue', 't' => t('Tue'))); break; case 4: $weekdays = array(array('day' => 'Thu', 't' => t('Thu')), array('day' => 'Fri', 't' => t('Fri')), array('day' => 'Sat', 't' => t('Sat')), array('day' => 'Sun', 't' => t('Sun')), array('day' => 'Mon', 't' => t('Mon')), array('day' => 'Tue', 't' => t('Tue')), array('day' => 'Wed', 't' => t('Wed'))); break; case 5: $weekdays = array(array('day' => 'Fri', 't' => t('Fri')), array('day' => 'Sat', 't' => t('Sat')), array('day' => 'Sun', 't' => t('Sun')), array('day' => 'Mon', 't' => t('Mon')), array('day' => 'Tue', 't' => t('Tue')), array('day' => 'Wed', 't' => t('Wed')), array('day' => 'Thu', 't' => t('Thu'))); break; case 6: $weekdays = array(array('day' => 'Sat', 't' => t('Sat')), array('day' => 'Sun', 't' => t('Sun')), array('day' => 'Mon', 't' => t('Mon')), array('day' => 'Tue', 't' => t('Tue')), array('day' => 'Wed', 't' => t('Wed')), array('day' => 'Thu', 't' => t('Thu')), array('day' => 'Fri', 't' => t('Fri'))); break; default: $weekdays = array(array('day' => 'Sun', 't' => t('Sun')), array('day' => 'Mon', 't' => t('Mon')), array('day' => 'Tue', 't' => t('Tue')), array('day' => 'Wed', 't' => t('Wed')), array('day' => 'Thu', 't' => t('Thu')), array('day' => 'Fri', 't' => t('Fri')), array('day' => 'Sat', 't' => t('Sat'))); break; } } return $weekdays; } /** * 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) { // create week header $days = calendar_week_days(); if ($with_week) { $row[] = array('class' => "days week", 'data' => ' '); } foreach ($days as $day) { $row[] = array('class' => strtolower("days ". $day['day']), 'data' => $mini ? drupal_substr($day['t'], 0 , 1) : $day['t']); } return $row; } /** * Return the day of week with start of week offset applied * @param $stamp GMT timestamp * @return integer day of the week */ function _calendar_day_of_week($stamp) { calendar_load_date_api(); $dow = date_format_date('w', $stamp); if ($dow - variable_get('date_first_day', 1) >= 0 ) { $dow = $dow - variable_get('date_first_day', 1); } else { $dow = 7 - variable_get('date_first_day', 1); } return $dow; }