home | career | drupal | java | mac | mysql | perl | php | scala | uml | unix

Drupal example source code file (calendar.module)

This example Drupal source code file (calendar.module) is included in the DevDaily.com "Drupal Source Code Warehouse" project. The intent of this project is to help you "Learn Drupal by Example".

PHP - Drupal tags/keywords

array, date, element, empty, foreach, function, if, isset, null, php, return, value, variable, view

The calendar.module Drupal example source code

<?php
// $Id: calendar.module,v 1.121.2.43 2010/12/31 16:25:43 karens Exp $
define('CALENDAR_SHOW_ALL', 0);
define('CALENDAR_HIDE_ALL', -1);

/**
 * Implementation of hook_views_api().
 *
 * This one is used as the base to reduce errors when updating.
 */
function calendar_views_api() {
  return array(
    'api' => 2,
    '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("<p>View complete documentation at !link.</p>", 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');
  require_once('./'. drupal_get_path('module', 'calendar') .'/theme/theme.inc');
}

function calendar_theme() {
  if (module_exists('calendar_multiday')) {
    return array();
  }
  $path = drupal_get_path('module', 'calendar');
  $base = array(
    'file' => 'theme.inc',
    'path' => "$path/theme",
  );
  return array(
    'calendar_day_node' => $base + array(
       'template' => 'calendar-day-node',
       'arguments' => array('node' => NULL, 'view' => NULL),
       ),
    'calendar_month_node' => $base + array(
      'template' => 'calendar-month-node',
      'arguments' => array('node' => NULL, 'view' => NULL),
      ),
    'calendar_week_node' => $base + array(
      'template' => 'calendar-week-node',
      'arguments' => array('node' => NULL, 'view' => NULL),
      ),
    'calendar_month_multiple_node' => $base + array(
      'template' => 'calendar-month-multiple-node',
      'arguments' => array('curday' => NULL, 'count' => NULL, 'view' => NULL, 'types' => NULL),
      ),
    'calendar_week_multiple_node' => $base + array(
      'template' => 'calendar-week-multiple-node',
      'arguments' => array('curday' => NULL, 'count' => NULL, 'view' => NULL, 'types' => NULL),
      ),
    'calendar_datebox' => $base + array(
      'template' => 'calendar-datebox',
      'arguments' => array(
        'date' => NULL, 'view' => NULL, 'items' => NULL, 'selected' => NULL),
      ),
    'calendar_date_combo' => $base + array(
      'arguments' => array('node', 'lable', 'view'),
      ),
    'calendar_empty_day' => $base + array(
      'arguments' => array('curday', 'view'),
      ),
    'calendar_stripe_legend' => $base + array(
      'arguments' => array('stripe_labels'),
      ),
    'calendar_stripe_stripe' => $base + array(
      'arguments' => array('node'),
      ),
    'calendar_colorpicker' => $base + array(
      'arguments' => array('element'),
      ),
    'calendar_colorfield' => $base + array(
      'arguments' => array('element'),
      ),
    'calendar_time_row_heading' => $base + array(
      'arguments' => array('start_time', 'next_start_time', 'curday_date'),
      ),
  );
}

/**
 *  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()
 */
function calendar_block($op = 'list', $delta = 0) {
  switch ($op) {
    case 'list' :
      $blocks[0]['info'] = t('Calendar Legend.');
      return $blocks;
      break;
    case 'view' :
      switch ($delta) {
      case 0:
        $block['subject'] = t('Calendar Legend');
        $content = theme('calendar_stripe_legend');
        $block['content'] = !empty($content) ? '<div class="calendar legend">'. $content .'</div>' : '';
        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_get_types('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;
  }
  
  // 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 = taxonomy_node_get_terms($node);
  if(!(isset($node->stripe))){
    $node->stripe = array();
    $node->stripe_label = array();
  }
  if (count($terms_for_node)){
    foreach($terms_for_node as $term_for_node){
      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 '<div class="calendar-date-select">'. drupal_get_form('calendar_date_select_form', $view) .'</div>';
}

/**
 * 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_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_name(),
    '#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_api_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'.");
  }
}
/**
 * Implementation of hook_elements.
 * 
 * Much of the colorpicker code was adapted from the Colorpicker module.
 * That module has no stable release yet nor any D6 branch.
 * 
 * TODO Consider dropping the duplicate code and adding a dependency
 * when that module is more stable, if calendar module customizations will 
 * work in it.
 */
function calendar_elements() {
  // the Farbtastic colorpicker
  $type['calendar_colorpicker'] = array(
    '#attributes' => array('class' => 'calendar_colorpicker'), 
    '#input' => TRUE,
  );
  
  // a textfield to associate with the Farbtastic colorpicker
  $type['calendar_colorfield'] = array(
    '#attributes' => array('class' => 'calendar_colorfield'), 
	  '#input' => TRUE,
	  '#validate' => array('calendar_validate_hex_color' => array())
  );
  return $type;
}

/**
 *  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, "'". check_plain($element['#value']) ."'". t(' is not a valid hex color'));
  }
  else {
    form_set_value($element, $element['#value']);
  }
}

/**
 * Format calendar_colorpicker.
 */
function theme_calendar_colorpicker($element) {

  $output = '';
  $output .= '<div id="'. $element['#id'] .'" '. drupal_attributes($element['#attributes']) .' ></div>';
  return theme('form_element', $element, $output);
}

/**
 * Format calendar_color textfield.
 */
function theme_calendar_colorfield($element) {
  $size = isset($element['#size']) ? ' size="' . $element['#size'] . '"' : '';
  $maxlength = isset($element['#maxlength']) ?  'maxlength="'.$element['#maxlength'] .'"' : '';
  $output = '';
  if (isset($element['#calendar_colorpicker'])) {
    $element['#attributes']['class'] .= ' edit-'. str_replace("_", "-", $element['#calendar_colorpicker']);
  }
  $output .= '<input type="text" name="'. $element['#name'] .'" id="'. $element['#id'] .'" '. $maxlength . $size .' value="'. check_plain($element['#value']) .'"'. drupal_attributes($element['#attributes']) .' />';
  return theme('form_element', $element, $output);
}

/**
 * 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, NULL);
    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 = drupal_clone($view->date_info->min_date);
  date_timezone_set($min_utc, timezone_open('UTC'));
  $max_utc = drupal_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_get_types('names');
  $datefields = array();
  $fields = date_api_fields($view->base_table);
  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_api_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'];
    $rrule_field  = str_replace(array('_value2', '_value'), '_rrule', $alias);
           
    // Set a flag to tell us if individual multi-day dates need to be
    // split into separate nodes.
    $split_dates = TRUE;
    if (strstr($view->current_display, '_ical')) {
      $split_dates = FALSE;
    }
   
    // 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')) {
        $format = $view->field[$field_name]->options['format'];
        $cck_field_name = str_replace(array('_value2', '_value'), '', $field_name);
        $format = date_formatter_format($format, $cck_field_name);
      }
      else {
        $format = $view->field[$field_name]->options['date_format'];
        $cck_field_name = NULL;
        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;
      $real_field = $field_name;
      if (substr($field['type'], 0, 3) == 'cck') {
        $real_field = str_replace(array('_value2', '_value'), '', $field_name);
      }
      
      $id = 'calendar.'. $item->{$view->base_field} .'.'. $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) && !empty($item->calendar_fields->$alias)) {
       
        // Create from and to date values for each item, adjusted to
        // the correct timezone.
        $values[0] = !empty($item->calendar_fields->$fromto[0]) ? $item->calendar_fields->$fromto[0] : $item->calendar_fields->$alias;
        $values[1] = !empty($item->calendar_fields->$fromto[1]) ? $item->calendar_fields->$fromto[1] : $item->calendar_fields->$alias;
              
        $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->date_info->min_date);
          date_timezone_set($date, $display_timezone);
          $min_zone_string[$display_timezone_name] = date_format($date, DATE_FORMAT_DATE);
          $date = drupal_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 = 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;
          }
          $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);
                  }
                }
              }
            }
          }
          // If we don't deconstruct dates into individual date parts,
          // use date values as-is.
          if (!$split_dates) {
            $node->calendar_start = $values[0];
            $node->calendar_end = $values[1];
          }
          // Split dates get intersection of current day and the node
          // value's duration (as strings in $to_zone timezone)
          else {
           // 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);
            $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));;
          
          // 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, 9) == 'field_') {
            $cck_field = content_fields($cck_field_name);
            $granularity = $cck_field['granularity'];
            $increment = $cck_field['widget']['increment'];
          }
          else {
            $granularity = 'second';
            $increment = 1;
          }
          $node->calendar_all_day = date_is_all_day($node->calendar_end, $node->calendar_end, $granularity, $increment);
         
          // Flag all day values specifically set in date.
          $all_day_field = str_replace(array('_value2', '_value'), '_all_day', $node->datefield);
          if (!empty($all_day_field) && !empty($item->$all_day_field)) {
            $node->calendar_all_day = TRUE;
          }
         
          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);
          }
          $processed[] = $id;
          if ($split_dates) {
            date_modify($next, '+1 second');
            $now = date_format($next, DATE_FORMAT_DATE);
          }
          else {
            break;
          }
        }
      }
    }
  }
  return $nodes;
}

Other Drupal examples (source code examples)

Here is a short list of links related to this Drupal calendar.module source code file:

new blog posts

"Drupal" is a registered trademark of Dries Buytaert.

my drupal tutorials and examples  

Copyright 1998-2016 Alvin Alexander, alvinalexander.com
All Rights Reserved.

Beginning in 2016, a portion of the proceeds from pages under the '/drupal-code-examples/' URI will be donated to charity.