You are here

function calendar_get_nodes in Calendar 5

The workhorse function that takes the beginning array of items and alters it to an array of calendar nodes that the theme can handle.

2 calls to calendar_get_nodes()
theme_calendar_ical_feed in ./calendar_ical.module
plugin that actually displays an ical feed
theme_calendar_view_calendar in ./calendar.theme
Calendar Views plugin theme, overrides default views theme to create a calendar view.

File

./calendar.module, line 125
Adds calendar filtering and displays to Views.

Code

function calendar_get_nodes(&$view, &$items, $type) {
  calendar_load_calendar_api();
  calendar_load_date_api();
  $view->nodes_per_page = 0;
  $type_names = node_get_types('names');
  unset($params['limit']);
  if ($type == 'block' || $view->calendar_type == 'year') {
    $params['mini'] = TRUE;
  }
  $fields = calendar_fields();
  $calendar_fields = (array) array_keys($fields);
  $nodes = array();
  $i = 0;
  $items_in = $items;

  // explode out field and format info from the view
  foreach ($view->field as $delta => $data) {
    if (in_array($data['field'], $calendar_fields)) {
      $option = $fields[$data['field']];
      $field_type = strstr($option['type'], 'string') ? 'string' : 'timestamp';
      $field_function = strstr($option['type'], 'cck') ? 'content_format' : $data['handler'];
      $field_formatter = $data['options'];
      $field_field = $option['query_name'];
      $field_end = $field_field . '2';
      $field_field_name = $option['field_name'];
      $timestamp_fromto = $option['timestamp_fromto'];
      $string_fromto = $option['string_fromto'];
      $field_id = $delta;
      $tz_handling = $option['tz_handling'];
      $offset_field = str_replace('.', '_', $option['offset_field']);
      $label = $data['label'];
      $granularity = $option['granularity'];
      $view_fields = _views_get_fields();

      // iterate through the $items array returned by the query and create date or pseudo date nodes
      foreach ($items as $delta => $item) {

        // we have to serialize and unserialize to force a completely new copy of $item when duplicate fields use the same node
        // without doing this, values added to the item in later iterations get applied to earlier ones
        $node = unserialize(serialize($item));
        $node->title = $node->node_title;
        $node->label = $label;
        foreach ($view->field as $field) {
          if (!in_array($field['field'], $calendar_fields) && $field['field'] != 'title') {
            if ($view_fields[$field['id']]['visible'] !== FALSE) {
              $node->fields[$field['queryname']] = views_theme_field('views_handle_field', $field['queryname'], $view_fields, $field, $node, $view);
            }
          }
        }

        // If we're dealing with an event node, join the start and to dates together in one node and get rid of the other
        if (module_exists('event') && ($field_field == 'event_event_start' || $field_field == 'event_event_end') && !$event_field_processed[$item->nid]) {
          if ($node->event_event_start > 0) {
            $node->calendar_start = $node->event_event_start;
            $node->calendar_end = $node->event_event_end;
            $event_field_processed[$item->nid] = TRUE;
          }
        }
        elseif (module_exists('event') && ($field_field == 'event_event_start' || $field_field == 'event_event_end') && $event_field_processed[$item->nid]) {

          // if more than one event field was added to the view (like start and end dates)
          // don't process it more than once
          unset($node);
        }
        if (isset($node) && !isset($node->calendar_start) && !isset($item->{$field_field})) {

          // if no date for the node and no date in the item
          // there is no way to display it on the calendar
          unset($node);
        }
        if (isset($node) && !$node->calendar_start && $item->{$field_field}) {

          // if calendar_start field holds a numeric value, treat it as a unix timestamp
          // if string, convert to timestamp
          if ($field_type == 'timestamp') {
            $node->calendar_start = $item->{$field_field};
            $node->calendar_end = $item->{$field_end} ? $item->{$field_end} : $item->{$field_field};
          }
          else {

            // get the timestamp value for this date, use UTC to make sure no timezone conversion gets done on it
            $node->calendar_start = date_iso2unix($item->{$field_field});
            $node->calendar_end = $item->{$field_end} ? date_iso2unix($item->{$field_end}) : date_iso2unix($item->{$field_field});
          }
        }
        if (isset($node)) {

          // get appropriate timezone offset
          switch ($tz_handling) {
            case 'user':
              global $user;
              $node->start_offset = $node->end_offset = $user->timezone;
              break;
            case 'none':
            case 'GMT':
              $node->start_offset = $node->end_offset = 0;
              break;
            case 'date':
              $node->start_offset = $node->end_offset = $node->{$offset_field};
              break;
            case 'event':
              $node->start_offset = date_get_offset($node->event_timezone, $node->event_event_start);
              $node->end_offset = date_get_offset($node->event_timezone, $node->event_event_end);
              break;
            default:
              $timezone = variable_get('date_default_timezone_name', 'UTC');
              $node->start_offset = date_offset(date_unix2array($node->calendar_start), $timezone);
              $node->end_offset = date_offset(date_unix2array($node->calendar_end), $timezone);
              break;
          }
        }
        if (isset($node) && function_exists($field_function) && $node->calendar_start && $item->{$field_field}) {
          if ($field_function == 'content_format') {

            // force the original value for this field into the array that content_format expects
            $node->start_format = content_format($field_field_name, array(
              'value' => $item->{$field_field},
              'value2' => $item->{$field_field},
            ), $field_formatter);
            if ($node->calendar_end) {
              $node->end_format = content_format($field_field_name, array(
                'value' => $item->{$field_end},
                'value2' => $item->{$field_end},
              ), $field_formatter);
            }
          }
          else {

            // or call date format function
            if (!$node->start_format) {
              $node->start_format = $field_function(NULL, NULL, $item->{$field_field}, NULL);
              if ($node->calendar_end && !$node->end_format) {
                $node->end_format = $field_function(NULL, NULL, $node->calendar_end, NULL);
              }
            }
          }

          // format a time-only display for the month calendar for dates that have time elements
          if (array_intersect($granularity, array(
            'H',
            'N',
            'S',
          ))) {
            $node->start_time_format = date_format_date(variable_get('calendar_time_format_' . $view->name, 'H:i'), intval($node->calendar_start + $node->start_offset));
            if ($node->calendar_end) {
              $node->end_time_format = date_format_date(variable_get('calendar_time_format_' . $view->name, 'H:i'), intval($node->calendar_end + $node->end_offset));
            }
          }
          else {
            $node->start_time_format = $node->start_format;
            $node->end_time_format = $node->end_format;
          }
          if ($node) {

            // we can have multiple representations with the same nid, like multi-day values
            // or different fields that refer to the same node
            // create a unique id so it gets displayed in the calendar
            // Add delta to key to make multiple value CCK fields display as separate items.
            if (strstr($option['type'], 'cck')) {
              $id = $item->nid . ':' . $delta . ':' . $field_field;
            }
            else {
              $id = $item->nid . ':0:' . $field_field;
            }
            $node->nid = $id;
            if ($view->build_type == 'page' && $view->calendar_type != 'year') {
              $node->stripe = calendar_node_stripe($view, $node, $option['query_name'], $field_field);
            }
            $nodes[$id] = $node;
            unset($node);
          }
        }
      }
    }
  }

  // make sure there is at least one item in $nodes to force the calendar to display
  // set the hour to 12 to minimize timezone adjustments that might push it to previous or next day
  if ($view->calendar_type == 'year') {

    // for the year view to work, must have at least one node in each month
    for ($i = 1; $i < 13; $i++) {
      $nodes[] = _calendar_make_node(NULL, NULL, _views_get_timezone(), $view->year, $i, 1, 12, 0);
    }
  }
  elseif ($view->calendar_type == 'week') {

    // make sure at least one node is created for the current week
    // add both start and end of week in case week crosses from one month to next
    $week_range = calendar_week_range($view->year, $view->week);
    $nodes[] = _calendar_make_node(NULL, NULL, _views_get_timezone(), date_format_date('Y', $week_range[0]), date_format_date('m', $week_range[0]), date_format_date('j', $week_range[0]), 12, 0);
    $nodes[] = _calendar_make_node(NULL, NULL, _views_get_timezone(), date_format_date('Y', $week_range[1]), date_format_date('m', $week_range[1]), date_format_date('j', $week_range[1]), 12, 0);
  }
  elseif (sizeof($nodes) == 0) {

    // otherwise add a blank node for the current day
    $nodes = array(
      _calendar_make_node(NULL, NULL, _views_get_timezone(), $view->year, $view->month, $view->day, 12, 0),
    );
  }
  if (calendar_part_is_valid($view->year, 'year')) {

    // valid year is a test that indicates if arguments were available to establish a date for the calendar
    // a full view with an argument date will display a single month, day or week calendar page
    // with navigation that mimics regular calendar
    // trim off date values that are outside the selected range to prevent display of incomplete extra calendars
    $params['limit'] = _calendar_limit_nodes($nodes, $view->calendar_type, $view->year, $view->month, $view->day, $view->week, _views_get_timezone());

    // hide the intermediate header rows created by the event api and
    // push title and navigation into calendar header
    $params['hide_header'] = $view->calendar_type == 'week' ? false : true;

    //$title = theme('calendar_nav_wrapper', calendar_nav($view, $params['mini']), array());

    // standard api displays a whole month instead of a single week
    // adjust here for single week display
    if ($view->calendar_type == 'week' && $view->week) {
      $params['force_week'] = $view->week;
    }
  }

  // use calendar_get_calendar api to draw the calendar
  $params['url'] = calendar_real_url($view, $view->args);
  $params['append'] = calendar_url_append($view);
  $params['stripe'] = 'stripe';
  $params['with_weekno'] = $view->build_type == 'block' || $view->calendar_type == 'year' || $view->year < 1970 ? FALSE : TRUE;
  return array(
    'nodes' => $nodes,
    'params' => $params,
  );
}