You are here

function date_ical_plugin_row_ical_fields::render in Date iCal 7.2

Same name and namespace in other branches
  1. 7.3 includes/date_ical_plugin_row_ical_fields.inc \date_ical_plugin_row_ical_fields::render()

Returns an Event array based on the query result from the view whose index is specified in the (hidden) second parameter of this function.

Overrides views_plugin_row::render

File

includes/date_ical_plugin_row_ical_fields.inc, line 102
Defines the iCal Fields row style plugin, which lets users map view fields to the components of the VEVENTs in the iCal feed.

Class

date_ical_plugin_row_ical_fields
Plugin which creates a view on the resulting object and formats it as an iCal VEVENT.

Code

function render($row) {

  // Using func_get_args() instead of declaring $row_index in the arguments,
  // because this function must be compatible with views_plugin_row::render().
  $args = func_get_args();
  $row_index = $args[1];
  $date_field_name = $this->options['date_field'];

  // Fetch the event's date information.
  try {
    $date = $this
      ->get_row_date($row_index);
  } catch (BlankDateFieldException $e) {

    // Unless the user has specifically said that they want to skip rows which
    // have blank dates, let this exception percolate.
    if ($this->options['additional_settings']['skip_blank_dates']) {
      return NULL;
    }
    else {
      throw $e;
    }
  }

  // Create the event by starting with the date array from this row.
  $event = $date;

  // Add the CREATED, LAST-MODIFIED, and URL components based on the entity.
  // According to the iCal standard, CREATED and LAST-MODIFIED must be UTC.
  // Fortunately, Drupal stores timestamps in the DB as UTC, so we just need
  // to specify that UTC be used rather than the server's local timezone.
  $entity = $row->_field_data[$this->view->base_field]['entity'];
  $entity_type = $row->_field_data[$this->view->base_field]['entity_type'];
  if (isset($entity->created)) {
    $event['created'] = new DateObject($entity->created, new DateTimeZone('UTC'));
  }
  if (isset($entity->changed)) {
    $event['last-modified'] = new DateObject($entity->changed, new DateTimeZone('UTC'));
  }
  else {
    if (isset($entity->created)) {

      // If changed is unset, but created is, use that for last-modified.
      $event['last-modified'] = new DateObject($entity->created, new DateTimeZone('UTC'));
    }
  }
  $uri = entity_uri($entity_type, $entity);
  $uri['options']['absolute'] = TRUE;
  $event['url'] = url($uri['path'], $uri['options']);

  // Generate a unique ID for this event by emulating the way the Date module
  // creates a Date ID.
  if (isset($row->{"field_data_{$date_field_name}_delta"})) {
    $date_field_delta = $row->{"field_data_{$date_field_name}_delta"};
  }
  else {

    // I'm not sure why the "field_data_{field_name}_delta" field is part of
    // the $row, so it's possible that it will sometimes be missing. If it
    // is, make an educated guess about the delta by comparing this row's
    // start date to each of the entity's dates.
    $date_field_delta = 0;
    foreach ($entity->{$date_field_name}['und'] as $ndx => $date_array) {
      if ($date['start']->originalTime == $date_array['value']) {
        $date_field_delta = $ndx;
        break;
      }
    }
  }
  $entity_id = $row->{$this->view->base_field};
  $domain = check_plain($_SERVER['SERVER_NAME']);
  $event['uid'] = "calendar.{$entity_id}.{$date_field_name}.{$date_field_delta}@{$domain}";

  // Because of the way that Date implements repeating dates, we're going to
  // be given a separate view result for each repeat. We only want to
  // render a VEVENT (with an RRULE) for the first instance of that date, so
  // we need to record the entity ID and field name for each result that has
  // an RRULE, then skip any that we've already seen.
  if (!empty($date['rrule'])) {
    $repeat_id = "{$entity_id}.{$date_field_name}";
    if (!isset($this->repeated_dates[$repeat_id])) {
      $this->repeated_dates[$repeat_id] = $repeat_id;
    }
    else {
      return FALSE;
    }
  }

  // Retrieve the rendered text fields.
  $text_fields['summary'] = $this
    ->get_field($row_index, $this->options['title_field']);
  $text_fields['description'] = $this
    ->get_field($row_index, $this->options['description_field']);
  $text_fields['location'] = $this
    ->get_field($row_index, $this->options['location_field']);

  // Allow other modules to alter the rendered text fields before they get
  // sanitized for iCal-compliance. This is most useful for fields of type
  // "Content: Rendered Node", which are likely to have complex HTML.
  $context = array(
    'row' => $row,
    'row_index' => $row_index,
    'language' => $this->language,
  );
  drupal_alter('date_ical_fields_html', $text_fields, $this->view, $context);

  // Sanitize the text fields for iCal compliance, and add them to the event.
  // Also strip all HTML from the summary and location fields, since they
  // must be plaintext, and may have been set as links by the view.
  $event['summary'] = date_ical_sanitize_text(strip_tags($text_fields['summary']));
  $event['location'] = date_ical_sanitize_text(strip_tags($text_fields['location']));
  $event['description'] = date_ical_sanitize_text($text_fields['description']);

  // Allow other modules to alter the event object, before it gets passed to
  // the style plugin to be converted into an iCal VEVENT.
  $context = array(
    'entity' => $entity,
    'entity_type' => $entity_type,
    'language' => $this->language,
  );
  drupal_alter('date_ical_feed_event_render', $event, $this->view, $context);
  return $event;
}