summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas BrĂ¼derli <bruederli@kolabsys.com>2012-10-23 13:05:38 (GMT)
committerThomas BrĂ¼derli <bruederli@kolabsys.com>2012-10-23 13:05:38 (GMT)
commitb4ced09d2e91a7be0649aa4c7866b4f817fcffbc (patch)
treeb7f5ffcaf575c5ec9976802c79acc74aba94c18c
parentae02c3d67078fa49c4212e39d28ad9e9aafec8a4 (diff)
downloadroundcubemail-plugins-kolab-b4ced09d2e91a7be0649aa4c7866b4f817fcffbc.tar.gz
Make use of libkolab/libcalendaring PHP bindings for computing recurring events
-rw-r--r--plugins/calendar/drivers/kolab/kolab_calendar.php10
-rw-r--r--plugins/libkolab/lib/kolab_date_recurrence.php107
-rw-r--r--plugins/libkolab/lib/kolab_format_event.php10
-rw-r--r--plugins/libkolab/lib/kolab_storage_cache.php4
4 files changed, 46 insertions, 85 deletions
diff --git a/plugins/calendar/drivers/kolab/kolab_calendar.php b/plugins/calendar/drivers/kolab/kolab_calendar.php
index e20133e..a62eb54 100644
--- a/plugins/calendar/drivers/kolab/kolab_calendar.php
+++ b/plugins/calendar/drivers/kolab/kolab_calendar.php
@@ -376,7 +376,15 @@ class kolab_calendar
*/
public function _get_recurring_events($event, $start, $end, $event_id = null)
{
- $recurrence = new kolab_date_recurrence($event);
+ $object = $event['_formatobj'];
+ if (!$object) {
+ $rec = $this->storage->get_object($event['id']);
+ $object = $rec['_formatobj'];
+ }
+ if (!is_object($object))
+ return array();
+
+ $recurrence = new kolab_date_recurrence($object);
$i = 0;
$events = array();
diff --git a/plugins/libkolab/lib/kolab_date_recurrence.php b/plugins/libkolab/lib/kolab_date_recurrence.php
index 427f62a..2e883d0 100644
--- a/plugins/libkolab/lib/kolab_date_recurrence.php
+++ b/plugins/libkolab/lib/kolab_date_recurrence.php
@@ -3,7 +3,8 @@
/**
* Recurrence computation class for xcal-based Kolab format objects
*
- * Uitility class to compute instances of recurring events.
+ * Utility class to compute instances of recurring events.
+ * It requires the libcalendaring PHP module to be installed and loaded.
*
* @version @package_version@
* @author Thomas Bruederli <bruederli@kolabsys.com>
@@ -25,14 +26,11 @@
*/
class kolab_date_recurrence
{
- private $engine;
- private $object;
- private $next;
- private $duration;
- private $tz_offset = 0;
- private $dst_start = 0;
- private $allday = false;
- private $hour = 0;
+ private /* EventCal */ $engine;
+ private /* kolab_format_xcal */ $object;
+ private /* DateTime */ $start;
+ private /* DateTime */ $next;
+ private /* DateInterval */ $duration;
/**
* Default constructor
@@ -41,27 +39,16 @@ class kolab_date_recurrence
*/
function __construct($object)
{
+ $data = $object->to_array();
+
$this->object = $object;
- $this->next = new Horde_Date($object['start'], kolab_format::$timezone->getName());
+ $this->engine = $object->to_libcal();
+ $this->start = $this->next = $data['start'];
- if (is_object($object['start']) && is_object($object['end']))
- $this->duration = $object['start']->diff($object['end']);
+ if (is_object($data['start']) && is_object($data['end']))
+ $this->duration = $data['start']->diff($data['end']);
else
- $this->duration = new DateInterval('PT' . ($object['end'] - $object['start']) . 'S');
-
- // use (copied) Horde classes to compute recurring instances
- // TODO: replace with something that has less than 6'000 lines of code
- $this->engine = new Horde_Date_Recurrence($this->next);
- $this->engine->fromRRule20($this->to_rrule($object['recurrence'])); // TODO: get that string directly from libkolabxml
-
- foreach ((array)$object['recurrence']['EXDATE'] as $exdate)
- $this->engine->addException($exdate->format('Y'), $exdate->format('n'), $exdate->format('j'));
-
- $now = new DateTime('now', kolab_format::$timezone);
- $this->tz_offset = $object['allday'] ? $now->getOffset() - date('Z') : 0;
- $this->dst_start = $this->next->format('I');
- $this->allday = $object['allday'];
- $this->hour = $this->next->hour;
+ $this->duration = new DateInterval('PT' . ($data['end'] - $data['start']) . 'S');
}
/**
@@ -73,20 +60,13 @@ class kolab_date_recurrence
public function next_start($timestamp = false)
{
$time = false;
- if ($this->next && ($next = $this->engine->nextActiveRecurrence(array('year' => $this->next->year, 'month' => $this->next->month, 'mday' => $this->next->mday + 1, 'hour' => $this->next->hour, 'min' => $this->next->min, 'sec' => $this->next->sec)))) {
- if ($this->allday) {
- $next->hour = $this->hour; # fix time for all-day events
- $next->min = 0;
- }
- if ($timestamp) {
- # consider difference in daylight saving between base event and recurring instance
- $dst_diff = ($this->dst_start - $next->format('I')) * 3600;
- $time = $next->timestamp() - $this->tz_offset - $dst_diff;
- }
- else {
- $time = $next->toDateTime();
+
+ if ($this->engine && $this->next) {
+ $cstart = kolab_format::get_datetime($this->next);
+ if ($next = kolab_format::php_datetime(new cDateTime($this->engine->getNextOccurence($cstart)))) {
+ $time = $timestamp ? $next->format('U') : $next;
+ $this->next = $next;
}
- $this->next = $next;
}
return $time;
@@ -103,7 +83,7 @@ class kolab_date_recurrence
$next_end = clone $next_start;
$next_end->add($this->duration);
- $next = $this->object;
+ $next = $this->object->to_array();
$next['recurrence_id'] = $next_start->format('Y-m-d');
$next['start'] = $next_start;
$next['end'] = $next_end;
@@ -123,49 +103,12 @@ class kolab_date_recurrence
*/
public function end($limit = 'now +1 year')
{
- if ($this->object['recurrence']['UNTIL'])
- return $this->object['recurrence']['UNTIL']->format('U');
-
- $limit_time = strtotime($limit);
- while ($next_start = $this->next_start(true)) {
- if ($next_start > $limit_time)
- break;
- }
-
- if ($this->next) {
- $next_end = $this->next->toDateTime();
- $next_end->add($this->duration);
- return $next_end->format('U');
+ $limit_dt = new DateTime($limit);
+ $cstart = kolab_format::get_datetime($this->start);
+ if ($this->engine && ($cend = $this->engine->getOccurenceEndDate($cstart)) && ($end_dt = kolab_format::php_datetime(new cDateTime($cend))) && $end_dt < $limit_dt) {
+ return $end_dt->format('U');
}
return false;
}
-
- /**
- * Convert the internal structured data into a vcalendar RRULE 2.0 string
- */
- private function to_rrule($recurrence)
- {
- if (is_string($recurrence))
- return $recurrence;
-
- $rrule = '';
- foreach ((array)$recurrence as $k => $val) {
- $k = strtoupper($k);
- switch ($k) {
- case 'UNTIL':
- $val = $val->format('Ymd\THis');
- break;
- case 'EXDATE':
- foreach ((array)$val as $i => $ex)
- $val[$i] = $ex->format('Ymd\THis');
- $val = join(',', (array)$val);
- break;
- }
- $rrule .= $k . '=' . $val . ';';
- }
-
- return $rrule;
- }
-
}
diff --git a/plugins/libkolab/lib/kolab_format_event.php b/plugins/libkolab/lib/kolab_format_event.php
index 33ed5af..4e790f2 100644
--- a/plugins/libkolab/lib/kolab_format_event.php
+++ b/plugins/libkolab/lib/kolab_format_event.php
@@ -51,6 +51,16 @@ class kolab_format_event extends kolab_format_xcal
$this->xmldata = $xmldata;
}
+ /**
+ * Clones into an instance of libcalendaring's extended EventCal class
+ *
+ * @return mixed EventCal object or false on failure
+ */
+ public function to_libcal()
+ {
+ return class_exists('kolabcalendaring') ? new EventCal($this->obj) : false;
+ }
+
/**
* Set event properties to the kolabformat object
*
diff --git a/plugins/libkolab/lib/kolab_storage_cache.php b/plugins/libkolab/lib/kolab_storage_cache.php
index c3e88da..866a795 100644
--- a/plugins/libkolab/lib/kolab_storage_cache.php
+++ b/plugins/libkolab/lib/kolab_storage_cache.php
@@ -517,8 +517,8 @@ class kolab_storage_cache
$sql_data['dtend'] = date('Y-m-d H:i:s', is_object($object['end']) ? $object['end']->format('U') : $object['end']);
// extend date range for recurring events
- if ($object['recurrence']) {
- $recurrence = new kolab_date_recurrence($object);
+ if ($object['recurrence'] && $object['_formatobj']) {
+ $recurrence = new kolab_date_recurrence($object['_formatobj']);
$sql_data['dtend'] = date('Y-m-d 23:59:59', $recurrence->end() ?: strtotime('now +1 year'));
}
}