adds recurring support for managed attachements
authorCornelius Weiß <mail@corneliusweiss.de>
Wed, 21 May 2014 09:22:25 +0000 (11:22 +0200)
committerPhilipp Schüle <p.schuele@metaways.de>
Thu, 4 Sep 2014 09:26:36 +0000 (11:26 +0200)
* support create exdate with existing attachment
* support add attachment with existing exdate

Change-Id: I7c037a4ddcfdea8b77a6c6fd2daee436778774e9
Reviewed-on: http://gerrit.tine20.com/customers/666
Tested-by: Jenkins CI (http://ci.tine20.com/)
Reviewed-by: Philipp Schüle <p.schuele@metaways.de>
tests/tine20/Calendar/Frontend/CalDAV/PluginManagedAttachmentsTest.php
tests/tine20/Calendar/Frontend/WebDAV/EventTest.php
tine20/Calendar/Convert/Event/VCalendar/Abstract.php
tine20/Calendar/Frontend/CalDAV/PluginManagedAttachments.php

index 0ac0ed7..2834536 100644 (file)
@@ -76,7 +76,7 @@ class Calendar_Frontend_CalDAV_PluginManagedAttachmentsTest extends TestCase
      */
     public function testAddAttachment()
     {
-        $event = $this->calDAVTests->testCreateEventWithInternalOrganizer();
+        $event = $this->calDAVTests->testCreateRepeatingEventAndPutExdate();
         
         $request = new Sabre\HTTP\Request(array(
             'HTTP_CONTENT_TYPE' => 'text/plain',
@@ -99,13 +99,17 @@ class Calendar_Frontend_CalDAV_PluginManagedAttachmentsTest extends TestCase
         $vcalendar = stream_get_contents($this->response->body);
 //         echo $vcalendar;
         
-        $attachments = Tinebase_FileSystem_RecordAttachments::getInstance()
-        ->getRecordAttachments($event->getRecord());
+        $baseAttachments = Tinebase_FileSystem_RecordAttachments::getInstance()
+            ->getRecordAttachments($event->getRecord());
+        $exdateAttachments = Tinebase_FileSystem_RecordAttachments::getInstance()
+            ->getRecordAttachments($event->getRecord()->exdate[0]);
         
         $this->assertEquals('HTTP/1.1 201 Created', $this->response->status);
         $this->assertContains('ATTACH;MANAGED-ID='. sha1($agenda), $vcalendar, $vcalendar);
-        $this->assertEquals(1, $attachments->count());
-        $this->assertEquals('agenda.txt', $attachments[0]->name);
+        $this->assertEquals(1, $baseAttachments->count());
+        $this->assertEquals('agenda.txt', $baseAttachments[0]->name);
+        $this->assertEquals(1, $exdateAttachments->count());
+        $this->assertEquals('agenda.txt', $exdateAttachments[0]->name);
     }
     
     /**
@@ -210,4 +214,34 @@ class Calendar_Frontend_CalDAV_PluginManagedAttachmentsTest extends TestCase
         $attachments = Tinebase_FileSystem_RecordAttachments::getInstance()->getRecordAttachments($event->getRecord());
         $this->assertEquals(0, $attachments->count());
     }
+    
+    public function testCreateRecurringExceptionWithManagedBaseAttachment()
+    {
+        $_SERVER['HTTP_USER_AGENT'] = 'CalendarStore/5.0 (1127); iCal/5.0 (1535); Mac OS X/10.7.1 (11B26)';
+        
+        $event = $this->calDAVTests->createEventWithAttachment();
+        
+        // assemble vcalendar with exception
+        $eventWithExdate = clone $event;
+        $exception = clone $eventWithExdate->getRecord();
+        $eventWithExdate->getRecord()->exdate->addRecord($exception);
+        $exception->exdate = NULL;
+        $exception->rrule = NULL;
+        $exception->dtstart->addDay(5)->addHour(1);
+        $exception->dtend->addDay(5)->addHour(1);
+        $exception->setRecurId();
+
+        $event->put($eventWithExdate->get());
+        
+        $createdException = $event->getRecord()->exdate
+            ->filter('recurid', '9d28b78f-aa6d-44fc-92f6-5ab98d35d692-2011-10-09 09:00:00')
+            ->getFirstRecord();
+        
+        $this->assertEquals(1, $createdException->attachments->count());
+        
+        $attachment = $createdException->attachments->getFirstRecord();
+        $this->assertEquals('agenda.html', $attachment->name);
+        
+
+    }
 }
index 3f1f652..47f2aaf 100644 (file)
@@ -241,6 +241,8 @@ class Calendar_Frontend_WebDAV_EventTest extends Calendar_TestCase
         $event->put($vcalendarStreamException);
         
         $this->_checkExdate($event);
+        
+        return $event;
     }
     
     /**
@@ -860,7 +862,7 @@ class Calendar_Frontend_WebDAV_EventTest extends Calendar_TestCase
      */
     public function createEventWithAttachment($count=1)
     {
-        $event = $this->testCreateEventWithInternalOrganizer();
+        $event = $this->testCreateRepeatingEvent();
         
         for ($i=1; $i<=$count; $i++) {
             $suffix = $i>1 ? $i : '';
index 58f1a08..a1b9bc3 100644 (file)
@@ -474,6 +474,21 @@ class Calendar_Convert_Event_VCalendar_Abstract implements Tinebase_Convert_Inte
                     }
                 }
                 
+                // initialize attachments from base event as clients may skip parameters like
+                // name and contentytpe and we can't backward relove them from managedId
+                if ($event->attachments instanceof Tinebase_Record_RecordSet && 
+                        ! $recurException->attachments instanceof Tinebase_Record_RecordSet) {
+                    $recurException->attachments = new Tinebase_Record_RecordSet('Tinebase_Model_Tree_Node');
+                    foreach ($event->attachments as $attachment) {
+                        $recurException->attachments->addRecord(new Tinebase_Model_Tree_Node(array(
+                            'name'         => $attachment->name,
+                            'type'         => Tinebase_Model_Tree_Node::TYPE_FILE,
+                            'contenttype'  => $attachment->contenttype,
+                            'hash'         => $attachment->hash,
+                        ), true));
+                    }
+                }
+                
                 if ($baseVevent) {
                     $this->_adaptBaseEventProperties($vevent, $baseVevent);
                 }
@@ -952,17 +967,38 @@ class Calendar_Convert_Event_VCalendar_Abstract implements Tinebase_Convert_Inte
                     break;
                     
                 case 'ATTACH':
-                    $name = $property['FILENAME'];
+                    $name = (string) $property['FILENAME'];
+                    $managedId = (string) $property['MANAGED-ID'];
                     
-                    $managedId = $property['MANAGED-ID'];
                     if ($managedId) {
-                        $attachment = $event->attachments->filter('hash', $property['MANAGED-ID'])->getFirstRecord();
+                        $attachment = $event->attachments instanceof Tinebase_Record_RecordSet ?
+                            $event->attachments->filter('hash', $property['MANAGED-ID'])->getFirstRecord() :
+                            NULL;
+                        
                         
-                        // client reuses managed id to add attachment
+                        // NOTE: we might miss a attachment here for the following reasons
+                        //       1. client reuses a managed id (we are server):
+                        //          We havn't observerd this yet. iCal client reuse manged id's
+                        //          from base events in exceptions but this is covered as we 
+                        //          initialize new exceptions with base event attachments
+                        //          
+                        //          When a client reuses a managed id it's not clear yet if
+                        //          this managed id needs to be in the same series/calendar/server
+                        //
+                        //          As we use the object hash the managed id might be used in the 
+                        //          same files with different names. We need to evaluate the name
+                        //          (if attached) in this case as well.
+                        //       
+                        //       2. server send his managed id (we are client)
+                        //          * we need to download the attachment (here?)
+                        //          * we need to have a mapping externalid / internalid (where?)
                         if (! $attachment) {
-//                             @TODO: implement
-//                             Tinebase_FileSystem_RecordAttachments::getInstance()
-//                                 ->addRecordAttachment($event, $name, $attachment);
+//                             $attachment = new Tinebase_Model_Tree_Node(array(
+//                                 'name'         => $name,
+//                                 'type'         => Tinebase_Model_Tree_Node::TYPE_FILE,
+//                                 'contenttype'  => (string) $property['FMTTYPE'],
+//                                 'hash'         => $managedId,
+//                             ), true);
                         }
                         
                         $attachments->addRecord($attachment);
index c3bf60e..091d661 100644 (file)
@@ -5,7 +5,6 @@
  * see: http://tools.ietf.org/html/draft-daboo-caldav-attachments-03
  * 
  * NOTE: At the moment Apple's iCal clients seem to support only a small subset of the spec:
- * - reusing managed attachments is not used
  * - deleting is done by PUT and not via managed-remove
  * - client does not update files
  * - client can not cope with recurring exceptions. It always acts on the whole serices and all exceptions
@@ -220,15 +219,15 @@ class Calendar_Frontend_CalDAV_PluginManagedAttachments extends \Sabre\DAV\Serve
             $affectedEvents->addRecord($event);
         }
         
-        if ($event->exceptions instanceof Tinebase_Record_RecordSet) {
-            foreach($event->exceptions as $exception) {
+        if ($event->exdate instanceof Tinebase_Record_RecordSet) {
+            foreach($event->exdate as $exception) {
                 if (! $rid /*|| $exception->recurid ...*/) {
                     $affectedEvents->addRecord($exception);
                 }
             }
         }
         foreach($affectedEvents as $record) {
-            if ($method($record) == false) break;
+            if ($method($record) === false) break;
         }
         
         return $affectedEvents;