$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->date_info->min_date_date && $item_start <= $view->date_info->max_date_date) || ($item_end >= $view->date_info->min_date_date && $item_end <= $view->date_info->max_date_date)) { $values[$item_start][date_format($item->date_start, 'H:i:s')][] = $item; } } $items = $values; ksort($items); $rows = array(); $curday = drupal_clone($view->date_info->min_date); switch ($view->date_info->granularity) { case 'year': $rows = array(); $view->date_info->mini = TRUE; for ($i = 1; $i <= 12; $i++) { $rows[$i] = calendar_build_mini_month($curday, $view, $items); } $view->date_info->mini = FALSE; break; case 'month': $rows = ($view->date_info->mini) ? calendar_build_mini_month($curday, $view, $items) : calendar_build_month($curday, $view, $items); break; case 'day': $rows = calendar_build_day($curday, $view, $items); break; case 'week': $rows = calendar_build_week($curday, $view, $items); // Merge the day names in as the first row. $rows = array_merge(array(calendar_week_header($view)), $rows); break; } return $rows; } /** * Build one month. */ function calendar_build_mini_month(&$curday, $view, $items) { $month = date_format($curday, 'n'); date_modify($curday, '-' . strval(date_format($curday, 'j')-1) . ' days'); $rows = array(); do { $rows = array_merge($rows, calendar_build_mini_week($curday, $view, $items, TRUE)); $curday_date = date_format($curday, DATE_FORMAT_DATE); $curday_month = date_format($curday, 'n'); } while ($curday_month == $month && $curday_date <= $view->date_info->max_date_date); // Merge the day names in as the first row. $rows = array_merge(array(calendar_week_header($view)), $rows); return $rows; } /** * Build one month. */ function calendar_build_month(&$curday, $view, $items) { $month = date_format($curday, 'n'); $curday_date = date_format($curday, DATE_FORMAT_DATE); $weekdays = calendar_untranslated_days($items, $view); date_modify($curday, '-' . strval(date_format($curday, 'j')-1) . ' days'); $rows = array(); do { $init_day = clone($curday); $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); $week_rows = calendar_build_week($curday, $view, $items, TRUE); $multiday_buckets = $week_rows['multiday_buckets']; $singleday_buckets = $week_rows['singleday_buckets']; $total_rows = $week_rows['total_rows']; // Theme each row $output = ""; $final_day = clone($curday); $iehint = 0; $max_multirow_cnt = 0; $max_singlerow_cnt = 0; for ($i = 0; $i < $total_rows + 1; $i++) { $inner = ""; // If we're displaying the week number, add it as the // first cell in the week. if ($i == 0 && !empty($view->date_info->style_with_weekno) && !in_array($view->date_info->granularity, array('day', 'week'))) { $url = $view->get_path() .'/'. $view->date_info->year .'-W'. $week; if (!empty($view->date_info->display_types['week'])) { $weekno = l($week, $url, array('query' => !empty($view->date_info->append) ? $view->date_info->append : '')); } else { // Do not link week numbers, if Week views are disabled. $weekno = $week; } $item = array( 'entry' => $weekno, 'colspan' => 1, 'rowspan' => $total_rows + 1, 'id' => $view->name . '-weekno-' . $curday_date, 'class' => 'week' ); $inner .= theme('calendar_month_col', $item); } $curday = clone($init_day); // 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'); for ( $wday = 0; $wday < 7; $wday++) { $curday_date = date_format($curday, DATE_FORMAT_DATE); $class = strtolower($weekdays[$wday]); $item = NULL; $in_month = !($curday_date < $view->date_info->min_date_date || $curday_date > $view->date_info->max_date_date || date_format($curday, 'n') != $month); // Add the datebox if ($i == 0) { $count = $in_month ? intval(count($multiday_buckets[$wday]) + count($singleday_buckets[$wday])) : FALSE; $item = array( 'entry' => theme('calendar_datebox', $curday_date, $view, $items, $count), 'colspan' => 1, 'rowspan' => 1, 'class' => 'date-box', 'date' => $curday_date, 'id' => $view->name . '-' . $curday_date . '-date-box' ); $item['class'] .= ($curday_date == $today && $in_month ? ' today' : '') . ($curday_date < $today ? ' past' : '') . ($curday_date > $today ? ' future' : ''); } else { $index = $i - 1; $multi_count = count($multiday_buckets[$wday]); // Process multiday buckets first. If there is a multiday-bucket item in this row... if ($index < $multi_count) { // If this item is filled with either a blank or an entry... if ($multiday_buckets[$wday][$index]['filled']) { // Add item and add class $item = $multiday_buckets[$wday][$index]; $item['class'] = 'multi-day'; $item['date'] = $curday_date; // Is this an entry? if (!$multiday_buckets[$wday][$index]['avail']) { // If the item either starts or ends on today, // then add tags so we can style the borders if ($curday_date == $today && $in_month) { $item['class'] .= ' starts-today'; } // Calculate on which day of this week this item ends on.. $end_day = clone($curday); $span = $item['colspan'] - 1; date_modify($end_day, '+' . $span .' day'); $endday_date = date_format($end_day, DATE_FORMAT_DATE); // If it ends today, add class if ($endday_date == $today && $in_month) { $item['class'] .= ' ends-today'; } } } // If this is an acutal entry, add classes regarding the state of the // item if ($multiday_buckets[$wday][$index]['avail']) { $item['class'] .= ' ' . $wday . ' ' . $index . ' no-entry ' . ($curday_date == $today && $in_month ? ' today' : '') . ($curday_date < $today ? ' past' : '') . ($curday_date > $today ? ' future' : ''); } // Else, process the single day bucket - we only do this once per day } elseif ($index == $multi_count) { $single_day_cnt = 0; // If it's empty, add class if (count($singleday_buckets[$wday]) == 0) { $single_days = " "; if ($max_multirow_cnt == 0 ) { $class = ($multi_count > 0 ) ? 'single-day no-entry noentry-multi-day' : 'single-day no-entry'; } else { $class = 'single-day'; } } else { $single_days = ""; foreach ($singleday_buckets[$wday] as $day) { foreach ($day as $event) { $single_day_cnt++; $single_days .= (isset($event['more_link'])) ? '
' . $event['entry'] . '
' : $event['entry']; } } $class = 'single-day'; } $rowspan = $total_rows - $index; // Add item... $item = array( 'entry' => $single_days, 'colspan' => 1, 'rowspan' => $rowspan, 'class' => $class, 'date' => $curday_date, 'id' => $view->name . '-' . $curday_date . '-' . $index ); // Hack for ie to help it properly space single day rows if ($rowspan > 1 && $in_month && $single_day_cnt > 0) { $max_multirow_cnt = max($max_multirow_cnt, $single_day_cnt); } else { $max_singlerow_cnt = max($max_singlerow_cnt, $single_day_cnt); } // If the singlerow is bigger than the multi-row, then null out // ieheight - I'm estimating that a single row is twice the size of // multi-row. This is really the best that can be done with ie if ($max_singlerow_cnt >= $max_multirow_cnt || $max_multirow_cnt <= $multi_count / 2 ) { $iehint = 0; } elseif ($rowspan > 1 && $in_month && $single_day_cnt > 0) { $iehint = max($iehint, $rowspan - 1); // How many rows to adjust for? } // Set the class $item['class'] .= ($curday_date == $today && $in_month ? ' today' : '') . ($curday_date < $today ? ' past' : '') . ($curday_date > $today ? ' future' : ''); } } // If there isn't an item, then add empty class if ($item != NULL) { if (!$in_month) { $item['class'] .= ' empty'; } // Style this entry - it will be a . $inner .= theme('calendar_month_col', $item); } date_modify($curday, '+1 day'); } if ($i == 0) { $output .= theme('calendar_month_row', $inner, 'date-box', $week, $iehint); } elseif ($i == $total_rows) { $output .= theme('calendar_month_row', $inner, 'single-day', $week, $iehint); $iehint = 0; $max_singlerow_cnt = 0; $max_multirow_cnt = 0; } else { // Style all the columns into a row $output .= theme('calendar_month_row', $inner, 'multi-day', $week); } } $curday = $final_day; // Add the row into the row array.... $rows[] = array('data' => $output); $curday_date = date_format($curday, DATE_FORMAT_DATE); $curday_month = date_format($curday, 'n'); } while ($curday_month == $month && $curday_date <= $view->date_info->max_date_date); // Merge the day names in as the first row. $rows = array_merge(array(calendar_week_header($view)), $rows); return $rows; } /** * Build one week row. */ function calendar_build_mini_week(&$curday, $view, $items, $check_month = FALSE) { $curday_date = date_format($curday, DATE_FORMAT_DATE); $weekdays = calendar_untranslated_days($items, $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. if (!empty($view->date_info->style_with_weekno) && !in_array($view->date_info->granularity, array('day', 'week'))) { $url = date_real_url($view, NULL, $view->date_info->year .'-W'. $week); if (!empty($view->date_info->display_types['week'])) { $weekno = l($week, $url, array('query' => !empty($view->date_info->append) ? $view->date_info->append : '')); } else { // Do not link week numbers, if Week views are disabled. $weekno = $week; } $rows[$week][] = array( 'data' => $weekno, 'id' => $view->name . '-weekno-' . $curday_date, 'class' => 'week'); } for ($i = 0; $i < 7; $i++) { $curday_date = date_format($curday, DATE_FORMAT_DATE); $class = strtolower($weekdays[$i] . ' mini'); if ($check_month && ($curday_date < $view->date_info->min_date_date || $curday_date > $view->date_info->max_date_date || date_format($curday, 'n') != $month)) { $class .= ' empty'; $content = array( 'date' => '', 'datebox' => '', 'empty' => theme('calendar_empty_day', $curday_date, $view), 'link' => '', 'all_day' => array(), 'items' => array(), ); } else { $content = calendar_build_day($curday, $view, $items); $class .= ($curday_date == $today ? ' today' : '') . ($curday_date < $today ? ' past' : '') . ($curday_date > $today ? ' future' : '') . (empty($items[$curday_date]) ? ' has-no-events' : ' has-events'); } $rows[$week][] = array( 'data' => $content, 'class' => $class, 'id' => $view->name . '-' . $curday_date); date_modify($curday, '+1 day'); } return $rows; } /** * Build one week row. */ function calendar_build_week(&$curday, $view, $items, $check_month = FALSE) { $curday_date = date_format($curday, DATE_FORMAT_DATE); $weekdays = calendar_untranslated_days($items, $view); $month = date_format($curday, 'n'); $first_day = variable_get('date_first_day', 0); // Set up buckets $total_rows = 0; $multiday_buckets = array( array(), array(), array(), array(), array(), array(), array()); $singleday_buckets = array( array(), array(), array(), array(), array(), array(), array()); // 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); for ($i = 0; $i < 7; $i++) { if ($check_month && ($curday_date < $view->date_info->min_date_date || $curday_date > $view->date_info->max_date_date || date_format($curday, 'n') != $month)) { $class = strtolower($weekdays[$i]) .' empty'; $singleday_buckets[$i][][] = array( 'entry' => theme('calendar_empty_day', $curday_date, $view), 'item' => NULL ); } else { calendar_build_week_day($curday, $view, $items, $i, $multiday_buckets, $singleday_buckets); } $total_rows = max(count($multiday_buckets[$i]) + 1, $total_rows); date_modify($curday, '+1 day'); $curday_date = date_format($curday, DATE_FORMAT_DATE); } $rows = array( 'multiday_buckets' => $multiday_buckets, 'singleday_buckets' => $singleday_buckets, 'total_rows' => $total_rows); return $rows; } /** * Build the contents of a single day for the $rows results. */ function calendar_build_week_day($curday, $view, $items, $wday, &$multiday_buckets, &$singleday_buckets) { $curday_date = date_format($curday, DATE_FORMAT_DATE); $max_events = !empty($view->date_info->style_max_items) ? $view->date_info->style_max_items : 0; $hide = !empty($view->date_info->style_max_items_behavior) ? ($view->date_info->style_max_items_behavior == 'hide') : FALSE; $multiday_theme = ($view->date_info->style_multiday_theme == '1'); $cur_cnt = 0; $total_cnt = 0; $types = array(); // If we are hiding, count before processing further if ($max_events != CALENDAR_SHOW_ALL) { foreach ($items as $date => $day) { if ($date == $curday_date) { foreach ($day as $time => $hour) { foreach ($hour as $key => $item) { $total_cnt++; $types[$item->type] = $item; } } } } } // If we haven't already exceeded the max or we'll showing all, then process the items if ($max_events == CALENDAR_SHOW_ALL || !$hide || $total_cnt <= $max_events) { // Count currently filled items foreach ($multiday_buckets[$wday] as $bucket) { if (!$bucket['avail']) { $cur_cnt++; } } foreach ($items as $date => $day) { if ($date == $curday_date) { $count = 0; ksort($day); foreach ($day as $time => $hour) { foreach ($hour as $key => $item) { $count++; // Can we add an item? if ($max_events == CALENDAR_SHOW_ALL || $cur_cnt <= $max_events) { $all_day = $item->calendar_start_date == $item->calendar_end_date; $theme = isset($item->calendar_node_theme) ? $item->calendar_node_theme : 'calendar_'. $view->date_info->granularity .'_node'; // Parse out date part $start_ydate = date_format($item->date_start, DATE_FORMAT_DATE); $end_ydate = date_format($item->date_end, DATE_FORMAT_DATE); $cur_ydate = date_format($curday, DATE_FORMAT_DATE); $is_multi_day = ($start_ydate < $cur_ydate || $end_ydate > $cur_ydate); // Does this event span multi-days? if ($multiday_theme && ($is_multi_day || $all_day)) { // If this the first day of the week, or is the start date of the multi-day event, // then record this item, otherwise skip over $day_no = date_format($curday, 'd'); if ($wday == 0 || $start_ydate == $cur_ydate || ($view->date_info->granularity == 'month' && $day_no == 1) || ($all_day && !$is_multi_day)) { $cur_cnt++; // Calculate the colspan for this event // If the last day of this event exceeds the end of the current month or week, // truncate the remaining days $diff = date_difference($view->date_info->max_date, $curday, 'days'); $remaining_days = ($view->date_info->granularity == 'month') ? min(6 - $wday, $diff) : $diff - 1; // The bucket_cnt defines the colspan. colspan = bucket_cnt + 1 $days = date_difference($curday, $item->date_end, 'days'); $bucket_cnt = max(0, min($days, $remaining_days)); // See if there is an avaiable slot to add an event. This will allow // an event to precede a row filled up by a previous day event $avail = FALSE; $bucket_index = count($multiday_buckets[$wday]); for ($i = 0; $i < $bucket_index; $i++) { if ($multiday_buckets[$wday][$i]['avail']) { $bucket_index = $i; break; } } // Add continuation attributes $item->continuation = ($item->date_start < $curday); $item->continues = ( $days > $bucket_cnt ); // Assign the item to the available bucket $multiday_buckets[$wday][$bucket_index] = array( 'colspan' => $bucket_cnt + 1, 'rowspan' => 1, 'filled' => TRUE, 'avail' => FALSE, 'all_day' => $all_day, 'item' => $item, 'wday' => $wday, 'entry' => theme($theme, $item, $view) ); // Block out empty buckets for the next days in this event for this week for ($i = 0; $i < $bucket_cnt; $i++) { $bucket = &$multiday_buckets[$i + $wday + 1]; $bucket_row_count = count($bucket); $row_diff = $bucket_index - $bucket_row_count; // Fill up the preceding buckets - these are available for future // events for ( $j = 0; $j < $row_diff; $j++) { $bucket[($bucket_row_count + $j) ] = array( 'entry' => ' ', 'colspan' => 1, 'rowspan' => 1, 'filled' => TRUE, 'avail' => TRUE, 'wday' => $wday, 'item' => NULL ); } $bucket[$bucket_index] = array( 'filled' => FALSE, 'avail' => FALSE ); } } } else { $cur_cnt++; // Assign to single day bucket $singleday_buckets[$wday][$time][] = array( 'entry' => theme($theme, $item, $view), 'item' => $item, 'colspan' => 1, 'rowspan' => 1, 'filled' => TRUE, 'avail' => FALSE, 'wday' => $wday, ); } } else { break; // exceeded count } } } } } } // Add a more link if necessary if ($max_events != CALENDAR_SHOW_ALL && $total_cnt > 0 && $cur_cnt < $total_cnt) { $singleday_buckets[$wday][][] = array( 'entry' => theme('calendar_'. $view->date_info->calendar_type .'_multiple_node', $curday_date, $total_cnt, $view, $types), 'more_link' => TRUE, 'item' => NULL ); } } /** * Build the contents of a single day for the $rows results. */ function calendar_build_day($curday, $view, $items) { $curday_date = date_format($curday, DATE_FORMAT_DATE); $selected = FALSE; $max_events = !empty($view->date_info->style_max_items) ? $view->date_info->style_max_items : 0; $types = array(); $inner = array(); $all_day = array(); $empty = ''; $link = ''; $count = 0; foreach ($items as $date => $day) { if ($date == $curday_date) { $count = 0; $selected = TRUE; ksort($day); foreach ($day as $time => $hour) { foreach ($hour as $key => $item) { $count++; $types[$item->type] = $item; if (!$view->date_info->mini && ($max_events == CALENDAR_SHOW_ALL || $count <= $max_events || ($count > 0 && $max_events == CALENDAR_HIDE_ALL))) { // Theme the item here unless this is a 'Day' or 'Week' view. // Day and week views need to do more processing before rendering // the item, so just past them the unrendered item. $theme = isset($item->calendar_node_theme) ? $item->calendar_node_theme : 'calendar_'. $view->date_info->granularity .'_node'; if ($item->calendar_all_day) { $all_day[] = in_array($view->date_info->calendar_type, array('day', 'week')) ? $item : theme($theme, $item, $view); } else { $key = date_format($item->date_start, 'H:i:s'); $inner[$key][] = in_array($view->date_info->calendar_type, array('day', 'week')) ? $item : theme($theme, $item, $view); } } } } } } ksort($inner); if (empty($inner) && empty($all_day)) { $empty = theme('calendar_empty_day', $curday_date, $view); } // We have hidden events on this day, use the theme('calendar_multiple_') to show a link. if ($max_events != CALENDAR_SHOW_ALL && $count > 0 && $count > $max_events && $view->date_info->calendar_type != 'day' && !$view->date_info->mini) { if ($view->date_info->style_max_items_behavior == 'hide' || $max_events == CALENDAR_HIDE_ALL) { $all_day = array(); $inner = array(); } $link = theme('calendar_'. $view->date_info->calendar_type .'_multiple_node', $curday_date, $count, $view, $types); } $content = array( 'date' => $curday_date, 'datebox' => theme('calendar_datebox', $curday_date, $view, $items, $selected), 'empty' => $empty, 'link' => $link, 'all_day' => $all_day, 'items' => $inner, ); return $content; }