3.0, 'path' => drupal_get_path('module', 'calendar') . '/includes', ); } /** * @file * Adds calendar filtering and displays to Views. */ /** * Implementation of hook_help(). */ function calendar_help($section, $arg) { switch ($section) { case 'admin/help#calendar': return t("

View complete documentation at !link.

", array('!link' => 'http://drupal.org/node/120710')); } } function calendar_init() { // If the multiday module is enabled, let it control the css. if (module_exists('calendar_multiday') || substr($_GET['q'], 0, 24) == 'admin/build/modules/list') { return; } // The css for Farbtastic color picker, painless to add it here // even though it isn't needed everywhere. drupal_add_css('misc/farbtastic/farbtastic.css'); drupal_add_css(drupal_get_path('module', 'calendar') . '/calendar.css'); module_load_include('inc', 'calendar', 'theme/theme.inc'); } function calendar_theme() { // If the multiday module is enabled, let it control the theme. if (module_exists('calendar_multiday')) { return array(); } $module_path = drupal_get_path('module', 'calendar'); $base = array( 'file' => 'theme.inc', 'path' => "$module_path/theme", ); return array( 'calendar_day_node' => $base + array( 'template' => 'calendar-day-node', 'variables' => array('node' => NULL, 'view' => NULL), ), 'calendar_month_node' => $base + array( 'template' => 'calendar-month-node', 'variables' => array('node' => NULL, 'view' => NULL), ), 'calendar_week_node' => $base + array( 'template' => 'calendar-week-node', 'variables' => array('node' => NULL, 'view' => NULL), ), 'calendar_month_multiple_node' => $base + array( 'template' => 'calendar-month-multiple-node', 'variables' => array('curday' => NULL, 'count' => NULL, 'view' => NULL, 'types' => NULL), ), 'calendar_week_multiple_node' => $base + array( 'template' => 'calendar-week-multiple-node', 'variables' => array('curday' => NULL, 'count' => NULL, 'view' => NULL, 'types' => NULL), ), 'calendar_datebox' => $base + array( 'template' => 'calendar-datebox', 'variables' => array( 'date' => NULL, 'view' => NULL, 'items' => NULL, 'selected' => NULL), ), 'calendar_date_combo' => $base + array( 'variables' => array('node' => NULL, 'lable' => NULL, 'view' => NULL), ), 'calendar_empty_day' => $base + array( 'variables' => array('curday' => NULL, 'view' => NULL), ), 'calendar_stripe_legend' => $base + array( 'variables' => array('stripe_labels' => NULL), ), 'calendar_stripe_stripe' => $base + array( 'variables' => array('node' => NULL), ), 'calendar_time_row_heading' => $base + array( 'variables' => array('start_time' => NULL, 'next_start_time' => NULL, 'curday_date' => NULL), ), 'calendar_month_col' => $base + array( 'template' => 'calendar-month-col', 'variables' => array('item' => NULL), ), 'calendar_month_row' => $base + array( 'template' => 'calendar-month-row', 'variables' => array('inner' => NULL, 'class' => NULL, 'iehint' => NULL), ), ); } /** * TODO need to identify type of timezone handling needed for each date field */ function calendar_offset($field_name) { $default_offset = variable_get('date_default_timezone', 0); $configurable_zones = variable_get('configurable_timezones', 1); } /** * A function to test the validity of various date parts */ function calendar_part_is_valid($value, $type) { if ( !preg_match('/^[0-9]*$/', $value) ) { return FALSE; } $value = intval($value); if ($value <= 0) return FALSE; switch ($type) { case 'year': if ($value < DATE_MIN_YEAR) return FALSE; break; case 'month': if ($value < 0 || $value > 12) return FALSE; break; case 'day': if ($value < 0 || $value > 31) return FALSE; break; case 'week': if ($value < 0 || $value > 53) return FALSE; } return TRUE; } /** * implementation of hook_block_list() */ function calendar_block_list($delta = 0) { $blocks[0]['info'] = t('Calendar Legend.'); return $blocks; } /** * implementation of hook_block_view() */ function calendar_block_view($delta = 0) { switch ($delta) { case 0: $block['subject'] = t('Calendar Legend'); $content = theme('calendar_stripe_legend'); $block['content'] = !empty($content) ? '
' . $content . '
' : ''; return $block; } } /** * Calendar display types */ function calendar_display_types() { return array('year' => t('Year'), 'month' => t('Month'), 'day' => t('Day'), 'week' => t('Week')); } /** * Figure out which type of display to use, * based on the current argument. * * @return year, month, day, or week. */ function calendar_current_type($view) { if (!is_object($view) || !isset($view->argument) || !is_array($view->argument)) { if (!empty($view->date_info->default_display)) { return $view->date_info->default_display; } return FALSE; } $i = 0; $date_handler = new date_sql_handler(); foreach ($view->argument as $argument) { if ($argument['id'] == 'date_argument') { $parts = array_keys($date_handler->arg_parts($view->args[$i])); break; } $i++; } return array_pop($parts); } /** * Create a stripe. * * @param $node - the node object * @param $query_name - the views queryname for this date field * @param $delta - the delta for this field, used to distinguish fields that appear more than once in the calendar * @param $stripe - the hex code for this stripe. * @param $label - the label to give this stripe. * * TODO Reconsider use of $GLOBALS as a method of triggering the legend, there * may be a better way. */ function calendar_node_stripe($view, &$node, $query_name, $delta, $stripe = NULL, $label = '') { $colors = isset($view->date_info->calendar_colors) ? $view->date_info->calendar_colors : array(); if (empty($colors)) { return; } $type_names = node_type_get_names(); $type = $node->raw->node_type; if (!(isset($node->stripe))) { $node->stripe = array(); $node->stripe_label = array(); } if (!$label && array_key_exists($type, $type_names)) { $label = $type_names[$type]; } if (!$stripe) { if (array_key_exists($type, $colors)) { $stripe = $colors[$type]; } else { $stripe = ''; } } $node->stripe[] = $stripe; $node->stripe_label[] = $label; $GLOBALS['calendar_stripe_labels'][][$type] = array('stripe' => $stripe, 'label' => $label); return $stripe; } /** * Create a stripe based on a taxonomy term. * * @param $node - the node object * @param $query_name - the views queryname for this date field * @param $delta - the delta for this field, used to distinguish fields that appear more than once in the calendar * @param $stripe - the hex code for this stripe. * @param $label - the label to give this stripe. * * TODO Reconsider use of $GLOBALS as a method of triggering the legend, there * may be a better way. */ function calendar_node_taxonomy_stripe($view, &$node, $query_name, $delta, $stripe = NULL, $label = '') { $colors_taxonomy = isset($view->date_info->calendar_colors_taxonomy) ? $view->date_info->calendar_colors_taxonomy : array(); if (empty($colors_taxonomy)) { return; } if (empty($node->raw->taxonomy_term_data_tid)) { return; } // Rename the vid added by Views to the normal name that // taxonomy will expect, it's in the raw results. $node->vid = $node->raw->node_vid; $terms_for_node = (array) $node->raw->taxonomy_term_data_tid; if (!(isset($node->stripe))) { $node->stripe = array(); $node->stripe_label = array(); } if (count($terms_for_node)) { foreach ($terms_for_node as $tid) { $term_for_node = taxonomy_term_load($tid); if (!array_key_exists($term_for_node->tid, $colors_taxonomy)) { continue; } $stripe = $colors_taxonomy[$term_for_node->tid]; $stripe_label = $term_for_node->name; $node->stripe[] = $stripe; $node->stripe_label[] = $stripe_label; $GLOBALS['calendar_stripe_labels'][][$term_for_node->tid] = array('stripe' => $stripe, 'label' => $stripe_label); } } else { $node->stripe[] = ''; $node->stripe_label[] = ''; } return; } /** * Create a stripe based on group. * * @param $node - the node object * @param $query_name - the views queryname for this date field * @param $delta - the delta for this field, used to distinguish fields that appear more than once in the calendar * @param $stripe - the hex code for this stripe. * @param $label - the label to give this stripe. * * TODO Reconsider use of $GLOBALS as a method of triggering the legend, there * may be a better way. */ function calendar_node_group_stripe($view, &$node, $query_name, $delta, $stripe = NULL, $label = '') { $colors_group = isset($view->date_info->calendar_colors_group) ? $view->date_info->calendar_colors_group : array(); if (empty($colors_group)) { return; } if (!function_exists('og_get_node_groups')) { return; } $groups_for_node = og_get_node_groups($node); if(!(isset($node->stripe))){ $node->stripe = array(); $node->stripe_label = array(); } if (count($groups_for_node)){ foreach($groups_for_node as $gid => $group_name){ if (!array_key_exists($gid, $colors_group)) { continue; } $stripe = $colors_group[$gid]; $stripe_label = $group_name; $node->stripe[] = $stripe; $node->stripe_label[] = $stripe_label; $GLOBALS['calendar_stripe_labels'][][$gid] = array('stripe' => $stripe, 'label' => $stripe_label); } } else { $node->stripe[] = ''; $node->stripe_label[] = ''; } return $stripe; } /** * Helper function to figure out a group gid to use in blocks. * * @return an array of group nodes that are relevant. * @todo this may need more work. */ function calendar_og_groups($view) { if (!$groupnode = og_get_group_context()) { global $user; $groupnodes = array_keys($user->og_groups); } else { $groupnodes = array($groupnode->nid); } return $groupnodes; } /** * A selector to jump to a new date in the calendar. * * @param unknown_type $view * @return unknown */ function calendar_date_select($view) { return '
' . drupal_render(drupal_get_form('calendar_date_select_form', $view)) . '
'; } /** * The date selector form. * * @param object $view * @return the form element * * @TODO is the title desired here or does it take up too much space?? */ function calendar_date_select_form($form, &$form_state, $view) { $format = date_limit_format(variable_get('date_format_short', 'm/d/Y - H:i'), array('year', 'month', 'day')); $form['calendar_goto'] = array( //'#title' => t('Calendar date'), '#type' => module_exists('date_popup') ? 'date_popup' : 'date_select', '#default_value' => date_format($view->date_info->min_date, 'Y-m-d'), '#date_timezone' => date_default_timezone(), '#date_format' => $format, ); $form['calendar_type'] = array( '#type' => 'hidden', '#value' => $view->date_info->calendar_type, ); $form['view_name'] = array( '#type' => 'hidden', '#value' => $view->name, ); $form['view_url'] = array( '#type' => 'hidden', '#value' => $view->get_url(), ); $pos = calendar_arg_position($view); $form['calendar_previous_arg'] = array( '#type' => 'hidden', '#value' => $view->args[$pos], ); $form['submit'] = array( '#type' => 'submit', '#value' => t('Change date'), ); return $form; } function calendar_arg_position($view) { $pos = 0; foreach ($view->argument as $argument) { if ($argument->definition['handler'] == 'date_views_argument_handler') { return $pos; } $pos++; } } /** * Get the url for a calendar node. * * @param $node - a calendar node object * @param $default - a default url to use when nothing specific is provided. */ function calendar_get_node_link($node, $default = NULL) { if (isset($node->url)) { return url($node->url, array('absolute' => TRUE)); } elseif (empty($node->remote) && is_numeric($node->nid)) { return url("node/$node->nid", array('absolute' => TRUE)); } elseif (!empty($default)) { return url($default, array('absolute' => TRUE)); } } function calendar_groupby_times($type = '') { $times = array(); switch ($type) { case 'hour': for ($i = 0; $i <= 23; $i++) { $times[] = date_pad($i) . ':00:00'; } break; case 'half': for ($i = 0; $i <= 23; $i++) { $times[] = date_pad($i) . ':00:00'; $times[] = date_pad($i) . ':30:00'; } break; default: break; } return $times; } /** * Define some error messages. */ function calendar_errors($error) { switch ($error) { case 'missing_argument_default': 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'."); } } /** * Check to make sure the user has entered a valid 6 digit hex color. */ function calendar_validate_hex_color($element) { if (!$element['#required'] && empty($element['#value'])) { return; } if (!preg_match('/^#(?:(?:[a-f\d]{3}) {1,2})$/i', $element['#value'])) { form_error($element, t('@value is not a valid hex color', array('@value' => check_plain($element['#value'])))); } else { form_set_value($element, $element['#value']); } } /** * Add link to calendar to nodes. * * Controlled by value of 'calendar_date_link' in the view. */ function calendar_link($type, $object, $teaser = FALSE) { if ($type == 'node' && !$teaser) { $path = variable_get('calendar_date_link_' . $object->type); if (!empty($path)) { return array('calendar_link' => array( 'title' => t('Calendar'), 'href' => $path, 'attributes' => array('title' => t('View the calendar.')), )); } } } /** * Callback to remove a default calendar from the system. */ function calendar_remove($view_name) { // Remove any variable that creates a default view with this name. $calendar_options = variable_get('calendar_default_view_options', array()); if (array_key_exists($view_name, $calendar_options)) { unset($calendar_options[$view_name]); } variable_set('calendar_default_view_options', $calendar_options); // Delete it from the database, if stored there. if ($view = views_get_view($view_name)) { $view->delete(); } views_invalidate_cache(); } /** * Formats the weekday information into table header format * * @ingroup event_support * @return array with weekday table header data */ function calendar_week_header($view) { $len = isset($view->date_info->style_name_size) ? $view->date_info->style_name_size : (!empty($view->date_info->mini) ? 1 : 3); $with_week = !empty($view->date_info->style_with_weekno); // 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 = $len < 3 ? 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; } /** * 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) { if (empty($view->date_info->min_date) || empty($view->date_info->max_date)) { return $items; } // Midnights are determined based on the same timezone as the View uses $display_timezone = date_timezone_get($view->date_info->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 = clone($view->date_info->min_date); date_timezone_set($min_utc, timezone_open('UTC')); $max_utc = clone($view->date_info->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->date_info->nodes_per_page = 0; $type_names = node_type_get_names(); $datefields = array(); $fields = date_views_fields(); if (!empty($view->filter['date_filter'])) { $date_filter = $view->filter['date_filter']; foreach ($view->filter['date_filter']->options['date_fields'] as $name) { $datefields[] = $fields['name'][$name]['query_name']; } } if (!empty($view->argument['date_argument'])) { $date_filter = $view->argument['date_argument']; foreach ($view->argument['date_argument']->options['date_fields'] as $name) { $datefields[] = $fields['name'][$name]['query_name']; } } $view_fields = date_views_views_fetch_fields('node', 'field'); $field_names = (array) array_keys($fields['name']); $nodes = array(); $i = 0; foreach ($date_filter->options['date_fields'] as $name) { $field = $fields['name'][$name]; $field_type = strstr($field['type'], 'string') ? 'string' : 'timestamp'; $alias = $field['query_name']; $field_name = $field['field_name']; $fromto = $field['fromto']; $tz_handling = $field['tz_handling']; $label = isset($view->field[$name]) ? $view->field[$name]['label'] : $field['field_name']; $tz_alias = str_replace('.', '_', $field['timezone_field']); $db_tz = date_get_timezone_db($field['tz_handling']); $local_tz = date_get_timezone($field['tz_handling'], 'date'); $field_name = $field['field_name']; $real_field = $field['real_field_name']; // If there is no field for this item, just default to the site format. if (!isset($view->field[$field_name])) { $format = variable_get('date_format_short', 'm/d/Y - H:i'); } else { if (strstr($field['type'], 'cck')) { $formatter = $view->field[$field_name]->options['type']; $format = date_formatter_format($formatter, $view->field[$field_name]->options['type']); } else { $format = $view->field[$field_name]->options['date_format']; switch ($format) { case 'long': $format = variable_get('date_format_long', 'l, F j, Y - H:i'); break; case 'medium': $format = variable_get('date_format_medium', 'D, m/d/Y - H:i'); break; case 'custom': $format = $view->field[$field_name]->options['custom_date_format']; break; case 'time ago': break; default: $format = variable_get('date_format_short', 'm/d/Y - H:i'); break; } } } // set the domain part of the id $domain = check_plain($_SERVER['SERVER_NAME']); // 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(); $rrule_processed = array(); foreach ($items as $pos => $item) { $delta = !empty($field['delta_field']) && !empty($item->{$field['delta_field']}) ? $item->{$field['delta_field']} : 0; $id = 'calendar.' . $item->nid . '.' . $real_field . '.' . $delta; // When creating iCal feeds for repeating dates we don't want all // the multiple values, send only the first value. if (strstr($view->current_display, '_ical')) { if (!isset($rrule_processed[$item->nid])) { $rrule_processed[$item->nid] = TRUE; } else { continue; } } if (!in_array($id, $processed) && isset($item->calendar_fields->$alias)) { // Create from and to date values for each item, adjusted to // the correct timezone. $values[0] = $item->calendar_fields->$fromto[0]; $values[1] = $item->calendar_fields->$fromto[1]; $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 = new DateObject($values[0], $db_tz); 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 = new DateObject($values[1], $db_tz); 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 = clone($view->date_info->min_date); date_timezone_set($date, $display_timezone); $min_zone_string[$display_timezone_name] = date_format($date, DATE_FORMAT_DATE); $date = clone($view->date_info->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 = new DateObject($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 = 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; } $exceptions = array('format_interval', 'time ago'); $node->label = $label; $node->format = $format; if (!in_array($node->format, $exceptions)) { if (!isset($formats[$format])) { $formats[$format] = date_limit_format($format, array('hour', 'minute', 'second')); $node->format_time = $formats[$format]; } } else { $node->format_time = ''; } $node->url = calendar_get_node_link($node); //$node->$fromto[0] = $values[0]; //$node->$fromto[1] = $values[1]; // Flag which datefield this node is using, in case // there are multiple date fields in the view. $node->datefield = $alias; // 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 != $alias && in_array($key, $datefields)) { unset($node->$key); foreach ($fields['name'] 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; $node->date_start = date_create($values[0], timezone_open($to_zone)); $node->date_end = date_create(!empty($values[1]) ? $values[1] : $values[0], timezone_open($to_zone));; // Actual start and end date as set in the node object $node->date_start = date_create($values[0], timezone_open($to_zone)); $node->date_end = date_create(!empty($values[1]) ? $values[1] : $values[0], timezone_open($to_zone));; // 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); if (substr($real_field, 0, 6) == 'field_') { $cck_field = field_info_field($real_field); $instance = field_info_instance($view->base_table, $real_field, $node->type); $granularity = $cck_field['settings']['granularity']; $increment = $instance['widget']['settings']['increment']; } else { $granularity = 'second'; $increment = 1; } $node->calendar_all_day = date_is_all_day($node->calendar_start, $node->calendar_end, $granularity, $increment); // 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 { calendar_node_stripe($view, $node, $alias, $alias); calendar_node_taxonomy_stripe($view, $node, $alias, $alias); calendar_node_group_stripe($view, $node, $alias, $alias); $node->date_id = $id . '.' . $pos; $nodes[] = $node; unset($node); } date_modify($next, '+1 second'); $processed[] = $id; $now = date_format($next, DATE_FORMAT_DATE); } } } } return $nodes; }