array( 'arguments' => array('url'), ), 'calendar_ical_feed' => array( 'arguments' => array('view', 'items', 'type'), ), 'calendar_ical_field' => array( 'arguments' => array('fieldname', 'fields', 'field', 'node', 'view', 'type'), ), 'calendar_ical_node' => array( 'arguments' => array('node', 'view'), ), ); } /** * Identify the cache where the ical feeds are stored. * * @return unknown */ function calendar_ical_cache() { return 'cache_views'; } /** * Implementation of hook_cron(). */ function calendar_ical_cron() { cache_clear_all('calendar_feeds_', calendar_ical_cache(), TRUE); } /** * Implementation of hook_calendar_add_items(). */ function calendar_ical_calendar_add_items($view) { include_once(drupal_get_path('module', 'date_api') .'/date_api_ical.inc'); $items = array(); $feeds = calendar_ical_add_feeds($view); foreach ($feeds as $feed) { if (!empty($feed->calendar_start) && !empty($feed->calendar_end)) { if ($feed->calendar_start >= date_format($view->min_date, DATE_FORMAT_DATETIME) && $feed->calendar_end <= date_format($view->max_date, DATE_FORMAT_DATETIME)) { // We have to add a calendar start and end object to the feed, // the cached date objects will not work correctly. $feed->calendar_start_date = date_make_date($feed->calendar_start, $feed->timezone); $feed->calendar_end_date = date_make_date($feed->calendar_end, $feed->timezone); $items[] = $feed; } } } return $items; } /** * Implementation of hook_calendar_add_types(). */ function calendar_ical_calendar_add_types($view) { return array('calendar_ical' => t('Calendar: iCal Feed')); } /** * Bring an ical feed into the calendar. * * @param $view - the view being manipulated * @param $refresh - whether or not to force a refresh of the feed * @return $nodes to add to calendar * @todo probably need to add more validation of the results in case the url doesn't work. */ function calendar_ical_add_feeds($view, $refresh = FALSE) { $nodes = array(); $feeds = variable_get('calendar_feeds_'. $view->name, array()); $expire = intval(variable_get('calendar_ical_expire_'. $view->name, 9676800) + time()); foreach ($feeds as $delta => $feed) { if ($view->build_type == 'page') { $GLOBALS['calendar_stripe_labels'][$feed['stripe']] = $feed['name']; } if (!$refresh && $cached = cache_get('calendar_feeds_'. $view->name .':'. $feed['url'], calendar_ical_cache())) { $nodes += (array) $cached->data; } else { $expire = intval(variable_get('calendar_ical_expire_'. $view->name, 9676800) + time()); include_once(drupal_get_path('module', 'date_api') .'/date_api_ical.inc'); switch ($feed['type']) { case 'ical': $filename = $feed['url']; $new_nodes = array(); $calendars = date_ical_import($filename); foreach ($calendars as $calendar) { if (empty($calendars)) { continue; } foreach ($calendars as $calendar) { if (empty($calendar) || empty($calendar['VEVENT'])) { continue; } if (empty($value['DTSTART'])) continue; $node = new stdClass(); $node->nid = $value['UID']; $node->title = $value['SUMMARY']; $node->label = $feed['name']; $node->teaser = $value['DESCRIPTION']; $node->timezone = $value['DTSTART']['tz']; $node->calendar_start_date = date_ical_date($value['DTSTART'], $value['DTSTART']['tz']); $node->calendar_start = date_format_date($node->calendar_start_date, 'custom', DATE_FORMAT_DATETIME); $node->calendar_end_date = date_ical_date($value['DTEND'], $value['DTEND']['tz']); $node->calendar_end = date_format_date($node->calendar_end_date, 'custom', DATE_FORMAT_DATETIME); $show_tz = ' e'; $granularity = $value['DTSTART']['type'] == 'DATE' ? array('year', 'month', 'day') : array('year', 'month', 'day', 'hour', 'minute', 'second'); $node->format_time = variable_get('calendar_time_format_'. $view->name, 'H:i'); $node->format = date_limit_format(variable_get('date_format_short', 'm/d/Y - H:i'), $granularity) . $show_tz; $node->all_day = $value['DTSTART']['all_day']; $node->stripe = $feed['stripe']; $node->stripe_label = $feed['name']; $node->remote = TRUE; $node->uid = $value['uid'] ? $value['UID'] : (is_numeric($node->nid) ? url("node/$node->nid", array('absolute' => TRUE)) : $node->nid); $node->url = $value['URL'] ? $value['URL'] : (is_numeric($node->nid) ? url("node/$node->nid", array('absolute' => TRUE)) : $node->nid); $node->calendar_node_theme = 'calendar_ical_node'; $node->calendar_field_theme = 'calendar_ical_field'; $new_nodes[$value['UID']] = $node; } if (!empty($new_nodes)) { cache_set('calendar_feeds_'. $view->name .':'. $feed['url'], $new_nodes, calendar_ical_cache(), $expire); $nodes += (array) $new_nodes; } break; } } } } return $nodes; } /** * feed argument hook that will convert us to ical or display an icon. * the 4th argument isn't part of the hook, but we use it to differentiate * when called as a hook or when called manually from calendar_ical_views_post_view */ function calendar_ical_views_feed_argument($op, &$view, $arg, $argtype = NULL) { if ($op == 'argument' && $arg == 'ical') { // Keep devel module from appending queries to ical export. $GLOBALS['devel_shutdown'] = FALSE; $view->page_type = 'calendar_ical'; // reset the 'real url' to the URL without the feed argument. $view_args = array(); $max = count($view->args); foreach ($view->args as $id => $view_arg) { ++$count; if ($view_arg == $arg && $view->argument[$id]['id'] == $argtype['id']) { if ($count != $max) { $view_args[] = $argtype['wildcard']; } } else { $view_args[] = $view_arg; } } $view->feed_url = views_get_url($view, $view_args); } else if ($op == 'post_view') { $args = calendar_ical_post_view_make_args($view, $arg, 'ical'); $url = views_get_url($view, $args); $title = views_get_title($view, 'page', $args); if ($view->used_filters) { $filters = drupal_query_string_encode($view->used_filters); } return implode(calendar_ical_add_ical(url($url, $filters), $title)); } } function calendar_ical_add_feed($url = NULL, $title = '') { if (!is_null($url)) { $stored_feed_links[$url] = theme('calendar_ical_icon', $url); drupal_add_link(array('rel' => 'alternate', 'type' => 'application/calendar', 'title' => $title, 'href' => $url)); } return $stored_feed_links; } function theme_calendar_ical_icon($url) { if ($image = theme('image', drupal_get_path('module', 'date_api') .'/images/ical16x16.gif', t('Add to calendar'), t('Add to calendar'))) { return '
'; } } /** * plugin that actually displays an ical feed */ function theme_calendar_ical_feed($view, $items, $type) { if ($type == 'block') { return; } drupal_set_header('Content-Type: text/calendar; charset=utf-8'); drupal_set_header('Content-Disposition: attachment; filename="calendar.ics"; '); $events = array(); include_once('./'. drupal_get_path('module', 'date_api') .'/date_api_ical.inc'); include_once('./'. drupal_get_path('module', 'calendar') .'/calendar.inc'); $items = calendar_build_nodes($view, $items); foreach ($items as $node) { $event = array(); // Allow modules to affect item fields node_invoke_nodeapi($node, 'ical item'); $event['start'] = $node->calendar_start_date; $event['end'] = $node->calendar_end_date; $event['location'] = $node->calendar_location; $event['summary'] = $node->title; $event['description'] = $node->teaser; $event['uid'] = $node->uid ? $node->uid : (is_numeric($node->nid) ? url("node/$node->nid", array('absolute' => TRUE)) : $node->nid); $event['url'] = $node->url ? $node->url : (is_numeric($node->nid) ? url("node/$node->nid", array('absolute' => TRUE)) : $node->nid); $events[] = $event; } $headertitle = filter_xss_admin(views_get_title($view, 'page')); $title = variable_get('site_name', 'Drupal'); $description = $headertitle . ($title ? ' | '. $title : ''); print date_ical_export($events, $description); module_invoke_all('exit'); exit; } /** * Theme for an entire ical node. */ function theme_calendar_ical_node($node, $view) { // Check plain may leave html entities in the title. $node->title = html_entity_decode(check_plain($node->title), ENT-QUOTES); $node->teaser = check_markup($node->teaser); if ($view->calendar_display == 'calendar') { // Remote nodes may come in with lengthy descriptions that won't fit // in small boxes of year, month, and week calendars. if ($view->date_type != 'day') { $node->teaser = ''; } $theme = 'calendar_node_'. $view->date_type; return theme($theme, $node, $view); } else { // Create a pseudo node view for this item. $output = '