0012212: creating exdate on iOS removes other attendee in default cal
authorCornelius Weiß <c.weiss@metaways.de>
Mon, 19 Sep 2016 15:55:46 +0000 (17:55 +0200)
committerPhilipp Schüle <p.schuele@metaways.de>
Tue, 27 Sep 2016 12:39:32 +0000 (14:39 +0200)
- working folder was not set for update path
- refactored tests

Change-Id: I3c35375327b759c5ab50be036625487fa5e3e178
Reviewed-on: http://gerrit.tine20.com/customers/3587
Tested-by: Jenkins CI (http://ci.tine20.com/)
Reviewed-by: Philipp Schüle <p.schuele@metaways.de>
tests/tine20/Calendar/Frontend/ActiveSyncTest.php
tests/tine20/Calendar/Frontend/files/event_with_attendee.xml [new file with mode: 0644]
tine20/ActiveSync/Frontend/Abstract.php
tine20/Calendar/Frontend/ActiveSync.php

index 8ea740a..1cf7f5b 100644 (file)
@@ -534,7 +534,7 @@ Zeile 3</AirSyncBase:Data>
         $syncrotonEvent = new Syncroton_Model_Event($xml->Collections->Collection->Commands->Change[0]->ApplicationData);
         
         $serverId = $controller->createEntry($syncrotonFolder->serverId, $syncrotonEvent);
-        
+
         $syncrotonEvent = $controller->getEntry(new Syncroton_Model_SyncCollection(array('collectionId' => $syncrotonFolder->serverId)), $serverId);
         
         $this->assertEquals(0,         $syncrotonEvent->allDayEvent, 'alldayEvent');
@@ -1221,37 +1221,37 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAFAAMA
         $this->assertNotEmpty($syncrotonEvent->attendees, 'Events attendees not found in default calendar');
     }
 
-    public function testUpdateEntriesIPhone()
+    public function testUpdateEntriesIPhone($syncrotonFolder = null)
     {
-        // create event
-        $syncrotonFolder = $this->testCreateFolder();
-        $syncrotonFolder2 = $this->testCreateFolder();
-        
-        //make $syncrotonFolder2 the default
-        Tinebase_Core::getPreference('Calendar')->setValue(Calendar_Preference::DEFAULTCALENDAR, $syncrotonFolder2->serverId);
-        
+        // ensure folder is default
+        $syncrotonFolder = $syncrotonFolder ? $syncrotonFolder : $this->testCreateFolder();
+        Tinebase_Core::getPreference('Calendar')->setValue(Calendar_Preference::DEFAULTCALENDAR, $syncrotonFolder->serverId);
+
+        // create event with external attendee in default calendar
+        $xml = new SimpleXMLElement(file_get_contents(__DIR__ . '/files/event_with_attendee.xml'));
+        $syncrotonEvent = new Syncroton_Model_Event($xml->Collections->Collection->Commands->Change[0]->ApplicationData);
         $controller = Syncroton_Data_Factory::factory($this->_class, $this->_getDevice(Syncroton_Model_Device::TYPE_IPHONE), Tinebase_DateTime::now());
-        list($serverId, $syncrotonEvent) = $this->testCreateEntry($syncrotonFolder);
+        $serverId = $controller->createEntry($syncrotonFolder->serverId, $syncrotonEvent);
 
-        // update event
+        // assert external attendee is present
         $syncrotonEventtoUpdate = $controller->getEntry(new Syncroton_Model_SyncCollection(array('collectionId' => $syncrotonFolder->serverId)), $serverId);
+        $this->assertEquals(2, count($syncrotonEventtoUpdate->attendees), 'event: ' . var_export($syncrotonEventtoUpdate->attendees, TRUE));
+
+        // update event in non default folder
         $syncrotonEventtoUpdate->exceptions[0]->subject = 'update';
         $syncrotonEventtoUpdate->exceptions[0]->startTime->addHour(1);
         $syncrotonEventtoUpdate->exceptions[0]->endTime->addHour(1);
-
         $syncTimestamp = Calendar_Controller_Event::getInstance()->get($serverId)->last_modified_time;
         $controller = Syncroton_Data_Factory::factory($this->_class, $this->_getDevice(Syncroton_Model_Device::TYPE_IPHONE), $syncTimestamp);
         $serverId = $controller->updateEntry($syncrotonFolder->serverId, $serverId, $syncrotonEventtoUpdate);
 
-        // assert update
+        // assert update in default folder
         $updatedSyncrotonEvent = $controller->getEntry(new Syncroton_Model_SyncCollection(array('collectionId' => $syncrotonFolder->serverId)), $serverId);
         $this->assertEquals('update', $updatedSyncrotonEvent->exceptions[0]->subject);
-        $this->assertNotEquals($syncrotonEvent->exceptions[0]->startTime->toString(), $updatedSyncrotonEvent->exceptions[0]->startTime->toString());
-        $this->assertEquals($syncrotonEventtoUpdate->exceptions[0]->startTime->toString(), $updatedSyncrotonEvent->exceptions[0]->startTime->toString());
+        $this->assertEquals('2012-11-25 15:00:00', $updatedSyncrotonEvent->exceptions[0]->startTime->toString());
+        $this->assertEquals(2, count($updatedSyncrotonEvent->attendees), 'event: ' . var_export($updatedSyncrotonEvent->attendees, TRUE));
 
-        // assert attendee are preserved
-        $updatedEvent = Calendar_Controller_MSEventFacade::getInstance()->get($serverId);
-        $this->assertNotEmpty($updatedEvent, 'attendee must be preserved during update');
+        return array($serverId, $updatedSyncrotonEvent);
     }
 
     /**
@@ -1262,21 +1262,21 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAFAAMA
      */
     public function testUpdateEntriesIPhoneNonDefaultFolder()
     {
-        // create event in folder1
+        // create event in default folder
         $syncrotonFolder = $this->testCreateFolder();
-        $controller = Syncroton_Data_Factory::factory($this->_class, $this->_getDevice(Syncroton_Model_Device::TYPE_IPHONE), Tinebase_DateTime::now());
-        list($serverId, $syncrotonEvent) = $this->testCreateEntry($syncrotonFolder);
+        list($serverId, $syncrotonEvent) = $this->testUpdateEntriesIPhone($syncrotonFolder);
 
         // create new default folder2
         $syncrotonFolder2 = $this->testCreateFolder();
         Tinebase_Core::getPreference('Calendar')->setValue(Calendar_Preference::DEFAULTCALENDAR, $syncrotonFolder2->serverId);
 
-        // load event in non default folder2
+        // load event in non default folder
+        $controller = Syncroton_Data_Factory::factory($this->_class, $this->_getDevice(Syncroton_Model_Device::TYPE_IPHONE), Tinebase_DateTime::now());
         $syncrotonEventtoUpdate = $controller->getEntry(new Syncroton_Model_SyncCollection(array('collectionId' => $syncrotonFolder->serverId)), $serverId);
         $this->assertEmpty($syncrotonEventtoUpdate->attendees, 'attendee in non default folders must be removed for ios');
 
         // update event in non default folder
-        $syncrotonEventtoUpdate->exceptions[0]->subject = 'update';
+        $syncrotonEventtoUpdate->exceptions[0]->subject = 'update2';
         $syncrotonEventtoUpdate->exceptions[0]->startTime->addHour(1);
         $syncrotonEventtoUpdate->exceptions[0]->endTime->addHour(1);
 
@@ -1284,13 +1284,11 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAFAAMA
         $controller = Syncroton_Data_Factory::factory($this->_class, $this->_getDevice(Syncroton_Model_Device::TYPE_IPHONE), $syncTimestamp);
         $serverId = $controller->updateEntry($syncrotonFolder->serverId, $serverId, $syncrotonEventtoUpdate);
 
-        // assert update from non default folder
+        // assert update from default folder
         $updatedSyncrotonEvent = $controller->getEntry(new Syncroton_Model_SyncCollection(array('collectionId' => $syncrotonFolder2->serverId)), $serverId);
-        $this->assertEquals('update', $updatedSyncrotonEvent->exceptions[0]->subject);
+        $this->assertEquals('update2', $updatedSyncrotonEvent->exceptions[0]->subject);
         $this->assertNotEquals($syncrotonEvent->exceptions[0]->startTime->toString(), $updatedSyncrotonEvent->exceptions[0]->startTime->toString());
         $this->assertEquals($syncrotonEventtoUpdate->exceptions[0]->startTime->toString(), $updatedSyncrotonEvent->exceptions[0]->startTime->toString());
-
-        // assert attendee are preserved
-        $this->assertNotEmpty($updatedSyncrotonEvent->attendees, 'attendee must be preserved during update');
+        $this->assertEquals(2, count($updatedSyncrotonEvent->attendees), 'event: ' . var_export($updatedSyncrotonEvent->attendees, TRUE));
     }
 }
diff --git a/tests/tine20/Calendar/Frontend/files/event_with_attendee.xml b/tests/tine20/Calendar/Frontend/files/event_with_attendee.xml
new file mode 100644 (file)
index 0000000..abf2ea0
--- /dev/null
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?><!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
+<Sync xmlns="uri:AirSync" xmlns:Calendar="uri:Calendar">
+    <Collections>
+        <Collection>
+            <Class>Calendar</Class>
+            <SyncKey>9</SyncKey>
+            <CollectionId>41</CollectionId>
+            <DeletesAsMoves/>
+            <GetChanges/>
+            <WindowSize>50</WindowSize>
+            <Options><FilterType>5</FilterType></Options>
+            <Commands>
+                <Change>
+                    <ServerId>6de7cb687964dc6eea109cd81750177979362217</ServerId>
+                    <ApplicationData>
+                        <Calendar:Timezone>xP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAFAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAFAAIAAAAAAAAAxP///w==</Calendar:Timezone>
+                        <Calendar:AllDayEvent>0</Calendar:AllDayEvent>
+                        <Calendar:BusyStatus>2</Calendar:BusyStatus>
+                        <Calendar:DtStamp>20121125T150537Z</Calendar:DtStamp>
+                        <Calendar:EndTime>20121123T160000Z</Calendar:EndTime>
+                        <Calendar:Sensitivity>2</Calendar:Sensitivity>
+                        <Calendar:Subject>Repeat</Calendar:Subject>
+                        <Calendar:StartTime>20121123T130000Z</Calendar:StartTime>
+                        <Calendar:UID>6de7cb687964dc6eea109cd81750177979362217</Calendar:UID>
+                        <Calendar:MeetingStatus>1</Calendar:MeetingStatus>
+                        <Calendar:Attendees>
+                            <Calendar:Attendee>
+                                <Calendar:Name>Lars Kneschke</Calendar:Name>
+                                <Calendar:Email>lars@kneschke.de</Calendar:Email>
+                            </Calendar:Attendee>
+                        </Calendar:Attendees>
+                        <Calendar:Recurrence>
+                            <Calendar:Type>0</Calendar:Type><Calendar:Interval>1</Calendar:Interval><Calendar:Until>20121128T225959Z</Calendar:Until>
+                        </Calendar:Recurrence>
+                        <Calendar:Exceptions>
+                            <Calendar:Exception>
+                                <Calendar:Deleted>0</Calendar:Deleted><Calendar:ExceptionStartTime>20121125T130000Z</Calendar:ExceptionStartTime><Calendar:StartTime>20121125T140000Z</Calendar:StartTime><Calendar:EndTime>20121125T170000Z</Calendar:EndTime><Calendar:Subject>Repeat mal anders</Calendar:Subject><Calendar:BusyStatus>2</Calendar:BusyStatus><Calendar:AllDayEvent>0</Calendar:AllDayEvent>
+                            </Calendar:Exception>
+                            <Calendar:Exception>
+                                <Calendar:Deleted>1</Calendar:Deleted><Calendar:ExceptionStartTime>20121124T130000Z</Calendar:ExceptionStartTime></Calendar:Exception>
+                        </Calendar:Exceptions>
+                        <Calendar:Reminder>15</Calendar:Reminder>
+                        <Body xmlns="uri:AirSyncBase"><Type>1</Type><Data>Hello</Data></Body>
+                    </ApplicationData>
+                </Change>
+            </Commands>
+        </Collection>
+    </Collections>
+</Sync>
\ No newline at end of file
index 18f10b2..bb40fe2 100644 (file)
@@ -372,6 +372,7 @@ abstract class ActiveSync_Frontend_Abstract implements Syncroton_Data_IData
             Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " update CollectionId: $folderId Id: $serverId");
         
         try {
+            $this->_assertContentControllerParams($folderId);
             $oldEntry = $this->_contentController->get($serverId);
         } catch (Tinebase_Exception_NotFound $tenf) {
             if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ 
index 50075c7..9504dbc 100644 (file)
@@ -577,8 +577,11 @@ class Calendar_Frontend_ActiveSync extends ActiveSync_Frontend_Abstract implemen
                     if ($entry && 
                         $this->_device->devicetype === Syncroton_Model_Device::TYPE_IPHONE &&
                         $this->_syncFolderId       !== $this->_getDefaultContainerId()) {
-                            // keep attendees as the are / they were not sent to the device before
-                            continue;
+
+                        if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(
+                            __METHOD__ . '::' . __LINE__ . " keep attendees as the are / they were not sent to the device before ");
+
+                        continue;
                     }
 
                     $newAttendees = array();