Commit 05caebca authored by Robert Rollins's avatar Robert Rollins

RRULE import works now!

I hadn't yet tested the RRULE import code when I first pushed Date iCal 3.x-dev,
but now I have. It's much more robust than it was in 2.x.

In addition, I moved the parsing class out of DateiCalFeedsParser.inc and into
libaries/ParserVcalendar.inc, which is like how Feeds' own CSV parser is set up.
parent 11f49c89
......@@ -31,7 +31,7 @@ class DateIcalParseException extends DateIcalException {}
*/
function date_ical_hook_info() {
// TODO: Finish this.
// Use two "groups": date_ical_parse and date_ical_output.
// Use two "groups": date_ical_import and date_ical_export.
}
/**
......@@ -44,6 +44,45 @@ function date_ical_views_api() {
);
}
/**
* Implements hook_feeds_plugins().
*/
function date_ical_feeds_plugins() {
$path = drupal_get_path('module', 'date_ical') . '/includes';
$info = array();
$info['DateIcalFeedsParserOld'] = array(
'hidden' => TRUE,
'handler' => array(
'parent' => 'FeedsParser',
'class' => 'DateIcalFeedsParserOld',
'file' => 'DateIcalFeedsParserOld.inc',
'path' => $path,
),
);
$info['DateIcalIcalcreatorParser'] = array(
'name' => 'iCal parser (old)',
'description' => t('Use the iCalcreator library to parse iCal feeds.'),
'help' => 'Parse iCal feeds.',
'handler' => array(
'parent' => 'DateIcalFeedsParserOld',
'class' => 'DateIcalIcalcreatorParser',
'file' => 'DateIcalIcalcreatorParser.inc',
'path' => $path,
),
);
$info['DateiCalFeedsParser'] = array(
'name' => 'iCal parser',
'description' => t('Parse iCal feeds.'),
'handler' => array(
'parent' => 'FeedsParser',
'class' => 'DateiCalFeedsParser',
'file' => 'DateiCalFeedsParser.inc',
'path' => $path,
),
);
return $info;
}
/**
* Implements hook_theme().
*/
......@@ -158,45 +197,6 @@ function date_ical_ctools_plugin_api($owner, $api) {
}
}
/**
* Implements hook_feeds_plugins().
*/
function date_ical_feeds_plugins() {
$path = drupal_get_path('module', 'date_ical') . '/includes';
$info = array();
$info['DateIcalFeedsParserOld'] = array(
'hidden' => TRUE,
'handler' => array(
'parent' => 'FeedsParser',
'class' => 'DateIcalFeedsParserOld',
'file' => 'DateIcalFeedsParserOld.inc',
'path' => $path,
),
);
$info['DateIcalIcalcreatorParser'] = array(
'name' => 'iCal parser (old)',
'description' => t('Use the iCalcreator library to parse iCal feeds.'),
'help' => 'Parse iCal feeds.',
'handler' => array(
'parent' => 'DateIcalFeedsParserOld',
'class' => 'DateIcalIcalcreatorParser',
'file' => 'DateIcalIcalcreatorParser.inc',
'path' => $path,
),
);
$info['DateiCalFeedsParser'] = array(
'name' => 'iCal parser',
'description' => t('Parse iCal feeds.'),
'handler' => array(
'parent' => 'FeedsParser',
'class' => 'DateiCalFeedsParser',
'file' => 'DateiCalFeedsParser.inc',
'path' => $path,
),
);
return $info;
}
/**
* Implements hook_feeds_processor_targets_alter().
*
......@@ -267,104 +267,13 @@ function date_ical_feeds_set_rrule($source, $entity, $target, $feed_element) {
$info = field_info_field($field_name);
foreach ($entity->{$field_name} as $lang => $field_array) {
// Add the multiple date values that Date Repeat Field uses to represent recurring dates.
$values = date_ical_build_repeating_dates($feed_element, NULL, $info, $field_array[0]);
$values = date_repeat_build_dates($feed_element, NULL, $info, $field_array[0]);
foreach ($values as $key => $value) {
$entity->{$field_name}[$lang][$key] = $value;
}
}
}
/**
* 99% copy-pasta from date_repeat_field.module's date_repeat_build_dates() function.
* The only change is that we assume COUNT=52 on indefinitely repeating RRULEs, rather than
* giving up completely.
*/
function date_ical_build_repeating_dates($rrule = NULL, $rrule_values = NULL, $field, $item) {
module_load_include('inc', 'date_api', 'date_api_ical');
$field_name = $field['field_name'];
if (empty($rrule)) {
$rrule = date_api_ical_build_rrule($rrule_values);
}
elseif (empty($rrule_values)) {
$rrule_values = date_ical_parse_rrule(NULL, $rrule);
}
// By the time we get here, the start and end dates have been
// adjusted back to UTC, but we want localtime dates to do
// things like '+1 Tuesday', so adjust back to localtime.
$timezone = date_get_timezone($field['settings']['tz_handling'], $item['timezone']);
$timezone_db = date_get_timezone_db($field['settings']['tz_handling']);
$start = new DateObject($item['value'], $timezone_db, date_type_format($field['type']));
$start->limitGranularity($field['settings']['granularity']);
if ($timezone != $timezone_db) {
date_timezone_set($start, timezone_open($timezone));
}
if (!empty($item['value2']) && $item['value2'] != $item['value']) {
$end = new DateObject($item['value2'], date_get_timezone_db($field['settings']['tz_handling']), date_type_format($field['type']));
$end->limitGranularity($field['settings']['granularity']);
date_timezone_set($end, timezone_open($timezone));
}
else {
$end = $start;
}
$duration = $start->difference($end);
$start_datetime = date_format($start, DATE_FORMAT_DATETIME);
if (!empty($rrule_values['UNTIL']['datetime'])) {
$end = date_ical_date($rrule_values['UNTIL'], $timezone);
$end_datetime = date_format($end, DATE_FORMAT_DATETIME);
}
elseif (!empty($rrule_values['COUNT'])) {
$end_datetime = NULL;
}
else {
// No UNTIL and no COUNT means this is an indefinitely repeating RRULE, which Date Repeat Field doesn't support.
// The best we can do is pretend it has a repeat count of 52 (52 weeks in a year, most repeats are weekly)
// by inserting a COUNT=52 param into the string, right after 'RRULE:'.
$rrule = substr_replace($rrule, 'COUNT=52;', 6, 0);
$end_datetime = NULL;
}
// Split the RRULE into RRULE, EXDATE, and RDATE parts.
$parts = date_repeat_split_rrule($rrule);
$parsed_exceptions = (array) $parts[1];
$exceptions = array();
foreach ($parsed_exceptions as $exception) {
$date = date_ical_date($exception, $timezone);
$exceptions[] = date_format($date, 'Y-m-d');
}
$parsed_rdates = (array) $parts[2];
$additions = array();
foreach ($parsed_rdates as $rdate) {
$date = date_ical_date($rdate, $timezone);
$additions[] = date_format($date, 'Y-m-d');
}
$dates = date_repeat_calc($rrule, $start_datetime, $end_datetime, $exceptions, $timezone, $additions);
$value = array();
foreach ($dates as $delta => $date) {
// date_repeat_calc always returns DATE_DATETIME dates, which is
// not necessarily $field['type'] dates.
// Convert returned dates back to db timezone before storing.
$date_start = new DateObject($date, $timezone, DATE_FORMAT_DATETIME);
$date_start->limitGranularity($field['settings']['granularity']);
date_timezone_set($date_start, timezone_open($timezone_db));
$date_end = clone($date_start);
date_modify($date_end, '+' . $duration . ' seconds');
$value[$delta] = array(
'value' => date_format($date_start, date_type_format($field['type'])),
'value2' => date_format($date_end, date_type_format($field['type'])),
'offset' => date_offset_get($date_start),
'offset2' => date_offset_get($date_end),
'timezone' => $timezone,
'rrule' => $rrule,
);
}
return $value;
}
/**
* Identify all potential fields that could populate the optional LOCATION component of iCal output.
*/
......
This diff is collapsed.
This diff is collapsed.
BEGIN:VCALENDAR
PRODID:-//Google Inc//Google Calendar 70.9054//EN
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:PUBLISH
X-WR-CALNAME:Events Feed
X-WR-TIMEZONE:America/New_York
X-WR-CALDESC:A calendar for the events feed
BEGIN:VTIMEZONE
TZID:America/New_York
X-LIC-LOCATION:America/New_York
BEGIN:DAYLIGHT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
TZNAME:EDT
DTSTART:19700308T020000
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
END:DAYLIGHT
BEGIN:STANDARD
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
TZNAME:EST
DTSTART:19701101T020000
RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
SUMMARY:Repeating Event (daily for 10 days)
DTSTART;TZID=America/New_York:20131009T190000
DTEND;TZID=America/New_York:20131009T210000
RRULE:FREQ=DAILY;COUNT=10
UID:date_ical_rrule_test01
DESCRIPTION:This is a 2-hour event in New York which repeats daily for 10 days.
END:VEVENT
BEGIN:VEVENT
SUMMARY:Repeating Event (weekly forever)
DTSTART;TZID=America/New_York:20131009T190000
DTEND;TZID=America/New_York:20131009T210000
RRULE:FREQ=WEEKLY
UID:date_ical_rrule_test02
DESCRIPTION:This is a 2-hour event in New York which repeats weekly forever (but because of Date's limitations, will actually only repeat for a year).
END:VEVENT
BEGIN:VEVENT
SUMMARY:Repeating Event (Multi-value RRULE)
DTSTART;TZID=America/New_York:20131001T190000
DTEND;TZID=America/New_York:20131001T210000
RRULE:FREQ=MONTHLY;BYMONTHDAY=1;COUNT=4
RRULE:FREQ=WEEKLY;COUNT=5
UID:date_ical_rrule_test03
DESCRIPTION:This event would repeat weekly and on the first of the month. But Date Repeat doesn't support multiple RRULEs, so it just repeats on the first of the month.
END:VEVENT
BEGIN:VEVENT
SUMMARY:Repeating Event (weekly) w/ RDATEs and EXDATEs
DTSTART;TZID=America/New_York:20131009T190000
DTEND;TZID=America/New_York:20131009T210000
RRULE:FREQ=WEEKLY;COUNT=10
RDATE;TZID=America/New_York:20131010T190000
EXDATE;TZID=America/New_York:20131016T190000
UID:date_ical_rrule_test04
DESCRIPTION:This event occurs on the 9th and repeats weekly (except the 16th), and also occurs on the 10th.
END:VEVENT
END:VALENDAR
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment