You are here

public function date_ical_plugin_row_ical_entity::render in Date iCal 7.3

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

Renders the entities returned by the view into event arrays.

Overrides views_plugin_row::render

File

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

Class

date_ical_plugin_row_ical_entity
A Views plugin which builds an iCal VEVENT from a single node.

Code

public function render($row) {
  $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']);
  $delta_field = $date_info['delta_field'];
  $is_field = $date_info['is_field'];

  // Sometimes the timestamp is actually the revision timestamp.
  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];
    global $base_url;
    $domain = preg_replace('#^https?://#', '', $base_url);
    $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 (!empty($date_field['value2'])) {
        $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 = $node->title;
        }
      }
      elseif ($location_info['type'] == 'addressfield') {
        $locations = array();

        // Get full country name
        if (!empty($location_field['country'])) {
          require_once DRUPAL_ROOT . '/includes/locale.inc';
          $countries = country_get_list();
          $location_field['country'] = $countries[$location_field['country']];
        }
        foreach ($location_field as $key => $loc) {
          if ($loc && !in_array($key, array(
            'first_name',
            'last_name',
          ))) {
            $locations[] = $loc;
          }
        }
        $location = implode(', ', array_reverse($locations));
      }
      elseif ($location_info['type'] == 'location') {
        $included_fields = array(
          'name',
          'additional',
          'street',
          'city',
          'province_name',
          'postal_code',
          'country_name',
        );
        $location_data = array();
        foreach ($included_fields as $included_field) {
          if (!empty($location_field[$included_field])) {
            $location_data[] = $location_field[$included_field];
          }
        }
        $location = implode(', ', $location_data);
      }
      elseif ($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 = $node->title;
        }
      }
      elseif ($location_info['type'] == 'taxonomy_term_reference') {
        $terms = taxonomy_term_load_multiple(array_column($items, 'tid'));

        // Make sure that there are terms that were loaded.
        if ($terms) {
          $term_names = array();
          foreach ($terms as $term) {
            $term_names[] = $term->name;
          }
          $location = implode(', ', $term_names);
        }
      }
      else {
        $location = $location_field['value'];
      }
    }
  }

  // Create the rendered event 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(array_column($items, 'tid'));

        // 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_export_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']);
  if ($is_field && !empty($date_field['rrule'])) {
    $event['rrule'] = $date_field['rrule'];
  }
  if ($location) {
    $event['location'] = date_ical_sanitize_text($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 (!empty($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 tell DateObject to treat the timestamp as UTC from the start.
  if (isset($entity->created)) {
    $event['created'] = new DateObject($entity->created, '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, 'UTC');
  }
  elseif (isset($entity->created)) {

    // If changed is unset, but created is, use that for last-modified.
    $event['last-modified'] = new DateObject($entity->created, 'UTC');
  }

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