Created on 19 March 2010, almost 15 years ago
Updated 8 March 2023, almost 2 years ago

Hi,

I came up with a handy way to add in support for exporting to an ICS format, in order to create an "Add to Outlook" feature to events. It works really well.

I'm not sure what the best way to go about this is, but I thought I'd post the code I used for consideration for inclusion into the next version of views_bonus. I just installed an update of views_bonus this morning and nearly lost this code: luckily I had a backup I was able to retrieve it from. If this was included in views_bonus, I wouldn't need to worry about that in the future.

I'm not familiar with how to create patches, so maybe somebody would be able to do that.

In views_bonus_export.module, I included the following:

/**
 * Preprocess ics output template.
 */
function template_preprocess_views_bonus_export_ics(&$vars) {
  drupal_set_header('Content-Type: text/calendar; charset=utf-8;');
  drupal_set_header('Content-Disposition: attachment; filename="add_event.ics"; ');

  _views_bonus_export_shared_preprocess($vars);
}

In views_bonus_export.views.inc, I added the following after the 'views_txt' section:

      'views_ics' => array(
        'title' => t('ICS file'),
        'help' => t('Display the view as a ics file.'),
        'path' => $path,
        'handler' => 'views_bonus_plugin_style_export_ics',
        'parent' => 'views_bonus_export',
        'theme' => 'views_bonus_export_ics',
        'theme file' => 'views_bonus_export.theme.inc',
        'uses row plugin' => FALSE,
        'uses fields' => TRUE,
        'uses options' => TRUE,
        'type' => 'feed',
      ),

Then, I added another file, views_bonus_plugin_style_export_ics.inc:

<?php
// $Id: views_bonus_plugin_style_export_ics.inc,v 1.5 2008/12/28 03:47:37 neclimdul Exp $
/**
 * @file
 * Plugin include file for export style plugin.
 */

/**
 * Generalized style plugin for export plugins.
 *
 * @ingroup views_style_plugins
 */
class views_bonus_plugin_style_export_ics extends views_bonus_plugin_style_export {
  /**
   * Initialize plugin.
   *
   * Set feed image for shared rendering later.
   */
  function init(&$view, &$display, $options = NULL) {
    parent::init($view, $display, $options = NULL);
    $this->feed_image = drupal_get_path('module', 'views_bonus_export') . '/images/ics.png';
  }

  /**
   * Set options fields and default values.
   *
   * @return
   * An array of options information.
   */
  function option_definition() {
    $options = parent::option_definition();

    $options['filename'] = array(
      'default' => 'view-%view.ics',
      'translatable' => FALSE,
    );

    return $options;
  }

  /**
   * Options form mini callback.
   *
   * @param $form
   * Form array to add additional fields to.
   * @param $form_state
   * State of the form.
   * @return
   * None.
   */
  function options_form(&$form, &$form_state) {
    $form['filename'] = array(
      '#type' => 'textfield',
      '#title' => t('ICS filename'),
      '#default_value' => $this->options['filename'],
      '#description' => t('The filename that will be suggested to the browser for downloading purposes. %view will be replaced with the view name.'),
      '#process' => array('views_process_dependency'),
      '#dependency' => array('edit-style-options-override' => array(FALSE)),
    );
  }
}

Finally, I added views-bonus-export-ics.tpl.php:

<?php
// $Id: views-bonus-export-ics.tpl.php,v 1.1 2008/10/08 05:50:10 neclimdul Exp $
/**
 * @file views-view-table.tpl.php
 * Template to display a view as a table.
 *
 * - $title : The title of this group of rows.  May be empty.
 * - $rows: An array of row items. Each row is an array of content
 *   keyed by field ID.
 * - $header: an array of haeaders(labels) for fields.
 * - $themed_rows: a array of rows with themed fields.
 * @ingroup views_templates
 */

foreach ($themed_rows as $count => $row):
$dtstart = strip_tags($row['field_event_date_time']);
$dtend = strip_tags($row['field_event_date_time_value2']);
?>
BEGIN:VCALENDAR
PRODID:-//Calendar//Calendar Event//EN
CALSCALE:GREGORIAN
METHOD:PUBLISH
DTSTAMP:<?php print(strip_tags($row['field_event_date_time']) . "\n") ?>
  
BEGIN:VEVENT
DTSTART:<?php print($dtstart . "00\n") ?>
<?php 
if ($dtend!=$dtstart) {?>
DTEND:<?php print($dtend . "00\n") ?>
<?php } ?>

SUMMARY: <?php print(html_entity_decode($row['title']) . "\n") ?>
DESCRIPTION: <?php print(html_entity_decode(strip_tags($row['body'])) . "\n") ?>
UID:1
LOCATION:<?php print($row['field_location_value'] . "\n") ?>
SEQUENCE:0
END:VEVENT
END:VCALENDAR


<?php endforeach;

I also created an icon for the images folder (attached).

Within Views, I created a Feed display on a CCK Date/Time calendar view. Here are the important settings I used:

Style: ICS file
Path: events/%/%/add_event.ics
Attach to: Add to Outlook block
Arguments: Node:Nid and Content: Date and time (field_event_date_time) - delta
Fields:

  • Node:Title
  • Content: Date and time (field_event_date_time) - From date (Format: iCal, Display From date only)
  • Content: Location (field_location)
  • Node: Body (Rewrite the output of this field checked, with nothing in the box)
  • Content: Date and time (field_event_date_time) - To date (Format: iCal, Display To date only)

As hinted above, I also have a Block display titled Add to Outlook, with an argument of Node:Nid (Provide default argument of Node ID from URL, Validator Node, Event content type, Node ID argument type). Fields are Node:Title and Content: Date and time (field_event_date_time) - delta (exclude from display) and Content: Date and time (field_event_date_time) - From date, with output rewritten as:

<strong>[title]: [field_event_date_time_value]</strong>

And link path of: events/!1/[delta]/add_event.ics, with a custom label of Add to Outlook, with a Short Format of Display From and To Dates.

The iCal Date format is in the form of yyyymmddThhmmss

The trick of course is that the views_bonus format is dependent on setting up the view correctly and having the same field names for the content type, which may or may not be true. In my perfect world, the necessary items would be added to the views_bonus folder, so all would work well, even if views_bonus is updated in the future. But maybe that wouldn't work so well, because of all the dependencies. I suppose this could be spun off as a separate module, although at the moment, that's beyond my powers. If nothing else, this should serve as documentation for this technique in case I ever lose the files again, or if anybody else would like to use it. I think it's a pretty useful addition to anybody creating events through Views and a CCK Date/Time Calendar.

Enjoy!

✨ Feature request
Status

Closed: outdated

Component

Code

Created by

πŸ‡ΊπŸ‡ΈUnited States RainbowArray Twin Cities, Minnesota

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

Production build 0.71.5 2024