Read/write RDATE properties from/to ical and libkolabxml (#2885)
This commit is contained in:
parent
1ef785c8c6
commit
79ae6282f8
4 changed files with 103 additions and 11 deletions
|
@ -368,8 +368,8 @@ class libvcalendar implements Iterator
|
||||||
private function _to_array($ve)
|
private function _to_array($ve)
|
||||||
{
|
{
|
||||||
$event = array(
|
$event = array(
|
||||||
'uid' => strval($ve->UID),
|
'uid' => self::convert_string($ve->UID),
|
||||||
'title' => strval($ve->SUMMARY),
|
'title' => self::convert_string($ve->SUMMARY),
|
||||||
'_type' => $ve->name == 'VTODO' ? 'task' : 'event',
|
'_type' => $ve->name == 'VTODO' ? 'task' : 'event',
|
||||||
// set defaults
|
// set defaults
|
||||||
'priority' => 0,
|
'priority' => 0,
|
||||||
|
@ -435,7 +435,11 @@ class libvcalendar implements Iterator
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'EXDATE':
|
case 'EXDATE':
|
||||||
$event['recurrence']['EXDATE'] = array_merge((array)$event['recurrence']['EXDATE'], (array)self::convert_datetime($prop));
|
$event['recurrence']['EXDATE'] = array_merge((array)$event['recurrence']['EXDATE'], self::convert_datetime($prop, true));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'RDATE':
|
||||||
|
$event['recurrence']['RDATE'] = array_merge((array)$event['recurrence']['RDATE'], self::convert_datetime($prop, true));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'RECURRENCE-ID':
|
case 'RECURRENCE-ID':
|
||||||
|
@ -459,7 +463,7 @@ class libvcalendar implements Iterator
|
||||||
case 'LOCATION':
|
case 'LOCATION':
|
||||||
case 'DESCRIPTION':
|
case 'DESCRIPTION':
|
||||||
case 'URL':
|
case 'URL':
|
||||||
$event[strtolower($prop->name)] = str_replace('\,', ',', $prop->value);
|
$event[strtolower($prop->name)] = self::convert_string($prop);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'CATEGORY':
|
case 'CATEGORY':
|
||||||
|
@ -671,13 +675,21 @@ class libvcalendar implements Iterator
|
||||||
return $this->freebusy;
|
return $this->freebusy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static function convert_string($prop)
|
||||||
|
{
|
||||||
|
return str_replace('\,', ',', strval($prop->value));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method to correctly interpret an all-day date value
|
* Helper method to correctly interpret an all-day date value
|
||||||
*/
|
*/
|
||||||
public static function convert_datetime($prop)
|
public static function convert_datetime($prop, $as_array = false)
|
||||||
{
|
{
|
||||||
if (empty($prop)) {
|
if (empty($prop)) {
|
||||||
return null;
|
return $as_array ? array() : null;
|
||||||
}
|
}
|
||||||
else if ($prop instanceof VObject\Property\MultiDateTime) {
|
else if ($prop instanceof VObject\Property\MultiDateTime) {
|
||||||
$dt = array();
|
$dt = array();
|
||||||
|
@ -693,10 +705,38 @@ class libvcalendar implements Iterator
|
||||||
$dt->_dateonly = true;
|
$dt->_dateonly = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if ($prop instanceof VObject\Property && ($prop['VALUE'] == 'DATE' || $prop['VALUE'] == 'DATE-TIME')) {
|
||||||
|
try {
|
||||||
|
list($type, $dt) = VObject\Property\DateTime::parseData($prop->value, $prop);
|
||||||
|
$dt->_dateonly = ($type & VObject\Property\DateTime::DATE);
|
||||||
|
}
|
||||||
|
catch (Exception $e) {
|
||||||
|
// ignore date parse errors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ($prop instanceof VObject\Property && $prop['VALUE'] == 'PERIOD') {
|
||||||
|
$dt = array();
|
||||||
|
foreach(explode(',', $prop->value) as $val) {
|
||||||
|
try {
|
||||||
|
list($start, $end) = explode('/', $val);
|
||||||
|
list($type, $item) = VObject\Property\DateTime::parseData($start, $prop);
|
||||||
|
$item->_dateonly = ($type & VObject\Property\DateTime::DATE);
|
||||||
|
$dt[] = $item;
|
||||||
|
}
|
||||||
|
catch (Exception $e) {
|
||||||
|
// ignore single date parse errors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else if ($prop instanceof DateTime) {
|
else if ($prop instanceof DateTime) {
|
||||||
$dt = $prop;
|
$dt = $prop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// force return value to array if requested
|
||||||
|
if ($as_array && !is_array($dt)) {
|
||||||
|
$dt = empty($dt) ? array() : array($dt);
|
||||||
|
}
|
||||||
|
|
||||||
return $dt;
|
return $dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -839,8 +879,13 @@ class libvcalendar implements Iterator
|
||||||
if ($exdates = $event['recurrence']['EXDATE']) {
|
if ($exdates = $event['recurrence']['EXDATE']) {
|
||||||
unset($event['recurrence']['EXDATE']); // don't serialize EXDATEs into RRULE value
|
unset($event['recurrence']['EXDATE']); // don't serialize EXDATEs into RRULE value
|
||||||
}
|
}
|
||||||
|
if ($rdates = $event['recurrence']['RDATE']) {
|
||||||
|
unset($event['recurrence']['RDATE']); // don't serialize RDATEs into RRULE value
|
||||||
|
}
|
||||||
|
|
||||||
$ve->add('RRULE', libcalendaring::to_rrule($event['recurrence']));
|
if ($event['recurrence']['FREQ']) {
|
||||||
|
$ve->add('RRULE', libcalendaring::to_rrule($event['recurrence']));
|
||||||
|
}
|
||||||
|
|
||||||
// add EXDATEs each one per line (for Thunderbird Lightning)
|
// add EXDATEs each one per line (for Thunderbird Lightning)
|
||||||
if ($exdates) {
|
if ($exdates) {
|
||||||
|
@ -853,6 +898,13 @@ class libvcalendar implements Iterator
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// add RDATEs
|
||||||
|
if (!empty($rdates)) {
|
||||||
|
$sample = self::datetime_prop('RDATE', $rdates[0]);
|
||||||
|
$rdprop = new VObject\Property\MultiDateTime('RDATE', null);
|
||||||
|
$rdprop->setDateTimes($rdates, $sample->getDateType());
|
||||||
|
$ve->add($rdprop);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($event['categories']) {
|
if ($event['categories']) {
|
||||||
|
|
|
@ -237,6 +237,19 @@ class libvcalendar_test extends PHPUnit_Framework_TestCase
|
||||||
$this->assertEquals("Me, meets Them\nThem, meet Me", $event['description'], "Decode description value");
|
$this->assertEquals("Me, meets Them\nThem, meet Me", $event['description'], "Decode description value");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse RDATE properties (#2885)
|
||||||
|
*/
|
||||||
|
function test_rdate()
|
||||||
|
{
|
||||||
|
$ical = new libvcalendar();
|
||||||
|
$events = $ical->import_from_file(__DIR__ . '/resources/multiple-rdate.ics', 'UTF-8');
|
||||||
|
$event = $events[0];
|
||||||
|
|
||||||
|
$this->assertEquals(9, count($event['recurrence']['RDATE']));
|
||||||
|
$this->assertInstanceOf('DateTime', $event['recurrence']['RDATE'][0]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @depends test_import
|
* @depends test_import
|
||||||
*/
|
*/
|
||||||
|
@ -388,7 +401,19 @@ class libvcalendar_test extends PHPUnit_Framework_TestCase
|
||||||
$this->assertContains('RECURRENCE-ID;VALUE=DATE-TIME:20131113', $ics, "Recurrence-ID (2) being the exception date");
|
$this->assertContains('RECURRENCE-ID;VALUE=DATE-TIME:20131113', $ics, "Recurrence-ID (2) being the exception date");
|
||||||
$this->assertContains('SUMMARY:'.$exception2['title'], $ics, "Exception title");
|
$this->assertContains('SUMMARY:'.$exception2['title'], $ics, "Exception title");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
function test_export_rdate()
|
||||||
|
{
|
||||||
|
$ical = new libvcalendar();
|
||||||
|
$events = $ical->import_from_file(__DIR__ . '/resources/multiple-rdate.ics', 'UTF-8');
|
||||||
|
$ics = $ical->export($events, null, false);
|
||||||
|
|
||||||
|
$this->assertContains('RDATE;VALUE=DATE-TIME:20140520T020000Z', $ics, "VALUE=PERIOD is translated into single DATE-TIME values");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @depends test_export
|
* @depends test_export
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -23,8 +23,8 @@ BEGIN:VEVENT
|
||||||
DTSTART;TZID="W. Europe":20140520T040000
|
DTSTART;TZID="W. Europe":20140520T040000
|
||||||
DTEND;TZID="W. Europe":20140520T200000
|
DTEND;TZID="W. Europe":20140520T200000
|
||||||
TRANSP:TRANSPARENT
|
TRANSP:TRANSPARENT
|
||||||
RDATE;VALUE=PERIOD:20140520T020000Z/20140520T180000Z
|
RDATE;VALUE=DATE-TIME:20140520T020000Z
|
||||||
,PERIOD:20150520T020000Z/20150520T180000Z
|
RDATE;VALUE=PERIOD:20150520T020000Z/20150520T180000Z
|
||||||
,20160520T020000Z/20160520T180000Z,20170520T020000Z/20170520T180000Z
|
,20160520T020000Z/20160520T180000Z,20170520T020000Z/20170520T180000Z
|
||||||
,20180520T020000Z/20180520T180000Z,20190520T020000Z/20190520T180000Z
|
,20180520T020000Z/20180520T180000Z,20190520T020000Z/20190520T180000Z
|
||||||
,20200520T020000Z/20200520T180000Z,20210520T020000Z/20210520T180000Z
|
,20200520T020000Z/20200520T180000Z,20210520T020000Z/20210520T180000Z
|
||||||
|
|
|
@ -203,6 +203,13 @@ abstract class kolab_format_xcal extends kolab_format
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($rdates = $this->obj->recurrenceDates()) {
|
||||||
|
for ($i=0; $i < $rdates->size(); $i++) {
|
||||||
|
if ($rdate = self::php_datetime($rdates->get($i)))
|
||||||
|
$object['recurrence']['RDATE'][] = $rdate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// read alarm
|
// read alarm
|
||||||
$valarms = $this->obj->alarms();
|
$valarms = $this->obj->alarms();
|
||||||
$alarm_types = array_flip($this->alarm_type_map);
|
$alarm_types = array_flip($this->alarm_type_map);
|
||||||
|
@ -338,7 +345,7 @@ abstract class kolab_format_xcal extends kolab_format
|
||||||
$rr = new RecurrenceRule;
|
$rr = new RecurrenceRule;
|
||||||
$rr->setFrequency(RecurrenceRule::FreqNone);
|
$rr->setFrequency(RecurrenceRule::FreqNone);
|
||||||
|
|
||||||
if ($object['recurrence']) {
|
if ($object['recurrence'] && !empty($object['recurrence']['FREQ'])) {
|
||||||
$rr->setFrequency($this->rrule_type_map[$object['recurrence']['FREQ']]);
|
$rr->setFrequency($this->rrule_type_map[$object['recurrence']['FREQ']]);
|
||||||
|
|
||||||
if ($object['recurrence']['INTERVAL'])
|
if ($object['recurrence']['INTERVAL'])
|
||||||
|
@ -395,6 +402,14 @@ abstract class kolab_format_xcal extends kolab_format
|
||||||
|
|
||||||
$this->obj->setRecurrenceRule($rr);
|
$this->obj->setRecurrenceRule($rr);
|
||||||
|
|
||||||
|
// save recurrence dates (aka RDATE)
|
||||||
|
if (!empty($object['recurrence']['RDATE'])) {
|
||||||
|
$rdates = new vectordatetime;
|
||||||
|
foreach ((array)$object['recurrence']['RDATE'] as $rdate)
|
||||||
|
$rdates->push(self::get_datetime($rdate, null, true));
|
||||||
|
$this->obj->setRecurrenceDates($rdates);
|
||||||
|
}
|
||||||
|
|
||||||
// save alarm
|
// save alarm
|
||||||
$valarms = new vectoralarm;
|
$valarms = new vectoralarm;
|
||||||
if ($object['alarms']) {
|
if ($object['alarms']) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue