Add a calendar/getChanges api method.
authorMichael J. Rubinsky <mrubinsk@horde.org>
Fri, 7 May 2010 23:32:55 +0000 (19:32 -0400)
committerMichael J. Rubinsky <mrubinsk@horde.org>
Fri, 7 May 2010 23:42:03 +0000 (19:42 -0400)
This is a much more efficient way for synch libraries to get all
server changes in a specified time period. Additionally, it fixes a
regression introduced when activesync switched to a horde_history
driver...we need a way to filter out uids that represent recurring
event exceptions since this information is passed as part of the
original event object sent to the device. Not filtering these out
leads to duplicate events on the device.

of listBy returning uids for events that may represent

kronolith/lib/Api.php

index 598212c..c02f707 100644 (file)
@@ -508,6 +508,75 @@ class Kronolith_Api extends Horde_Registry_Api
     }
 
     /**
+     * Method for obtaining all server changes between two timestamps. Basically
+     * a wrapper around listBy(), but returns an array containing all adds,
+     * edits and deletions. If $ignoreExceptions is true, events representing
+     * recurring event exceptions will not be included in the results.
+     *
+     * @param integer $start             The starting timestamp
+     * @param integer $end               The ending timestamp.
+     * @param boolean $ignoreExceptions  Do not include exceptions in results.
+     *
+     * @return array  An hash with 'add', 'modify' and 'delete' arrays.
+     * @throws Horde_Exception_PermissionDenied
+     * @throws Kronolith_Exception
+     */
+    public function getChanges($start, $end, $ignoreExceptions = true)
+    {
+        /* Only get the calendar once */
+        $c = Kronolith::getDefaultCalendar();
+        if ($c === false ||
+            !array_key_exists($c, Kronolith::listCalendars(false, Horde_Perms::READ))) {
+            throw new Horde_Exception_PermissionDenied();
+        }
+
+        /* Need to get changes, then ensure they are not from an exception */
+        $changes = array('add' => array(),
+                         'modify' => array(),
+                         'delete' => array());
+
+        /* New events */
+        $uids = $this->listBy('add', $start, $c, $end);
+        if ($ignoreExceptions) {
+            foreach ($uids as $uid) {
+                try {
+                    $event = Kronolith::getDriver()->getByUID($uid);
+                } catch (Kronolith_Exception $e) {
+                    continue;
+                }
+                if (empty($event->baseid)) {
+                    $changes['add'][] = $uid;
+                }
+            }
+        } else {
+            $changes['add'] = $uids;
+        }
+
+        /* Edits */
+        $uids = $this->listBy('modify', $start, $c, $end);
+        if ($ignoreExceptions) {
+            foreach ($uids as $uid) {
+                try {
+                    $event = Kronolith::getDriver()->getByUID($uid);
+                } catch (Kronolith_Exception $e) {
+                    continue;
+                }
+                if (empty($event->baseid)) {
+                    $changes['modify'][] = $uid;
+                }
+            }
+        } else {
+            $changes['modify'] = $uids;
+        }
+        
+        /* No way to figure out if this was an exception, so we must include all */
+        $changes['delete'] = $this->listBy('delete', $start, $c, $end);
+
+        return $changes;
+    }
+
+
+    /**
      * Returns the timestamp of an operation for a given uid an action
      *
      * @param string $uid      The uid to look for.