| 1 |
<?php
|
| 2 |
// $Id: parser_ical.module,v 1.3 2008/11/26 19:44:56 alexb Exp $
|
| 3 |
|
| 4 |
/**
|
| 5 |
* @file
|
| 6 |
* Parse the incoming URL with date_api_ical
|
| 7 |
*/
|
| 8 |
|
| 9 |
/**
|
| 10 |
* Implementation of hook_help().
|
| 11 |
*/
|
| 12 |
function parser_ical_help($path, $arg) {
|
| 13 |
switch ($path) {
|
| 14 |
case 'admin/modules#description':
|
| 15 |
return t('Provide a common iCal parser for FeedAPI-compatible modules.');
|
| 16 |
case 'feedapi/full_name':
|
| 17 |
return t('iCal Parser');
|
| 18 |
}
|
| 19 |
}
|
| 20 |
|
| 21 |
/**
|
| 22 |
* Implementation of hook_feedapi_feed().
|
| 23 |
*/
|
| 24 |
function parser_ical_feedapi_feed($op) {
|
| 25 |
$args = func_get_args();
|
| 26 |
switch ($op) {
|
| 27 |
case 'type':
|
| 28 |
return array('iCal feed');
|
| 29 |
|
| 30 |
case 'compatible':
|
| 31 |
$url = is_object($args[1]) ? $args[1] : FALSE;
|
| 32 |
$ical_array = _parser_ical_feedapi_parse($url, FALSE);
|
| 33 |
if ($ical_array !== FALSE) {
|
| 34 |
return 'iCal feed';
|
| 35 |
}
|
| 36 |
else {
|
| 37 |
return FALSE;
|
| 38 |
}
|
| 39 |
|
| 40 |
case 'parse':
|
| 41 |
$feed = is_object($args[1]) ? $args[1] : FALSE;
|
| 42 |
$cache = isset($args[2]) ? $args[2] : FALSE;
|
| 43 |
return _parser_ical_feedapi_parse($feed, $cache);
|
| 44 |
}
|
| 45 |
}
|
| 46 |
|
| 47 |
/**
|
| 48 |
* Parse the feed into a data structure
|
| 49 |
*
|
| 50 |
* @param $url
|
| 51 |
* The feed's url
|
| 52 |
* @param $cache
|
| 53 |
* If the results can be cached or not
|
| 54 |
* @return stdClass
|
| 55 |
* The structured datas extracted from the feed
|
| 56 |
*/
|
| 57 |
function _parser_ical_feedapi_parse($feed, $cache = FALSE) {
|
| 58 |
$url = $feed->url;
|
| 59 |
// Substitute webcal with http.
|
| 60 |
if (stripos($url, 'webcal') === 0) {
|
| 61 |
$url = 'http'. substr($url, 6);
|
| 62 |
}
|
| 63 |
$downloaded_string = _parser_ical_download($url);
|
| 64 |
|
| 65 |
if ($downloaded_string === FALSE || empty($downloaded_string)) {
|
| 66 |
return $downloaded_string;
|
| 67 |
}
|
| 68 |
|
| 69 |
return _parser_ical_parse($downloaded_string);
|
| 70 |
}
|
| 71 |
|
| 72 |
/**
|
| 73 |
* Parse iCal feeds.
|
| 74 |
*
|
| 75 |
* Uses patched ical_upload.
|
| 76 |
*/
|
| 77 |
function _parser_ical_parse($feed_content) {
|
| 78 |
include_once(drupal_get_path('module', 'date_api') .'/date_api_ical.inc');
|
| 79 |
$feed_folded = explode("\n", $feed_content);
|
| 80 |
$ical_parsed = date_ical_parse($feed_folded);
|
| 81 |
$ical = $ical_parsed[0];
|
| 82 |
|
| 83 |
// Any or all of these items could be missing, so always use isset() to test.
|
| 84 |
$parsed_source = new stdClass();
|
| 85 |
// Detect the title
|
| 86 |
$parsed_source->title = isset($ical['X-WR-CALNAME']) ? $ical['X-WR-CALNAME'] : '';
|
| 87 |
// Detect the description
|
| 88 |
$parsed_source->description = isset($ical['X-WR-CALDESC']) ? $ical['X-WR-CALDESC'] : '';
|
| 89 |
$parsed_source->options = new stdClass();
|
| 90 |
$parsed_source->options->calscale = isset($ical['CALSCALE']) ? $ical['CALSCALE'] : '';
|
| 91 |
$parsed_source->options->timezone = isset($ical['X-WR-TIMEZONE']) ? $ical['X-WR-TIMEZONE'] : '';
|
| 92 |
$parsed_source->items = array();
|
| 93 |
|
| 94 |
foreach ($ical['VEVENT'] as $event) {
|
| 95 |
$item = new stdClass();
|
| 96 |
$item->title = $event['SUMMARY'];
|
| 97 |
$item->description = isset($event['DESCRIPTION']) ? $event['DESCRIPTION'] : '';
|
| 98 |
|
| 99 |
$item->options = new stdClass();
|
| 100 |
$item->options->original_author = '';
|
| 101 |
$item->options->location = isset($event['URL']) ? $event['URL'] : '';
|
| 102 |
$item->options->original_url = $item->options->location;
|
| 103 |
|
| 104 |
// Make sure a valid timestamp is created.
|
| 105 |
$item->options->timestamp = time();
|
| 106 |
if (isset($event['DTSTAMP'])) {
|
| 107 |
$date = date_ical_date($event['DTSTAMP']);
|
| 108 |
if (date_is_valid($date, DATE_OBJECT)) {
|
| 109 |
$item->options->timestamp = date_format($date, 'U');
|
| 110 |
}
|
| 111 |
}
|
| 112 |
|
| 113 |
$item->options->guid = isset($event['UID']) ? $event['UID'] : ''; // intention
|
| 114 |
$item->options->tags = isset($event['CATEGORIES']) ? explode(',', $event['CATEGORIES']) : array();
|
| 115 |
|
| 116 |
// Keep iCal timezone information in the feed item so we can create the right date value.
|
| 117 |
$dates = array('CREATED', 'LAST-MODIFIED', 'DTSTART', 'DTEND', 'DTSTAMP', 'RDATE', 'TRIGGER', 'FREEBUSY', 'DUE', 'COMPLETED', 'EXDATE');
|
| 118 |
foreach ($dates as $key) {
|
| 119 |
if (isset($event[$key])) {
|
| 120 |
$date = date_ical_date($event[$key]);
|
| 121 |
$item->options->$key = date_format($date, DATE_FORMAT_DATETIME) .';tz='. $event[$key]['tz'];
|
| 122 |
unset($event[$key]);
|
| 123 |
}
|
| 124 |
}
|
| 125 |
|
| 126 |
$item->raw = $event;
|
| 127 |
$parsed_source->items[] = $item;
|
| 128 |
}
|
| 129 |
return $parsed_source;
|
| 130 |
}
|
| 131 |
|
| 132 |
/**
|
| 133 |
* Copied from _parser_common_syndication_download().
|
| 134 |
*
|
| 135 |
* Changed to allow passing of $allowed_mine array().
|
| 136 |
*/
|
| 137 |
function _parser_ical_download($url) {
|
| 138 |
$method = 'GET';
|
| 139 |
$follow = 3;
|
| 140 |
$data = NULL;
|
| 141 |
$headers = array();
|
| 142 |
if (!empty($username)) {
|
| 143 |
$headers['Authorization'] = 'Basic '. base64_encode("$username:$password");
|
| 144 |
}
|
| 145 |
$result = drupal_http_request($url, $headers, $method, $data, $follow);
|
| 146 |
return $result->data;
|
| 147 |
}
|