From: Michael J. Rubinsky Date: Sun, 11 Jul 2010 14:56:58 +0000 (-0400) Subject: Fixes for importing iCalendar files with RECURRENCE-ID set. X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=d8d246e45b047210bac2e6292f6f563d7922eee7;p=horde.git Fixes for importing iCalendar files with RECURRENCE-ID set. The original recurring event must be imported before any instances of RECURRENCE-ID exceptions or the original event will not be found to modify. --- diff --git a/kronolith/data.php b/kronolith/data.php index 8d7fefdbc..4bda27d22 100644 --- a/kronolith/data.php +++ b/kronolith/data.php @@ -244,6 +244,7 @@ if (is_array($next_step)) { } } + $recurrences = array(); foreach ($next_step as $row) { if ($max_events !== true && $num_events >= $max_events) { try { @@ -264,7 +265,15 @@ if (is_array($next_step)) { break; } if ($row instanceof Horde_iCalendar_vevent) { - $event->fromiCalendar($row); + // RECURRENCE-ID entries must be imported after the original + // recurring event is imported. + $recurrence = $row->getAttribute('RECURRENCE-ID'); + if (!($recurrence instanceof PEAR_Error)) { + $recurrences[] = $row; + continue; + } else { + $event->fromiCalendar($row); + } } elseif ($row instanceof Horde_iCalendar) { // Skip other iCalendar components for now. continue; @@ -290,6 +299,20 @@ if (is_array($next_step)) { $num_events++; } } + + // Any RECURRENCE-ID entries? + foreach ($recurrences as $recurrence) { + $event = $kronolith_driver->getEvent(); + $event->fromiCalendar($row); + try { + $event->save(); + } catch (Exception $e) { + $notification->push($e, 'horde.error'); + $error = true; + break; + } + } + if (!$error) { $notification->push(sprintf(_("%s file successfully imported"), $file_types[$_SESSION['import_data']['format']]), 'horde.success'); diff --git a/kronolith/lib/Api.php b/kronolith/lib/Api.php index 24f3e098e..acb5ea939 100644 --- a/kronolith/lib/Api.php +++ b/kronolith/lib/Api.php @@ -642,42 +642,32 @@ class Kronolith_Api extends Horde_Registry_Api } $ids = array(); + $recurrences = array(); foreach ($components as $content) { if ($content instanceof Horde_iCalendar_vevent) { - $event = $kronolith_driver->getEvent(); - $event->fromiCalendar($content); - // Check if the entry already exists in the data source, - // first by UID. - $uid = $event->uid; - try { - $existing_event = $kronolith_driver->getByUID($uid, array($calendar)); - throw new Kronolith_Exception(_("Already Exists"), - 'horde.message', null, null, $uid); - } catch (Horde_Exception $e) { - } - $result = $kronolith_driver->search($event); - // Check if the match really is an exact match: - if (is_array($result) && count($result) > 0) { - foreach($result as $match) { - if ($match->start == $event->start && - $match->end == $event->end && - $match->title == $event->title && - $match->location == $event->location && - $match->hasPermission(Horde_Perms::EDIT)) { - throw new Kronolith_Exception(_("Already Exists"), 'horde.message', null, null, $match->uid); - } - } + // Need to ensure that the original recurring event is + // added before any of the instance exceptions. Easiest way + // to do that is just add all the recurrence-id entries last + $recurrenceId = $content->getAttribute('RECURRENCE-ID'); + if (!($recurrenceId instanceof PEAR_Error)) { + $recurrences[] = $content; + } else { + $ids[] = $this->_addiCalEvent($content, $kronolith_driver); } - - $eventId = $event->save(); - $ids[] = $event->uid; } } + if (count($ids) == 0) { throw new Kronolith_Exception(_("No iCalendar data was found.")); } else if (count($ids) == 1) { return $ids[0]; } + + // Now add all the exception instances + foreach ($recurrences as $recurrence) { + $ids[] = $this->_addiCalEvent($recurrence, $kronolith_driver); + } + return $ids; case 'activesync': @@ -691,6 +681,43 @@ class Kronolith_Api extends Horde_Registry_Api } /** + * Imports a single vEvent part to storage. + * + * @param Horde_iCalendar_vEvent $content The vEvent part + * @param Kronolith_Driver $driver The kronolith driver + * + * @return string The new event's uid + */ + protected function _addiCalEvent($content, $driver) + { + $event = $driver->getEvent(); + $event->fromiCalendar($content); + // Check if the entry already exists in the data source, + // first by UID. + $uid = $event->uid; + try { + $existing_event = $driver->getByUID($uid, array($driver->calendar)); + throw new Kronolith_Exception(_("Already Exists"), 'horde.message', null, null, $uid); + } catch (Horde_Exception $e) {} + $result = $driver->search($event); + // Check if the match really is an exact match: + if (is_array($result) && count($result) > 0) { + foreach($result as $match) { + if ($match->start == $event->start && + $match->end == $event->end && + $match->title == $event->title && + $match->location == $event->location && + $match->hasPermission(Horde_Perms::EDIT)) { + throw new Kronolith_Exception(_("Already Exists"), 'horde.message', null, null, $match->uid); + } + } + } + $event->save(); + + return $event->uid; + } + + /** * Imports an event parsed from a string. * * @param string $text The text to parse into an event