[sync] patches 2/2

Karsten Fourmont fourmont at gmx.de
Tue Jul 13 05:08:39 PDT 2004


and the second half...

 Karsten
-------------- next part --------------
Index: lib/Driver.php
===================================================================
RCS file: /repository/nag/lib/Driver.php,v
retrieving revision 1.50
diff -u -r1.50 Driver.php
--- lib/Driver.php	7 Apr 2004 14:43:38 -0000	1.50
+++ lib/Driver.php	11 Jul 2004 20:43:43 -0000
@@ -168,4 +168,122 @@
         return $instances[$signature];
     }
 
+
+  /**
+     * Export this task in iCalendar format.
+     *
+     * @param array  task      the task (hash array) to export
+     * @param object vcal      a Horde_iCalendar object that acts as container.
+     *
+     * @return object  Horde_iCalendar_vtodo object for this event
+     */
+     
+    function toiCalendar($task, &$calendar)
+    {
+        require_once 'Horde/History.php';
+        
+        global $prefs;
+
+
+        $vtodo = &Horde_iCalendar::newComponent('vtodo', $calendar);
+
+        $guid = $this->getGUID($task['task_id']);
+        $vtodo->setAttribute('UID', $guid);
+        
+        if (isset($task['name'])) {
+            $vtodo->setAttribute('SUMMARY', $task['name']);
+        }
+        if (isset($task['desc'])) {
+            $vtodo->setAttribute('DESCRIPTION', $task['desc']);
+        }
+
+        if (isset($task['priority'])) {
+            $vtodo->setAttribute('PRIORITY', $task['priority']);
+        }
+
+        if (isset($task['due'])) {
+            $vtodo->setAttribute('DUE', $task['due']);
+        }
+
+        if(!empty($task['completed'])) {
+            $vtodo->setAttribute('STATUS', 'COMPLETED');
+        }
+
+        if(!empty($task['category'])) {
+            $vtodo->setAttribute('CATEGORIES', $task['category']);
+        }
+
+
+        // missing: alarm
+
+        /* Get the task's history. */
+        $history = &Horde_History::singleton();
+        $log = $history->getHistory($guid);
+        foreach ($log->getData() as $entry) {
+            switch ($entry['action']) {
+            case 'add':
+                $created = $entry['ts'];
+                break;
+
+            case 'modify':
+                $modified = $entry['ts'];
+                break;
+            }
+        }
+        if(!empty($created)) {
+            $vtodo->setAttribute('DCREATED', $created);
+        }
+        if(!empty($modified)) {
+            $vtodo->setAttribute('LAST-MODIFIED', $modified);
+        }
+        
+        return $vtodo;
+    }
+    
+    /**
+     * create a memo (hash array) from an 
+     * Horde_iCalendar_vtodo object.
+     *
+     * @param Horde_iCalendar_vtodo $vtodo  The iCalendar data to update from.
+     *
+     * @return array memo (hash array) created from vtodo
+     */
+    function fromiCalendar($vtodo)
+    {
+        $r = array();
+
+        $name = $vtodo->getAttribute('SUMMARY');
+        if (!is_array($name) && !is_a($name, 'PEAR_Error')) {
+            $r['name'] = $name;
+        }
+        $desc = $vtodo->getAttribute('DESCRIPTION');
+        if (!is_array($desc) && !is_a($desc, 'PEAR_Error')) {
+            $r['desc'] = $desc;
+        }
+
+        $priority = $vtodo->getAttribute('PRIORITY');
+        if (!is_array($priority) && !is_a($priority, 'PEAR_Error')) {
+            $r['priority'] = $priority;
+        }
+
+        $due = $vtodo->getAttribute('DTSTAMP');
+        if (!is_array($due) && !is_a($due, 'PEAR_Error')) {
+            $r['due'] = $due;
+        }
+
+        $cat = $vtodo->getAttribute('CATEGORIES');
+        if (!is_array($cat) && !is_a($cat, 'PEAR_Error')) {
+            $r['category'] = $cat;
+        }
+
+        $status = $vtodo->getAttribute('STATUS');
+        if (!is_array($status) && !is_a($status, 'PEAR_Error') && strcasecmp($status,'COMPLETED')==0) {
+            $r['completed'] = 1;
+        }
+
+        // missing: alarm
+
+        return $r;        
+    }
+
 }
Index: lib/api.php
===================================================================
RCS file: /repository/nag/lib/api.php,v
retrieving revision 1.90
diff -u -r1.90 api.php
--- lib/api.php	7 Jul 2004 01:22:13 -0000	1.90
+++ lib/api.php	11 Jul 2004 20:43:44 -0000
@@ -282,10 +282,7 @@
                 return PEAR::raiseError(_("No iCalendar data was found."));
 
             case 1:
-                $content = $components[0];
-                if (!is_a($content, 'Horde_iCalendar_vtodo')) {
-                    return PEAR::raiseError(_("vTodo not found."));
-                }
+                $vtodo = $components[0];
                 break;
 
             default:
@@ -296,11 +293,20 @@
         /**
          * @TODO Need to check for alarms and set due date, etc.
          */
-        $hash = $content->toArray();
-        $taskId = $storage->add(isset($hash['name']) ? $hash['name'] : '',
-                                isset($hash['desc']) ? $hash['desc'] : '',
-                                0,
-                                isset($hash['priority']) ? $hash['priority'] : 3);
+        /**
+         * @TODO Need to check for alarms and completed
+         */
+        $task = $storage->fromiCalendar($vtodo);
+
+        $taskId = $storage->add(isset($task['name']) ? $task['name'] : '',
+                                isset($task['desc']) ? $task['desc'] : '',
+                                isset($task['due']) ? $task['due'] : '',
+                                isset($task['priority']) ? $task['priority'] : 3,
+                                !empty($task['completed']) ? 1 : 0,
+                                isset($task['category']) ? $task['category'] : '',
+                                0 // alarm: missing
+                                );
+
         break;
 
     default:
@@ -318,9 +324,15 @@
  * Export a task, identified by GUID, in the requested contentType.
  *
  * @param string $guid         Identify the task to export.
- * @param string $contentType  What format should the data be in? Currently supports:
- *                             text/x-icalendar
+ * @param mixed  $contentType  What format should the data be in?
+ *                             Either a string with one of:
+ *                             text/x-vtodo
  *                             text/x-vcalendar
+ *                             text/x-icalendar
+ *                             'ContentType':  as above
+ *                             'ENCODING': (optional) character encoding 
+ *                                         for strings fields
+ *                             'CHARSET':  (optional) charset. Like UTF-8
  *
  * @return string  The requested data.
  */
@@ -338,13 +350,45 @@
         return PEAR::raiseError(_("Permission Denied"));
     }
 
+    if( is_array($contentType)) {
+        $options = $contentType;
+        $contentType = $options['ContentType'];
+    } else {
+        $options = array();
+    }
+
     switch ($contentType) {
-    case 'text/x-icalendar':
-    case 'text/x-vcalendar':
-        require_once 'Horde/Data.php';
-        $vtodo = &Horde_Data::singleton('vtodo');
-        return $vtodo->exportData(array($task));
+    case 'text/x-icalendar':     
+    case 'text/x-vcalendar':     
+    case 'text/x-vtodo':
+        require_once 'Horde/iCalendar.php';
+
+        // Create the new iCalendar.
+        $vCal = &new Horde_iCalendar();
+        $vCal->setAttribute('VERSION', '2.0');
+        $vCal->setAttribute('PRODID', '-//The Horde Project//Nag //EN');
+        $vCal->setAttribute('METHOD', 'PUBLISH');
+
+        // Create new vtodo.
+        $vtodo = $storage->toiCalendar($task,$vCal);
+        
+        if(!empty($options['ENCODING'])) {
+            $o['ENCODING'] = $options['ENCODING'];
+        }
+        if(!empty($options['CHARSET'])) {
+            $o['CHARSET'] = $options['CHARSET'];
+        }
 
+        // Set encoding options for all string values. 
+        // For vnote only body:
+        if(isset($o) && is_array($o)) {
+            $vtodo->setParameter('SUMMARY', $o);
+            $vtodo->setParameter('DESCRIPTION', $o);
+        }
+
+        $vCal->addComponent($vtodo);
+        
+        return $vCal->exportvCalendar();
     default:
         return PEAR::raiseError(_("Unsupported Content-Type."));
     }
@@ -432,10 +476,7 @@
                 return PEAR::raiseError(_("No iCalendar data was found."));
 
             case 1:
-                $content = $components[0];
-                if (!is_a($content, 'Horde_iCalendar_vtodo')) {
-                    return PEAR::raiseError(_("vTodo not found."));
-                }
+                $vtodo = $components[0];
                 break;
 
             default:
@@ -444,14 +485,19 @@
         }
 
         /**
-         * @TODO Need to check for alarms and set due date, etc.
+         * @TODO Need to check for alarms and completed
          */
-        $hash = $content->toArray();
-        $result = $storage->modify($task['task_id'],
-                                   isset($hash['name']) ? $hash['name'] : '',
-                                   isset($hash['desc']) ? $hash['desc'] : '',
-                                   0,
-                                   isset($hash['priority']) ? $hash['priority'] : 3);
+        $task = $storage->fromiCalendar($vtodo);
+
+        $result = $storage->modify($guid,
+                                   isset($task['name']) ? $task['name'] : '',
+                                   isset($task['desc']) ? $task['desc'] : '',
+                                   isset($task['due']) ? $task['due'] : '',
+                                   isset($task['priority']) ? $task['priority'] : 3,
+                                   !empty($task['completed']) ? 1 : 0,
+                                   isset($task['category']) ? $task['category'] : '',
+                                   0 // alarm: missing
+                                   );
         break;
 
     default:
-------------- next part --------------
Index: SyncML/SyncML/State.php
===================================================================
RCS file: /repository/framework/SyncML/SyncML/State.php,v
retrieving revision 1.13
diff -u -r1.13 State.php
--- SyncML/SyncML/State.php	7 Jul 2004 03:49:08 -0000	1.13
+++ SyncML/SyncML/State.php	11 Jul 2004 20:37:38 -0000
@@ -473,6 +473,32 @@
         }
     }
 
+    /**
+     * returns the preferred contenttype
+     * of the client for the given sync data type (database)
+     * this is passed as an option to the Horde api export functions.
+     *
+     */
+    function getPreferedContentTypeClient($type)
+    {
+        if ($type == 'contacts') {
+            return 'text/x-vcard';
+        } elseif ($type == 'notes') {
+            // return 'text/x-vnote'
+            return array('ContentType' => 'text/x-vnote',
+                         'ENCODING'    => 'QUOTED-PRINTABLE',
+                         'CHARSET'     => 'UTF-8');                 
+        } elseif ($type == 'tasks') {
+            return 'text/x-vcalendar';
+        } elseif ($type == 'calendar') {
+            // return 'text/x-vcalendar';
+            return array('ContentType' => 'text/x-vcalendar',
+                         'ENCODING'    => 'QUOTED-PRINTABLE',
+                         'CHARSET'     => 'UTF-8');                 
+
+        }
+    }
+
     function setClientAnchorNext($type, $a)
     {
         $this->_clientAnchorNext[$type] = $a;
Index: SyncML/SyncML/Sync.php
===================================================================
RCS file: /repository/framework/SyncML/SyncML/Sync.php,v
retrieving revision 1.4
diff -u -r1.4 Sync.php
--- SyncML/SyncML/Sync.php	3 Jul 2004 15:28:35 -0000	1.4
+++ SyncML/SyncML/Sync.php	11 Jul 2004 20:37:38 -0000
@@ -91,11 +91,8 @@
         $state = &$_SESSION['SyncML.state'];
         $hordeType = $type = $this->_targetLocURI;
         $contentType = $state->getPreferedContentType($type);
-
         if ($this->_targetLocURI == 'calendar' && strpos($command->getContent(), 'BEGIN:VTODO') !== false) {
-            Horde::logMessage('ignoring todo entry for calender, not implemented yet ', __FILE__, __LINE__, PEAR_LOG_DEBUG);
-            // return false;
-            $hordeType = 'tasks'; // Currently disabled. Not working yet.
+            $hordeType = 'tasks';
         }
 
         $guid = false;
@@ -129,7 +126,7 @@
             }
         } elseif (is_a($command, 'Horde_SyncML_Command_Sync_Replace')) {
             $guid = $state->getGlobalUID($type, $command->getLocURI());
-
+            $ok = false;
             if ($guid) {
                 // Entry exists: replace current one.
                 $ok = $registry->call($hordeType . '/replace',
@@ -139,12 +136,13 @@
                     $state->setUID($type, $command->getLocURI(), $guid, $ts);
                     Horde::logMessage('SyncML: replaced entry ' . $guid . ' due to client request', __FILE__, __LINE__, PEAR_LOG_DEBUG);
                     $state->log("Client-Replace");
+                    $ok = true;
                 } else {
-                    $state->log("Client-ReplaceFailure");
-                    Horde::logMessage('SyncML: Error in replacing client entry:' . $guid->message, __FILE__, __LINE__, PEAR_LOG_ERR);
+                    $ok = false; // maybe removed from database, try add.
                 }
-            } else {
-                // Entry does not exist, add a new one.
+            }
+            if(!$ok) {
+                // Entry does not exist in map or database: add a new one.
                 $guid = $registry->call($hordeType . '/import',
                                         array($state->convertClient2Server($command->getContent(), $contentType), $contentType));
                 if (!is_a($guid, 'PEAR_Error')) {
Index: SyncML/SyncML/Sync/TwoWaySync.php
===================================================================
RCS file: /repository/framework/SyncML/SyncML/Sync/TwoWaySync.php,v
retrieving revision 1.10
diff -u -r1.10 TwoWaySync.php
--- SyncML/SyncML/Sync/TwoWaySync.php	8 Jul 2004 18:15:00 -0000	1.10
+++ SyncML/SyncML/Sync/TwoWaySync.php	11 Jul 2004 20:37:40 -0000
@@ -35,7 +35,6 @@
                                           $syncType,
                                           $output,
                                           $refts);
-
         if ($syncType == 'calendar' && $state->handleTasksInCalendar()) {
             Horde::logMessage("SyncML: handling tasks in calendar sync", __FILE__, __LINE__, PEAR_LOG_DEBUG);
 
@@ -69,7 +68,7 @@
             }
 
             // Create a replace request for client.
-            $contentType = $state->getPreferedContentType($syncType);
+            $contentType = $state->getPreferedContentTypeClient($syncType);
             $c = $registry->call($hordeType. '/export',
                                  array('guid' => $guid, 'contentType' => $contentType));
             if (!is_a($c, 'PEAR_Error')) {
@@ -114,6 +113,7 @@
 
         // Get adds.
         $adds = $registry->call($hordeType. '/listBy', array('action' => 'add', 'timestamp' => $refts));
+        // var_dump($adds); die("$hordeType OK");
         foreach ($adds as $guid) {
             $guid_ts = HistoryTools::getTSforAction($guid, 'add');
             $sync_ts = $state->getChangeTS($syncType, $guid);
@@ -136,7 +136,7 @@
             Horde::logMessage("SyncML: add: $guid", __FILE__, __LINE__, PEAR_LOG_DEBUG);
 
             // Create an Add request for client.
-            $contentType = $state->getPreferedContentType($syncType);
+            $contentType = $state->getPreferedContentTypeClient($syncType);
 
             $cmd = &new Horde_SyncML_Command_Sync_ContentSyncElement();
             $c = $registry->call($hordeType . '/export',


More information about the sync mailing list