You are here

function date_ical_plugin_row_ical_entity::render in Date iCal 7.2

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

Render a row object. This usually passes through to a theme template of some form, but not always.

Parameters

stdClass $row: A single row of the query result, so an element of $view->result.

Return value

string The rendered output of a single row, used by the style plugin.

Overrides views_plugin_row::render

File

includes/date_ical_plugin_row_ical_entity.inc, line 143
Contains the iCal row style plugin.

Class

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

Code

function render($row) {
  global $base_url;
  $id = $row->{$this->field_alias};
  if (!is_numeric($id)) {
    return NULL;
  }

  // Load the specified entity:
  $entity = $this->entities[$id];
  if (empty($entity)) {

    // This can happen when an RRULE is involved.
    return NULL;
  }
  $date_fields = date_views_fields($this->base_table);
  $date_info = $date_fields['name'][$this->options['date_field']];
  $field_name = str_replace(array(
    '_value',
    '_value2',
  ), '', $date_info['real_field_name']);
  $table_name = $date_info['table_name'];
  $delta_field = $date_info['delta_field'];
  $is_field = $date_info['is_field'];

  // This is ugly and hacky but I can't figure out any generic way to
  // recognize that the node module is going to give some the revision timestamp
  // a different field name on the entity than the actual column name in the database.
  if ($this->view->base_table == 'node_revision' && $field_name == 'timestamp') {
    $field_name = 'revision_timestamp';
  }
  if (!isset($entity->{$field_name})) {

    // This entity doesn't have the date property that the user configured
    // our view to use. We can't do anything with it
    return NULL;
  }
  $date_field = $entity->{$field_name};

  // Pull the date value from the specified field of the entity.
  $entity->date_id = array();
  $start = NULL;
  $end = NULL;
  $delta = isset($row->{$delta_field}) ? $row->{$delta_field} : 0;
  if ($is_field) {
    $items = field_get_items($this->entity_type, $entity, $field_name);
    if (!$items) {

      // This entity doesn't have data in the date field that the user
      // configured our view to use. We can't do anything with it.
      return;
    }
    $date_field = $items[$delta];
    $domain = check_plain($_SERVER['SERVER_NAME']);
    $entity->date_id[] = "calendar.{$id}.{$field_name}.{$delta}@{$domain}";
    if (!empty($date_field['value'])) {
      $start = new DateObject($date_field['value'], $date_field['timezone_db']);
      if (array_key_exists('value2', $date_field)) {
        $end = new DateObject($date_field['value2'], $date_field['timezone_db']);
      }
      else {
        $end = clone $start;
      }
    }
  }
  elseif (!$is_field && !empty($date_field)) {
    $start = new DateObject($date_field, $date_field['timezone_db']);
    $end = new DateObject($date_field, $date_field['timezone_db']);
  }

  // Set the item date to the proper display timezone.
  $start
    ->setTimezone(new dateTimezone($date_field['timezone']));
  $end
    ->setTimezone(new dateTimezone($date_field['timezone']));

  // Check if the start and end dates indicate that this is an All Day event.
  $all_day = date_is_all_day(date_format($start, DATE_FORMAT_DATETIME), date_format($end, DATE_FORMAT_DATETIME), date_granularity_precision($date_info['granularity']));
  if ($all_day) {

    // According to RFC 2445 (clarified in RFC 5545) the DTEND value is
    // non-inclusive. When dealing with All Day values, they're DATEs rather
    // than DATETIMEs, so we need to add a day to conform to RFC.
    $end
      ->modify("+1 day");
  }

  // If the user specified a LOCATION field, pull that data from the entity.
  $location = '';
  if (!empty($this->options['location_field']) && $this->options['location_field'] != 'none') {
    $location_fields = date_ical_get_location_fields($this->base_table);
    $location_info = $location_fields['name'][$this->options['location_field']];
    $location_field_name = $location_info['real_field_name'];

    // Only attempt this is the entity actually has this field.
    $items = field_get_items($this->entity_type, $entity, $location_field_name);
    if ($items) {
      $location_field = $items[0];
      if ($location_info['type'] == 'node_reference') {

        // Make sure this Node Reference actually references a node.
        if ($location_field['nid']) {
          $node = node_load($location_field['nid']);
          $location = check_plain($node->title);
        }
      }
      elseif ($location_info['type'] == 'addressfield') {
        $locations = array();
        foreach ($location_field as $key => $loc) {
          if ($loc && !in_array($key, array(
            'first_name',
            'last_name',
          ))) {
            $locations[] = $loc;
          }
        }
        $location = implode(', ', array_reverse($locations));
      }
      else {
        $location = check_plain($location_field['value']);
      }
    }
  }

  // Create the rendered display using the display settings from the 'iCal' view mode.
  $rendered_array = entity_view($this->entity_type, array(
    $entity,
  ), 'ical', $this->language, TRUE);
  $data = array(
    'description' => drupal_render($rendered_array),
    'summary' => entity_label($this->entity_type, $entity),
  );
  if (!empty($this->options['summary_field']) && $this->options['summary_field'] != 'default_title') {
    $summary_fields = date_ical_get_summary_fields();
    $summary_info = $summary_fields['name'][$this->options['summary_field']];
    $summary_field_name = $summary_info['real_field_name'];

    // Only attempt this is the entity actually has this field.
    $items = field_get_items($this->entity_type, $entity, $summary_field_name);
    $summary = '';
    if ($items) {
      $summary_field = $items[0];
      if ($summary_info['type'] == 'node_reference') {

        // Make sure this Node Reference actually references a node.
        if ($summary_field['nid']) {
          $node = node_load($summary_field['nid']);
          $summary = $node->title;
        }
      }
      elseif ($summary_info['type'] == 'taxonomy_term_reference') {
        $terms = taxonomy_term_load_multiple($items);

        // Make sure that there are terms that were loaded
        if ($terms) {
          $term_names = array();
          foreach ($terms as $term) {
            $term_names[] = $term->name;
          }
          $summary = implode(', ', $term_names);
        }
      }
      else {
        $summary = trim($summary_field['value']);
      }
      $data['summary'] = $summary ? $summary : $data['summary'];
    }
  }

  // Allow other modules to alter the HTML of the Summary and Description,
  // before it gets converted to iCal-compliant plaintext. This allows users
  // to set up a newline between fields, for instance.
  $context = array(
    'entity' => $entity,
    'entity_type' => $this->entity_type,
    'language' => $this->language,
  );
  drupal_alter('date_ical_html', $data, $this->view, $context);
  $event = array();
  $event['summary'] = date_ical_sanitize_text($data['summary']);
  $event['description'] = date_ical_sanitize_text($data['description']);
  $event['all_day'] = $all_day;
  $event['start'] = $start;
  $event['end'] = $end;
  $uri = entity_uri($this->entity_type, $entity);
  $uri['options']['absolute'] = TRUE;
  $event['url'] = url($uri['path'], $uri['options']);
  $event['rrule'] = $is_field && array_key_exists('rrule', $date_field) ? $date_field['rrule'] : '';
  if ($location) {
    $event['location'] = $location;
  }

  // For this event's UID, use either the date_id generated by the Date module, or the
  // event page's URL, if the date_id isn't available.
  $event['uid'] = !empty($entity->date_id) ? $entity->date_id[0] : $event['url'];

  // If we are using a repeat rule (and not just multi-day events) we
  // remove the item from the entities list so that its VEVENT won't be
  // re-created.
  if ($event['rrule']) {
    $this->entities[$id] = NULL;
  }

  // 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.
  if (isset($entity->created)) {
    $event['created'] = new DateObject($entity->created, new DateTimeZone('UTC'));
  }

  // Pull the 'changed' date from the entity (if available), so that
  // subscription clients can tell if the event has been updated.
  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'));
    }
  }

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