Skip to content

Commit

Permalink
MDL-47993 calendar: Fix ical import Microsoft calendar issue
Browse files Browse the repository at this point in the history
  • Loading branch information
Oleg Demeshev committed Nov 13, 2014
1 parent c106341 commit 741063b
Show file tree
Hide file tree
Showing 9 changed files with 218 additions and 8 deletions.
50 changes: 49 additions & 1 deletion calendar/lib.php
Expand Up @@ -1890,6 +1890,51 @@ function calendar_add_event_allowed($event) {
}
}

/**
* Convert region timezone to php supported timezone
*
* @param string $tz value from ical file
* @return string $tz php supported timezone
*/
function calendar_normalize_tz($tz) {
switch ($tz) {
case('CST'):
case('Central Time'):
case('Central Standard Time'):
$tz = 'America/Chicago';
break;
case('CET'):
case('Central European Time'):
$tz = 'Europe/Berlin';
break;
case('EST'):
case('Eastern Time'):
case('Eastern Standard Time'):
$tz = 'America/New_York';
break;
case('PST'):
case('Pacific Time'):
case('Pacific Standard Time'):
$tz = 'America/Los_Angeles';
break;
case('China Time'):
case('China Standard Time'):
$tz = 'Asia/Beijing';
break;
case('IST'):
case('India Time'):
case('India Standard Time'):
$tz = 'Asia/New_Delhi';
break;
case('JST');
case('Japan Time'):
case('Japan Standard Time'):
$tz = 'Asia/Tokyo';
break;
}
return $tz;
}

/**
* Manage calendar events
*
Expand Down Expand Up @@ -2919,6 +2964,7 @@ function calendar_add_icalendar_event($event, $courseid, $subscriptionid, $timez
$defaulttz = date_default_timezone_get();
$tz = isset($event->properties['DTSTART'][0]->parameters['TZID']) ? $event->properties['DTSTART'][0]->parameters['TZID'] :
$timezone;
$tz = calendar_normalize_tz($tz);
$eventrecord->timestart = strtotime($event->properties['DTSTART'][0]->value . ' ' . $tz);
if (empty($event->properties['DTEND'])) {
$eventrecord->timeduration = 0; // no duration if no end time specified
Expand Down Expand Up @@ -3065,7 +3111,9 @@ function calendar_import_icalendar_events($ical, $courseid, $subscriptionid = nu
$updatecount = 0;

// Large calendars take a while...
core_php_time_limit::raise(300);
if (!CLI_SCRIPT) {
core_php_time_limit::raise(300);
}

// Mark all events in a subscription with a zero timestamp.
if (!empty($subscriptionid)) {
Expand Down
59 changes: 59 additions & 0 deletions calendar/tests/ical_test.php
Expand Up @@ -74,4 +74,63 @@ public function test_calendar_update_subscription() {
$this->setExpectedException('coding_exception');
calendar_update_subscription($subscription);
}

public function test_calendar_add_subscription() {
global $DB, $CFG;

require_once($CFG->dirroot . '/lib/bennu/bennu.inc.php');

$this->resetAfterTest(true);

// Test for Microsoft Outlook 2010.
$subscription = new stdClass();
$subscription->name = 'Microsoft Outlook 2010';
$subscription->importfrom = CALENDAR_IMPORT_FROM_FILE;
$subscription->eventtype = 'site';
$id = calendar_add_subscription($subscription);

$calendar = file_get_contents($CFG->dirroot . '/lib/tests/fixtures/ms_outlook_2010.ics');
$ical = new iCalendar();
$ical->unserialize($calendar);
$this->assertEquals($ical->parser_errors, array());

$sub = calendar_get_subscription($id);
$result = calendar_import_icalendar_events($ical, $sub->courseid, $sub->id);
$count = $DB->count_records('event', array('subscriptionid' => $sub->id));
$this->assertEquals($count, 1);

// Test for OSX Yosemite.
$subscription = new stdClass();
$subscription->name = 'OSX Yosemite';
$subscription->importfrom = CALENDAR_IMPORT_FROM_FILE;
$subscription->eventtype = 'site';
$id = calendar_add_subscription($subscription);

$calendar = file_get_contents($CFG->dirroot . '/lib/tests/fixtures/osx_yosemite.ics');
$ical = new iCalendar();
$ical->unserialize($calendar);
$this->assertEquals($ical->parser_errors, array());

$sub = calendar_get_subscription($id);
$result = calendar_import_icalendar_events($ical, $sub->courseid, $sub->id);
$count = $DB->count_records('event', array('subscriptionid' => $sub->id));
$this->assertEquals($count, 1);

// Test for Google Gmail.
$subscription = new stdClass();
$subscription->name = 'Google Gmail';
$subscription->importfrom = CALENDAR_IMPORT_FROM_FILE;
$subscription->eventtype = 'site';
$id = calendar_add_subscription($subscription);

$calendar = file_get_contents($CFG->dirroot . '/lib/tests/fixtures/google_gmail.ics');
$ical = new iCalendar();
$ical->unserialize($calendar);
$this->assertEquals($ical->parser_errors, array());

$sub = calendar_get_subscription($id);
$result = calendar_import_icalendar_events($ical, $sub->courseid, $sub->id);
$count = $DB->count_records('event', array('subscriptionid' => $sub->id));
$this->assertEquals($count, 1);
}
}
6 changes: 4 additions & 2 deletions lib/bennu/iCalendar_components.php
Expand Up @@ -287,8 +287,10 @@ function unserialize($string) {
if($parent_component == null) {
$parent_component = $this; // If there's no components on the stack, use the iCalendar object
}
if ($parent_component->add_component($component) === false) {
$this->parser_error("Failed to add component on line $key");
if ($component !== null) {
if ($parent_component->add_component($component) === false) {
$this->parser_error("Failed to add component on line $key");
}
}
if ($parent_component != $this) { // If we're not using the iCalendar
array_push($components, $parent_component); // Put the component back on the stack
Expand Down
8 changes: 3 additions & 5 deletions lib/bennu/iCalendar_parameters.php
Expand Up @@ -104,9 +104,7 @@ static function is_valid_value(&$parent_property, $parameter, $value) {
'VIDEO' => array('MPEG', 'QUICKTIME', 'VND.VIVO', 'VND.MOTOROLA.VIDEO', 'VND.MOTOROLA.VIDEOP')
);
$value = strtoupper($value);
if(rfc2445_is_xname($value)) {
return true;
}
// Mimetype is enumerated above and anything else results in false.
@list($type, $subtype) = explode('/', $value);
if(empty($type) || empty($subtype)) {
return false;
Expand Down Expand Up @@ -178,7 +176,7 @@ static function is_valid_value(&$parent_property, $parameter, $value) {
if(empty($value)) {
return false;
}
return (strcspn($value, '";:,') == strlen($value));
return (strcspn($value, ';:,') == strlen($value));
break;

case 'VALUE':
Expand Down Expand Up @@ -227,7 +225,7 @@ static function do_value_formatting($parameter, $value) {

// Parameters we shouldn't be messing with
case 'TZID':
return $value;
return str_replace('"', '', $value);
break;
}
}
Expand Down
2 changes: 2 additions & 0 deletions lib/bennu/iCalendar_properties.php
Expand Up @@ -1227,6 +1227,8 @@ class iCalendar_property_x extends iCalendar_property {
function __construct() {
parent::__construct();
$this->valid_parameters = array(
// X-ALT-DESC (Description) can have FMTTYPE declaration of text/html is a property for HTML content.
'FMTTYPE' => RFC2445_OPTIONAL | RFC2445_ONCE,
'LANGUAGE' => RFC2445_OPTIONAL | RFC2445_ONCE,
RFC2445_XNAME => RFC2445_OPTIONAL
);
Expand Down
2 changes: 2 additions & 0 deletions lib/bennu/readme_moodle.txt
Expand Up @@ -5,3 +5,5 @@ modifications:
2/ replaced mbstring functions with moodle core_text (28 Nov 2011)
3/ replaced explode in iCalendar_component::unserialize() with preg_split to support various line breaks (20 Nov 2012)
4/ updated rfc2445_is_valid_value() to accept single part rrule as a valid value (16 Jun 2014)
5/ updated DTEND;TZID and DTSTAR;TZID values to support quotations (7 Nov 2014)
6/ added calendar_normalize_tz function to convert region timezone to php supported timezone (7 Nov 2014)
21 changes: 21 additions & 0 deletions lib/tests/fixtures/google_gmail.ics
@@ -0,0 +1,21 @@
BEGIN:VCALENDAR
PRODID:-//Google Inc//Google Calendar 70.9054//EN
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:REQUEST
BEGIN:VEVENT
DTSTART:20141028T213000Z
DTEND:20141028T223000Z
DTSTAMP:20141028T211302Z
ORGANIZER;CN=John Smith:mailto:john.smith@gmail.com
UID:hjlv3v1lcerpi629s5gpfuijk0@google.com
CREATED:20141028T210927Z
DESCRIPTION:Lorem ipsum dolor sit amet\, consectetur adipisicing elit.
LAST-MODIFIED:20141028T211302Z
LOCATION:150 Willis St\, Te Aro\, Wellington 6011\, New Zealand
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:Google calendar
TRANSP:OPAQUE
END:VEVENT
END:VCALENDAR
42 changes: 42 additions & 0 deletions lib/tests/fixtures/ms_outlook_2010.ics
@@ -0,0 +1,42 @@
BEGIN:VCALENDAR
PRODID:-//Microsoft Corporation//Outlook 14.0 MIMEDIR//EN
VERSION:2.0
METHOD:PUBLISH
X-MS-OLK-FORCEINSPECTOROPEN:TRUE
BEGIN:VTIMEZONE
TZID:Central Standard Time
BEGIN:STANDARD
DTSTART:16011104T020000
RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=11
TZOFFSETFROM:-0500
TZOFFSETTO:-0600
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:16010311T020000
RRULE:FREQ=YEARLY;BYDAY=2SU;BYMONTH=3
TZOFFSETFROM:-0600
TZOFFSETTO:-0500
END:DAYLIGHT
END:VTIMEZONE
BEGIN:VEVENT
CLASS:PUBLIC
CREATED:20140916T144857Z
DESCRIPTION:\n
DTSTART;TZID="Central Standard Time":20140916T090000
DTSTAMP:20140916T144857Z
DTEND;TZID="Central Standard Time":20140916T093000
LAST-MODIFIED:20140916T144857Z
PRIORITY:5
SEQUENCE:0
SUMMARY;LANGUAGE=en-us:test
TRANSP:OPAQUE
UID:040000008200E00074C5B7101A82E0080000000000D9F06393D1CF010000000000000000100000007B710E58C9CE8146B1403BF7E84162FB
X-ALT-DESC;FMTTYPE=text/html:<!DOCTYPE>\n<HTML>\n<HEAD>\n<TITLE></TITLE>\n</HEAD>\n<BODY>\n<!-- Converted from text/rtf format -->\n\n<P DIR=LTR></P>\n\n</BODY>\n</HTML>
X-MICROSOFT-CDO-BUSYSTATUS:BUSY
X-MICROSOFT-CDO-IMPORTANCE:1
X-MICROSOFT-DISALLOW-COUNTER:FALSE
X-MS-OLK-AUTOFILLLOCATION:TRUE
X-MS-OLK-AUTOSTARTCHECK:FALSE
X-MS-OLK-CONFTYPE:0
END:VEVENT
END:VCALENDAR
36 changes: 36 additions & 0 deletions lib/tests/fixtures/osx_yosemite.ics
@@ -0,0 +1,36 @@
BEGIN:VCALENDAR
CALSCALE:GREGORIAN
VERSION:2.0
METHOD:PUBLISH
X-WR-CALNAME:pokus
X-WR-TIMEZONE:Pacific/Auckland
X-APPLE-CALENDAR-COLOR:#1BADF8
BEGIN:VTIMEZONE
TZID:Pacific/Auckland
BEGIN:DAYLIGHT
TZOFFSETFROM:+1200
RRULE:FREQ=YEARLY;BYMONTH=9;BYDAY=-1SU
DTSTART:20070930T020000
TZNAME:NZDT
TZOFFSETTO:+1300
END:DAYLIGHT
BEGIN:STANDARD
TZOFFSETFROM:+1300
RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=1SU
DTSTART:20080406T030000
TZNAME:NZST
TZOFFSETTO:+1200
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
CREATED:20141028T204253Z
UID:5571BBDC-AC05-4486-9E57-118EBDFFA385
DTEND;TZID=Pacific/Auckland:20140917T023000
TRANSP:OPAQUE
SUMMARY:Test event
DTSTART;TZID=Pacific/Auckland:20140917T020000
DTSTAMP:20141028T204253Z
SEQUENCE:0
DESCRIPTION:This is a note.
END:VEVENT
END:VCALENDAR

0 comments on commit 741063b

Please sign in to comment.